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

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)