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

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)