1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
5 * Copyright (C) 2008 by David T.L. Wong *
7 * Copyright (C) 2009 by David N. Claffey <dnclaffey@gmail.com> *
9 * Copyright (C) 2011 by Drasko DRASKOVIC *
10 * drasko.draskovic@gmail.com *
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. *
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. *
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 ***************************************************************************/
29 * This version has optimized assembly routines for 32 bit operations:
32 * - write array of words
34 * One thing to be aware of is that the MIPS32 cpu will execute the
35 * instruction after a branch instruction (one delay slot).
42 * The LW $1, ($2 +100) instruction is also executed. If this is
43 * not wanted a NOP can be inserted:
50 * or the code can be changed to:
56 * The original code contained NOPs. I have removed these and moved
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.
65 * These changes result in a 35% speed increase when programming an
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.
79 #include <helper/time_support.h>
82 #include "mips32_pracc.h"
84 struct mips32_pracc_context
{
85 uint32_t *local_iparam
;
87 uint32_t *local_oparam
;
93 struct mips_ejtag
*ejtag_info
;
96 static int wait_for_pracc_rw(struct mips_ejtag
*ejtag_info
, uint32_t *ctrl
)
99 long long then
= timeval_ms();
103 /* wait for the PrAcc to become "1" */
104 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_CONTROL
);
107 ejtag_ctrl
= ejtag_info
->ejtag_ctrl
;
108 retval
= mips_ejtag_drscan_32(ejtag_info
, &ejtag_ctrl
);
109 if (retval
!= ERROR_OK
)
112 if (ejtag_ctrl
& EJTAG_CTRL_PRACC
)
115 timeout
= timeval_ms() - then
;
116 if (timeout
> 1000) {
117 LOG_DEBUG("DEBUGMODULE: No memory access in progress!");
118 return ERROR_JTAG_DEVICE_ERROR
;
126 static int mips32_pracc_exec_read(struct mips32_pracc_context
*ctx
, uint32_t address
)
128 struct mips_ejtag
*ejtag_info
= ctx
->ejtag_info
;
130 uint32_t ejtag_ctrl
, data
;
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
;
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);
160 LOG_ERROR("Error reading unexpected address 0x%8.8" PRIx32
"", address
);
161 return ERROR_JTAG_DEVICE_ERROR
;
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
);
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
);
173 return jtag_execute_queue();
176 static int mips32_pracc_exec_write(struct mips32_pracc_context
*ctx
, uint32_t address
)
178 uint32_t ejtag_ctrl
, data
;
180 struct mips_ejtag
*ejtag_info
= ctx
->ejtag_info
;
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
)
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
);
193 retval
= jtag_execute_queue();
194 if (retval
!= ERROR_OK
)
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
;
206 /* save data onto our stack */
207 ctx
->stack
[ctx
->stack_offset
++] = data
;
209 LOG_ERROR("Error writing unexpected address 0x%8.8" PRIx32
"", address
);
210 return ERROR_JTAG_DEVICE_ERROR
;
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
)
221 struct mips32_pracc_context ctx
;
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
;
230 ctx
.code_len
= code_len
;
231 ctx
.ejtag_info
= ejtag_info
;
232 ctx
.stack_offset
= 0;
235 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
236 if (retval
!= ERROR_OK
)
240 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_ADDRESS
);
241 retval
= mips_ejtag_drscan_32(ejtag_info
, &address
);
242 if (retval
!= ERROR_OK
)
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
)
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
++))
257 retval
= mips32_pracc_exec_read(&ctx
, address
);
258 if (retval
!= ERROR_OK
)
266 /* stack sanity check */
267 if (ctx
.stack_offset
!= 0)
268 LOG_DEBUG("Pracc Stack not zero");
273 inline void pracc_queue_init(struct pracc_queue_info
*ctx
)
275 ctx
->retval
= ERROR_OK
;
277 ctx
->store_count
= 0;
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
;
286 inline void pracc_add(struct pracc_queue_info
*ctx
, uint32_t addr
, uint32_t instr
)
288 ctx
->pracc_list
[ctx
->max_code
+ ctx
->code_count
] = addr
;
289 ctx
->pracc_list
[ctx
->code_count
++] = instr
;
294 inline void pracc_queue_free(struct pracc_queue_info
*ctx
)
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
);
302 int mips32_pracc_queue_exec(struct mips_ejtag
*ejtag_info
, struct pracc_queue_info
*ctx
, uint32_t *buf
)
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);
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");
322 unsigned num_clocks
=
323 ((uint64_t)(ejtag_info
->scan_delay
) * jtag_get_speed_khz() + 500000) / 1000000;
325 uint32_t ejtag_ctrl
= ejtag_info
->ejtag_ctrl
& ~EJTAG_CTRL_PRACC
;
326 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_ALL
);
329 for (int i
= 0; i
!= 2 * ctx
->code_count
; i
++) {
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])
335 data
= ctx
->pracc_list
[i
/ 2];
337 jtag_add_clocks(num_clocks
);
338 mips_ejtag_add_scan_96(ejtag_info
, ejtag_ctrl
, data
, scan_in
[scan_count
++].scan_96
);
341 int retval
= jtag_execute_queue(); /* execute queued scans */
342 if (retval
!= ERROR_OK
)
345 uint32_t fetch_addr
= MIPS32_PRACC_TEXT
; /* start address */
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
)
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
);
362 uint32_t addr
= buf_get_u32(scan_in
[scan_count
].scan_32
.addr
, 0, 32);
364 if (store_addr
!= 0) {
365 if (!(ejtag_ctrl
& EJTAG_CTRL_PRNW
)) {
366 LOG_ERROR("Not a store/write access, count: %d", scan_count
);
370 if (addr
!= store_addr
) {
371 LOG_ERROR("Store address mismatch, read: %" PRIx32
" expected: %" PRIx32
" count: %d",
372 addr
, store_addr
, scan_count
);
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);
380 if (ejtag_ctrl
& EJTAG_CTRL_PRNW
) {
381 LOG_ERROR("Not a fetch/read access, count: %d", scan_count
);
385 if (addr
!= fetch_addr
) {
386 LOG_ERROR("Fetch addr mismatch, read: %" PRIx32
" expected: %" PRIx32
" count: %d",
387 addr
, fetch_addr
, scan_count
);
400 int mips32_pracc_read_u32(struct mips_ejtag
*ejtag_info
, uint32_t addr
, uint32_t *buf
)
402 struct pracc_queue_info ctx
= {.max_code
= 8};
403 pracc_queue_init(&ctx
);
404 if (ctx
.retval
!= ERROR_OK
)
407 pracc_add(&ctx
, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR
)); /* $15 = MIPS32_PRACC_BASE_ADDR */
408 pracc_add(&ctx
, 0, MIPS32_LUI(8, UPPER16((addr
+ 0x8000)))); /* load $8 with modified upper address */
409 pracc_add(&ctx
, 0, MIPS32_LW(8, LOWER16(addr
), 8)); /* lw $8, LOWER16(addr)($8) */
410 pracc_add(&ctx
, MIPS32_PRACC_PARAM_OUT
,
411 MIPS32_SW(8, PRACC_OUT_OFFSET
, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */
412 pracc_add(&ctx
, 0, MIPS32_LUI(8, UPPER16(ejtag_info
->reg8
))); /* restore upper 16 of $8 */
413 pracc_add(&ctx
, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info
->reg8
))); /* restore lower 16 of $8 */
414 pracc_add(&ctx
, 0, MIPS32_B(NEG16(ctx
.code_count
+ 1))); /* jump to start */
415 pracc_add(&ctx
, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
417 ctx
.retval
= mips32_pracc_queue_exec(ejtag_info
, &ctx
, buf
);
419 pracc_queue_free(&ctx
);
423 int mips32_pracc_read_mem(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int size
, int count
, void *buf
)
425 if (count
== 1 && size
== 4)
426 return mips32_pracc_read_u32(ejtag_info
, addr
, (uint32_t *)buf
);
428 uint32_t *data
= NULL
;
429 struct pracc_queue_info ctx
= {.max_code
= 256 * 3 + 8 + 1}; /* alloc memory for the worst case */
430 pracc_queue_init(&ctx
);
431 if (ctx
.retval
!= ERROR_OK
)
435 data
= malloc(256 * sizeof(uint32_t));
437 LOG_ERROR("Out of memory");
442 uint32_t *buf32
= buf
;
443 uint16_t *buf16
= buf
;
449 int this_round_count
= (count
> 256) ? 256 : count
;
450 uint32_t last_upper_base_addr
= UPPER16((addr
+ 0x8000));
452 pracc_add(&ctx
, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR
)); /* $15 = MIPS32_PRACC_BASE_ADDR */
453 pracc_add(&ctx
, 0, MIPS32_LUI(9, last_upper_base_addr
)); /* load the upper memory address in $9 */
455 for (int i
= 0; i
!= this_round_count
; i
++) { /* Main code loop */
456 uint32_t upper_base_addr
= UPPER16((addr
+ 0x8000));
457 if (last_upper_base_addr
!= upper_base_addr
) { /* if needed, change upper address in $9 */
458 pracc_add(&ctx
, 0, MIPS32_LUI(9, upper_base_addr
));
459 last_upper_base_addr
= upper_base_addr
;
463 pracc_add(&ctx
, 0, MIPS32_LW(8, LOWER16(addr
), 9)); /* load from memory to $8 */
465 pracc_add(&ctx
, 0, MIPS32_LHU(8, LOWER16(addr
), 9));
467 pracc_add(&ctx
, 0, MIPS32_LBU(8, LOWER16(addr
), 9));
469 pracc_add(&ctx
, MIPS32_PRACC_PARAM_OUT
+ i
* 4,
470 MIPS32_SW(8, PRACC_OUT_OFFSET
+ i
* 4, 15)); /* store $8 at param out */
473 pracc_add(&ctx
, 0, MIPS32_LUI(8, UPPER16(ejtag_info
->reg8
))); /* restore upper 16 bits of reg 8 */
474 pracc_add(&ctx
, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info
->reg8
))); /* restore lower 16 bits of reg 8 */
475 pracc_add(&ctx
, 0, MIPS32_LUI(9, UPPER16(ejtag_info
->reg9
))); /* restore upper 16 bits of reg 9 */
476 pracc_add(&ctx
, 0, MIPS32_ORI(9, 9, LOWER16(ejtag_info
->reg9
))); /* restore lower 16 bits of reg 9 */
478 pracc_add(&ctx
, 0, MIPS32_B(NEG16(ctx
.code_count
+ 1))); /* jump to start */
479 pracc_add(&ctx
, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
482 ctx
.retval
= mips32_pracc_queue_exec(ejtag_info
, &ctx
, buf32
);
483 if (ctx
.retval
!= ERROR_OK
)
485 buf32
+= this_round_count
;
487 ctx
.retval
= mips32_pracc_queue_exec(ejtag_info
, &ctx
, data
);
488 if (ctx
.retval
!= ERROR_OK
)
491 uint32_t *data_p
= data
;
492 for (int i
= 0; i
!= this_round_count
; i
++) {
494 *buf16
++ = *data_p
++;
499 count
-= this_round_count
;
502 pracc_queue_free(&ctx
);
508 int mips32_cp0_read(struct mips_ejtag
*ejtag_info
, uint32_t *val
, uint32_t cp0_reg
, uint32_t cp0_sel
)
510 struct pracc_queue_info ctx
= {.max_code
= 7};
511 pracc_queue_init(&ctx
);
512 if (ctx
.retval
!= ERROR_OK
)
515 pracc_add(&ctx
, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR
)); /* $15 = MIPS32_PRACC_BASE_ADDR */
516 pracc_add(&ctx
, 0, MIPS32_MFC0(8, 0, 0) | (cp0_reg
<< 11) | cp0_sel
); /* move COP0 [cp0_reg select] to $8 */
517 pracc_add(&ctx
, MIPS32_PRACC_PARAM_OUT
,
518 MIPS32_SW(8, PRACC_OUT_OFFSET
, 15)); /* store $8 to pracc_out */
519 pracc_add(&ctx
, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
520 pracc_add(&ctx
, 0, MIPS32_LUI(8, UPPER16(ejtag_info
->reg8
))); /* restore upper 16 bits of $8 */
521 pracc_add(&ctx
, 0, MIPS32_B(NEG16(ctx
.code_count
+ 1))); /* jump to start */
522 pracc_add(&ctx
, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info
->reg8
))); /* restore lower 16 bits of $8 */
524 ctx
.retval
= mips32_pracc_queue_exec(ejtag_info
, &ctx
, val
);
526 pracc_queue_free(&ctx
);
530 * Note that our input parametes cp0_reg and cp0_sel
531 * are numbers (not gprs) which make part of mfc0 instruction opcode.
533 * These are not fix, but can be different for each mips32_cp0_read() function call,
534 * and that is why we must insert them directly into opcode,
535 * i.e. we can not pass it on EJTAG microprogram stack (via param_in),
536 * and put them into the gprs later from MIPS32_PRACC_STACK
537 * because mfc0 do not use gpr as a parameter for the cp0_reg and select part,
538 * but plain (immediate) number.
540 * MIPS32_MTC0 is implemented via MIPS32_R_INST macro.
541 * In order to insert our parameters, we must change rd and funct fields.
543 * code[2] |= (cp0_reg << 11) | cp0_sel; change rd and funct of MIPS32_R_INST macro
547 int mips32_cp0_write(struct mips_ejtag
*ejtag_info
, uint32_t val
, uint32_t cp0_reg
, uint32_t cp0_sel
)
549 struct pracc_queue_info ctx
= {.max_code
= 6};
550 pracc_queue_init(&ctx
);
551 if (ctx
.retval
!= ERROR_OK
)
554 pracc_add(&ctx
, 0, MIPS32_LUI(15, UPPER16(val
))); /* Load val to $15 */
555 pracc_add(&ctx
, 0, MIPS32_ORI(15, 15, LOWER16(val
)));
557 pracc_add(&ctx
, 0, MIPS32_MTC0(15, 0, 0) | (cp0_reg
<< 11) | cp0_sel
); /* write cp0 reg / sel */
559 pracc_add(&ctx
, 0, MIPS32_B(NEG16(ctx
.code_count
+ 1))); /* jump to start */
560 pracc_add(&ctx
, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
562 ctx
.retval
= mips32_pracc_queue_exec(ejtag_info
, &ctx
, NULL
);
564 pracc_queue_free(&ctx
);
568 * Note that MIPS32_MTC0 macro is implemented via MIPS32_R_INST macro.
569 * In order to insert our parameters, we must change rd and funct fields.
570 * code[3] |= (cp0_reg << 11) | cp0_sel; change rd and funct fields of MIPS32_R_INST macro
575 * \b mips32_pracc_sync_cache
577 * Synchronize Caches to Make Instruction Writes Effective
578 * (ref. doc. MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set,
579 * Document Number: MD00086, Revision 2.00, June 9, 2003)
581 * When the instruction stream is written, the SYNCI instruction should be used
582 * in conjunction with other instructions to make the newly-written instructions effective.
585 * A program that loads another program into memory is actually writing the D- side cache.
586 * The instructions it has loaded can't be executed until they reach the I-cache.
588 * After the instructions have been written, the loader should arrange
589 * to write back any containing D-cache line and invalidate any locations
590 * already in the I-cache.
592 * If the cache coherency attribute (CCA) is set to zero, it's a write through cache, there is no need
595 * In the latest MIPS32/64 CPUs, MIPS provides the synci instruction,
596 * which does the whole job for a cache-line-sized chunk of the memory you just loaded:
597 * That is, it arranges a D-cache write-back (if CCA = 3) and an I-cache invalidate.
599 * The line size is obtained with the rdhwr SYNCI_Step in release 2 or from cp0 config 1 register in release 1.
601 static int mips32_pracc_synchronize_cache(struct mips_ejtag
*ejtag_info
,
602 uint32_t start_addr
, uint32_t end_addr
, int cached
, int rel
)
604 struct pracc_queue_info ctx
= {.max_code
= 256 * 2 + 5};
605 pracc_queue_init(&ctx
);
606 if (ctx
.retval
!= ERROR_OK
)
608 /** Find cache line size in bytes */
610 if (rel
) { /* Release 2 (rel = 1) */
611 pracc_add(&ctx
, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR
)); /* $15 = MIPS32_PRACC_BASE_ADDR */
613 pracc_add(&ctx
, 0, MIPS32_RDHWR(8, MIPS32_SYNCI_STEP
)); /* load synci_step value to $8 */
615 pracc_add(&ctx
, MIPS32_PRACC_PARAM_OUT
,
616 MIPS32_SW(8, PRACC_OUT_OFFSET
, 15)); /* store $8 to pracc_out */
618 pracc_add(&ctx
, 0, MIPS32_LUI(8, UPPER16(ejtag_info
->reg8
))); /* restore upper 16 bits of $8 */
619 pracc_add(&ctx
, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info
->reg8
))); /* restore lower 16 bits of $8 */
620 pracc_add(&ctx
, 0, MIPS32_B(NEG16(ctx
.code_count
+ 1))); /* jump to start */
621 pracc_add(&ctx
, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
623 ctx
.retval
= mips32_pracc_queue_exec(ejtag_info
, &ctx
, &clsiz
);
624 if (ctx
.retval
!= ERROR_OK
)
627 } else { /* Release 1 (rel = 0) */
629 ctx
.retval
= mips32_cp0_read(ejtag_info
, &conf
, 16, 1);
630 if (ctx
.retval
!= ERROR_OK
)
633 uint32_t dl
= (conf
& MIPS32_CONFIG1_DL_MASK
) >> MIPS32_CONFIG1_DL_SHIFT
;
635 /* dl encoding : dl=1 => 4 bytes, dl=2 => 8 bytes, etc... max dl=6 => 128 bytes cache line size */
642 goto exit
; /* Nothing to do */
644 /* make sure clsiz is power of 2 */
645 if (clsiz
& (clsiz
- 1)) {
646 LOG_DEBUG("clsiz must be power of 2");
647 ctx
.retval
= ERROR_FAIL
;
651 /* make sure start_addr and end_addr have the same offset inside de cache line */
652 start_addr
|= clsiz
- 1;
653 end_addr
|= clsiz
- 1;
657 uint32_t last_upper_base_addr
= UPPER16((start_addr
+ 0x8000));
659 pracc_add(&ctx
, 0, MIPS32_LUI(15, last_upper_base_addr
)); /* load upper memory base address to $15 */
661 while (start_addr
<= end_addr
) { /* main loop */
662 uint32_t upper_base_addr
= UPPER16((start_addr
+ 0x8000));
663 if (last_upper_base_addr
!= upper_base_addr
) { /* if needed, change upper address in $15 */
664 pracc_add(&ctx
, 0, MIPS32_LUI(15, upper_base_addr
));
665 last_upper_base_addr
= upper_base_addr
;
668 pracc_add(&ctx
, 0, MIPS32_SYNCI(LOWER16(start_addr
), 15)); /* synci instruction, offset($15) */
672 pracc_add(&ctx
, 0, MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK
,
673 LOWER16(start_addr
), 15)); /* cache Hit_Writeback_D, offset($15) */
675 pracc_add(&ctx
, 0, MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE
,
676 LOWER16(start_addr
), 15)); /* cache Hit_Invalidate_I, offset($15) */
680 if (count
== 256 && start_addr
<= end_addr
) { /* more ?, then execute code list */
681 pracc_add(&ctx
, 0, MIPS32_B(NEG16(ctx
.code_count
+ 1))); /* jump to start */
682 pracc_add(&ctx
, 0, MIPS32_NOP
); /* nop in delay slot */
684 ctx
.retval
= mips32_pracc_queue_exec(ejtag_info
, &ctx
, NULL
);
685 if (ctx
.retval
!= ERROR_OK
)
692 pracc_add(&ctx
, 0, MIPS32_SYNC
);
693 pracc_add(&ctx
, 0, MIPS32_B(NEG16(ctx
.code_count
+ 1))); /* jump to start */
694 pracc_add(&ctx
, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave*/
696 ctx
.retval
= mips32_pracc_queue_exec(ejtag_info
, &ctx
, NULL
);
698 pracc_queue_free(&ctx
);
702 static int mips32_pracc_write_mem_generic(struct mips_ejtag
*ejtag_info
,
703 uint32_t addr
, int size
, int count
, const void *buf
)
705 struct pracc_queue_info ctx
= {.max_code
= 128 * 3 + 5 + 1}; /* alloc memory for the worst case */
706 pracc_queue_init(&ctx
);
707 if (ctx
.retval
!= ERROR_OK
)
710 const uint32_t *buf32
= buf
;
711 const uint16_t *buf16
= buf
;
712 const uint8_t *buf8
= buf
;
717 int this_round_count
= (count
> 128) ? 128 : count
;
718 uint32_t last_upper_base_addr
= UPPER16((addr
+ 0x8000));
720 pracc_add(&ctx
, 0, MIPS32_LUI(15, last_upper_base_addr
)); /* load $15 with memory base address */
722 for (int i
= 0; i
!= this_round_count
; i
++) {
723 uint32_t upper_base_addr
= UPPER16((addr
+ 0x8000));
724 if (last_upper_base_addr
!= upper_base_addr
) {
725 pracc_add(&ctx
, 0, MIPS32_LUI(15, upper_base_addr
)); /* if needed, change upper address in $15*/
726 last_upper_base_addr
= upper_base_addr
;
729 if (size
== 4) { /* for word writes check if one half word is 0 and load it accordingly */
730 if (LOWER16(*buf32
) == 0)
731 pracc_add(&ctx
, 0, MIPS32_LUI(8, UPPER16(*buf32
))); /* load only upper value */
732 else if (UPPER16(*buf32
) == 0)
733 pracc_add(&ctx
, 0, MIPS32_ORI(8, 0, LOWER16(*buf32
))); /* load only lower */
735 pracc_add(&ctx
, 0, MIPS32_LUI(8, UPPER16(*buf32
))); /* load upper and lower */
736 pracc_add(&ctx
, 0, MIPS32_ORI(8, 8, LOWER16(*buf32
)));
738 pracc_add(&ctx
, 0, MIPS32_SW(8, LOWER16(addr
), 15)); /* store word to memory */
741 } else if (size
== 2) {
742 pracc_add(&ctx
, 0, MIPS32_ORI(8, 0, *buf16
)); /* load lower value */
743 pracc_add(&ctx
, 0, MIPS32_SH(8, LOWER16(addr
), 15)); /* store half word to memory */
747 pracc_add(&ctx
, 0, MIPS32_ORI(8, 0, *buf8
)); /* load lower value */
748 pracc_add(&ctx
, 0, MIPS32_SB(8, LOWER16(addr
), 15)); /* store byte to memory */
754 pracc_add(&ctx
, 0, MIPS32_LUI(8, UPPER16(ejtag_info
->reg8
))); /* restore upper 16 bits of reg 8 */
755 pracc_add(&ctx
, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info
->reg8
))); /* restore lower 16 bits of reg 8 */
757 pracc_add(&ctx
, 0, MIPS32_B(NEG16(ctx
.code_count
+ 1))); /* jump to start */
758 pracc_add(&ctx
, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
760 ctx
.retval
= mips32_pracc_queue_exec(ejtag_info
, &ctx
, NULL
);
761 if (ctx
.retval
!= ERROR_OK
)
763 count
-= this_round_count
;
766 pracc_queue_free(&ctx
);
770 int mips32_pracc_write_mem(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int size
, int count
, const void *buf
)
772 int retval
= mips32_pracc_write_mem_generic(ejtag_info
, addr
, size
, count
, buf
);
773 if (retval
!= ERROR_OK
)
777 * If we are in the cacheable region and cache is activated,
778 * we must clean D$ (if Cache Coherency Attribute is set to 3) + invalidate I$ after we did the write,
779 * so that changes do not continue to live only in D$ (if CCA = 3), but to be
780 * replicated in I$ also (maybe we wrote the istructions)
785 if ((KSEGX(addr
) == KSEG1
) || ((addr
>= 0xff200000) && (addr
<= 0xff3fffff)))
786 return retval
; /*Nothing to do*/
788 mips32_cp0_read(ejtag_info
, &conf
, 16, 0);
790 switch (KSEGX(addr
)) {
792 cached
= (conf
& MIPS32_CONFIG0_KU_MASK
) >> MIPS32_CONFIG0_KU_SHIFT
;
795 cached
= (conf
& MIPS32_CONFIG0_K0_MASK
) >> MIPS32_CONFIG0_K0_SHIFT
;
799 cached
= (conf
& MIPS32_CONFIG0_K23_MASK
) >> MIPS32_CONFIG0_K23_SHIFT
;
807 * Check cachablitiy bits coherency algorithm
808 * is the region cacheable or uncached.
809 * If cacheable we have to synchronize the cache
811 if (cached
== 3 || cached
== 0) { /* Write back cache or write through cache */
812 uint32_t start_addr
= addr
;
813 uint32_t end_addr
= addr
+ count
* size
;
814 uint32_t rel
= (conf
& MIPS32_CONFIG0_AR_MASK
) >> MIPS32_CONFIG0_AR_SHIFT
;
816 LOG_DEBUG("Unknown release in cache code");
819 retval
= mips32_pracc_synchronize_cache(ejtag_info
, start_addr
, end_addr
, cached
, rel
);
825 int mips32_pracc_write_regs(struct mips_ejtag
*ejtag_info
, uint32_t *regs
)
827 static const uint32_t cp0_write_code
[] = {
828 MIPS32_MTC0(1, 12, 0), /* move $1 to status */
829 MIPS32_MTLO(1), /* move $1 to lo */
830 MIPS32_MTHI(1), /* move $1 to hi */
831 MIPS32_MTC0(1, 8, 0), /* move $1 to badvaddr */
832 MIPS32_MTC0(1, 13, 0), /* move $1 to cause*/
833 MIPS32_MTC0(1, 24, 0), /* move $1 to depc (pc) */
836 struct pracc_queue_info ctx
= {.max_code
= 37 * 2 + 7 + 1};
837 pracc_queue_init(&ctx
);
838 if (ctx
.retval
!= ERROR_OK
)
841 /* load registers 2 to 31 with lui and ori instructions, check if some instructions can be saved */
842 for (int i
= 2; i
< 32; i
++) {
843 if (LOWER16((regs
[i
])) == 0) /* if lower half word is 0, lui instruction only */
844 pracc_add(&ctx
, 0, MIPS32_LUI(i
, UPPER16((regs
[i
]))));
845 else if (UPPER16((regs
[i
])) == 0) /* if upper half word is 0, ori with $0 only*/
846 pracc_add(&ctx
, 0, MIPS32_ORI(i
, 0, LOWER16((regs
[i
]))));
847 else { /* default, load with lui and ori instructions */
848 pracc_add(&ctx
, 0, MIPS32_LUI(i
, UPPER16((regs
[i
]))));
849 pracc_add(&ctx
, 0, MIPS32_ORI(i
, i
, LOWER16((regs
[i
]))));
853 for (int i
= 0; i
!= 6; i
++) {
854 pracc_add(&ctx
, 0, MIPS32_LUI(1, UPPER16((regs
[i
+ 32])))); /* load CPO value in $1, with lui and ori */
855 pracc_add(&ctx
, 0, MIPS32_ORI(1, 1, LOWER16((regs
[i
+ 32]))));
856 pracc_add(&ctx
, 0, cp0_write_code
[i
]); /* write value from $1 to CPO register */
858 pracc_add(&ctx
, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */
859 pracc_add(&ctx
, 0, MIPS32_LUI(1, UPPER16((regs
[1])))); /* load upper half word in $1 */
860 pracc_add(&ctx
, 0, MIPS32_B(NEG16(ctx
.code_count
+ 1))); /* jump to start */
861 pracc_add(&ctx
, 0, MIPS32_ORI(1, 1, LOWER16((regs
[1])))); /* load lower half word in $1 */
863 ctx
.retval
= mips32_pracc_queue_exec(ejtag_info
, &ctx
, NULL
);
865 ejtag_info
->reg8
= regs
[8];
866 ejtag_info
->reg9
= regs
[9];
868 pracc_queue_free(&ctx
);
872 int mips32_pracc_read_regs(struct mips_ejtag
*ejtag_info
, uint32_t *regs
)
874 static int cp0_read_code
[] = {
875 MIPS32_MFC0(8, 12, 0), /* move status to $8 */
876 MIPS32_MFLO(8), /* move lo to $8 */
877 MIPS32_MFHI(8), /* move hi to $8 */
878 MIPS32_MFC0(8, 8, 0), /* move badvaddr to $8 */
879 MIPS32_MFC0(8, 13, 0), /* move cause to $8 */
880 MIPS32_MFC0(8, 24, 0), /* move depc (pc) to $8 */
883 struct pracc_queue_info ctx
= {.max_code
= 49};
884 pracc_queue_init(&ctx
);
885 if (ctx
.retval
!= ERROR_OK
)
888 pracc_add(&ctx
, 0, MIPS32_MTC0(1, 31, 0)); /* move $1 to COP0 DeSave */
889 pracc_add(&ctx
, 0, MIPS32_LUI(1, PRACC_UPPER_BASE_ADDR
)); /* $1 = MIP32_PRACC_BASE_ADDR */
891 for (int i
= 2; i
!= 32; i
++) /* store GPR's 2 to 31 */
892 pracc_add(&ctx
, MIPS32_PRACC_PARAM_OUT
+ (i
* 4),
893 MIPS32_SW(i
, PRACC_OUT_OFFSET
+ (i
* 4), 1));
895 for (int i
= 0; i
!= 6; i
++) {
896 pracc_add(&ctx
, 0, cp0_read_code
[i
]); /* load COP0 needed registers to $8 */
897 pracc_add(&ctx
, MIPS32_PRACC_PARAM_OUT
+ (i
+ 32) * 4, /* store $8 at PARAM OUT */
898 MIPS32_SW(8, PRACC_OUT_OFFSET
+ (i
+ 32) * 4, 1));
900 pracc_add(&ctx
, 0, MIPS32_MFC0(8, 31, 0)); /* move DeSave to $8, reg1 value */
901 pracc_add(&ctx
, MIPS32_PRACC_PARAM_OUT
+ 4, /* store reg1 value from $8 to param out */
902 MIPS32_SW(8, PRACC_OUT_OFFSET
+ 4, 1));
904 pracc_add(&ctx
, 0, MIPS32_MFC0(1, 31, 0)); /* move COP0 DeSave to $1, restore reg1 */
905 pracc_add(&ctx
, 0, MIPS32_B(NEG16(ctx
.code_count
+ 1))); /* jump to start */
906 pracc_add(&ctx
, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */
908 if (ejtag_info
->mode
== 0)
909 ctx
.store_count
++; /* Needed by legacy code, due to offset from reg0 */
911 ctx
.retval
= mips32_pracc_queue_exec(ejtag_info
, &ctx
, regs
);
913 ejtag_info
->reg8
= regs
[8]; /* reg8 is saved but not restored, next called function should restore it */
914 ejtag_info
->reg9
= regs
[9];
916 pracc_queue_free(&ctx
);
920 /* fastdata upload/download requires an initialized working area
921 * to load the download code; it should not be called otherwise
922 * fetch order from the fastdata area
927 int mips32_pracc_fastdata_xfer(struct mips_ejtag
*ejtag_info
, struct working_area
*source
,
928 int write_t
, uint32_t addr
, int count
, uint32_t *buf
)
930 uint32_t handler_code
[] = {
931 /* caution when editing, table is modified below */
932 /* r15 points to the start of this code */
933 MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE
- 4, 15),
934 MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE
- 8, 15),
935 MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE
- 12, 15),
936 MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE
- 16, 15),
937 /* start of fastdata area in t0 */
938 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA
)),
939 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA
)),
940 MIPS32_LW(9, 0, 8), /* start addr in t1 */
941 MIPS32_LW(10, 0, 8), /* end addr to t2 */
943 /* 8 */ MIPS32_LW(11, 0, 0), /* lw t3,[t8 | r9] */
944 /* 9 */ MIPS32_SW(11, 0, 0), /* sw t3,[r9 | r8] */
945 MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */
946 MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */
948 MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE
- 4, 15),
949 MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE
- 8, 15),
950 MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE
- 12, 15),
951 MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE
- 16, 15),
953 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT
)),
954 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT
)),
955 MIPS32_JR(15), /* jr start */
956 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
959 uint32_t jmp_code
[] = {
960 /* 0 */ MIPS32_LUI(15, 0), /* addr of working area added below */
961 /* 1 */ MIPS32_ORI(15, 15, 0), /* addr of working area added below */
962 MIPS32_JR(15), /* jump to ram program */
967 uint32_t val
, ejtag_ctrl
, address
;
969 if (source
->size
< MIPS32_FASTDATA_HANDLER_SIZE
)
970 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
973 handler_code
[8] = MIPS32_LW(11, 0, 8); /* load data from probe at fastdata area */
974 handler_code
[9] = MIPS32_SW(11, 0, 9); /* store data to RAM @ r9 */
976 handler_code
[8] = MIPS32_LW(11, 0, 9); /* load data from RAM @ r9 */
977 handler_code
[9] = MIPS32_SW(11, 0, 8); /* store data to probe at fastdata area */
980 /* write program into RAM */
981 if (write_t
!= ejtag_info
->fast_access_save
) {
982 mips32_pracc_write_mem(ejtag_info
, source
->address
, 4, ARRAY_SIZE(handler_code
), handler_code
);
983 /* save previous operation to speed to any consecutive read/writes */
984 ejtag_info
->fast_access_save
= write_t
;
987 LOG_DEBUG("%s using 0x%.8" PRIx32
" for write handler", __func__
, source
->address
);
989 jmp_code
[0] |= UPPER16(source
->address
);
990 jmp_code
[1] |= LOWER16(source
->address
);
992 for (i
= 0; i
< (int) ARRAY_SIZE(jmp_code
); i
++) {
993 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
994 if (retval
!= ERROR_OK
)
997 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_DATA
);
998 mips_ejtag_drscan_32_out(ejtag_info
, jmp_code
[i
]);
1000 /* Clear the access pending bit (let the processor eat!) */
1001 ejtag_ctrl
= ejtag_info
->ejtag_ctrl
& ~EJTAG_CTRL_PRACC
;
1002 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_CONTROL
);
1003 mips_ejtag_drscan_32_out(ejtag_info
, ejtag_ctrl
);
1006 /* wait PrAcc pending bit for FASTDATA write */
1007 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1008 if (retval
!= ERROR_OK
)
1011 /* next fetch to dmseg should be in FASTDATA_AREA, check */
1013 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_ADDRESS
);
1014 retval
= mips_ejtag_drscan_32(ejtag_info
, &address
);
1015 if (retval
!= ERROR_OK
)
1018 if (address
!= MIPS32_PRACC_FASTDATA_AREA
)
1021 /* Send the load start address */
1023 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_FASTDATA
);
1024 mips_ejtag_fastdata_scan(ejtag_info
, 1, &val
);
1026 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1027 if (retval
!= ERROR_OK
)
1030 /* Send the load end address */
1031 val
= addr
+ (count
- 1) * 4;
1032 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_FASTDATA
);
1033 mips_ejtag_fastdata_scan(ejtag_info
, 1, &val
);
1035 unsigned num_clocks
= 0; /* like in legacy code */
1036 if (ejtag_info
->mode
!= 0)
1037 num_clocks
= ((uint64_t)(ejtag_info
->scan_delay
) * jtag_get_speed_khz() + 500000) / 1000000;
1039 for (i
= 0; i
< count
; i
++) {
1040 jtag_add_clocks(num_clocks
);
1041 retval
= mips_ejtag_fastdata_scan(ejtag_info
, write_t
, buf
++);
1042 if (retval
!= ERROR_OK
)
1046 retval
= jtag_execute_queue();
1047 if (retval
!= ERROR_OK
) {
1048 LOG_ERROR("fastdata load failed");
1052 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1053 if (retval
!= ERROR_OK
)
1057 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_ADDRESS
);
1058 retval
= mips_ejtag_drscan_32(ejtag_info
, &address
);
1059 if (retval
!= ERROR_OK
)
1062 if (address
!= MIPS32_PRACC_TEXT
)
1063 LOG_ERROR("mini program did not return to start");
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)