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

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)