2ccbfc7fc4891484e41beae4892554799591b085
[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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 mips32_pracc_sync_cache(struct mips_ejtag *ejtag_info,
97 uint32_t start_addr, uint32_t end_addr);
98 static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag *ejtag_info,
99 uint32_t start_addr, uint32_t end_addr);
100
101 static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
102 {
103 uint32_t ejtag_ctrl;
104 long long then = timeval_ms();
105 int timeout;
106 int retval;
107
108 /* wait for the PrAcc to become "1" */
109 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
110
111 while (1) {
112 ejtag_ctrl = ejtag_info->ejtag_ctrl;
113 retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
114 if (retval != ERROR_OK)
115 return retval;
116
117 if (ejtag_ctrl & EJTAG_CTRL_PRACC)
118 break;
119
120 timeout = timeval_ms() - then;
121 if (timeout > 1000) {
122 LOG_DEBUG("DEBUGMODULE: No memory access in progress!");
123 return ERROR_JTAG_DEVICE_ERROR;
124 }
125 }
126
127 *ctrl = ejtag_ctrl;
128 return ERROR_OK;
129 }
130
131 static int mips32_pracc_exec_read(struct mips32_pracc_context *ctx, uint32_t address)
132 {
133 struct mips_ejtag *ejtag_info = ctx->ejtag_info;
134 int offset;
135 uint32_t ejtag_ctrl, data;
136
137 if ((address >= MIPS32_PRACC_PARAM_IN)
138 && (address < MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) {
139 offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
140 data = ctx->local_iparam[offset];
141 } else if ((address >= MIPS32_PRACC_PARAM_OUT)
142 && (address < MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
143 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
144 data = ctx->local_oparam[offset];
145 } else if ((address >= MIPS32_PRACC_TEXT)
146 && (address < MIPS32_PRACC_TEXT + ctx->code_len * 4)) {
147 offset = (address - MIPS32_PRACC_TEXT) / 4;
148 data = ctx->code[offset];
149 } else if (address == MIPS32_PRACC_STACK) {
150 if (ctx->stack_offset <= 0) {
151 LOG_ERROR("Error: Pracc stack out of bounds");
152 return ERROR_JTAG_DEVICE_ERROR;
153 }
154 /* save to our debug stack */
155 data = ctx->stack[--ctx->stack_offset];
156 } else {
157 /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back
158 * to start of debug vector */
159
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 static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
274 {
275 uint32_t code[] = {
276 /* start: */
277 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
278 MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR), /* $15 = MIPS32_PRACC_BASE_ADDR */
279
280 MIPS32_LUI(8, UPPER16((addr + 0x8000))), /* load $8 with modified upper address */
281 MIPS32_LW(8, LOWER16(addr), 8), /* lw $8, LOWER16(addr)($8) */
282 MIPS32_SW(8, PRACC_OUT_OFFSET, 15), /* sw $8,PRACC_OUT_OFFSET($15) */
283
284 MIPS32_LUI(8, UPPER16(ejtag_info->reg8)), /* restore upper 16 bits of reg 8 */
285 MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8)), /* restore lower 16 bits of reg 8 */
286 MIPS32_B(NEG16(8)), /* b start */
287 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
288 };
289
290 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 0, NULL, 1, buf, 1);
291 }
292
293 int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
294 {
295 if (count == 1 && size == 4)
296 return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf);
297
298 int retval = ERROR_FAIL;
299
300 uint32_t *code = NULL;
301 uint32_t *data = NULL;
302
303 code = malloc((256 * 2 + 10) * sizeof(uint32_t));
304 if (code == NULL) {
305 LOG_ERROR("Out of memory");
306 goto exit;
307 }
308
309 if (size != 4) {
310 data = malloc(256 * sizeof(uint32_t));
311 if (data == NULL) {
312 LOG_ERROR("Out of memory");
313 goto exit;
314 }
315 }
316
317 uint32_t *buf32 = buf;
318 uint16_t *buf16 = buf;
319 uint8_t *buf8 = buf;
320
321 int i;
322 uint32_t upper_base_addr, last_upper_base_addr;
323 int this_round_count;
324 int code_len;
325
326 while (count) {
327 this_round_count = (count > 256) ? 256 : count;
328 last_upper_base_addr = UPPER16((addr + 0x8000));
329 uint32_t *code_p = code;
330
331 *code_p++ = MIPS32_MTC0(15, 31, 0); /* save $15 in DeSave */
332 *code_p++ = MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR); /* $15 = MIPS32_PRACC_BASE_ADDR */
333 *code_p++ = MIPS32_LUI(9, last_upper_base_addr); /* load the upper memory address in $9*/
334 code_len = 3;
335
336 for (i = 0; i != this_round_count; i++) { /* Main code loop */
337 upper_base_addr = UPPER16((addr + 0x8000));
338 if (last_upper_base_addr != upper_base_addr) {
339 *code_p++ = MIPS32_LUI(9, upper_base_addr); /* if needed, change upper address in $9*/
340 code_len++;
341 last_upper_base_addr = upper_base_addr;
342 }
343
344 if (size == 4)
345 *code_p++ = MIPS32_LW(8, LOWER16(addr), 9); /* load from memory to $8 */
346 else if (size == 2)
347 *code_p++ = MIPS32_LHU(8, LOWER16(addr), 9);
348 else
349 *code_p++ = MIPS32_LBU(8, LOWER16(addr), 9);
350
351 *code_p++ = MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15); /* store $8 at param out */
352
353 code_len += 2;
354 addr += size;
355 }
356
357 *code_p++ = MIPS32_LUI(8, UPPER16(ejtag_info->reg8)); /* restore upper 16 bits of reg 8 */
358 *code_p++ = MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8)); /* restore lower 16 bits of reg 8 */
359 *code_p++ = MIPS32_LUI(9, UPPER16(ejtag_info->reg8)); /* restore upper 16 bits of reg 9 */
360 *code_p++ = MIPS32_ORI(9, 9, LOWER16(ejtag_info->reg8)); /* restore lower 16 bits of reg 9 */
361
362 code_len += 6;
363 *code_p++ = MIPS32_B(NEG16(code_len - 1)); /* jump to start */
364 *code_p = MIPS32_MFC0(15, 31, 0); /* restore $15 from DeSave */
365
366 if (size == 4) {
367 retval = mips32_pracc_exec(ejtag_info, code_len, code, 0, NULL, this_round_count, buf32, 1);
368 if (retval != ERROR_OK)
369 goto exit;
370 buf32 += this_round_count;
371 } else {
372 retval = mips32_pracc_exec(ejtag_info, code_len, code, 0, NULL, this_round_count, data, 1);
373 if (retval != ERROR_OK)
374 goto exit;
375 uint32_t *data_p = data;
376 for (i = 0; i != this_round_count; i++) {
377 if (size == 2)
378 *buf16++ = *data_p++;
379 else
380 *buf8++ = *data_p++;
381 }
382 }
383 count -= this_round_count;
384 }
385
386 exit:
387 if (code)
388 free(code);
389 if (data)
390 free(data);
391 return retval;
392 }
393
394 int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel)
395 {
396 /**
397 * Do not make this code static, but regenerate it every time,
398 * as 2th element has to be changed to add parameters
399 */
400 uint32_t code[] = {
401 /* start: */
402 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
403 MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR), /* $15 = MIPS32_PRACC_BASE_ADDR */
404
405 /* 2 */ MIPS32_MFC0(8, 0, 0), /* move COP0 [cp0_reg select] to $8 */
406 MIPS32_SW(8, PRACC_OUT_OFFSET, 15), /* sw $8,PRACC_OUT_OFFSET($15) */
407
408 MIPS32_LUI(8, UPPER16(ejtag_info->reg8)), /* restore upper 16 bits of reg 8 */
409 MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8)), /* restore lower 16 bits of reg 8 */
410 MIPS32_B(NEG16(7)), /* b start */
411 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
412 };
413
414 /**
415 * Note that our input parametes cp0_reg and cp0_sel
416 * are numbers (not gprs) which make part of mfc0 instruction opcode.
417 *
418 * These are not fix, but can be different for each mips32_cp0_read() function call,
419 * and that is why we must insert them directly into opcode,
420 * i.e. we can not pass it on EJTAG microprogram stack (via param_in),
421 * and put them into the gprs later from MIPS32_PRACC_STACK
422 * because mfc0 do not use gpr as a parameter for the cp0_reg and select part,
423 * but plain (immediate) number.
424 *
425 * MIPS32_MTC0 is implemented via MIPS32_R_INST macro.
426 * In order to insert our parameters, we must change rd and funct fields.
427 */
428 code[2] |= (cp0_reg << 11) | cp0_sel; /* change rd and funct of MIPS32_R_INST macro */
429
430 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 0, NULL, 1, val, 1);
431 }
432
433 int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel)
434 {
435 uint32_t code[] = {
436 /* start: */
437 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
438 MIPS32_LUI(15, UPPER16(val)), /* Load val to $15 */
439 MIPS32_ORI(15, 15, LOWER16(val)),
440
441 /* 3 */ MIPS32_MTC0(15, 0, 0), /* move $15 to COP0 [cp0_reg select] */
442
443 MIPS32_B(NEG16(5)), /* b start */
444 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
445 };
446
447 /**
448 * Note that MIPS32_MTC0 macro is implemented via MIPS32_R_INST macro.
449 * In order to insert our parameters, we must change rd and funct fields.
450 */
451 code[3] |= (cp0_reg << 11) | cp0_sel; /* change rd and funct fields of MIPS32_R_INST macro */
452
453 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 0, NULL, 0, NULL, 1);
454 }
455
456 /**
457 * \b mips32_pracc_sync_cache
458 *
459 * Synchronize Caches to Make Instruction Writes Effective
460 * (ref. doc. MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set,
461 * Document Number: MD00086, Revision 2.00, June 9, 2003)
462 *
463 * When the instruction stream is written, the SYNCI instruction should be used
464 * in conjunction with other instructions to make the newly-written instructions effective.
465 *
466 * Explanation :
467 * A program that loads another program into memory is actually writing the D- side cache.
468 * The instructions it has loaded can't be executed until they reach the I-cache.
469 *
470 * After the instructions have been written, the loader should arrange
471 * to write back any containing D-cache line and invalidate any locations
472 * already in the I-cache.
473 *
474 * You can do that with cache instructions, but those instructions are only available in kernel mode,
475 * and a loader writing instructions for the use of its own process need not be privileged software.
476 *
477 * In the latest MIPS32/64 CPUs, MIPS provides the synci instruction,
478 * which does the whole job for a cache-line-sized chunk of the memory you just loaded:
479 * That is, it arranges a D-cache write-back and an I-cache invalidate.
480 *
481 * To employ synci at user level, you need to know the size of a cache line,
482 * and that can be obtained with a rdhwr SYNCI_Step
483 * from one of the standard “hardware registers”.
484 */
485 static int mips32_pracc_sync_cache(struct mips_ejtag *ejtag_info,
486 uint32_t start_addr, uint32_t end_addr)
487 {
488 static const uint32_t code[] = {
489 /* start: */
490 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
491 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
492 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
493 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
494 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
495 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
496 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
497
498 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
499 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN)),
500 MIPS32_LW(9, 0, 8), /* Load write start_addr to $9 */
501 MIPS32_LW(10, 4, 8), /* Load write end_addr to $10 */
502
503 MIPS32_RDHWR(11, MIPS32_SYNCI_STEP), /* $11 = MIPS32_SYNCI_STEP */
504 MIPS32_BEQ(11, 0, 6), /* beq $11, $0, end */
505 MIPS32_NOP,
506 /* synci_loop : */
507 MIPS32_SYNCI(0, 9), /* synci 0($9) */
508 MIPS32_SLTU(8, 10, 9), /* sltu $8, $10, $9 # $8 = $10 < $9 ? 1 : 0 */
509 MIPS32_BNE(8, 0, NEG16(3)), /* bne $8, $0, synci_loop */
510 MIPS32_ADDU(9, 9, 11), /* $9 += MIPS32_SYNCI_STEP */
511 MIPS32_SYNC,
512 /* end: */
513 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
514 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
515 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
516 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
517 MIPS32_B(NEG16(24)), /* b start */
518 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
519 };
520
521 /* TODO remove array */
522 uint32_t *param_in = malloc(2 * sizeof(uint32_t));
523 int retval;
524 param_in[0] = start_addr;
525 param_in[1] = end_addr;
526
527 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 2, param_in, 0, NULL, 1);
528
529 free(param_in);
530
531 return retval;
532 }
533
534 /**
535 * \b mips32_pracc_clean_invalidate_cache
536 *
537 * Writeback D$ and Invalidate I$
538 * so that the instructions written can be visible to CPU
539 */
540 static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag *ejtag_info,
541 uint32_t start_addr, uint32_t end_addr)
542 {
543 static const uint32_t code[] = {
544 /* start: */
545 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
546 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
547 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
548 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
549 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
550 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
551 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
552
553 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
554 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN)),
555 MIPS32_LW(9, 0, 8), /* Load write start_addr to $9 */
556 MIPS32_LW(10, 4, 8), /* Load write end_addr to $10 */
557 MIPS32_LW(11, 8, 8), /* Load write clsiz to $11 */
558
559 /* cache_loop: */
560 MIPS32_SLTU(8, 10, 9), /* sltu $8, $10, $9 : $8 <- $10 < $9 ? */
561 MIPS32_BGTZ(8, 6), /* bgtz $8, end */
562 MIPS32_NOP,
563
564 MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK, 0, 9), /* cache Hit_Writeback_D, 0($9) */
565 MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE, 0, 9), /* cache Hit_Invalidate_I, 0($9) */
566
567 MIPS32_ADDU(9, 9, 11), /* $9 += $11 */
568
569 MIPS32_B(NEG16(7)), /* b cache_loop */
570 MIPS32_NOP,
571 /* end: */
572 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
573 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
574 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
575 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
576 MIPS32_B(NEG16(25)), /* b start */
577 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
578 };
579
580 /**
581 * Find cache line size in bytes
582 */
583 uint32_t conf;
584 uint32_t dl, clsiz;
585
586 mips32_cp0_read(ejtag_info, &conf, 16, 1);
587 dl = (conf & MIPS32_CONFIG1_DL_MASK) >> MIPS32_CONFIG1_DL_SHIFT;
588
589 /* dl encoding : dl=1 => 4 bytes, dl=2 => 8 bytes, etc... */
590 clsiz = 0x2 << dl;
591
592 /* TODO remove array */
593 uint32_t *param_in = malloc(3 * sizeof(uint32_t));
594 int retval;
595 param_in[0] = start_addr;
596 param_in[1] = end_addr;
597 param_in[2] = clsiz;
598
599 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 3, param_in, 0, NULL, 1);
600
601 free(param_in);
602
603 return retval;
604 }
605
606 static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
607 {
608 uint32_t *code;
609 code = malloc((128 * 3 + 9) * sizeof(uint32_t)); /* alloc memory for the worst case */
610 if (code == NULL) {
611 LOG_ERROR("Out of memory");
612 return ERROR_FAIL;
613 }
614
615 uint32_t *buf32 = buf;
616 uint16_t *buf16 = buf;
617 uint8_t *buf8 = buf;
618
619 int i;
620 int retval = ERROR_FAIL;
621 uint32_t *code_p;
622 uint32_t upper_base_addr, last_upper_base_addr;
623 int this_round_count;
624 int code_len;
625
626 while (count) {
627 this_round_count = (count > 128) ? 128 : count;
628 last_upper_base_addr = UPPER16((addr + 0x8000));
629 code_p = code;
630
631 *code_p++ = MIPS32_MTC0(15, 31, 0); /* save $15 in DeSave */
632 *code_p++ = MIPS32_LUI(15, last_upper_base_addr); /* load $15 with memory base address */
633 code_len = 2;
634
635 for (i = 0; i != this_round_count; i++) {
636 upper_base_addr = UPPER16((addr + 0x8000));
637 if (last_upper_base_addr != upper_base_addr) {
638 *code_p++ = MIPS32_LUI(15, upper_base_addr); /* if needed, change upper address in $15*/
639 code_len++;
640 last_upper_base_addr = upper_base_addr;
641 }
642
643 if (size == 4) { /* for word write check if one half word is 0 and load it accordingly */
644 if (LOWER16(*buf32) == 0) {
645 *code_p++ = MIPS32_LUI(8, UPPER16(*buf32)); /* load only upper value */
646 code_len++;
647 } else if (UPPER16(*buf32) == 0) {
648 *code_p++ = MIPS32_ORI(8, 0, LOWER16(*buf32)); /* load only lower value */
649 code_len++;
650 } else {
651 *code_p++ = MIPS32_LUI(8, UPPER16(*buf32)); /* load upper and lower */
652 *code_p++ = MIPS32_ORI(8, 8, LOWER16(*buf32));
653 code_len += 2;
654 }
655 *code_p++ = MIPS32_SW(8, LOWER16(addr), 15); /* store word to memory */
656 code_len++;
657 buf32++;
658
659 } else if (size == 2) {
660 *code_p++ = MIPS32_ORI(8, 0, *buf16); /* load lower value */
661 *code_p++ = MIPS32_SH(8, LOWER16(addr), 15); /* store half word to memory */
662 code_len += 2;
663 buf16++;
664
665 } else {
666 *code_p++ = MIPS32_ORI(8, 0, *buf8); /* load lower value */
667 *code_p++ = MIPS32_SB(8, LOWER16(addr), 15); /* store byte to memory */
668 code_len += 2;
669 buf8++;
670 }
671
672 addr += size;
673 }
674
675 *code_p++ = MIPS32_LUI(8, UPPER16(ejtag_info->reg8)), /* restore upper 16 bits of reg 8 */
676 *code_p++ = MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8)), /* restore lower 16 bits of reg 8 */
677
678 code_len += 4;
679 *code_p++ = MIPS32_B(NEG16(code_len - 1)); /* jump to start */
680 *code_p = MIPS32_MFC0(15, 31, 0); /* restore $15 from DeSave */
681
682 retval = mips32_pracc_exec(ejtag_info, code_len, code, 0, NULL, 0, NULL, 1);
683 if (retval != ERROR_OK)
684 goto exit;
685
686 count -= this_round_count;
687 }
688
689 exit:
690 free(code);
691 return retval;
692 }
693
694 int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
695 {
696 int retval = mips32_pracc_write_mem_generic(ejtag_info, addr, size, count, buf);
697 if (retval != ERROR_OK)
698 return retval;
699
700 /**
701 * If we are in the cachable regoion and cache is activated,
702 * we must clean D$ + invalidate I$ after we did the write,
703 * so that changes do not continue to live only in D$, but to be
704 * replicated in I$ also (maybe we wrote the istructions)
705 */
706 uint32_t conf = 0;
707 int cached = 0;
708
709 if ((KSEGX(addr) == KSEG1) || ((addr >= 0xff200000) && (addr <= 0xff3fffff)))
710 return retval; /*Nothing to do*/
711
712 mips32_cp0_read(ejtag_info, &conf, 16, 0);
713
714 switch (KSEGX(addr)) {
715 case KUSEG:
716 cached = (conf & MIPS32_CONFIG0_KU_MASK) >> MIPS32_CONFIG0_KU_SHIFT;
717 break;
718 case KSEG0:
719 cached = (conf & MIPS32_CONFIG0_K0_MASK) >> MIPS32_CONFIG0_K0_SHIFT;
720 break;
721 case KSEG2:
722 case KSEG3:
723 cached = (conf & MIPS32_CONFIG0_K23_MASK) >> MIPS32_CONFIG0_K23_SHIFT;
724 break;
725 default:
726 /* what ? */
727 break;
728 }
729
730 /**
731 * Check cachablitiy bits coherency algorithm -
732 * is the region cacheable or uncached.
733 * If cacheable we have to synchronize the cache
734 */
735 if (cached == 0x3) {
736 uint32_t start_addr, end_addr;
737 uint32_t rel;
738
739 start_addr = addr;
740 end_addr = addr + count * size;
741
742 /** select cache synchronisation mechanism based on Architecture Release */
743 rel = (conf & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT;
744 switch (rel) {
745 case MIPS32_ARCH_REL1:
746 /* MIPS32/64 Release 1 - we must use cache instruction */
747 mips32_pracc_clean_invalidate_cache(ejtag_info, start_addr, end_addr);
748 break;
749 case MIPS32_ARCH_REL2:
750 /* MIPS32/64 Release 2 - we can use synci instruction */
751 mips32_pracc_sync_cache(ejtag_info, start_addr, end_addr);
752 break;
753 default:
754 /* what ? */
755 break;
756 }
757 }
758
759 return retval;
760 }
761
762 int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
763 {
764 static const uint32_t cp0_write_code[] = {
765 MIPS32_MTC0(1, 12, 0), /* move $1 to status */
766 MIPS32_MTLO(1), /* move $1 to lo */
767 MIPS32_MTHI(1), /* move $1 to hi */
768 MIPS32_MTC0(1, 8, 0), /* move $1 to badvaddr */
769 MIPS32_MTC0(1, 13, 0), /* move $1 to cause*/
770 MIPS32_MTC0(1, 24, 0), /* move $1 to depc (pc) */
771 };
772
773 uint32_t *code;
774 code = malloc((37 * 2 + 6 + 1) * sizeof(uint32_t)); /* alloc memory for the worst case */
775 if (code == NULL) {
776 LOG_ERROR("Out of memory");
777 return ERROR_FAIL;
778 }
779
780 uint32_t *code_p = code;
781 int code_len = 0;
782 /* load registers 2 to 31 with lui an ori instructions, check if same instructions can be saved */
783 for (int i = 2; i < 32; i++) {
784 if (LOWER16((regs[i])) == 0) {
785 *code_p++ = MIPS32_LUI(i, UPPER16((regs[i]))); /* if lower half word is 0, lui instruction only */
786 code_len++;
787 } else if (UPPER16((regs[i])) == 0) {
788 *code_p++ = MIPS32_ORI(i, 0, LOWER16((regs[i]))); /* if upper half word is 0, ori with $0 only*/
789 code_len++;
790 } else {
791 *code_p++ = MIPS32_LUI(i, UPPER16((regs[i]))); /* default, load with lui and ori instructions */
792 *code_p++ = MIPS32_ORI(i, i, LOWER16((regs[i])));
793 code_len += 2;
794 }
795 }
796
797 for (int i = 0; i != 6; i++) {
798 *code_p++ = MIPS32_LUI(1, UPPER16((regs[i + 32]))); /* load CPO value in $1, with lui and ori */
799 *code_p++ = MIPS32_ORI(1, 1, LOWER16((regs[i + 32])));
800 *code_p++ = cp0_write_code[i]; /* write value from $1 to CPO register */
801 code_len += 3;
802 }
803
804 *code_p++ = MIPS32_LUI(1, UPPER16((regs[1]))); /* load upper half word in $1 */
805 code_len += 3;
806 *code_p++ = MIPS32_B(NEG16(code_len - 1)), /* b start */
807 *code_p = MIPS32_ORI(1, 1, LOWER16((regs[1]))); /* load lower half word in $1 */
808
809 int retval = mips32_pracc_exec(ejtag_info, code_len, code, 0, NULL, 0, NULL, 1);
810 free(code);
811
812 ejtag_info->reg8 = regs[8];
813 ejtag_info->reg9 = regs[9];
814 return retval;
815 }
816
817 int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
818 {
819 static int cp0_read_code[] = {
820 MIPS32_MFC0(2, 12, 0), /* move status to $2 */
821 MIPS32_MFLO(2), /* move lo to $2 */
822 MIPS32_MFHI(2), /* move hi to $2 */
823 MIPS32_MFC0(2, 8, 0), /* move badvaddr to $2 */
824 MIPS32_MFC0(2, 13, 0), /* move cause to $2 */
825 MIPS32_MFC0(2, 24, 0), /* move depc (pc) to $2 */
826 };
827
828 uint32_t *code;
829 code = malloc(49 * sizeof(uint32_t));
830 if (code == NULL) {
831 LOG_ERROR("Out of memory");
832 return ERROR_FAIL;
833 }
834
835 uint32_t *code_p = code;
836
837 *code_p++ = MIPS32_MTC0(1, 31, 0), /* move $1 to COP0 DeSave */
838 *code_p++ = MIPS32_LUI(1, PRACC_UPPER_BASE_ADDR); /* $1 = MIP32_PRACC_BASE_ADDR */
839
840 for (int i = 2; i != 32; i++)
841 *code_p++ = MIPS32_SW(i, PRACC_OUT_OFFSET + (i * 4), 1); /* store GPR's 2 to 31 */
842
843 for (int i = 0; i != 6; i++) {
844 *code_p++ = cp0_read_code[i]; /* load COP0 needed registers to $2 */
845 *code_p++ = MIPS32_SW(2, PRACC_OUT_OFFSET + (i + 32) * 4, 1); /* store COP0 registers from $2 to param out */
846 }
847
848 *code_p++ = MIPS32_MFC0(2, 31, 0), /* move DeSave to $2, reg1 value */
849 *code_p++ = MIPS32_SW(2, PRACC_OUT_OFFSET + 4, 1); /* store reg1 value from $2 to param out */
850
851 *code_p++ = MIPS32_LW(2, PRACC_OUT_OFFSET + 8, 1); /* restore $2 from param out (singularity) */
852 *code_p++ = MIPS32_B(NEG16(48)); /* b start */
853 *code_p = MIPS32_MFC0(1, 31, 0); /* move COP0 DeSave to $1 */
854
855 int retval = mips32_pracc_exec(ejtag_info, 49, code, 0, NULL, MIPS32NUMCOREREGS, regs, 1);
856 free(code);
857
858 ejtag_info->reg8 = regs[8];
859 ejtag_info->reg9 = regs[9];
860 return retval;
861 }
862
863 /* fastdata upload/download requires an initialized working area
864 * to load the download code; it should not be called otherwise
865 * fetch order from the fastdata area
866 * 1. start addr
867 * 2. end addr
868 * 3. data ...
869 */
870 int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
871 int write_t, uint32_t addr, int count, uint32_t *buf)
872 {
873 uint32_t handler_code[] = {
874 /* caution when editing, table is modified below */
875 /* r15 points to the start of this code */
876 MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
877 MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
878 MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
879 MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
880 /* start of fastdata area in t0 */
881 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)),
882 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)),
883 MIPS32_LW(9, 0, 8), /* start addr in t1 */
884 MIPS32_LW(10, 0, 8), /* end addr to t2 */
885 /* loop: */
886 /* 8 */ MIPS32_LW(11, 0, 0), /* lw t3,[t8 | r9] */
887 /* 9 */ MIPS32_SW(11, 0, 0), /* sw t3,[r9 | r8] */
888 MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */
889 MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */
890
891 MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
892 MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
893 MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
894 MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
895
896 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT)),
897 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT)),
898 MIPS32_JR(15), /* jr start */
899 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
900 };
901
902 uint32_t jmp_code[] = {
903 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
904 /* 1 */ MIPS32_LUI(15, 0), /* addr of working area added below */
905 /* 2 */ MIPS32_ORI(15, 15, 0), /* addr of working area added below */
906 MIPS32_JR(15), /* jump to ram program */
907 MIPS32_NOP,
908 };
909
910 int retval, i;
911 uint32_t val, ejtag_ctrl, address;
912
913 if (source->size < MIPS32_FASTDATA_HANDLER_SIZE)
914 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
915
916 if (write_t) {
917 handler_code[8] = MIPS32_LW(11, 0, 8); /* load data from probe at fastdata area */
918 handler_code[9] = MIPS32_SW(11, 0, 9); /* store data to RAM @ r9 */
919 } else {
920 handler_code[8] = MIPS32_LW(11, 0, 9); /* load data from RAM @ r9 */
921 handler_code[9] = MIPS32_SW(11, 0, 8); /* store data to probe at fastdata area */
922 }
923
924 /* write program into RAM */
925 if (write_t != ejtag_info->fast_access_save) {
926 mips32_pracc_write_mem_generic(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code);
927 /* save previous operation to speed to any consecutive read/writes */
928 ejtag_info->fast_access_save = write_t;
929 }
930
931 LOG_DEBUG("%s using 0x%.8" PRIx32 " for write handler", __func__, source->address);
932
933 jmp_code[1] |= UPPER16(source->address);
934 jmp_code[2] |= LOWER16(source->address);
935
936 for (i = 0; i < (int) ARRAY_SIZE(jmp_code); i++) {
937 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
938 if (retval != ERROR_OK)
939 return retval;
940
941 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
942 mips_ejtag_drscan_32_out(ejtag_info, jmp_code[i]);
943
944 /* Clear the access pending bit (let the processor eat!) */
945 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
946 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
947 mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl);
948 }
949
950 /* wait PrAcc pending bit for FASTDATA write */
951 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
952 if (retval != ERROR_OK)
953 return retval;
954
955 /* next fetch to dmseg should be in FASTDATA_AREA, check */
956 address = 0;
957 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
958 retval = mips_ejtag_drscan_32(ejtag_info, &address);
959 if (retval != ERROR_OK)
960 return retval;
961
962 if (address != MIPS32_PRACC_FASTDATA_AREA)
963 return ERROR_FAIL;
964
965 /* Send the load start address */
966 val = addr;
967 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
968 mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
969
970 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
971 if (retval != ERROR_OK)
972 return retval;
973
974 /* Send the load end address */
975 val = addr + (count - 1) * 4;
976 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
977 mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
978
979 for (i = 0; i < count; i++) {
980 retval = mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++);
981 if (retval != ERROR_OK)
982 return retval;
983 }
984
985 retval = jtag_execute_queue();
986 if (retval != ERROR_OK) {
987 LOG_ERROR("fastdata load failed");
988 return retval;
989 }
990
991 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
992 if (retval != ERROR_OK)
993 return retval;
994
995 address = 0;
996 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
997 retval = mips_ejtag_drscan_32(ejtag_info, &address);
998 if (retval != ERROR_OK)
999 return retval;
1000
1001 if (address != MIPS32_PRACC_TEXT)
1002 LOG_ERROR("mini program did not return to start");
1003
1004 return retval;
1005 }

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)