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

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)