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

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)