72effb8e8a7381eb8582ea119a7e484e7cd04306
[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_read_mem8(struct mips_ejtag *ejtag_info,
97 uint32_t addr, int count, uint8_t *buf);
98 static int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info,
99 uint32_t addr, int count, uint16_t *buf);
100 static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info,
101 uint32_t addr, int count, uint32_t *buf);
102 static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info,
103 uint32_t addr, uint32_t *buf);
104
105 static int mips32_pracc_write_mem8(struct mips_ejtag *ejtag_info,
106 uint32_t addr, int count, uint8_t *buf);
107 static int mips32_pracc_write_mem16(struct mips_ejtag *ejtag_info,
108 uint32_t addr, int count, uint16_t *buf);
109 static int mips32_pracc_write_mem32(struct mips_ejtag *ejtag_info,
110 uint32_t addr, int count, uint32_t *buf);
111 static int mips32_pracc_write_u32(struct mips_ejtag *ejtag_info,
112 uint32_t addr, uint32_t *buf);
113
114 static int mips32_pracc_sync_cache(struct mips_ejtag *ejtag_info,
115 uint32_t start_addr, uint32_t end_addr);
116 static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag *ejtag_info,
117 uint32_t start_addr, uint32_t end_addr);
118
119 static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
120 {
121 uint32_t ejtag_ctrl;
122 long long then = timeval_ms();
123 int timeout;
124 int retval;
125
126 /* wait for the PrAcc to become "1" */
127 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
128
129 while (1) {
130 ejtag_ctrl = ejtag_info->ejtag_ctrl;
131 retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
132 if (retval != ERROR_OK)
133 return retval;
134
135 if (ejtag_ctrl & EJTAG_CTRL_PRACC)
136 break;
137
138 timeout = timeval_ms() - then;
139 if (timeout > 1000) {
140 LOG_DEBUG("DEBUGMODULE: No memory access in progress!");
141 return ERROR_JTAG_DEVICE_ERROR;
142 }
143 }
144
145 *ctrl = ejtag_ctrl;
146 return ERROR_OK;
147 }
148
149 static int mips32_pracc_exec_read(struct mips32_pracc_context *ctx, uint32_t address)
150 {
151 struct mips_ejtag *ejtag_info = ctx->ejtag_info;
152 int offset;
153 uint32_t ejtag_ctrl, data;
154
155 if ((address >= MIPS32_PRACC_PARAM_IN)
156 && (address < MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) {
157 offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
158 data = ctx->local_iparam[offset];
159 } else if ((address >= MIPS32_PRACC_PARAM_OUT)
160 && (address < MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
161 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
162 data = ctx->local_oparam[offset];
163 } else if ((address >= MIPS32_PRACC_TEXT)
164 && (address < MIPS32_PRACC_TEXT + ctx->code_len * 4)) {
165 offset = (address - MIPS32_PRACC_TEXT) / 4;
166 data = ctx->code[offset];
167 } else if (address == MIPS32_PRACC_STACK) {
168 if (ctx->stack_offset <= 0) {
169 LOG_ERROR("Error: Pracc stack out of bounds");
170 return ERROR_JTAG_DEVICE_ERROR;
171 }
172 /* save to our debug stack */
173 data = ctx->stack[--ctx->stack_offset];
174 } else {
175 /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back
176 * to start of debug vector */
177
178 LOG_ERROR("Error reading unexpected address 0x%8.8" PRIx32 "", address);
179 return ERROR_JTAG_DEVICE_ERROR;
180 }
181
182 /* Send the data out */
183 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA);
184 mips_ejtag_drscan_32_out(ctx->ejtag_info, data);
185
186 /* Clear the access pending bit (let the processor eat!) */
187 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
188 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL);
189 mips_ejtag_drscan_32_out(ctx->ejtag_info, ejtag_ctrl);
190
191 return jtag_execute_queue();
192 }
193
194 static int mips32_pracc_exec_write(struct mips32_pracc_context *ctx, uint32_t address)
195 {
196 uint32_t ejtag_ctrl, data;
197 int offset;
198 struct mips_ejtag *ejtag_info = ctx->ejtag_info;
199 int retval;
200
201 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA);
202 retval = mips_ejtag_drscan_32(ctx->ejtag_info, &data);
203 if (retval != ERROR_OK)
204 return retval;
205
206 /* Clear access pending bit */
207 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
208 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL);
209 mips_ejtag_drscan_32_out(ctx->ejtag_info, ejtag_ctrl);
210
211 retval = jtag_execute_queue();
212 if (retval != ERROR_OK)
213 return retval;
214
215 if ((address >= MIPS32_PRACC_PARAM_IN)
216 && (address < MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) {
217 offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
218 ctx->local_iparam[offset] = data;
219 } else if ((address >= MIPS32_PRACC_PARAM_OUT)
220 && (address < MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
221 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
222 ctx->local_oparam[offset] = data;
223 } else if (address == MIPS32_PRACC_STACK) {
224 if (ctx->stack_offset >= 32) {
225 LOG_ERROR("Error: Pracc stack out of bounds");
226 return ERROR_JTAG_DEVICE_ERROR;
227 }
228 /* save data onto our stack */
229 ctx->stack[ctx->stack_offset++] = data;
230 } else {
231 LOG_ERROR("Error writing unexpected address 0x%8.8" PRIx32 "", address);
232 return ERROR_JTAG_DEVICE_ERROR;
233 }
234
235 return ERROR_OK;
236 }
237
238 int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_t *code,
239 int num_param_in, uint32_t *param_in, int num_param_out, uint32_t *param_out, int cycle)
240 {
241 uint32_t ejtag_ctrl;
242 uint32_t address;
243 struct mips32_pracc_context ctx;
244 int retval;
245 int pass = 0;
246
247 ctx.local_iparam = param_in;
248 ctx.local_oparam = param_out;
249 ctx.num_iparam = num_param_in;
250 ctx.num_oparam = num_param_out;
251 ctx.code = code;
252 ctx.code_len = code_len;
253 ctx.ejtag_info = ejtag_info;
254 ctx.stack_offset = 0;
255
256 while (1) {
257 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
258 if (retval != ERROR_OK)
259 return retval;
260
261 address = 0;
262 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
263 retval = mips_ejtag_drscan_32(ejtag_info, &address);
264 if (retval != ERROR_OK)
265 return retval;
266
267 /* Check for read or write */
268 if (ejtag_ctrl & EJTAG_CTRL_PRNW) {
269 retval = mips32_pracc_exec_write(&ctx, address);
270 if (retval != ERROR_OK)
271 return retval;
272 } else {
273 /* Check to see if its reading at the debug vector. The first pass through
274 * the module is always read at the vector, so the first one we allow. When
275 * the second read from the vector occurs we are done and just exit. */
276 if ((address == MIPS32_PRACC_TEXT) && (pass++))
277 break;
278
279 retval = mips32_pracc_exec_read(&ctx, address);
280 if (retval != ERROR_OK)
281 return retval;
282 }
283
284 if (cycle == 0)
285 break;
286 }
287
288 /* stack sanity check */
289 if (ctx.stack_offset != 0)
290 LOG_DEBUG("Pracc Stack not zero");
291
292 return ERROR_OK;
293 }
294
295 int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
296 {
297 switch (size) {
298 case 1:
299 return mips32_pracc_read_mem8(ejtag_info, addr, count, (uint8_t *)buf);
300 case 2:
301 return mips32_pracc_read_mem16(ejtag_info, addr, count, (uint16_t *)buf);
302 case 4:
303 if (count == 1)
304 return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf);
305 else
306 return mips32_pracc_read_mem32(ejtag_info, addr, count, (uint32_t *)buf);
307 }
308
309 return ERROR_OK;
310 }
311
312 static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
313 {
314 static const uint32_t code[] = {
315 /* start: */
316 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
317 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
318 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
319 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
320 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
321 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
322 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
323
324 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
325 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN)),
326 MIPS32_LW(9, 0, 8), /* $9 = mem[$8]; read addr */
327 MIPS32_LW(10, 4, 8), /* $10 = mem[$8 + 4]; read count */
328 MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11 = MIPS32_PRACC_PARAM_OUT */
329 MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT)),
330 /* loop: */
331 MIPS32_BEQ(0, 10, 8), /* beq 0, $10, end */
332 MIPS32_NOP,
333
334 MIPS32_LW(8, 0, 9), /* lw $8,0($9), Load $8 with the word @mem[$9] */
335 MIPS32_SW(8, 0, 11), /* sw $8,0($11) */
336
337 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
338 MIPS32_ADDI(9, 9, 4), /* $1 += 4 */
339 MIPS32_ADDI(11, 11, 4), /* $11 += 4 */
340
341 MIPS32_B(NEG16(8)), /* b loop */
342 MIPS32_NOP,
343 /* end: */
344 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
345 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
346 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
347 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
348 MIPS32_B(NEG16(27)), /* b start */
349 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
350 };
351
352 int retval = ERROR_OK;
353 int blocksize;
354 int wordsread;
355 uint32_t param_in[2];
356
357 wordsread = 0;
358
359 while (count > 0) {
360 blocksize = count;
361 if (count > 0x400)
362 blocksize = 0x400;
363
364 param_in[0] = addr;
365 param_in[1] = blocksize;
366
367 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
368 ARRAY_SIZE(param_in), param_in, blocksize, &buf[wordsread], 1);
369 if (retval != ERROR_OK)
370 return retval;
371
372 count -= blocksize;
373 addr += blocksize*sizeof(uint32_t);
374 wordsread += blocksize;
375 }
376
377 return retval;
378 }
379
380 static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
381 {
382 uint32_t code[] = {
383 /* start: */
384 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
385 MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR), /* $15 = MIPS32_PRACC_BASE_ADDR */
386 MIPS32_SW(8, PRACC_STACK_OFFSET, 15), /* sw $8,PRACC_STACK_OFFSET($15) */
387
388 MIPS32_LUI(8, UPPER16((addr + 0x8000))), /* load $8 with modified upper address */
389 MIPS32_LW(8, LOWER16(addr), 8), /* lw $8, LOWER16(addr)($8) */
390 MIPS32_SW(8, PRACC_OUT_OFFSET, 15), /* sw $8,PRACC_OUT_OFFSET($15) */
391
392 MIPS32_LW(8, PRACC_STACK_OFFSET, 15), /* lw $8,PRACC_STACK_OFFSET($15) */
393 MIPS32_B(NEG16(8)), /* b start */
394 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
395 };
396
397 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 0, NULL, 1, buf, 1);
398 }
399
400 static int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
401 {
402 static const uint32_t code[] = {
403 /* start: */
404 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
405 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
406 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
407 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
408 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
409 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
410 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
411
412 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
413 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN)),
414 MIPS32_LW(9, 0, 8), /* $9 = mem[$8]; read addr */
415 MIPS32_LW(10, 4, 8), /* $10 = mem[$8 + 4]; read count */
416 MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11 = MIPS32_PRACC_PARAM_OUT */
417 MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT)),
418 /* loop: */
419 MIPS32_BEQ(0, 10, 8), /* beq 0, $10, end */
420 MIPS32_NOP,
421
422 MIPS32_LHU(8, 0, 9), /* lw $8,0($9), Load $8 with the halfword @mem[$9] */
423 MIPS32_SW(8, 0, 11), /* sw $8,0($11) */
424
425 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
426 MIPS32_ADDI(9, 9, 2), /* $9 += 2 */
427 MIPS32_ADDI(11, 11, 4), /* $11 += 4 */
428 MIPS32_B(NEG16(8)), /* b loop */
429 MIPS32_NOP,
430 /* end: */
431 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
432 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
433 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
434 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
435 MIPS32_B(NEG16(27)), /* b start */
436 MIPS32_MFC0(15, 30, 0), /* move COP0 DeSave to $15 */
437 };
438
439 /* TODO remove array */
440 uint32_t *param_out = malloc(count * sizeof(uint32_t));
441 if (param_out == NULL) {
442 LOG_ERROR("Out of memory");
443 return ERROR_FAIL;
444 }
445
446 int retval = ERROR_OK;
447 int blocksize;
448 int hwordsread = 0;
449 uint32_t param_in[2];
450
451 while (count > 0) {
452 blocksize = count;
453 if (count > 0x400)
454 blocksize = 0x400;
455
456 param_in[0] = addr;
457 param_in[1] = blocksize;
458
459 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
460 ARRAY_SIZE(param_in), param_in, blocksize, &param_out[hwordsread], 1);
461
462 if (retval != ERROR_OK)
463 return retval;
464
465 count -= blocksize;
466 addr += blocksize*sizeof(uint16_t);
467 hwordsread += blocksize;
468 }
469
470 int i;
471 for (i = 0; i < hwordsread; i++)
472 buf[i] = param_out[i];
473
474 free(param_out);
475 return retval;
476 }
477
478 static int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
479 {
480 static const uint32_t code[] = {
481 /* start: */
482 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
483 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
484 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
485 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
486 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
487 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
488 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
489
490 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
491 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN)),
492 MIPS32_LW(9, 0, 8), /* $9 = mem[$8]; read addr */
493 MIPS32_LW(10, 4, 8), /* $10 = mem[$8 + 4]; read count */
494 MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11 = MIPS32_PRACC_PARAM_OUT */
495 MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT)),
496 /* loop: */
497 MIPS32_BEQ(0, 10, 8), /* beq 0, $10, end */
498 MIPS32_NOP,
499
500 MIPS32_LBU(8, 0, 9), /* lw $8,0($9), Load t4 with the byte @mem[t1] */
501 MIPS32_SW(8, 0, 11), /* sw $8,0($11) */
502
503 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
504 MIPS32_ADDI(9, 9, 1), /* $9 += 1 */
505 MIPS32_ADDI(11, 11, 4), /* $11 += 4 */
506 MIPS32_B(NEG16(8)), /* b loop */
507 MIPS32_NOP,
508 /* end: */
509 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
510 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
511 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
512 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
513 MIPS32_B(NEG16(27)), /* b start */
514 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
515 };
516
517 /* TODO remove array */
518 uint32_t *param_out = malloc(count * sizeof(uint32_t));
519 if (param_out == NULL) {
520 LOG_ERROR("Out of memory");
521 return ERROR_FAIL;
522 }
523
524 int retval = ERROR_OK;
525 int blocksize;
526 uint32_t param_in[2];
527 int bytesread = 0;
528
529 while (count > 0) {
530 blocksize = count;
531 if (count > 0x400)
532 blocksize = 0x400;
533
534 param_in[0] = addr;
535 param_in[1] = blocksize;
536
537 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
538 ARRAY_SIZE(param_in), param_in, count, &param_out[bytesread], 1);
539
540 if (retval != ERROR_OK)
541 return retval;
542
543 count -= blocksize;
544 addr += blocksize;
545 bytesread += blocksize;
546 }
547 int i;
548 for (i = 0; i < bytesread; i++)
549 buf[i] = param_out[i];
550
551 free(param_out);
552 return retval;
553 }
554
555 int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel)
556 {
557 /**
558 * Do not make this code static, but regenerate it every time,
559 * as 3th element has to be changed to add parameters
560 */
561 uint32_t code[] = {
562 /* start: */
563 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
564 MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR), /* $15 = MIPS32_PRACC_BASE_ADDR */
565 MIPS32_SW(8, PRACC_STACK_OFFSET, 15), /* sw $8,PRACC_STACK_OFFSET($15) */
566
567 /* 3 */ MIPS32_MFC0(8, 0, 0), /* move COP0 [cp0_reg select] to $8 */
568 MIPS32_SW(8, PRACC_OUT_OFFSET, 15), /* sw $8,PRACC_OUT_OFFSET($15) */
569
570 MIPS32_LW(8, PRACC_STACK_OFFSET, 15), /* lw $8,PRACC_STACK_OFFSET($15) */
571 MIPS32_B(NEG16(7)), /* b start */
572 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
573 };
574
575 /**
576 * Note that our input parametes cp0_reg and cp0_sel
577 * are numbers (not gprs) which make part of mfc0 instruction opcode.
578 *
579 * These are not fix, but can be different for each mips32_cp0_read() function call,
580 * and that is why we must insert them directly into opcode,
581 * i.e. we can not pass it on EJTAG microprogram stack (via param_in),
582 * and put them into the gprs later from MIPS32_PRACC_STACK
583 * because mfc0 do not use gpr as a parameter for the cp0_reg and select part,
584 * but plain (immediate) number.
585 *
586 * MIPS32_MTC0 is implemented via MIPS32_R_INST macro.
587 * In order to insert our parameters, we must change rd and funct fields.
588 */
589 code[3] |= (cp0_reg << 11) | cp0_sel; /* change rd and funct of MIPS32_R_INST macro */
590
591 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 0, NULL, 1, val, 1);
592 }
593
594 int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel)
595 {
596 uint32_t code[] = {
597 /* start: */
598 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
599 MIPS32_LUI(15, UPPER16(val)), /* Load val to $15 */
600 MIPS32_ORI(15, 15, LOWER16(val)),
601
602 /* 3 */ MIPS32_MTC0(15, 0, 0), /* move $15 to COP0 [cp0_reg select] */
603
604 MIPS32_B(NEG16(5)), /* b start */
605 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
606 };
607
608 /**
609 * Note that MIPS32_MTC0 macro is implemented via MIPS32_R_INST macro.
610 * In order to insert our parameters, we must change rd and funct fields.
611 */
612 code[3] |= (cp0_reg << 11) | cp0_sel; /* change rd and funct fields of MIPS32_R_INST macro */
613
614 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 0, NULL, 0, NULL, 1);
615 }
616
617 /**
618 * \b mips32_pracc_sync_cache
619 *
620 * Synchronize Caches to Make Instruction Writes Effective
621 * (ref. doc. MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set,
622 * Document Number: MD00086, Revision 2.00, June 9, 2003)
623 *
624 * When the instruction stream is written, the SYNCI instruction should be used
625 * in conjunction with other instructions to make the newly-written instructions effective.
626 *
627 * Explanation :
628 * A program that loads another program into memory is actually writing the D- side cache.
629 * The instructions it has loaded can't be executed until they reach the I-cache.
630 *
631 * After the instructions have been written, the loader should arrange
632 * to write back any containing D-cache line and invalidate any locations
633 * already in the I-cache.
634 *
635 * You can do that with cache instructions, but those instructions are only available in kernel mode,
636 * and a loader writing instructions for the use of its own process need not be privileged software.
637 *
638 * In the latest MIPS32/64 CPUs, MIPS provides the synci instruction,
639 * which does the whole job for a cache-line-sized chunk of the memory you just loaded:
640 * That is, it arranges a D-cache write-back and an I-cache invalidate.
641 *
642 * To employ synci at user level, you need to know the size of a cache line,
643 * and that can be obtained with a rdhwr SYNCI_Step
644 * from one of the standard “hardware registers”.
645 */
646 static int mips32_pracc_sync_cache(struct mips_ejtag *ejtag_info,
647 uint32_t start_addr, uint32_t end_addr)
648 {
649 static const uint32_t code[] = {
650 /* start: */
651 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
652 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
653 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
654 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
655 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
656 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
657 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
658
659 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
660 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN)),
661 MIPS32_LW(9, 0, 8), /* Load write start_addr to $9 */
662 MIPS32_LW(10, 4, 8), /* Load write end_addr to $10 */
663
664 MIPS32_RDHWR(11, MIPS32_SYNCI_STEP), /* $11 = MIPS32_SYNCI_STEP */
665 MIPS32_BEQ(11, 0, 6), /* beq $11, $0, end */
666 MIPS32_NOP,
667 /* synci_loop : */
668 MIPS32_SYNCI(0, 9), /* synci 0($9) */
669 MIPS32_SLTU(8, 10, 9), /* sltu $8, $10, $9 # $8 = $10 < $9 ? 1 : 0 */
670 MIPS32_BNE(8, 0, NEG16(3)), /* bne $8, $0, synci_loop */
671 MIPS32_ADDU(9, 9, 11), /* $9 += MIPS32_SYNCI_STEP */
672 MIPS32_SYNC,
673 /* end: */
674 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
675 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
676 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
677 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
678 MIPS32_B(NEG16(24)), /* b start */
679 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
680 };
681
682 /* TODO remove array */
683 uint32_t *param_in = malloc(2 * sizeof(uint32_t));
684 int retval;
685 param_in[0] = start_addr;
686 param_in[1] = end_addr;
687
688 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 2, param_in, 0, NULL, 1);
689
690 free(param_in);
691
692 return retval;
693 }
694
695 /**
696 * \b mips32_pracc_clean_invalidate_cache
697 *
698 * Writeback D$ and Invalidate I$
699 * so that the instructions written can be visible to CPU
700 */
701 static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag *ejtag_info,
702 uint32_t start_addr, uint32_t end_addr)
703 {
704 static const uint32_t code[] = {
705 /* start: */
706 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
707 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
708 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
709 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
710 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
711 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
712 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
713
714 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
715 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN)),
716 MIPS32_LW(9, 0, 8), /* Load write start_addr to $9 */
717 MIPS32_LW(10, 4, 8), /* Load write end_addr to $10 */
718 MIPS32_LW(11, 8, 8), /* Load write clsiz to $11 */
719
720 /* cache_loop: */
721 MIPS32_SLTU(8, 10, 9), /* sltu $8, $10, $9 : $8 <- $10 < $9 ? */
722 MIPS32_BGTZ(8, 6), /* bgtz $8, end */
723 MIPS32_NOP,
724
725 MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK, 0, 9), /* cache Hit_Writeback_D, 0($9) */
726 MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE, 0, 9), /* cache Hit_Invalidate_I, 0($9) */
727
728 MIPS32_ADDU(9, 9, 11), /* $9 += $11 */
729
730 MIPS32_B(NEG16(7)), /* b cache_loop */
731 MIPS32_NOP,
732 /* end: */
733 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
734 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
735 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
736 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
737 MIPS32_B(NEG16(25)), /* b start */
738 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
739 };
740
741 /**
742 * Find cache line size in bytes
743 */
744 uint32_t conf;
745 uint32_t dl, clsiz;
746
747 mips32_cp0_read(ejtag_info, &conf, 16, 1);
748 dl = (conf & MIPS32_CONFIG1_DL_MASK) >> MIPS32_CONFIG1_DL_SHIFT;
749
750 /* dl encoding : dl=1 => 4 bytes, dl=2 => 8 bytes, etc... */
751 clsiz = 0x2 << dl;
752
753 /* TODO remove array */
754 uint32_t *param_in = malloc(3 * sizeof(uint32_t));
755 int retval;
756 param_in[0] = start_addr;
757 param_in[1] = end_addr;
758 param_in[2] = clsiz;
759
760 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 3, param_in, 0, NULL, 1);
761
762 free(param_in);
763
764 return retval;
765 }
766
767
768 int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
769 {
770 int retval;
771
772 switch (size) {
773 case 1:
774 retval = mips32_pracc_write_mem8(ejtag_info, addr, count, (uint8_t *)buf);
775 break;
776 case 2:
777 retval = mips32_pracc_write_mem16(ejtag_info, addr, count, (uint16_t *)buf);
778 break;
779 case 4:
780 if (count == 1)
781 retval = mips32_pracc_write_u32(ejtag_info, addr, (uint32_t *)buf);
782 else
783 retval = mips32_pracc_write_mem32(ejtag_info, addr, count, (uint32_t *)buf);
784 break;
785 default:
786 retval = ERROR_FAIL;
787 }
788
789 /**
790 * If we are in the cachable regoion and cache is activated,
791 * we must clean D$ + invalidate I$ after we did the write,
792 * so that changes do not continue to live only in D$, but to be
793 * replicated in I$ also (maybe we wrote the istructions)
794 */
795 uint32_t conf = 0;
796 int cached = 0;
797
798 if ((KSEGX(addr) == KSEG1) || ((addr >= 0xff200000) && (addr <= 0xff3fffff)))
799 return retval; /*Nothing to do*/
800
801 mips32_cp0_read(ejtag_info, &conf, 16, 0);
802
803 switch (KSEGX(addr)) {
804 case KUSEG:
805 cached = (conf & MIPS32_CONFIG0_KU_MASK) >> MIPS32_CONFIG0_KU_SHIFT;
806 break;
807 case KSEG0:
808 cached = (conf & MIPS32_CONFIG0_K0_MASK) >> MIPS32_CONFIG0_K0_SHIFT;
809 break;
810 case KSEG2:
811 case KSEG3:
812 cached = (conf & MIPS32_CONFIG0_K23_MASK) >> MIPS32_CONFIG0_K23_SHIFT;
813 break;
814 default:
815 /* what ? */
816 break;
817 }
818
819 /**
820 * Check cachablitiy bits coherency algorithm -
821 * is the region cacheable or uncached.
822 * If cacheable we have to synchronize the cache
823 */
824 if (cached == 0x3) {
825 uint32_t start_addr, end_addr;
826 uint32_t rel;
827
828 start_addr = addr;
829 end_addr = addr + count * size;
830
831 /** select cache synchronisation mechanism based on Architecture Release */
832 rel = (conf & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT;
833 switch (rel) {
834 case MIPS32_ARCH_REL1:
835 /* MIPS32/64 Release 1 - we must use cache instruction */
836 mips32_pracc_clean_invalidate_cache(ejtag_info, start_addr, end_addr);
837 break;
838 case MIPS32_ARCH_REL2:
839 /* MIPS32/64 Release 2 - we can use synci instruction */
840 mips32_pracc_sync_cache(ejtag_info, start_addr, end_addr);
841 break;
842 default:
843 /* what ? */
844 break;
845 }
846 }
847
848 return retval;
849 }
850
851 static int mips32_pracc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
852 {
853 static const uint32_t code[] = {
854 /* start: */
855 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
856 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
857 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
858 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
859 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
860 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
861 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
862
863 MIPS32_ADDI(8, 15, NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)), /* $8= MIPS32_PRACC_PARAM_IN */
864 MIPS32_LW(9, 0, 8), /* Load write addr to $9 */
865 MIPS32_LW(10, 4, 8), /* Load write count to $10 */
866 MIPS32_ADDI(8, 8, 8), /* $8 += 8 beginning of data */
867
868 /* loop: */
869 MIPS32_LW(11, 0, 8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
870 MIPS32_SW(11, 0, 9), /* sw $11,0($9) */
871
872 MIPS32_ADDI(9, 9, 4), /* $9 += 4 */
873 MIPS32_BNE(10, 9, NEG16(4)), /* bne $10, $9, loop */
874 MIPS32_ADDI(8, 8, 4), /* $8 += 4 */
875
876 /* end: */
877 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
878 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
879 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
880 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
881 MIPS32_B(NEG16(21)), /* b start */
882 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
883 };
884
885 /* TODO remove array */
886 uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
887 param_in[0] = addr;
888 param_in[1] = addr + (count * sizeof(uint32_t)); /* last address */
889
890 memcpy(&param_in[2], buf, count * sizeof(uint32_t));
891
892 int retval;
893 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
894 count + 2, param_in, 0, NULL, 1);
895
896 free(param_in);
897
898 return retval;
899 }
900
901 static int mips32_pracc_write_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
902 {
903 static const uint32_t code[] = {
904 /* start: */
905 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
906 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
907 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
908 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
909 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
910
911 MIPS32_LW(8, NEG16((MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)-4), 15), /* load R8 @ param_in[1] = data */
912 MIPS32_LW(9, NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN), 15), /* load R9 @ param_in[0] = address */
913
914 MIPS32_SW(8, 0, 9), /* sw $8,0($9) */
915
916 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
917 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
918 MIPS32_B(NEG16(11)), /* b start */
919 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
920 };
921
922 /* TODO remove array */
923 uint32_t param_in[1 + 1];
924 param_in[0] = addr;
925 param_in[1] = *buf;
926
927 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
928 ARRAY_SIZE(param_in), param_in, 0, NULL, 1);
929 }
930
931 static int mips32_pracc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
932 {
933 static const uint32_t code[] = {
934 /* start: */
935 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
936 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
937 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
938 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
939 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
940 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
941 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
942
943 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
944 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN)),
945 MIPS32_LW(9, 0, 8), /* Load write addr to $9 */
946 MIPS32_LW(10, 4, 8), /* Load write count to $10 */
947 MIPS32_ADDI(8, 8, 8), /* $8 += 8 */
948 /* loop: */
949 MIPS32_BEQ(0, 10, 8), /* beq $0, $10, end */
950 MIPS32_NOP,
951
952 MIPS32_LW(11, 0, 8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
953 MIPS32_SH(11, 0, 9), /* sh $11,0($9) */
954
955 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
956 MIPS32_ADDI(9, 9, 2), /* $9 += 2 */
957 MIPS32_ADDI(8, 8, 4), /* $8 += 4 */
958
959 MIPS32_B(NEG16(8)), /* b loop */
960 MIPS32_NOP,
961 /* end: */
962 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
963 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
964 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
965 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
966 MIPS32_B(NEG16(26)), /* b start */
967 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
968 };
969
970 /* TODO remove array */
971 uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
972 int i;
973 param_in[0] = addr;
974 param_in[1] = count;
975
976 for (i = 0; i < count; i++)
977 param_in[i + 2] = buf[i];
978
979 int retval;
980 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
981 count + 2, param_in, 0, NULL, 1);
982
983 free(param_in);
984
985 return retval;
986 }
987
988 static int mips32_pracc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
989 {
990 static const uint32_t code[] = {
991 /* start: */
992 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
993 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
994 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
995 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
996 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
997 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
998 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
999
1000 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
1001 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN)),
1002 MIPS32_LW(9, 0, 8), /* Load write addr to $9 */
1003 MIPS32_LW(10, 4, 8), /* Load write count to $10 */
1004 MIPS32_ADDI(8, 8, 8), /* $8 += 8 */
1005 /* loop: */
1006 MIPS32_BEQ(0, 10, 8), /* beq $0, $10, end */
1007 MIPS32_NOP,
1008
1009 MIPS32_LW(11, 0, 8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
1010 MIPS32_SB(11, 0, 9), /* sb $11,0($9) */
1011
1012 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
1013 MIPS32_ADDI(9, 9, 1), /* $9 += 1 */
1014 MIPS32_ADDI(8, 8, 4), /* $8 += 4 */
1015
1016 MIPS32_B(NEG16(8)), /* b loop */
1017 MIPS32_NOP,
1018 /* end: */
1019 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
1020 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
1021 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
1022 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
1023 MIPS32_B(NEG16(26)), /* b start */
1024 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1025 };
1026
1027 /* TODO remove array */
1028 uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
1029 int retval;
1030 int i;
1031 param_in[0] = addr;
1032 param_in[1] = count;
1033
1034 for (i = 0; i < count; i++)
1035 param_in[i + 2] = buf[i];
1036
1037 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
1038 count + 2, param_in, 0, NULL, 1);
1039
1040 free(param_in);
1041
1042 return retval;
1043 }
1044
1045 int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
1046 {
1047 static const uint32_t code[] = {
1048 /* start: */
1049 MIPS32_LUI(2, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $2 = MIPS32_PRACC_PARAM_IN */
1050 MIPS32_ORI(2, 2, LOWER16(MIPS32_PRACC_PARAM_IN)),
1051 MIPS32_LW(1, 1*4, 2), /* lw $1,1*4($2) */
1052 MIPS32_LW(15, 15*4, 2), /* lw $15,15*4($2) */
1053 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1054 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
1055 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
1056 MIPS32_SW(1, 0, 15), /* sw $1,($15) */
1057 MIPS32_LUI(1, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $1 = MIPS32_PRACC_PARAM_IN */
1058 MIPS32_ORI(1, 1, LOWER16(MIPS32_PRACC_PARAM_IN)),
1059 MIPS32_LW(3, 3*4, 1), /* lw $3,3*4($1) */
1060 MIPS32_LW(4, 4*4, 1), /* lw $4,4*4($1) */
1061 MIPS32_LW(5, 5*4, 1), /* lw $5,5*4($1) */
1062 MIPS32_LW(6, 6*4, 1), /* lw $6,6*4($1) */
1063 MIPS32_LW(7, 7*4, 1), /* lw $7,7*4($1) */
1064 MIPS32_LW(8, 8*4, 1), /* lw $8,8*4($1) */
1065 MIPS32_LW(9, 9*4, 1), /* lw $9,9*4($1) */
1066 MIPS32_LW(10, 10*4, 1), /* lw $10,10*4($1) */
1067 MIPS32_LW(11, 11*4, 1), /* lw $11,11*4($1) */
1068 MIPS32_LW(12, 12*4, 1), /* lw $12,12*4($1) */
1069 MIPS32_LW(13, 13*4, 1), /* lw $13,13*4($1) */
1070 MIPS32_LW(14, 14*4, 1), /* lw $14,14*4($1) */
1071 MIPS32_LW(16, 16*4, 1), /* lw $16,16*4($1) */
1072 MIPS32_LW(17, 17*4, 1), /* lw $17,17*4($1) */
1073 MIPS32_LW(18, 18*4, 1), /* lw $18,18*4($1) */
1074 MIPS32_LW(19, 19*4, 1), /* lw $19,19*4($1) */
1075 MIPS32_LW(20, 20*4, 1), /* lw $20,20*4($1) */
1076 MIPS32_LW(21, 21*4, 1), /* lw $21,21*4($1) */
1077 MIPS32_LW(22, 22*4, 1), /* lw $22,22*4($1) */
1078 MIPS32_LW(23, 23*4, 1), /* lw $23,23*4($1) */
1079 MIPS32_LW(24, 24*4, 1), /* lw $24,24*4($1) */
1080 MIPS32_LW(25, 25*4, 1), /* lw $25,25*4($1) */
1081 MIPS32_LW(26, 26*4, 1), /* lw $26,26*4($1) */
1082 MIPS32_LW(27, 27*4, 1), /* lw $27,27*4($1) */
1083 MIPS32_LW(28, 28*4, 1), /* lw $28,28*4($1) */
1084 MIPS32_LW(29, 29*4, 1), /* lw $29,29*4($1) */
1085 MIPS32_LW(30, 30*4, 1), /* lw $30,30*4($1) */
1086 MIPS32_LW(31, 31*4, 1), /* lw $31,31*4($1) */
1087
1088 MIPS32_LW(2, 32*4, 1), /* lw $2,32*4($1) */
1089 MIPS32_MTC0(2, 12, 0), /* move $2 to status */
1090 MIPS32_LW(2, 33*4, 1), /* lw $2,33*4($1) */
1091 MIPS32_MTLO(2), /* move $2 to lo */
1092 MIPS32_LW(2, 34*4, 1), /* lw $2,34*4($1) */
1093 MIPS32_MTHI(2), /* move $2 to hi */
1094 MIPS32_LW(2, 35*4, 1), /* lw $2,35*4($1) */
1095 MIPS32_MTC0(2, 8, 0), /* move $2 to badvaddr */
1096 MIPS32_LW(2, 36*4, 1), /* lw $2,36*4($1) */
1097 MIPS32_MTC0(2, 13, 0), /* move $2 to cause*/
1098 MIPS32_LW(2, 37*4, 1), /* lw $2,37*4($1) */
1099 MIPS32_MTC0(2, 24, 0), /* move $2 to depc (pc) */
1100
1101 MIPS32_LW(2, 2*4, 1), /* lw $2,2*4($1) */
1102 MIPS32_LW(1, 0, 15), /* lw $1,($15) */
1103 MIPS32_B(NEG16(53)), /* b start */
1104 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1105 };
1106
1107 int retval;
1108
1109 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
1110 MIPS32NUMCOREREGS, regs, 0, NULL, 1);
1111
1112 return retval;
1113 }
1114
1115 int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
1116 {
1117 static const uint32_t code[] = {
1118 /* start: */
1119 MIPS32_MTC0(2, 31, 0), /* move $2 to COP0 DeSave */
1120 MIPS32_LUI(2, UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $2 = MIPS32_PRACC_PARAM_OUT */
1121 MIPS32_ORI(2, 2, LOWER16(MIPS32_PRACC_PARAM_OUT)),
1122 MIPS32_SW(0, 0*4, 2), /* sw $0,0*4($2) */
1123 MIPS32_SW(1, 1*4, 2), /* sw $1,1*4($2) */
1124 MIPS32_SW(15, 15*4, 2), /* sw $15,15*4($2) */
1125 MIPS32_MFC0(2, 31, 0), /* move COP0 DeSave to $2 */
1126 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1127 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
1128 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK)),
1129 MIPS32_SW(1, 0, 15), /* sw $1,($15) */
1130 MIPS32_SW(2, 0, 15), /* sw $2,($15) */
1131 MIPS32_LUI(1, UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $1 = MIPS32_PRACC_PARAM_OUT */
1132 MIPS32_ORI(1, 1, LOWER16(MIPS32_PRACC_PARAM_OUT)),
1133 MIPS32_SW(2, 2*4, 1), /* sw $2,2*4($1) */
1134 MIPS32_SW(3, 3*4, 1), /* sw $3,3*4($1) */
1135 MIPS32_SW(4, 4*4, 1), /* sw $4,4*4($1) */
1136 MIPS32_SW(5, 5*4, 1), /* sw $5,5*4($1) */
1137 MIPS32_SW(6, 6*4, 1), /* sw $6,6*4($1) */
1138 MIPS32_SW(7, 7*4, 1), /* sw $7,7*4($1) */
1139 MIPS32_SW(8, 8*4, 1), /* sw $8,8*4($1) */
1140 MIPS32_SW(9, 9*4, 1), /* sw $9,9*4($1) */
1141 MIPS32_SW(10, 10*4, 1), /* sw $10,10*4($1) */
1142 MIPS32_SW(11, 11*4, 1), /* sw $11,11*4($1) */
1143 MIPS32_SW(12, 12*4, 1), /* sw $12,12*4($1) */
1144 MIPS32_SW(13, 13*4, 1), /* sw $13,13*4($1) */
1145 MIPS32_SW(14, 14*4, 1), /* sw $14,14*4($1) */
1146 MIPS32_SW(16, 16*4, 1), /* sw $16,16*4($1) */
1147 MIPS32_SW(17, 17*4, 1), /* sw $17,17*4($1) */
1148 MIPS32_SW(18, 18*4, 1), /* sw $18,18*4($1) */
1149 MIPS32_SW(19, 19*4, 1), /* sw $19,19*4($1) */
1150 MIPS32_SW(20, 20*4, 1), /* sw $20,20*4($1) */
1151 MIPS32_SW(21, 21*4, 1), /* sw $21,21*4($1) */
1152 MIPS32_SW(22, 22*4, 1), /* sw $22,22*4($1) */
1153 MIPS32_SW(23, 23*4, 1), /* sw $23,23*4($1) */
1154 MIPS32_SW(24, 24*4, 1), /* sw $24,24*4($1) */
1155 MIPS32_SW(25, 25*4, 1), /* sw $25,25*4($1) */
1156 MIPS32_SW(26, 26*4, 1), /* sw $26,26*4($1) */
1157 MIPS32_SW(27, 27*4, 1), /* sw $27,27*4($1) */
1158 MIPS32_SW(28, 28*4, 1), /* sw $28,28*4($1) */
1159 MIPS32_SW(29, 29*4, 1), /* sw $29,29*4($1) */
1160 MIPS32_SW(30, 30*4, 1), /* sw $30,30*4($1) */
1161 MIPS32_SW(31, 31*4, 1), /* sw $31,31*4($1) */
1162
1163 MIPS32_MFC0(2, 12, 0), /* move status to $2 */
1164 MIPS32_SW(2, 32*4, 1), /* sw $2,32*4($1) */
1165 MIPS32_MFLO(2), /* move lo to $2 */
1166 MIPS32_SW(2, 33*4, 1), /* sw $2,33*4($1) */
1167 MIPS32_MFHI(2), /* move hi to $2 */
1168 MIPS32_SW(2, 34*4, 1), /* sw $2,34*4($1) */
1169 MIPS32_MFC0(2, 8, 0), /* move badvaddr to $2 */
1170 MIPS32_SW(2, 35*4, 1), /* sw $2,35*4($1) */
1171 MIPS32_MFC0(2, 13, 0), /* move cause to $2 */
1172 MIPS32_SW(2, 36*4, 1), /* sw $2,36*4($1) */
1173 MIPS32_MFC0(2, 24, 0), /* move depc (pc) to $2 */
1174 MIPS32_SW(2, 37*4, 1), /* sw $2,37*4($1) */
1175
1176 MIPS32_LW(2, 0, 15), /* lw $2,($15) */
1177 MIPS32_LW(1, 0, 15), /* lw $1,($15) */
1178 MIPS32_B(NEG16(58)), /* b start */
1179 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1180 };
1181
1182 int retval;
1183
1184 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
1185 0, NULL, MIPS32NUMCOREREGS, regs, 1);
1186
1187 return retval;
1188 }
1189
1190 /* fastdata upload/download requires an initialized working area
1191 * to load the download code; it should not be called otherwise
1192 * fetch order from the fastdata area
1193 * 1. start addr
1194 * 2. end addr
1195 * 3. data ...
1196 */
1197 int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
1198 int write_t, uint32_t addr, int count, uint32_t *buf)
1199 {
1200 uint32_t handler_code[] = {
1201 /* caution when editing, table is modified below */
1202 /* r15 points to the start of this code */
1203 MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
1204 MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
1205 MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
1206 MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
1207 /* start of fastdata area in t0 */
1208 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)),
1209 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)),
1210 MIPS32_LW(9, 0, 8), /* start addr in t1 */
1211 MIPS32_LW(10, 0, 8), /* end addr to t2 */
1212 /* loop: */
1213 /* 8 */ MIPS32_LW(11, 0, 0), /* lw t3,[t8 | r9] */
1214 /* 9 */ MIPS32_SW(11, 0, 0), /* sw t3,[r9 | r8] */
1215 MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */
1216 MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */
1217
1218 MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
1219 MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
1220 MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
1221 MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
1222
1223 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT)),
1224 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT)),
1225 MIPS32_JR(15), /* jr start */
1226 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1227 };
1228
1229 uint32_t jmp_code[] = {
1230 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1231 /* 1 */ MIPS32_LUI(15, 0), /* addr of working area added below */
1232 /* 2 */ MIPS32_ORI(15, 15, 0), /* addr of working area added below */
1233 MIPS32_JR(15), /* jump to ram program */
1234 MIPS32_NOP,
1235 };
1236
1237 int retval, i;
1238 uint32_t val, ejtag_ctrl, address;
1239
1240 if (source->size < MIPS32_FASTDATA_HANDLER_SIZE)
1241 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1242
1243 if (write_t) {
1244 handler_code[8] = MIPS32_LW(11, 0, 8); /* load data from probe at fastdata area */
1245 handler_code[9] = MIPS32_SW(11, 0, 9); /* store data to RAM @ r9 */
1246 } else {
1247 handler_code[8] = MIPS32_LW(11, 0, 9); /* load data from RAM @ r9 */
1248 handler_code[9] = MIPS32_SW(11, 0, 8); /* store data to probe at fastdata area */
1249 }
1250
1251 /* write program into RAM */
1252 if (write_t != ejtag_info->fast_access_save) {
1253 mips32_pracc_write_mem32(ejtag_info, source->address, ARRAY_SIZE(handler_code), handler_code);
1254 /* save previous operation to speed to any consecutive read/writes */
1255 ejtag_info->fast_access_save = write_t;
1256 }
1257
1258 LOG_DEBUG("%s using 0x%.8" PRIx32 " for write handler", __func__, source->address);
1259
1260 jmp_code[1] |= UPPER16(source->address);
1261 jmp_code[2] |= LOWER16(source->address);
1262
1263 for (i = 0; i < (int) ARRAY_SIZE(jmp_code); i++) {
1264 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
1265 if (retval != ERROR_OK)
1266 return retval;
1267
1268 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
1269 mips_ejtag_drscan_32_out(ejtag_info, jmp_code[i]);
1270
1271 /* Clear the access pending bit (let the processor eat!) */
1272 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
1273 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
1274 mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl);
1275 }
1276
1277 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
1278 if (retval != ERROR_OK)
1279 return retval;
1280
1281 /* next fetch to dmseg should be in FASTDATA_AREA, check */
1282 address = 0;
1283 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
1284 retval = mips_ejtag_drscan_32(ejtag_info, &address);
1285 if (retval != ERROR_OK)
1286 return retval;
1287
1288 if (address != MIPS32_PRACC_FASTDATA_AREA)
1289 return ERROR_FAIL;
1290
1291 /* wait PrAcc pending bit for FASTDATA write */
1292 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
1293 if (retval != ERROR_OK)
1294 return retval;
1295
1296 /* Send the load start address */
1297 val = addr;
1298 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
1299 mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
1300
1301 /* Send the load end address */
1302 val = addr + (count - 1) * 4;
1303 mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
1304
1305 for (i = 0; i < count; i++) {
1306 retval = mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++);
1307 if (retval != ERROR_OK)
1308 return retval;
1309 }
1310
1311 retval = jtag_execute_queue();
1312 if (retval != ERROR_OK) {
1313 LOG_ERROR("fastdata load failed");
1314 return retval;
1315 }
1316
1317 retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
1318 if (retval != ERROR_OK)
1319 return retval;
1320
1321 address = 0;
1322 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
1323 retval = mips_ejtag_drscan_32(ejtag_info, &address);
1324 if (retval != ERROR_OK)
1325 return retval;
1326
1327 if (address != MIPS32_PRACC_TEXT)
1328 LOG_ERROR("mini program did not return to start");
1329
1330 return retval;
1331 }

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)