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

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)