Add BCM2835 (as found in Raspberry Pi) interface driver
[openocd.git] / src / target / mips32_pracc.c
1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
4 * *
5 * Copyright (C) 2008 by David T.L. Wong *
6 * *
7 * Copyright (C) 2009 by David N. Claffey <dnclaffey@gmail.com> *
8 * *
9 * Copyright (C) 2011 by Drasko DRASKOVIC *
10 * drasko.draskovic@gmail.com *
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 * This program is distributed in the hope that it will be useful, *
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20 * GNU General Public License for more details. *
21 * *
22 * You should have received a copy of the GNU General Public License *
23 * along with this program; if not, write to the *
24 * Free Software Foundation, Inc., *
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
26 ***************************************************************************/
27
28 /*
29 * This version has optimized assembly routines for 32 bit operations:
30 * - read word
31 * - write word
32 * - write array of words
33 *
34 * One thing to be aware of is that the MIPS32 cpu will execute the
35 * instruction after a branch instruction (one delay slot).
36 *
37 * For example:
38 * LW $2, ($5 +10)
39 * B foo
40 * LW $1, ($2 +100)
41 *
42 * The LW $1, ($2 +100) instruction is also executed. If this is
43 * not wanted a NOP can be inserted:
44 *
45 * LW $2, ($5 +10)
46 * B foo
47 * NOP
48 * LW $1, ($2 +100)
49 *
50 * or the code can be changed to:
51 *
52 * B foo
53 * LW $2, ($5 +10)
54 * LW $1, ($2 +100)
55 *
56 * The original code contained NOPs. I have removed these and moved
57 * the branches.
58 *
59 * I also moved the PRACC_STACK to 0xFF204000. This allows
60 * the use of 16 bits offsets to get pointers to the input
61 * and output area relative to the stack. Note that the stack
62 * isn't really a stack (the stack pointer is not 'moving')
63 * but a FIFO simulated in software.
64 *
65 * These changes result in a 35% speed increase when programming an
66 * external flash.
67 *
68 * More improvement could be gained if the registers do no need
69 * to be preserved but in that case the routines should be aware
70 * OpenOCD is used as a flash programmer or as a debug tool.
71 *
72 * Nico Coesel
73 */
74
75 #ifdef HAVE_CONFIG_H
76 #include "config.h"
77 #endif
78
79 #include <helper/time_support.h>
80
81 #include "mips32.h"
82 #include "mips32_pracc.h"
83
84 struct mips32_pracc_context {
85 uint32_t *local_iparam;
86 int num_iparam;
87 uint32_t *local_oparam;
88 int num_oparam;
89 const uint32_t *code;
90 int code_len;
91 uint32_t stack[32];
92 int stack_offset;
93 struct mips_ejtag *ejtag_info;
94 };
95
96 static int mips32_pracc_sync_cache(struct mips_ejtag *ejtag_info,
97 uint32_t start_addr, uint32_t end_addr);
98 static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag *ejtag_info,
99 uint32_t start_addr, uint32_t end_addr);
100
101 static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
102 {
103 uint32_t ejtag_ctrl;
104 long long then = timeval_ms();
105 int timeout;
106 int retval;
107
108 /* wait for the PrAcc to become "1" */
109 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
110
111 while (1) {
112 ejtag_ctrl = ejtag_info->ejtag_ctrl;
113 retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
114 if (retval != ERROR_OK)
115 return retval;
116
117 if (ejtag_ctrl & EJTAG_CTRL_PRACC)
118 break;
119
120 timeout = timeval_ms() - then;
121 if (timeout > 1000) {
122 LOG_DEBUG("DEBUGMODULE: No memory access in progress!");
123 return ERROR_JTAG_DEVICE_ERROR;
124 }
125 }
126
127 *ctrl = ejtag_ctrl;
128 return ERROR_OK;
129 }
130
131 static int mips32_pracc_exec_read(struct mips32_pracc_context *ctx, uint32_t address)
132 {
133 struct mips_ejtag *ejtag_info = ctx->ejtag_info;
134 int offset;
135 uint32_t ejtag_ctrl, data;
136
137 if ((address >= MIPS32_PRACC_PARAM_IN)
138 && (address < MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) {
139 offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
140 data = ctx->local_iparam[offset];
141 } else if ((address >= MIPS32_PRACC_PARAM_OUT)
142 && (address < MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
143 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
144 data = ctx->local_oparam[offset];
145 } else if ((address >= MIPS32_PRACC_TEXT)
146 && (address < MIPS32_PRACC_TEXT + ctx->code_len * 4)) {
147 offset = (address - MIPS32_PRACC_TEXT) / 4;
148 data = ctx->code[offset];
149 } else if (address == MIPS32_PRACC_STACK) {
150 if (ctx->stack_offset <= 0) {
151 LOG_ERROR("Error: Pracc stack out of bounds");
152 return ERROR_JTAG_DEVICE_ERROR;
153 }
154 /* save to our debug stack */
155 data = ctx->stack[--ctx->stack_offset];
156 } else {
157 /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back
158 * to start of debug vector */
159
160 LOG_ERROR("Error reading unexpected address 0x%8.8" PRIx32 "", address);
161 return ERROR_JTAG_DEVICE_ERROR;
162 }
163
164 /* Send the data out */
165 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA);
166 mips_ejtag_drscan_32_out(ctx->ejtag_info, data);
167
168 /* Clear the access pending bit (let the processor eat!) */
169 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
170 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL);
171 mips_ejtag_drscan_32_out(ctx->ejtag_info, ejtag_ctrl);
172
173 return jtag_execute_queue();
174 }
175
176 static int mips32_pracc_exec_write(struct mips32_pracc_context *ctx, uint32_t address)
177 {
178 uint32_t ejtag_ctrl, data;
179 int offset;
180 struct mips_ejtag *ejtag_info = ctx->ejtag_info;
181 int retval;
182
183 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA);
184 retval = mips_ejtag_drscan_32(ctx->ejtag_info, &data);
185 if (retval != ERROR_OK)
186 return retval;
187
188 /* Clear access pending bit */
189 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
190 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL);
191 mips_ejtag_drscan_32_out(ctx->ejtag_info, ejtag_ctrl);
192
193 retval = jtag_execute_queue();
194 if (retval != ERROR_OK)
195 return retval;
196
197 if ((address >= MIPS32_PRACC_PARAM_OUT)
198 && (address < MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
199 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
200 ctx->local_oparam[offset] = data;
201 } else if (address == MIPS32_PRACC_STACK) {
202 if (ctx->stack_offset >= 32) {
203 LOG_ERROR("Error: Pracc stack out of bounds");
204 return ERROR_JTAG_DEVICE_ERROR;
205 }
206 /* save data onto our stack */
207 ctx->stack[ctx->stack_offset++] = data;
208 } else {
209 LOG_ERROR("Error writing unexpected address 0x%8.8" PRIx32 "", address);
210 return ERROR_JTAG_DEVICE_ERROR;
211 }
212
213 return ERROR_OK;
214 }
215
216 int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_t *code,
217 int num_param_in, uint32_t *param_in, int num_param_out, uint32_t *param_out, int cycle)
218 {
219 uint32_t ejtag_ctrl;
220 uint32_t address;
221 struct mips32_pracc_context ctx;
222 int retval;
223 int pass = 0;
224
225 ctx.local_iparam = param_in;
226 ctx.local_oparam = param_out;
227 ctx.num_iparam = num_param_in;
228 ctx.num_oparam = num_param_out;
229 ctx.code = code;
230 ctx.code_len = code_len;
231 ctx.ejtag_info = ejtag_info;
232 ctx.stack_offset = 0;
233
234 while (1) {
235 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
236 if (retval != ERROR_OK)
237 return retval;
238
239 address = 0;
240 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
241 retval = mips_ejtag_drscan_32(ejtag_info, &address);
242 if (retval != ERROR_OK)
243 return retval;
244
245 /* Check for read or write */
246 if (ejtag_ctrl & EJTAG_CTRL_PRNW) {
247 retval = mips32_pracc_exec_write(&ctx, address);
248 if (retval != ERROR_OK)
249 return retval;
250 } else {
251 /* Check to see if its reading at the debug vector. The first pass through
252 * the module is always read at the vector, so the first one we allow. When
253 * the second read from the vector occurs we are done and just exit. */
254 if ((address == MIPS32_PRACC_TEXT) && (pass++))
255 break;
256
257 retval = mips32_pracc_exec_read(&ctx, address);
258 if (retval != ERROR_OK)
259 return retval;
260 }
261
262 if (cycle == 0)
263 break;
264 }
265
266 /* stack sanity check */
267 if (ctx.stack_offset != 0)
268 LOG_DEBUG("Pracc Stack not zero");
269
270 return ERROR_OK;
271 }
272
273 inline void pracc_queue_init(struct pracc_queue_info *ctx)
274 {
275 ctx->retval = ERROR_OK;
276 ctx->code_count = 0;
277 ctx->store_count = 0;
278
279 ctx->pracc_list = malloc(2 * ctx->max_code * sizeof(uint32_t));
280 if (ctx->pracc_list == NULL) {
281 LOG_ERROR("Out of memory");
282 ctx->retval = ERROR_FAIL;
283 }
284 }
285
286 inline void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr)
287 {
288 ctx->pracc_list[ctx->max_code + ctx->code_count] = addr;
289 ctx->pracc_list[ctx->code_count++] = instr;
290 if (addr)
291 ctx->store_count++;
292 }
293
294 inline void pracc_queue_free(struct pracc_queue_info *ctx)
295 {
296 if (ctx->code_count > ctx->max_code) /* Only for internal check, will be erased */
297 LOG_ERROR("Internal error, code count: %d > max code: %d", ctx->code_count, ctx->max_code);
298 if (ctx->pracc_list != NULL)
299 free(ctx->pracc_list);
300 }
301
302 int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *buf)
303 {
304 if (ejtag_info->mode == 0)
305 return mips32_pracc_exec(ejtag_info, ctx->code_count, ctx->pracc_list, 0, NULL,
306 ctx->store_count, buf, ctx->code_count - 1);
307
308 union scan_in {
309 uint8_t scan_96[12];
310 struct {
311 uint8_t ctrl[4];
312 uint8_t data[4];
313 uint8_t addr[4];
314 } scan_32;
315
316 } *scan_in = malloc(sizeof(union scan_in) * (ctx->code_count + ctx->store_count));
317 if (scan_in == NULL) {
318 LOG_ERROR("Out of memory");
319 return ERROR_FAIL;
320 }
321
322 unsigned num_clocks =
323 ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000;
324
325 uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
326 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL);
327
328 int scan_count = 0;
329 for (int i = 0; i != 2 * ctx->code_count; i++) {
330 uint32_t data = 0;
331 if (i & 1u) { /* Check store address from previous instruction, if not the first */
332 if (i < 2 || 0 == ctx->pracc_list[ctx->max_code + (i / 2) - 1])
333 continue;
334 } else
335 data = ctx->pracc_list[i / 2];
336
337 jtag_add_clocks(num_clocks);
338 mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, data, scan_in[scan_count++].scan_96);
339 }
340
341 int retval = jtag_execute_queue(); /* execute queued scans */
342 if (retval != ERROR_OK)
343 goto exit;
344
345 uint32_t fetch_addr = MIPS32_PRACC_TEXT; /* start address */
346 scan_count = 0;
347 for (int i = 0; i != 2 * ctx->code_count; i++) { /* verify every pracc access */
348 uint32_t store_addr = 0;
349 if (i & 1u) { /* Read store addres from previous instruction, if not the first */
350 store_addr = ctx->pracc_list[ctx->max_code + (i / 2) - 1];
351 if (i < 2 || 0 == store_addr)
352 continue;
353 }
354
355 ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32);
356 if (!(ejtag_ctrl & EJTAG_CTRL_PRACC)) {
357 LOG_ERROR("Error: access not pending count: %d", scan_count);
358 retval = ERROR_FAIL;
359 goto exit;
360 }
361
362 uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32);
363
364 if (store_addr != 0) {
365 if (!(ejtag_ctrl & EJTAG_CTRL_PRNW)) {
366 LOG_ERROR("Not a store/write access, count: %d", scan_count);
367 retval = ERROR_FAIL;
368 goto exit;
369 }
370 if (addr != store_addr) {
371 LOG_ERROR("Store address mismatch, read: %x expected: %x count: %d",
372 addr, store_addr, scan_count);
373 retval = ERROR_FAIL;
374 goto exit;
375 }
376 int buf_index = (addr - MIPS32_PRACC_PARAM_OUT) / 4;
377 buf[buf_index] = buf_get_u32(scan_in[scan_count].scan_32.data, 0, 32);
378
379 } else {
380 if (ejtag_ctrl & EJTAG_CTRL_PRNW) {
381 LOG_ERROR("Not a fetch/read access, count: %d", scan_count);
382 retval = ERROR_FAIL;
383 goto exit;
384 }
385 if (addr != fetch_addr) {
386 LOG_ERROR("Fetch addr mismatch, read: %x expected: %x count: %d", addr, fetch_addr, scan_count);
387 retval = ERROR_FAIL;
388 goto exit;
389 }
390 fetch_addr += 4;
391 }
392 scan_count++;
393 }
394 exit:
395 free(scan_in);
396 return retval;
397 }
398
399 int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
400 {
401 struct pracc_queue_info ctx = {.max_code = 9};
402 pracc_queue_init(&ctx);
403 if (ctx.retval != ERROR_OK)
404 goto exit;
405
406 pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* move $15 to COP0 DeSave */
407 pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
408 pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16((addr + 0x8000)))); /* load $8 with modified upper address */
409 pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 8)); /* lw $8, LOWER16(addr)($8) */
410 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
411 MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */
412 pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 of $8 */
413 pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 of $8 */
414 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
415 pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
416
417 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf);
418 exit:
419 pracc_queue_free(&ctx);
420 return ctx.retval;
421 }
422
423 int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
424 {
425 if (count == 1 && size == 4)
426 return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf);
427
428 uint32_t *data = NULL;
429 struct pracc_queue_info ctx = {.max_code = 256 * 3 + 9 + 1}; /* alloc memory for the worst case */
430 pracc_queue_init(&ctx);
431 if (ctx.retval != ERROR_OK)
432 goto exit;
433
434 if (size != 4) {
435 data = malloc(256 * sizeof(uint32_t));
436 if (data == NULL) {
437 LOG_ERROR("Out of memory");
438 goto exit;
439 }
440 }
441
442 uint32_t *buf32 = buf;
443 uint16_t *buf16 = buf;
444 uint8_t *buf8 = buf;
445
446 while (count) {
447 ctx.code_count = 0;
448 ctx.store_count = 0;
449 int this_round_count = (count > 256) ? 256 : count;
450 uint32_t last_upper_base_addr = UPPER16((addr + 0x8000));
451
452 pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* save $15 in DeSave */
453 pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
454 pracc_add(&ctx, 0, MIPS32_LUI(9, last_upper_base_addr)); /* load the upper memory address in $9 */
455
456 for (int i = 0; i != this_round_count; i++) { /* Main code loop */
457 uint32_t upper_base_addr = UPPER16((addr + 0x8000));
458 if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $9 */
459 pracc_add(&ctx, 0, MIPS32_LUI(9, upper_base_addr));
460 last_upper_base_addr = upper_base_addr;
461 }
462
463 if (size == 4)
464 pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 9)); /* load from memory to $8 */
465 else if (size == 2)
466 pracc_add(&ctx, 0, MIPS32_LHU(8, LOWER16(addr), 9));
467 else
468 pracc_add(&ctx, 0, MIPS32_LBU(8, LOWER16(addr), 9));
469
470 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4,
471 MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15)); /* store $8 at param out */
472 addr += size;
473 }
474 pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of reg 8 */
475 pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of reg 8 */
476 pracc_add(&ctx, 0, MIPS32_LUI(9, UPPER16(ejtag_info->reg9))); /* restore upper 16 bits of reg 9 */
477 pracc_add(&ctx, 0, MIPS32_ORI(9, 9, LOWER16(ejtag_info->reg9))); /* restore lower 16 bits of reg 9 */
478
479 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
480 pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
481
482 if (size == 4) {
483 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32);
484 if (ctx.retval != ERROR_OK)
485 goto exit;
486 buf32 += this_round_count;
487 } else {
488 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data);
489 if (ctx.retval != ERROR_OK)
490 goto exit;
491
492 uint32_t *data_p = data;
493 for (int i = 0; i != this_round_count; i++) {
494 if (size == 2)
495 *buf16++ = *data_p++;
496 else
497 *buf8++ = *data_p++;
498 }
499 }
500 count -= this_round_count;
501 }
502 exit:
503 pracc_queue_free(&ctx);
504 if (data != NULL)
505 free(data);
506 return ctx.retval;
507 }
508
509 int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel)
510 {
511 struct pracc_queue_info ctx = {.max_code = 8};
512 pracc_queue_init(&ctx);
513 if (ctx.retval != ERROR_OK)
514 goto exit;
515
516 pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* move $15 to COP0 DeSave */
517 pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
518 pracc_add(&ctx, 0, MIPS32_MFC0(8, 0, 0) | (cp0_reg << 11) | cp0_sel); /* move COP0 [cp0_reg select] to $8 */
519 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
520 MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */
521 pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
522 pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */
523 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
524 pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */
525
526 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val);
527 exit:
528 pracc_queue_free(&ctx);
529 return ctx.retval;
530
531 /**
532 * Note that our input parametes cp0_reg and cp0_sel
533 * are numbers (not gprs) which make part of mfc0 instruction opcode.
534 *
535 * These are not fix, but can be different for each mips32_cp0_read() function call,
536 * and that is why we must insert them directly into opcode,
537 * i.e. we can not pass it on EJTAG microprogram stack (via param_in),
538 * and put them into the gprs later from MIPS32_PRACC_STACK
539 * because mfc0 do not use gpr as a parameter for the cp0_reg and select part,
540 * but plain (immediate) number.
541 *
542 * MIPS32_MTC0 is implemented via MIPS32_R_INST macro.
543 * In order to insert our parameters, we must change rd and funct fields.
544 *
545 * code[2] |= (cp0_reg << 11) | cp0_sel; change rd and funct of MIPS32_R_INST macro
546 **/
547 }
548
549 int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel)
550 {
551 struct pracc_queue_info ctx = {.max_code = 6};
552 pracc_queue_init(&ctx);
553 if (ctx.retval != ERROR_OK)
554 goto exit;
555
556 pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* move $15 to COP0 DeSave */
557 pracc_add(&ctx, 0, MIPS32_LUI(15, UPPER16(val))); /* Load val to $15 */
558 pracc_add(&ctx, 0, MIPS32_ORI(15, 15, LOWER16(val)));
559
560 pracc_add(&ctx, 0, MIPS32_MTC0(15, 0, 0) | (cp0_reg << 11) | cp0_sel); /* write cp0 reg / sel */
561
562 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
563 pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
564
565 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
566 exit:
567 pracc_queue_free(&ctx);
568 return ctx.retval;
569
570 /**
571 * Note that MIPS32_MTC0 macro is implemented via MIPS32_R_INST macro.
572 * In order to insert our parameters, we must change rd and funct fields.
573 * code[3] |= (cp0_reg << 11) | cp0_sel; change rd and funct fields of MIPS32_R_INST macro
574 **/
575 }
576
577 /**
578 * \b mips32_pracc_sync_cache
579 *
580 * Synchronize Caches to Make Instruction Writes Effective
581 * (ref. doc. MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set,
582 * Document Number: MD00086, Revision 2.00, June 9, 2003)
583 *
584 * When the instruction stream is written, the SYNCI instruction should be used
585 * in conjunction with other instructions to make the newly-written instructions effective.
586 *
587 * Explanation :
588 * A program that loads another program into memory is actually writing the D- side cache.
589 * The instructions it has loaded can't be executed until they reach the I-cache.
590 *
591 * After the instructions have been written, the loader should arrange
592 * to write back any containing D-cache line and invalidate any locations
593 * already in the I-cache.
594 *
595 * You can do that with cache instructions, but those instructions are only available in kernel mode,
596 * and a loader writing instructions for the use of its own process need not be privileged software.
597 *
598 * In the latest MIPS32/64 CPUs, MIPS provides the synci instruction,
599 * which does the whole job for a cache-line-sized chunk of the memory you just loaded:
600 * That is, it arranges a D-cache write-back and an I-cache invalidate.
601 *
602 * To employ synci at user level, you need to know the size of a cache line,
603 * and that can be obtained with a rdhwr SYNCI_Step
604 * from one of the standard “hardware registers”.
605 */
606 static int mips32_pracc_sync_cache(struct mips_ejtag *ejtag_info,
607 uint32_t start_addr, uint32_t end_addr)
608 {
609 static const uint32_t code[] = {
610 /* start: */
611 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
612 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
613 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
614 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
615 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
616 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
617 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
618
619 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
620 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN)),
621 MIPS32_LW(9, 0, 8), /* Load write start_addr to $9 */
622 MIPS32_LW(10, 4, 8), /* Load write end_addr to $10 */
623
624 MIPS32_RDHWR(11, MIPS32_SYNCI_STEP), /* $11 = MIPS32_SYNCI_STEP */
625 MIPS32_BEQ(11, 0, 6), /* beq $11, $0, end */
626 MIPS32_NOP,
627 /* synci_loop : */
628 MIPS32_SYNCI(0, 9), /* synci 0($9) */
629 MIPS32_SLTU(8, 10, 9), /* sltu $8, $10, $9 # $8 = $10 < $9 ? 1 : 0 */
630 MIPS32_BNE(8, 0, NEG16(3)), /* bne $8, $0, synci_loop */
631 MIPS32_ADDU(9, 9, 11), /* $9 += MIPS32_SYNCI_STEP */
632 MIPS32_SYNC,
633 /* end: */
634 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
635 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
636 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
637 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
638 MIPS32_B(NEG16(24)), /* b start */
639 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
640 };
641
642 /* TODO remove array */
643 uint32_t *param_in = malloc(2 * sizeof(uint32_t));
644 int retval;
645 param_in[0] = start_addr;
646 param_in[1] = end_addr;
647
648 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 2, param_in, 0, NULL, 1);
649
650 free(param_in);
651
652 return retval;
653 }
654
655 /**
656 * \b mips32_pracc_clean_invalidate_cache
657 *
658 * Writeback D$ and Invalidate I$
659 * so that the instructions written can be visible to CPU
660 */
661 static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag *ejtag_info,
662 uint32_t start_addr, uint32_t end_addr)
663 {
664 static const uint32_t code[] = {
665 /* start: */
666 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
667 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
668 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
669 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
670 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
671 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
672 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
673
674 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
675 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN)),
676 MIPS32_LW(9, 0, 8), /* Load write start_addr to $9 */
677 MIPS32_LW(10, 4, 8), /* Load write end_addr to $10 */
678 MIPS32_LW(11, 8, 8), /* Load write clsiz to $11 */
679
680 /* cache_loop: */
681 MIPS32_SLTU(8, 10, 9), /* sltu $8, $10, $9 : $8 <- $10 < $9 ? */
682 MIPS32_BGTZ(8, 6), /* bgtz $8, end */
683 MIPS32_NOP,
684
685 MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK, 0, 9), /* cache Hit_Writeback_D, 0($9) */
686 MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE, 0, 9), /* cache Hit_Invalidate_I, 0($9) */
687
688 MIPS32_ADDU(9, 9, 11), /* $9 += $11 */
689
690 MIPS32_B(NEG16(7)), /* b cache_loop */
691 MIPS32_NOP,
692 /* end: */
693 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
694 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
695 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
696 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
697 MIPS32_B(NEG16(25)), /* b start */
698 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
699 };
700
701 /**
702 * Find cache line size in bytes
703 */
704 uint32_t conf;
705 uint32_t dl, clsiz;
706
707 mips32_cp0_read(ejtag_info, &conf, 16, 1);
708 dl = (conf & MIPS32_CONFIG1_DL_MASK) >> MIPS32_CONFIG1_DL_SHIFT;
709
710 /* dl encoding : dl=1 => 4 bytes, dl=2 => 8 bytes, etc... */
711 clsiz = 0x2 << dl;
712
713 /* TODO remove array */
714 uint32_t *param_in = malloc(3 * sizeof(uint32_t));
715 int retval;
716 param_in[0] = start_addr;
717 param_in[1] = end_addr;
718 param_in[2] = clsiz;
719
720 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 3, param_in, 0, NULL, 1);
721
722 free(param_in);
723
724 return retval;
725 }
726
727 static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
728 {
729 struct pracc_queue_info ctx = {.max_code = 128 * 3 + 6 + 1}; /* alloc memory for the worst case */
730 pracc_queue_init(&ctx);
731 if (ctx.retval != ERROR_OK)
732 goto exit;
733
734 uint32_t *buf32 = buf;
735 uint16_t *buf16 = buf;
736 uint8_t *buf8 = buf;
737
738 while (count) {
739 ctx.code_count = 0;
740 ctx.store_count = 0;
741 int this_round_count = (count > 128) ? 128 : count;
742 uint32_t last_upper_base_addr = UPPER16((addr + 0x8000));
743
744 pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* save $15 in DeSave */
745 pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr)); /* load $15 with memory base address */
746
747 for (int i = 0; i != this_round_count; i++) {
748 uint32_t upper_base_addr = UPPER16((addr + 0x8000));
749 if (last_upper_base_addr != upper_base_addr) {
750 pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr)); /* if needed, change upper address in $15*/
751 last_upper_base_addr = upper_base_addr;
752 }
753
754 if (size == 4) { /* for word writes check if one half word is 0 and load it accordingly */
755 if (LOWER16(*buf32) == 0)
756 pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(*buf32))); /* load only upper value */
757 else if (UPPER16(*buf32) == 0)
758 pracc_add(&ctx, 0, MIPS32_ORI(8, 0, LOWER16(*buf32))); /* load only lower */
759 else {
760 pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(*buf32))); /* load upper and lower */
761 pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(*buf32)));
762 }
763 pracc_add(&ctx, 0, MIPS32_SW(8, LOWER16(addr), 15)); /* store word to memory */
764 buf32++;
765
766 } else if (size == 2) {
767 pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf16)); /* load lower value */
768 pracc_add(&ctx, 0, MIPS32_SH(8, LOWER16(addr), 15)); /* store half word to memory */
769 buf16++;
770
771 } else {
772 pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf8)); /* load lower value */
773 pracc_add(&ctx, 0, MIPS32_SB(8, LOWER16(addr), 15)); /* store byte to memory */
774 buf8++;
775 }
776 addr += size;
777 }
778
779 pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of reg 8 */
780 pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of reg 8 */
781
782 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
783 pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
784
785 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
786 if (ctx.retval != ERROR_OK)
787 goto exit;
788 count -= this_round_count;
789 }
790 exit:
791 pracc_queue_free(&ctx);
792 return ctx.retval;
793 }
794
795 int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
796 {
797 int retval = mips32_pracc_write_mem_generic(ejtag_info, addr, size, count, buf);
798 if (retval != ERROR_OK)
799 return retval;
800
801 /**
802 * If we are in the cachable regoion and cache is activated,
803 * we must clean D$ + invalidate I$ after we did the write,
804 * so that changes do not continue to live only in D$, but to be
805 * replicated in I$ also (maybe we wrote the istructions)
806 */
807 uint32_t conf = 0;
808 int cached = 0;
809
810 if ((KSEGX(addr) == KSEG1) || ((addr >= 0xff200000) && (addr <= 0xff3fffff)))
811 return retval; /*Nothing to do*/
812
813 mips32_cp0_read(ejtag_info, &conf, 16, 0);
814
815 switch (KSEGX(addr)) {
816 case KUSEG:
817 cached = (conf & MIPS32_CONFIG0_KU_MASK) >> MIPS32_CONFIG0_KU_SHIFT;
818 break;
819 case KSEG0:
820 cached = (conf & MIPS32_CONFIG0_K0_MASK) >> MIPS32_CONFIG0_K0_SHIFT;
821 break;
822 case KSEG2:
823 case KSEG3:
824 cached = (conf & MIPS32_CONFIG0_K23_MASK) >> MIPS32_CONFIG0_K23_SHIFT;
825 break;
826 default:
827 /* what ? */
828 break;
829 }
830
831 /**
832 * Check cachablitiy bits coherency algorithm -
833 * is the region cacheable or uncached.
834 * If cacheable we have to synchronize the cache
835 */
836 if (cached == 0x3) {
837 uint32_t start_addr, end_addr;
838 uint32_t rel;
839
840 start_addr = addr;
841 end_addr = addr + count * size;
842
843 /** select cache synchronisation mechanism based on Architecture Release */
844 rel = (conf & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT;
845 switch (rel) {
846 case MIPS32_ARCH_REL1:
847 /* MIPS32/64 Release 1 - we must use cache instruction */
848 mips32_pracc_clean_invalidate_cache(ejtag_info, start_addr, end_addr);
849 break;
850 case MIPS32_ARCH_REL2:
851 /* MIPS32/64 Release 2 - we can use synci instruction */
852 mips32_pracc_sync_cache(ejtag_info, start_addr, end_addr);
853 break;
854 default:
855 /* what ? */
856 break;
857 }
858 }
859
860 return retval;
861 }
862
863 int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
864 {
865 static const uint32_t cp0_write_code[] = {
866 MIPS32_MTC0(1, 12, 0), /* move $1 to status */
867 MIPS32_MTLO(1), /* move $1 to lo */
868 MIPS32_MTHI(1), /* move $1 to hi */
869 MIPS32_MTC0(1, 8, 0), /* move $1 to badvaddr */
870 MIPS32_MTC0(1, 13, 0), /* move $1 to cause*/
871 MIPS32_MTC0(1, 24, 0), /* move $1 to depc (pc) */
872 };
873
874 struct pracc_queue_info ctx = {.max_code = 37 * 2 + 6 + 1};
875 pracc_queue_init(&ctx);
876 if (ctx.retval != ERROR_OK)
877 goto exit;
878
879 /* load registers 2 to 31 with lui and ori instructions, check if some instructions can be saved */
880 for (int i = 2; i < 32; i++) {
881 if (LOWER16((regs[i])) == 0) /* if lower half word is 0, lui instruction only */
882 pracc_add(&ctx, 0, MIPS32_LUI(i, UPPER16((regs[i]))));
883 else if (UPPER16((regs[i])) == 0) /* if upper half word is 0, ori with $0 only*/
884 pracc_add(&ctx, 0, MIPS32_ORI(i, 0, LOWER16((regs[i]))));
885 else { /* default, load with lui and ori instructions */
886 pracc_add(&ctx, 0, MIPS32_LUI(i, UPPER16((regs[i]))));
887 pracc_add(&ctx, 0, MIPS32_ORI(i, i, LOWER16((regs[i]))));
888 }
889 }
890
891 for (int i = 0; i != 6; i++) {
892 pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[i + 32])))); /* load CPO value in $1, with lui and ori */
893 pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[i + 32]))));
894 pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */
895 }
896
897 pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[1])))); /* load upper half word in $1 */
898 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
899 pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */
900
901 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
902
903 ejtag_info->reg8 = regs[8];
904 ejtag_info->reg9 = regs[9];
905 exit:
906 pracc_queue_free(&ctx);
907 return ctx.retval;
908 }
909
910 int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
911 {
912 static int cp0_read_code[] = {
913 MIPS32_MFC0(8, 12, 0), /* move status to $8 */
914 MIPS32_MFLO(8), /* move lo to $8 */
915 MIPS32_MFHI(8), /* move hi to $8 */
916 MIPS32_MFC0(8, 8, 0), /* move badvaddr to $8 */
917 MIPS32_MFC0(8, 13, 0), /* move cause to $8 */
918 MIPS32_MFC0(8, 24, 0), /* move depc (pc) to $8 */
919 };
920
921 struct pracc_queue_info ctx = {.max_code = 48};
922 pracc_queue_init(&ctx);
923 if (ctx.retval != ERROR_OK)
924 goto exit;
925
926 pracc_add(&ctx, 0, MIPS32_MTC0(1, 31, 0)); /* move $1 to COP0 DeSave */
927 pracc_add(&ctx, 0, MIPS32_LUI(1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */
928
929 for (int i = 2; i != 32; i++) /* store GPR's 2 to 31 */
930 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i * 4),
931 MIPS32_SW(i, PRACC_OUT_OFFSET + (i * 4), 1));
932
933 for (int i = 0; i != 6; i++) {
934 pracc_add(&ctx, 0, cp0_read_code[i]); /* load COP0 needed registers to $8 */
935 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4, /* store $8 at PARAM OUT */
936 MIPS32_SW(8, PRACC_OUT_OFFSET + (i + 32) * 4, 1));
937 }
938 pracc_add(&ctx, 0, MIPS32_MFC0(8, 31, 0)); /* move DeSave to $8, reg1 value */
939 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4, /* store reg1 value from $8 to param out */
940 MIPS32_SW(8, PRACC_OUT_OFFSET + 4, 1));
941
942 pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
943 pracc_add(&ctx, 0, MIPS32_MFC0(1, 31, 0)); /* move COP0 DeSave to $1, restore reg1 */
944
945 if (ejtag_info->mode == 0)
946 ctx.store_count++; /* Needed by legacy code, due to offset from reg0 */
947
948 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs);
949
950 ejtag_info->reg8 = regs[8]; /* reg8 is saved but not restored, next called function should restore it */
951 ejtag_info->reg9 = regs[9];
952 exit:
953 pracc_queue_free(&ctx);
954 return ctx.retval;
955 }
956
957 /* fastdata upload/download requires an initialized working area
958 * to load the download code; it should not be called otherwise
959 * fetch order from the fastdata area
960 * 1. start addr
961 * 2. end addr
962 * 3. data ...
963 */
964 int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
965 int write_t, uint32_t addr, int count, uint32_t *buf)
966 {
967 uint32_t handler_code[] = {
968 /* caution when editing, table is modified below */
969 /* r15 points to the start of this code */
970 MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
971 MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
972 MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
973 MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
974 /* start of fastdata area in t0 */
975 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)),
976 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)),
977 MIPS32_LW(9, 0, 8), /* start addr in t1 */
978 MIPS32_LW(10, 0, 8), /* end addr to t2 */
979 /* loop: */
980 /* 8 */ MIPS32_LW(11, 0, 0), /* lw t3,[t8 | r9] */
981 /* 9 */ MIPS32_SW(11, 0, 0), /* sw t3,[r9 | r8] */
982 MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */
983 MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */
984
985 MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
986 MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
987 MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
988 MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
989
990 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT)),
991 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT)),
992 MIPS32_JR(15), /* jr start */
993 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
994 };
995
996 uint32_t jmp_code[] = {
997 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
998 /* 1 */ MIPS32_LUI(15, 0), /* addr of working area added below */
999 /* 2 */ MIPS32_ORI(15, 15, 0), /* addr of working area added below */
1000 MIPS32_JR(15), /* jump to ram program */
1001 MIPS32_NOP,
1002 };
1003
1004 int retval, i;
1005 uint32_t val, ejtag_ctrl, address;
1006
1007 if (source->size < MIPS32_FASTDATA_HANDLER_SIZE)
1008 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1009
1010 if (write_t) {
1011 handler_code[8] = MIPS32_LW(11, 0, 8); /* load data from probe at fastdata area */
1012 handler_code[9] = MIPS32_SW(11, 0, 9); /* store data to RAM @ r9 */
1013 } else {
1014 handler_code[8] = MIPS32_LW(11, 0, 9); /* load data from RAM @ r9 */
1015 handler_code[9] = MIPS32_SW(11, 0, 8); /* store data to probe at fastdata area */
1016 }
1017
1018 /* write program into RAM */
1019 if (write_t != ejtag_info->fast_access_save) {
1020 mips32_pracc_write_mem_generic(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code);
1021 /* save previous operation to speed to any consecutive read/writes */
1022 ejtag_info->fast_access_save = write_t;
1023 }
1024
1025 LOG_DEBUG("%s using 0x%.8" PRIx32 " for write handler", __func__, source->address);
1026
1027 jmp_code[1] |= UPPER16(source->address);
1028 jmp_code[2] |= LOWER16(source->address);
1029
1030 for (i = 0; i < (int) ARRAY_SIZE(jmp_code); i++) {
1031 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
1032 if (retval != ERROR_OK)
1033 return retval;
1034
1035 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
1036 mips_ejtag_drscan_32_out(ejtag_info, jmp_code[i]);
1037
1038 /* Clear the access pending bit (let the processor eat!) */
1039 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
1040 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
1041 mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl);
1042 }
1043
1044 /* wait PrAcc pending bit for FASTDATA write */
1045 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
1046 if (retval != ERROR_OK)
1047 return retval;
1048
1049 /* next fetch to dmseg should be in FASTDATA_AREA, check */
1050 address = 0;
1051 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
1052 retval = mips_ejtag_drscan_32(ejtag_info, &address);
1053 if (retval != ERROR_OK)
1054 return retval;
1055
1056 if (address != MIPS32_PRACC_FASTDATA_AREA)
1057 return ERROR_FAIL;
1058
1059 /* Send the load start address */
1060 val = addr;
1061 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
1062 mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
1063
1064 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
1065 if (retval != ERROR_OK)
1066 return retval;
1067
1068 /* Send the load end address */
1069 val = addr + (count - 1) * 4;
1070 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
1071 mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
1072
1073 unsigned num_clocks = 0; /* like in legacy code */
1074 if (ejtag_info->mode != 0)
1075 num_clocks = ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000;
1076
1077 for (i = 0; i < count; i++) {
1078 jtag_add_clocks(num_clocks);
1079 retval = mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++);
1080 if (retval != ERROR_OK)
1081 return retval;
1082 }
1083
1084 retval = jtag_execute_queue();
1085 if (retval != ERROR_OK) {
1086 LOG_ERROR("fastdata load failed");
1087 return retval;
1088 }
1089
1090 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
1091 if (retval != ERROR_OK)
1092 return retval;
1093
1094 address = 0;
1095 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
1096 retval = mips_ejtag_drscan_32(ejtag_info, &address);
1097 if (retval != ERROR_OK)
1098 return retval;
1099
1100 if (address != MIPS32_PRACC_TEXT)
1101 LOG_ERROR("mini program did not return to start");
1102
1103 return retval;
1104 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)