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

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)