Cortex-A8: hook up DPM
[openocd.git] / src / target / cortex_a8.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2006 by Magnus Lundin *
6 * lundin@mlu.mine.nu *
7 * *
8 * Copyright (C) 2008 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
10 * *
11 * Copyright (C) 2009 by Dirk Behme *
12 * dirk.behme@gmail.com - copy from cortex_m3 *
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program; if not, write to the *
26 * Free Software Foundation, Inc., *
27 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
28 * *
29 * Cortex-A8(tm) TRM, ARM DDI 0344H *
30 * *
31 ***************************************************************************/
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include "breakpoints.h"
37 #include "cortex_a8.h"
38 #include "register.h"
39 #include "target_request.h"
40 #include "target_type.h"
41
42 static int cortex_a8_poll(struct target *target);
43 static int cortex_a8_debug_entry(struct target *target);
44 static int cortex_a8_restore_context(struct target *target);
45 static int cortex_a8_set_breakpoint(struct target *target,
46 struct breakpoint *breakpoint, uint8_t matchmode);
47 static int cortex_a8_unset_breakpoint(struct target *target,
48 struct breakpoint *breakpoint);
49 static int cortex_a8_dap_read_coreregister_u32(struct target *target,
50 uint32_t *value, int regnum);
51 static int cortex_a8_dap_write_coreregister_u32(struct target *target,
52 uint32_t value, int regnum);
53 /*
54 * FIXME do topology discovery using the ROM; don't
55 * assume this is an OMAP3.
56 */
57 #define swjdp_memoryap 0
58 #define swjdp_debugap 1
59 #define OMAP3530_DEBUG_BASE 0x54011000
60
61 /*
62 * Cortex-A8 Basic debug access, very low level assumes state is saved
63 */
64 static int cortex_a8_init_debug_access(struct target *target)
65 {
66 struct armv7a_common *armv7a = target_to_armv7a(target);
67 struct swjdp_common *swjdp = &armv7a->swjdp_info;
68
69 int retval;
70 uint32_t dummy;
71
72 LOG_DEBUG(" ");
73
74 /* Unlocking the debug registers for modification */
75 /* The debugport might be uninitialised so try twice */
76 retval = mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
77 if (retval != ERROR_OK)
78 mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
79 /* Clear Sticky Power Down status Bit in PRSR to enable access to
80 the registers in the Core Power Domain */
81 retval = mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_PRSR, &dummy);
82 /* Enabling of instruction execution in debug mode is done in debug_entry code */
83
84 /* Resync breakpoint registers */
85
86 /* Since this is likley called from init or reset, update targtet state information*/
87 cortex_a8_poll(target);
88
89 return retval;
90 }
91
92 /* FIXME we waste a *LOT* of round-trips with needless DSCR reads, which
93 * slows down operations considerably. One good way to start reducing
94 * them would pass current values into and out of this routine. That
95 * should also help synch DCC read/write.
96 */
97 static int cortex_a8_exec_opcode(struct target *target, uint32_t opcode)
98 {
99 uint32_t dscr;
100 int retval;
101 struct armv7a_common *armv7a = target_to_armv7a(target);
102 struct swjdp_common *swjdp = &armv7a->swjdp_info;
103
104 LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode);
105 do
106 {
107 retval = mem_ap_read_atomic_u32(swjdp,
108 armv7a->debug_base + CPUDBG_DSCR, &dscr);
109 if (retval != ERROR_OK)
110 {
111 LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32, opcode);
112 return retval;
113 }
114 }
115 while ((dscr & (1 << DSCR_INSTR_COMP)) == 0); /* Wait for InstrCompl bit to be set */
116
117 mem_ap_write_u32(swjdp, armv7a->debug_base + CPUDBG_ITR, opcode);
118
119 do
120 {
121 retval = mem_ap_read_atomic_u32(swjdp,
122 armv7a->debug_base + CPUDBG_DSCR, &dscr);
123 if (retval != ERROR_OK)
124 {
125 LOG_ERROR("Could not read DSCR register");
126 return retval;
127 }
128 }
129 while ((dscr & (1 << DSCR_INSTR_COMP)) == 0); /* Wait for InstrCompl bit to be set */
130
131 return retval;
132 }
133
134 /**************************************************************************
135 Read core register with very few exec_opcode, fast but needs work_area.
136 This can cause problems with MMU active.
137 **************************************************************************/
138 static int cortex_a8_read_regs_through_mem(struct target *target, uint32_t address,
139 uint32_t * regfile)
140 {
141 int retval = ERROR_OK;
142 struct armv7a_common *armv7a = target_to_armv7a(target);
143 struct swjdp_common *swjdp = &armv7a->swjdp_info;
144
145 cortex_a8_dap_read_coreregister_u32(target, regfile, 0);
146 cortex_a8_dap_write_coreregister_u32(target, address, 0);
147 cortex_a8_exec_opcode(target, ARMV4_5_STMIA(0, 0xFFFE, 0, 0));
148 dap_ap_select(swjdp, swjdp_memoryap);
149 mem_ap_read_buf_u32(swjdp, (uint8_t *)(&regfile[1]), 4*15, address);
150 dap_ap_select(swjdp, swjdp_debugap);
151
152 return retval;
153 }
154
155 static int cortex_a8_read_cp(struct target *target, uint32_t *value, uint8_t CP,
156 uint8_t op1, uint8_t CRn, uint8_t CRm, uint8_t op2)
157 {
158 int retval;
159 struct armv7a_common *armv7a = target_to_armv7a(target);
160 struct swjdp_common *swjdp = &armv7a->swjdp_info;
161
162 cortex_a8_exec_opcode(target, ARMV4_5_MRC(CP, op1, 0, CRn, CRm, op2));
163 /* Move R0 to DTRTX */
164 cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0));
165
166 /* Read DCCTX */
167 retval = mem_ap_read_atomic_u32(swjdp,
168 armv7a->debug_base + CPUDBG_DTRTX, value);
169
170 return retval;
171 }
172
173 static int cortex_a8_write_cp(struct target *target, uint32_t value,
174 uint8_t CP, uint8_t op1, uint8_t CRn, uint8_t CRm, uint8_t op2)
175 {
176 int retval;
177 uint32_t dscr;
178 struct armv7a_common *armv7a = target_to_armv7a(target);
179 struct swjdp_common *swjdp = &armv7a->swjdp_info;
180
181 LOG_DEBUG("CP%i, CRn %i, value 0x%08" PRIx32, CP, CRn, value);
182
183 /* Check that DCCRX is not full */
184 retval = mem_ap_read_atomic_u32(swjdp,
185 armv7a->debug_base + CPUDBG_DSCR, &dscr);
186 if (dscr & (1 << DSCR_DTR_RX_FULL))
187 {
188 LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
189 /* Clear DCCRX with MCR(p14, 0, Rd, c0, c5, 0), opcode 0xEE000E15 */
190 cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
191 }
192
193 retval = mem_ap_write_u32(swjdp,
194 armv7a->debug_base + CPUDBG_DTRRX, value);
195 /* Move DTRRX to r0 */
196 cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
197
198 cortex_a8_exec_opcode(target, ARMV4_5_MCR(CP, op1, 0, CRn, CRm, op2));
199 return retval;
200 }
201
202 static int cortex_a8_read_cp15(struct target *target, uint32_t op1, uint32_t op2,
203 uint32_t CRn, uint32_t CRm, uint32_t *value)
204 {
205 return cortex_a8_read_cp(target, value, 15, op1, CRn, CRm, op2);
206 }
207
208 static int cortex_a8_write_cp15(struct target *target, uint32_t op1, uint32_t op2,
209 uint32_t CRn, uint32_t CRm, uint32_t value)
210 {
211 return cortex_a8_write_cp(target, value, 15, op1, CRn, CRm, op2);
212 }
213
214 static int cortex_a8_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
215 {
216 if (cpnum!=15)
217 {
218 LOG_ERROR("Only cp15 is supported");
219 return ERROR_FAIL;
220 }
221 return cortex_a8_read_cp15(target, op1, op2, CRn, CRm, value);
222 }
223
224 static int cortex_a8_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
225 {
226 if (cpnum!=15)
227 {
228 LOG_ERROR("Only cp15 is supported");
229 return ERROR_FAIL;
230 }
231 return cortex_a8_write_cp15(target, op1, op2, CRn, CRm, value);
232 }
233
234
235
236 static int cortex_a8_dap_read_coreregister_u32(struct target *target,
237 uint32_t *value, int regnum)
238 {
239 int retval = ERROR_OK;
240 uint8_t reg = regnum&0xFF;
241 uint32_t dscr;
242 struct armv7a_common *armv7a = target_to_armv7a(target);
243 struct swjdp_common *swjdp = &armv7a->swjdp_info;
244
245 if (reg > 17)
246 return retval;
247
248 if (reg < 15)
249 {
250 /* Rn to DCCTX, "MCR p14, 0, Rn, c0, c5, 0" 0xEE00nE15 */
251 cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, reg, 0, 5, 0));
252 }
253 else if (reg == 15)
254 {
255 /* "MOV r0, r15"; then move r0 to DCCTX */
256 cortex_a8_exec_opcode(target, 0xE1A0000F);
257 cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0));
258 }
259 else
260 {
261 /* "MRS r0, CPSR" or "MRS r0, SPSR"
262 * then move r0 to DCCTX
263 */
264 cortex_a8_exec_opcode(target, ARMV4_5_MRS(0, reg & 1));
265 cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0));
266 }
267
268 /* Read DTRRTX */
269 do
270 {
271 retval = mem_ap_read_atomic_u32(swjdp,
272 armv7a->debug_base + CPUDBG_DSCR, &dscr);
273 }
274 while ((dscr & (1 << DSCR_DTR_TX_FULL)) == 0); /* Wait for DTRRXfull */
275
276 retval = mem_ap_read_atomic_u32(swjdp,
277 armv7a->debug_base + CPUDBG_DTRTX, value);
278 LOG_DEBUG("read DCC 0x%08" PRIx32, *value);
279
280 return retval;
281 }
282
283 static int cortex_a8_dap_write_coreregister_u32(struct target *target,
284 uint32_t value, int regnum)
285 {
286 int retval = ERROR_OK;
287 uint8_t Rd = regnum&0xFF;
288 uint32_t dscr;
289 struct armv7a_common *armv7a = target_to_armv7a(target);
290 struct swjdp_common *swjdp = &armv7a->swjdp_info;
291
292 LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value);
293
294 /* Check that DCCRX is not full */
295 retval = mem_ap_read_atomic_u32(swjdp,
296 armv7a->debug_base + CPUDBG_DSCR, &dscr);
297 if (dscr & (1 << DSCR_DTR_RX_FULL))
298 {
299 LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
300 /* Clear DCCRX with MCR(p14, 0, Rd, c0, c5, 0), opcode 0xEE000E15 */
301 cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
302 }
303
304 if (Rd > 17)
305 return retval;
306
307 /* Write to DCCRX */
308 LOG_DEBUG("write DCC 0x%08" PRIx32, value);
309 retval = mem_ap_write_u32(swjdp,
310 armv7a->debug_base + CPUDBG_DTRRX, value);
311
312 if (Rd < 15)
313 {
314 /* DCCRX to Rn, "MCR p14, 0, Rn, c0, c5, 0", 0xEE00nE15 */
315 cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0));
316 }
317 else if (Rd == 15)
318 {
319 /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15
320 * then "mov r15, r0"
321 */
322 cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
323 cortex_a8_exec_opcode(target, 0xE1A0F000);
324 }
325 else
326 {
327 /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15
328 * then "MSR CPSR_cxsf, r0" or "MSR SPSR_cxsf, r0" (all fields)
329 */
330 cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
331 cortex_a8_exec_opcode(target, ARMV4_5_MSR_GP(0, 0xF, Rd & 1));
332
333 /* "Prefetch flush" after modifying execution status in CPSR */
334 if (Rd == 16)
335 cortex_a8_exec_opcode(target,
336 ARMV4_5_MCR(15, 0, 0, 7, 5, 4));
337 }
338
339 return retval;
340 }
341
342 /* Write to memory mapped registers directly with no cache or mmu handling */
343 static int cortex_a8_dap_write_memap_register_u32(struct target *target, uint32_t address, uint32_t value)
344 {
345 int retval;
346 struct armv7a_common *armv7a = target_to_armv7a(target);
347 struct swjdp_common *swjdp = &armv7a->swjdp_info;
348
349 retval = mem_ap_write_atomic_u32(swjdp, address, value);
350
351 return retval;
352 }
353
354 /*
355 * Cortex-A8 implementation of Debug Programmer's Model
356 *
357 * NOTE that in several of these cases the "stall" mode might be useful.
358 * It'd let us queue a few operations together... prepare/finish might
359 * be the places to enable/disable that mode.
360 */
361
362 static inline struct cortex_a8_common *dpm_to_a8(struct arm_dpm *dpm)
363 {
364 return container_of(dpm, struct cortex_a8_common, armv7a_common.dpm);
365 }
366
367 static int cortex_a8_write_dcc(struct cortex_a8_common *a8, uint32_t data)
368 {
369 LOG_DEBUG("write DCC 0x%08" PRIx32, data);
370 return mem_ap_write_u32(&a8->armv7a_common.swjdp_info,
371 a8->armv7a_common.debug_base + CPUDBG_DTRRX, data);
372 }
373
374 static int cortex_a8_read_dcc(struct cortex_a8_common *a8, uint32_t *data)
375 {
376 struct swjdp_common *swjdp = &a8->armv7a_common.swjdp_info;
377 uint32_t dscr;
378 int retval;
379
380 /* Wait for DTRRXfull */
381 do {
382 retval = mem_ap_read_atomic_u32(swjdp,
383 a8->armv7a_common.debug_base + CPUDBG_DSCR,
384 &dscr);
385 } while ((dscr & (1 << DSCR_DTR_TX_FULL)) == 0);
386
387 retval = mem_ap_read_atomic_u32(swjdp,
388 a8->armv7a_common.debug_base + CPUDBG_DTRTX, data);
389 LOG_DEBUG("read DCC 0x%08" PRIx32, *data);
390
391 return retval;
392 }
393
394 static int cortex_a8_dpm_prepare(struct arm_dpm *dpm)
395 {
396 struct cortex_a8_common *a8 = dpm_to_a8(dpm);
397 struct swjdp_common *swjdp = &a8->armv7a_common.swjdp_info;
398 uint32_t dscr;
399 int retval;
400
401 retval = mem_ap_read_atomic_u32(swjdp,
402 a8->armv7a_common.debug_base + CPUDBG_DSCR,
403 &dscr);
404
405 /* this "should never happen" ... */
406 if (dscr & (1 << DSCR_DTR_RX_FULL)) {
407 LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
408 /* Clear DCCRX */
409 retval = cortex_a8_exec_opcode(
410 a8->armv7a_common.armv4_5_common.target,
411 ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
412 }
413
414 return retval;
415 }
416
417 static int cortex_a8_dpm_finish(struct arm_dpm *dpm)
418 {
419 /* REVISIT what could be done here? */
420 return ERROR_OK;
421 }
422
423 static int cortex_a8_instr_write_data_dcc(struct arm_dpm *dpm,
424 uint32_t opcode, uint32_t data)
425 {
426 struct cortex_a8_common *a8 = dpm_to_a8(dpm);
427 int retval;
428
429 retval = cortex_a8_write_dcc(a8, data);
430
431 return cortex_a8_exec_opcode(
432 a8->armv7a_common.armv4_5_common.target,
433 opcode);
434 }
435
436 static int cortex_a8_instr_write_data_r0(struct arm_dpm *dpm,
437 uint32_t opcode, uint32_t data)
438 {
439 struct cortex_a8_common *a8 = dpm_to_a8(dpm);
440 int retval;
441
442 retval = cortex_a8_write_dcc(a8, data);
443
444 /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */
445 retval = cortex_a8_exec_opcode(
446 a8->armv7a_common.armv4_5_common.target,
447 ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
448
449 /* then the opcode, taking data from R0 */
450 retval = cortex_a8_exec_opcode(
451 a8->armv7a_common.armv4_5_common.target,
452 opcode);
453
454 return retval;
455 }
456
457 static int cortex_a8_instr_cpsr_sync(struct arm_dpm *dpm)
458 {
459 struct target *target = dpm->arm->target;
460
461 /* "Prefetch flush" after modifying execution status in CPSR */
462 return cortex_a8_exec_opcode(target, ARMV4_5_MCR(15, 0, 0, 7, 5, 4));
463 }
464
465 static int cortex_a8_instr_read_data_dcc(struct arm_dpm *dpm,
466 uint32_t opcode, uint32_t *data)
467 {
468 struct cortex_a8_common *a8 = dpm_to_a8(dpm);
469 int retval;
470
471 /* the opcode, writing data to DCC */
472 retval = cortex_a8_exec_opcode(
473 a8->armv7a_common.armv4_5_common.target,
474 opcode);
475
476 return cortex_a8_read_dcc(a8, data);
477 }
478
479
480 static int cortex_a8_instr_read_data_r0(struct arm_dpm *dpm,
481 uint32_t opcode, uint32_t *data)
482 {
483 struct cortex_a8_common *a8 = dpm_to_a8(dpm);
484 int retval;
485
486 /* the opcode, writing data to R0 */
487 retval = cortex_a8_exec_opcode(
488 a8->armv7a_common.armv4_5_common.target,
489 opcode);
490
491 /* write R0 to DCC */
492 retval = cortex_a8_exec_opcode(
493 a8->armv7a_common.armv4_5_common.target,
494 ARMV4_5_MCR(14, 0, 0, 0, 5, 0));
495
496 return cortex_a8_read_dcc(a8, data);
497 }
498
499 static int cortex_a8_dpm_setup(struct cortex_a8_common *a8, uint32_t didr)
500 {
501 struct arm_dpm *dpm = &a8->armv7a_common.dpm;
502
503 dpm->arm = &a8->armv7a_common.armv4_5_common;
504 dpm->didr = didr;
505
506 dpm->prepare = cortex_a8_dpm_prepare;
507 dpm->finish = cortex_a8_dpm_finish;
508
509 dpm->instr_write_data_dcc = cortex_a8_instr_write_data_dcc;
510 dpm->instr_write_data_r0 = cortex_a8_instr_write_data_r0;
511 dpm->instr_cpsr_sync = cortex_a8_instr_cpsr_sync;
512
513 dpm->instr_read_data_dcc = cortex_a8_instr_read_data_dcc;
514 dpm->instr_read_data_r0 = cortex_a8_instr_read_data_r0;
515
516 return arm_dpm_setup(dpm);
517 }
518
519
520 /*
521 * Cortex-A8 Run control
522 */
523
524 static int cortex_a8_poll(struct target *target)
525 {
526 int retval = ERROR_OK;
527 uint32_t dscr;
528 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
529 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
530 struct swjdp_common *swjdp = &armv7a->swjdp_info;
531 enum target_state prev_target_state = target->state;
532 uint8_t saved_apsel = dap_ap_get_select(swjdp);
533
534 dap_ap_select(swjdp, swjdp_debugap);
535 retval = mem_ap_read_atomic_u32(swjdp,
536 armv7a->debug_base + CPUDBG_DSCR, &dscr);
537 if (retval != ERROR_OK)
538 {
539 dap_ap_select(swjdp, saved_apsel);
540 return retval;
541 }
542 cortex_a8->cpudbg_dscr = dscr;
543
544 if ((dscr & 0x3) == 0x3)
545 {
546 if (prev_target_state != TARGET_HALTED)
547 {
548 /* We have a halting debug event */
549 LOG_DEBUG("Target halted");
550 target->state = TARGET_HALTED;
551 if ((prev_target_state == TARGET_RUNNING)
552 || (prev_target_state == TARGET_RESET))
553 {
554 retval = cortex_a8_debug_entry(target);
555 if (retval != ERROR_OK)
556 return retval;
557
558 target_call_event_callbacks(target,
559 TARGET_EVENT_HALTED);
560 }
561 if (prev_target_state == TARGET_DEBUG_RUNNING)
562 {
563 LOG_DEBUG(" ");
564
565 retval = cortex_a8_debug_entry(target);
566 if (retval != ERROR_OK)
567 return retval;
568
569 target_call_event_callbacks(target,
570 TARGET_EVENT_DEBUG_HALTED);
571 }
572 }
573 }
574 else if ((dscr & 0x3) == 0x2)
575 {
576 target->state = TARGET_RUNNING;
577 }
578 else
579 {
580 LOG_DEBUG("Unknown target state dscr = 0x%08" PRIx32, dscr);
581 target->state = TARGET_UNKNOWN;
582 }
583
584 dap_ap_select(swjdp, saved_apsel);
585
586 return retval;
587 }
588
589 static int cortex_a8_halt(struct target *target)
590 {
591 int retval = ERROR_OK;
592 uint32_t dscr;
593 struct armv7a_common *armv7a = target_to_armv7a(target);
594 struct swjdp_common *swjdp = &armv7a->swjdp_info;
595 uint8_t saved_apsel = dap_ap_get_select(swjdp);
596 dap_ap_select(swjdp, swjdp_debugap);
597
598 /*
599 * Tell the core to be halted by writing DRCR with 0x1
600 * and then wait for the core to be halted.
601 */
602 retval = mem_ap_write_atomic_u32(swjdp,
603 armv7a->debug_base + CPUDBG_DRCR, 0x1);
604
605 /*
606 * enter halting debug mode
607 */
608 mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DSCR, &dscr);
609 retval = mem_ap_write_atomic_u32(swjdp,
610 armv7a->debug_base + CPUDBG_DSCR, dscr | (1 << DSCR_HALT_DBG_MODE));
611
612 if (retval != ERROR_OK)
613 goto out;
614
615 do {
616 mem_ap_read_atomic_u32(swjdp,
617 armv7a->debug_base + CPUDBG_DSCR, &dscr);
618 } while ((dscr & (1 << DSCR_CORE_HALTED)) == 0);
619
620 target->debug_reason = DBG_REASON_DBGRQ;
621
622 out:
623 dap_ap_select(swjdp, saved_apsel);
624 return retval;
625 }
626
627 static int cortex_a8_resume(struct target *target, int current,
628 uint32_t address, int handle_breakpoints, int debug_execution)
629 {
630 struct armv7a_common *armv7a = target_to_armv7a(target);
631 struct arm *armv4_5 = &armv7a->armv4_5_common;
632 struct swjdp_common *swjdp = &armv7a->swjdp_info;
633
634 // struct breakpoint *breakpoint = NULL;
635 uint32_t resume_pc, dscr;
636
637 uint8_t saved_apsel = dap_ap_get_select(swjdp);
638 dap_ap_select(swjdp, swjdp_debugap);
639
640 if (!debug_execution)
641 {
642 target_free_all_working_areas(target);
643 // cortex_m3_enable_breakpoints(target);
644 // cortex_m3_enable_watchpoints(target);
645 }
646
647 #if 0
648 if (debug_execution)
649 {
650 /* Disable interrupts */
651 /* We disable interrupts in the PRIMASK register instead of
652 * masking with C_MASKINTS,
653 * This is probably the same issue as Cortex-M3 Errata 377493:
654 * C_MASKINTS in parallel with disabled interrupts can cause
655 * local faults to not be taken. */
656 buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1);
657 armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1;
658 armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1;
659
660 /* Make sure we are in Thumb mode */
661 buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32,
662 buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1 << 24));
663 armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
664 armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1;
665 }
666 #endif
667
668 /* current = 1: continue on current pc, otherwise continue at <address> */
669 resume_pc = buf_get_u32(
670 armv4_5->core_cache->reg_list[15].value,
671 0, 32);
672 if (!current)
673 resume_pc = address;
674
675 /* Make sure that the Armv7 gdb thumb fixups does not
676 * kill the return address
677 */
678 switch (armv4_5->core_state)
679 {
680 case ARMV4_5_STATE_ARM:
681 resume_pc &= 0xFFFFFFFC;
682 break;
683 case ARMV4_5_STATE_THUMB:
684 case ARM_STATE_THUMB_EE:
685 /* When the return address is loaded into PC
686 * bit 0 must be 1 to stay in Thumb state
687 */
688 resume_pc |= 0x1;
689 break;
690 case ARMV4_5_STATE_JAZELLE:
691 LOG_ERROR("How do I resume into Jazelle state??");
692 return ERROR_FAIL;
693 }
694 LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc);
695 buf_set_u32(armv4_5->core_cache->reg_list[15].value,
696 0, 32, resume_pc);
697 armv4_5->core_cache->reg_list[15].dirty = 1;
698 armv4_5->core_cache->reg_list[15].valid = 1;
699
700 cortex_a8_restore_context(target);
701
702 #if 0
703 /* the front-end may request us not to handle breakpoints */
704 if (handle_breakpoints)
705 {
706 /* Single step past breakpoint at current address */
707 if ((breakpoint = breakpoint_find(target, resume_pc)))
708 {
709 LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
710 cortex_m3_unset_breakpoint(target, breakpoint);
711 cortex_m3_single_step_core(target);
712 cortex_m3_set_breakpoint(target, breakpoint);
713 }
714 }
715
716 #endif
717 /* Restart core and wait for it to be started */
718 mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DRCR, 0x2);
719
720 do {
721 mem_ap_read_atomic_u32(swjdp,
722 armv7a->debug_base + CPUDBG_DSCR, &dscr);
723 } while ((dscr & (1 << DSCR_CORE_RESTARTED)) == 0);
724
725 target->debug_reason = DBG_REASON_NOTHALTED;
726 target->state = TARGET_RUNNING;
727
728 /* registers are now invalid */
729 register_cache_invalidate(armv4_5->core_cache);
730
731 if (!debug_execution)
732 {
733 target->state = TARGET_RUNNING;
734 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
735 LOG_DEBUG("target resumed at 0x%" PRIx32, resume_pc);
736 }
737 else
738 {
739 target->state = TARGET_DEBUG_RUNNING;
740 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
741 LOG_DEBUG("target debug resumed at 0x%" PRIx32, resume_pc);
742 }
743
744 dap_ap_select(swjdp, saved_apsel);
745
746 return ERROR_OK;
747 }
748
749 static int cortex_a8_debug_entry(struct target *target)
750 {
751 int i;
752 uint32_t regfile[16], pc, cpsr, dscr;
753 int retval = ERROR_OK;
754 struct working_area *regfile_working_area = NULL;
755 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
756 struct armv7a_common *armv7a = target_to_armv7a(target);
757 struct arm *armv4_5 = &armv7a->armv4_5_common;
758 struct swjdp_common *swjdp = &armv7a->swjdp_info;
759 struct reg *reg;
760
761 LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a8->cpudbg_dscr);
762
763 /* Enable the ITR execution once we are in debug mode */
764 mem_ap_read_atomic_u32(swjdp,
765 armv7a->debug_base + CPUDBG_DSCR, &dscr);
766
767 /* REVISIT see A8 TRM 12.11.4 steps 2..3 -- make sure that any
768 * imprecise data aborts get discarded by issuing a Data
769 * Synchronization Barrier: ARMV4_5_MCR(15, 0, 0, 7, 10, 4).
770 */
771
772 dscr |= (1 << DSCR_EXT_INT_EN);
773 retval = mem_ap_write_atomic_u32(swjdp,
774 armv7a->debug_base + CPUDBG_DSCR, dscr);
775
776 /* Examine debug reason */
777 switch ((cortex_a8->cpudbg_dscr >> 2)&0xF)
778 {
779 case 0: /* DRCR[0] write */
780 case 4: /* EDBGRQ */
781 target->debug_reason = DBG_REASON_DBGRQ;
782 break;
783 case 1: /* HW breakpoint */
784 case 3: /* SW BKPT */
785 case 5: /* vector catch */
786 target->debug_reason = DBG_REASON_BREAKPOINT;
787 break;
788 case 10: /* precise watchpoint */
789 target->debug_reason = DBG_REASON_WATCHPOINT;
790 /* REVISIT could collect WFAR later, to see just
791 * which instruction triggered the watchpoint.
792 */
793 break;
794 default:
795 target->debug_reason = DBG_REASON_UNDEFINED;
796 break;
797 }
798
799 /* REVISIT fast_reg_read is never set ... */
800
801 /* Examine target state and mode */
802 if (cortex_a8->fast_reg_read)
803 target_alloc_working_area(target, 64, &regfile_working_area);
804
805 /* First load register acessible through core debug port*/
806 if (!regfile_working_area)
807 {
808 retval = arm_dpm_read_current_registers(&armv7a->dpm);
809 }
810 else
811 {
812 dap_ap_select(swjdp, swjdp_memoryap);
813 cortex_a8_read_regs_through_mem(target,
814 regfile_working_area->address, regfile);
815 dap_ap_select(swjdp, swjdp_memoryap);
816 target_free_working_area(target, regfile_working_area);
817
818 /* read Current PSR */
819 cortex_a8_dap_read_coreregister_u32(target, &cpsr, 16);
820 pc = regfile[15];
821 dap_ap_select(swjdp, swjdp_debugap);
822 LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
823
824 arm_set_cpsr(armv4_5, cpsr);
825
826 /* update cache */
827 for (i = 0; i <= ARM_PC; i++)
828 {
829 reg = arm_reg_current(armv4_5, i);
830
831 buf_set_u32(reg->value, 0, 32, regfile[i]);
832 reg->valid = 1;
833 reg->dirty = 0;
834 }
835
836 /* Fixup PC Resume Address */
837 if (cpsr & (1 << 5))
838 {
839 // T bit set for Thumb or ThumbEE state
840 regfile[ARM_PC] -= 4;
841 }
842 else
843 {
844 // ARM state
845 regfile[ARM_PC] -= 8;
846 }
847
848 reg = armv4_5->core_cache->reg_list + 15;
849 buf_set_u32(reg->value, 0, 32, regfile[ARM_PC]);
850 reg->dirty = reg->valid;
851 }
852
853 #if 0
854 /* TODO, Move this */
855 uint32_t cp15_control_register, cp15_cacr, cp15_nacr;
856 cortex_a8_read_cp(target, &cp15_control_register, 15, 0, 1, 0, 0);
857 LOG_DEBUG("cp15_control_register = 0x%08x", cp15_control_register);
858
859 cortex_a8_read_cp(target, &cp15_cacr, 15, 0, 1, 0, 2);
860 LOG_DEBUG("cp15 Coprocessor Access Control Register = 0x%08x", cp15_cacr);
861
862 cortex_a8_read_cp(target, &cp15_nacr, 15, 0, 1, 1, 2);
863 LOG_DEBUG("cp15 Nonsecure Access Control Register = 0x%08x", cp15_nacr);
864 #endif
865
866 /* Are we in an exception handler */
867 // armv4_5->exception_number = 0;
868 if (armv7a->post_debug_entry)
869 armv7a->post_debug_entry(target);
870
871
872
873 return retval;
874
875 }
876
877 static void cortex_a8_post_debug_entry(struct target *target)
878 {
879 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
880 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
881
882 // cortex_a8_read_cp(target, &cp15_control_register, 15, 0, 1, 0, 0);
883 /* examine cp15 control reg */
884 armv7a->read_cp15(target, 0, 0, 1, 0, &cortex_a8->cp15_control_reg);
885 jtag_execute_queue();
886 LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, cortex_a8->cp15_control_reg);
887
888 if (armv7a->armv4_5_mmu.armv4_5_cache.ctype == -1)
889 {
890 uint32_t cache_type_reg;
891 /* identify caches */
892 armv7a->read_cp15(target, 0, 1, 0, 0, &cache_type_reg);
893 jtag_execute_queue();
894 /* FIXME the armv4_4 cache info DOES NOT APPLY to Cortex-A8 */
895 armv4_5_identify_cache(cache_type_reg,
896 &armv7a->armv4_5_mmu.armv4_5_cache);
897 }
898
899 armv7a->armv4_5_mmu.mmu_enabled =
900 (cortex_a8->cp15_control_reg & 0x1U) ? 1 : 0;
901 armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled =
902 (cortex_a8->cp15_control_reg & 0x4U) ? 1 : 0;
903 armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled =
904 (cortex_a8->cp15_control_reg & 0x1000U) ? 1 : 0;
905
906
907 }
908
909 static int cortex_a8_step(struct target *target, int current, uint32_t address,
910 int handle_breakpoints)
911 {
912 struct armv7a_common *armv7a = target_to_armv7a(target);
913 struct arm *armv4_5 = &armv7a->armv4_5_common;
914 struct breakpoint *breakpoint = NULL;
915 struct breakpoint stepbreakpoint;
916 struct reg *r;
917
918 int timeout = 100;
919
920 if (target->state != TARGET_HALTED)
921 {
922 LOG_WARNING("target not halted");
923 return ERROR_TARGET_NOT_HALTED;
924 }
925
926 /* current = 1: continue on current pc, otherwise continue at <address> */
927 r = armv4_5->core_cache->reg_list + 15;
928 if (!current)
929 {
930 buf_set_u32(r->value, 0, 32, address);
931 }
932 else
933 {
934 address = buf_get_u32(r->value, 0, 32);
935 }
936
937 /* The front-end may request us not to handle breakpoints.
938 * But since Cortex-A8 uses breakpoint for single step,
939 * we MUST handle breakpoints.
940 */
941 handle_breakpoints = 1;
942 if (handle_breakpoints) {
943 breakpoint = breakpoint_find(target, address);
944 if (breakpoint)
945 cortex_a8_unset_breakpoint(target, breakpoint);
946 }
947
948 /* Setup single step breakpoint */
949 stepbreakpoint.address = address;
950 stepbreakpoint.length = (armv4_5->core_state == ARMV4_5_STATE_THUMB)
951 ? 2 : 4;
952 stepbreakpoint.type = BKPT_HARD;
953 stepbreakpoint.set = 0;
954
955 /* Break on IVA mismatch */
956 cortex_a8_set_breakpoint(target, &stepbreakpoint, 0x04);
957
958 target->debug_reason = DBG_REASON_SINGLESTEP;
959
960 cortex_a8_resume(target, 1, address, 0, 0);
961
962 while (target->state != TARGET_HALTED)
963 {
964 cortex_a8_poll(target);
965 if (--timeout == 0)
966 {
967 LOG_WARNING("timeout waiting for target halt");
968 break;
969 }
970 }
971
972 cortex_a8_unset_breakpoint(target, &stepbreakpoint);
973 if (timeout > 0) target->debug_reason = DBG_REASON_BREAKPOINT;
974
975 if (breakpoint)
976 cortex_a8_set_breakpoint(target, breakpoint, 0);
977
978 if (target->state != TARGET_HALTED)
979 LOG_DEBUG("target stepped");
980
981 return ERROR_OK;
982 }
983
984 static int cortex_a8_restore_context(struct target *target)
985 {
986 struct armv7a_common *armv7a = target_to_armv7a(target);
987
988 LOG_DEBUG(" ");
989
990 if (armv7a->pre_restore_context)
991 armv7a->pre_restore_context(target);
992
993 arm_dpm_write_dirty_registers(&armv7a->dpm);
994
995 if (armv7a->post_restore_context)
996 armv7a->post_restore_context(target);
997
998 return ERROR_OK;
999 }
1000
1001
1002 /*
1003 * Cortex-A8 Breakpoint and watchpoint fuctions
1004 */
1005
1006 /* Setup hardware Breakpoint Register Pair */
1007 static int cortex_a8_set_breakpoint(struct target *target,
1008 struct breakpoint *breakpoint, uint8_t matchmode)
1009 {
1010 int retval;
1011 int brp_i=0;
1012 uint32_t control;
1013 uint8_t byte_addr_select = 0x0F;
1014 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1015 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
1016 struct cortex_a8_brp * brp_list = cortex_a8->brp_list;
1017
1018 if (breakpoint->set)
1019 {
1020 LOG_WARNING("breakpoint already set");
1021 return ERROR_OK;
1022 }
1023
1024 if (breakpoint->type == BKPT_HARD)
1025 {
1026 while (brp_list[brp_i].used && (brp_i < cortex_a8->brp_num))
1027 brp_i++ ;
1028 if (brp_i >= cortex_a8->brp_num)
1029 {
1030 LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
1031 return ERROR_FAIL;
1032 }
1033 breakpoint->set = brp_i + 1;
1034 if (breakpoint->length == 2)
1035 {
1036 byte_addr_select = (3 << (breakpoint->address & 0x02));
1037 }
1038 control = ((matchmode & 0x7) << 20)
1039 | (byte_addr_select << 5)
1040 | (3 << 1) | 1;
1041 brp_list[brp_i].used = 1;
1042 brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC);
1043 brp_list[brp_i].control = control;
1044 cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
1045 + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
1046 brp_list[brp_i].value);
1047 cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
1048 + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
1049 brp_list[brp_i].control);
1050 LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
1051 brp_list[brp_i].control,
1052 brp_list[brp_i].value);
1053 }
1054 else if (breakpoint->type == BKPT_SOFT)
1055 {
1056 uint8_t code[4];
1057 if (breakpoint->length == 2)
1058 {
1059 buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
1060 }
1061 else
1062 {
1063 buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11));
1064 }
1065 retval = target->type->read_memory(target,
1066 breakpoint->address & 0xFFFFFFFE,
1067 breakpoint->length, 1,
1068 breakpoint->orig_instr);
1069 if (retval != ERROR_OK)
1070 return retval;
1071 retval = target->type->write_memory(target,
1072 breakpoint->address & 0xFFFFFFFE,
1073 breakpoint->length, 1, code);
1074 if (retval != ERROR_OK)
1075 return retval;
1076 breakpoint->set = 0x11; /* Any nice value but 0 */
1077 }
1078
1079 return ERROR_OK;
1080 }
1081
1082 static int cortex_a8_unset_breakpoint(struct target *target, struct breakpoint *breakpoint)
1083 {
1084 int retval;
1085 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1086 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
1087 struct cortex_a8_brp * brp_list = cortex_a8->brp_list;
1088
1089 if (!breakpoint->set)
1090 {
1091 LOG_WARNING("breakpoint not set");
1092 return ERROR_OK;
1093 }
1094
1095 if (breakpoint->type == BKPT_HARD)
1096 {
1097 int brp_i = breakpoint->set - 1;
1098 if ((brp_i < 0) || (brp_i >= cortex_a8->brp_num))
1099 {
1100 LOG_DEBUG("Invalid BRP number in breakpoint");
1101 return ERROR_OK;
1102 }
1103 LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
1104 brp_list[brp_i].control, brp_list[brp_i].value);
1105 brp_list[brp_i].used = 0;
1106 brp_list[brp_i].value = 0;
1107 brp_list[brp_i].control = 0;
1108 cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
1109 + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
1110 brp_list[brp_i].control);
1111 cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
1112 + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
1113 brp_list[brp_i].value);
1114 }
1115 else
1116 {
1117 /* restore original instruction (kept in target endianness) */
1118 if (breakpoint->length == 4)
1119 {
1120 retval = target->type->write_memory(target,
1121 breakpoint->address & 0xFFFFFFFE,
1122 4, 1, breakpoint->orig_instr);
1123 if (retval != ERROR_OK)
1124 return retval;
1125 }
1126 else
1127 {
1128 retval = target->type->write_memory(target,
1129 breakpoint->address & 0xFFFFFFFE,
1130 2, 1, breakpoint->orig_instr);
1131 if (retval != ERROR_OK)
1132 return retval;
1133 }
1134 }
1135 breakpoint->set = 0;
1136
1137 return ERROR_OK;
1138 }
1139
1140 static int cortex_a8_add_breakpoint(struct target *target,
1141 struct breakpoint *breakpoint)
1142 {
1143 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1144
1145 if ((breakpoint->type == BKPT_HARD) && (cortex_a8->brp_num_available < 1))
1146 {
1147 LOG_INFO("no hardware breakpoint available");
1148 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1149 }
1150
1151 if (breakpoint->type == BKPT_HARD)
1152 cortex_a8->brp_num_available--;
1153 cortex_a8_set_breakpoint(target, breakpoint, 0x00); /* Exact match */
1154
1155 return ERROR_OK;
1156 }
1157
1158 static int cortex_a8_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
1159 {
1160 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1161
1162 #if 0
1163 /* It is perfectly possible to remove brakpoints while the taget is running */
1164 if (target->state != TARGET_HALTED)
1165 {
1166 LOG_WARNING("target not halted");
1167 return ERROR_TARGET_NOT_HALTED;
1168 }
1169 #endif
1170
1171 if (breakpoint->set)
1172 {
1173 cortex_a8_unset_breakpoint(target, breakpoint);
1174 if (breakpoint->type == BKPT_HARD)
1175 cortex_a8->brp_num_available++ ;
1176 }
1177
1178
1179 return ERROR_OK;
1180 }
1181
1182
1183
1184 /*
1185 * Cortex-A8 Reset fuctions
1186 */
1187
1188 static int cortex_a8_assert_reset(struct target *target)
1189 {
1190 struct armv7a_common *armv7a = target_to_armv7a(target);
1191
1192 LOG_DEBUG(" ");
1193
1194 /* registers are now invalid */
1195 register_cache_invalidate(armv7a->armv4_5_common.core_cache);
1196
1197 target->state = TARGET_RESET;
1198
1199 return ERROR_OK;
1200 }
1201
1202 static int cortex_a8_deassert_reset(struct target *target)
1203 {
1204
1205 LOG_DEBUG(" ");
1206
1207 if (target->reset_halt)
1208 {
1209 int retval;
1210 if ((retval = target_halt(target)) != ERROR_OK)
1211 return retval;
1212 }
1213
1214 return ERROR_OK;
1215 }
1216
1217 /*
1218 * Cortex-A8 Memory access
1219 *
1220 * This is same Cortex M3 but we must also use the correct
1221 * ap number for every access.
1222 */
1223
1224 static int cortex_a8_read_memory(struct target *target, uint32_t address,
1225 uint32_t size, uint32_t count, uint8_t *buffer)
1226 {
1227 struct armv7a_common *armv7a = target_to_armv7a(target);
1228 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1229 int retval = ERROR_INVALID_ARGUMENTS;
1230
1231 /* cortex_a8 handles unaligned memory access */
1232
1233 // ??? dap_ap_select(swjdp, swjdp_memoryap);
1234
1235 if (count && buffer) {
1236 switch (size) {
1237 case 4:
1238 retval = mem_ap_read_buf_u32(swjdp, buffer, 4 * count, address);
1239 break;
1240 case 2:
1241 retval = mem_ap_read_buf_u16(swjdp, buffer, 2 * count, address);
1242 break;
1243 case 1:
1244 retval = mem_ap_read_buf_u8(swjdp, buffer, count, address);
1245 break;
1246 }
1247 }
1248
1249 return retval;
1250 }
1251
1252 static int cortex_a8_write_memory(struct target *target, uint32_t address,
1253 uint32_t size, uint32_t count, uint8_t *buffer)
1254 {
1255 struct armv7a_common *armv7a = target_to_armv7a(target);
1256 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1257 int retval = ERROR_INVALID_ARGUMENTS;
1258
1259 // ??? dap_ap_select(swjdp, swjdp_memoryap);
1260
1261 if (count && buffer) {
1262 switch (size) {
1263 case 4:
1264 retval = mem_ap_write_buf_u32(swjdp, buffer, 4 * count, address);
1265 break;
1266 case 2:
1267 retval = mem_ap_write_buf_u16(swjdp, buffer, 2 * count, address);
1268 break;
1269 case 1:
1270 retval = mem_ap_write_buf_u8(swjdp, buffer, count, address);
1271 break;
1272 }
1273 }
1274
1275 if (retval == ERROR_OK && target->state == TARGET_HALTED)
1276 {
1277 /* The Cache handling will NOT work with MMU active, the wrong addresses will be invalidated */
1278 /* invalidate I-Cache */
1279 if (armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
1280 {
1281 /* Invalidate ICache single entry with MVA, repeat this for all cache
1282 lines in the address range, Cortex-A8 has fixed 64 byte line length */
1283 /* Invalidate Cache single entry with MVA to PoU */
1284 for (uint32_t cacheline=address; cacheline<address+size*count; cacheline+=64)
1285 armv7a->write_cp15(target, 0, 1, 7, 5, cacheline); /* I-Cache to PoU */
1286 }
1287 /* invalidate D-Cache */
1288 if (armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
1289 {
1290 /* Invalidate Cache single entry with MVA to PoC */
1291 for (uint32_t cacheline=address; cacheline<address+size*count; cacheline+=64)
1292 armv7a->write_cp15(target, 0, 1, 7, 6, cacheline); /* U/D cache to PoC */
1293 }
1294 }
1295
1296 return retval;
1297 }
1298
1299 static int cortex_a8_bulk_write_memory(struct target *target, uint32_t address,
1300 uint32_t count, uint8_t *buffer)
1301 {
1302 return cortex_a8_write_memory(target, address, 4, count, buffer);
1303 }
1304
1305
1306 static int cortex_a8_dcc_read(struct swjdp_common *swjdp, uint8_t *value, uint8_t *ctrl)
1307 {
1308 #if 0
1309 u16 dcrdr;
1310
1311 mem_ap_read_buf_u16(swjdp, (uint8_t*)&dcrdr, 1, DCB_DCRDR);
1312 *ctrl = (uint8_t)dcrdr;
1313 *value = (uint8_t)(dcrdr >> 8);
1314
1315 LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl);
1316
1317 /* write ack back to software dcc register
1318 * signify we have read data */
1319 if (dcrdr & (1 << 0))
1320 {
1321 dcrdr = 0;
1322 mem_ap_write_buf_u16(swjdp, (uint8_t*)&dcrdr, 1, DCB_DCRDR);
1323 }
1324 #endif
1325 return ERROR_OK;
1326 }
1327
1328
1329 static int cortex_a8_handle_target_request(void *priv)
1330 {
1331 struct target *target = priv;
1332 struct armv7a_common *armv7a = target_to_armv7a(target);
1333 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1334
1335 if (!target_was_examined(target))
1336 return ERROR_OK;
1337 if (!target->dbg_msg_enabled)
1338 return ERROR_OK;
1339
1340 if (target->state == TARGET_RUNNING)
1341 {
1342 uint8_t data = 0;
1343 uint8_t ctrl = 0;
1344
1345 cortex_a8_dcc_read(swjdp, &data, &ctrl);
1346
1347 /* check if we have data */
1348 if (ctrl & (1 << 0))
1349 {
1350 uint32_t request;
1351
1352 /* we assume target is quick enough */
1353 request = data;
1354 cortex_a8_dcc_read(swjdp, &data, &ctrl);
1355 request |= (data << 8);
1356 cortex_a8_dcc_read(swjdp, &data, &ctrl);
1357 request |= (data << 16);
1358 cortex_a8_dcc_read(swjdp, &data, &ctrl);
1359 request |= (data << 24);
1360 target_request(target, request);
1361 }
1362 }
1363
1364 return ERROR_OK;
1365 }
1366
1367 /*
1368 * Cortex-A8 target information and configuration
1369 */
1370
1371 static int cortex_a8_examine_first(struct target *target)
1372 {
1373 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1374 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
1375 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1376 int i;
1377 int retval = ERROR_OK;
1378 uint32_t didr, ctypr, ttypr, cpuid;
1379
1380 LOG_DEBUG("TODO");
1381
1382 /* Here we shall insert a proper ROM Table scan */
1383 armv7a->debug_base = OMAP3530_DEBUG_BASE;
1384
1385 /* We do one extra read to ensure DAP is configured,
1386 * we call ahbap_debugport_init(swjdp) instead
1387 */
1388 ahbap_debugport_init(swjdp);
1389 mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_CPUID, &cpuid);
1390 if ((retval = mem_ap_read_atomic_u32(swjdp,
1391 armv7a->debug_base + CPUDBG_CPUID, &cpuid)) != ERROR_OK)
1392 {
1393 LOG_DEBUG("Examine failed");
1394 return retval;
1395 }
1396
1397 if ((retval = mem_ap_read_atomic_u32(swjdp,
1398 armv7a->debug_base + CPUDBG_CTYPR, &ctypr)) != ERROR_OK)
1399 {
1400 LOG_DEBUG("Examine failed");
1401 return retval;
1402 }
1403
1404 if ((retval = mem_ap_read_atomic_u32(swjdp,
1405 armv7a->debug_base + CPUDBG_TTYPR, &ttypr)) != ERROR_OK)
1406 {
1407 LOG_DEBUG("Examine failed");
1408 return retval;
1409 }
1410
1411 if ((retval = mem_ap_read_atomic_u32(swjdp,
1412 armv7a->debug_base + CPUDBG_DIDR, &didr)) != ERROR_OK)
1413 {
1414 LOG_DEBUG("Examine failed");
1415 return retval;
1416 }
1417
1418 LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid);
1419 LOG_DEBUG("ctypr = 0x%08" PRIx32, ctypr);
1420 LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr);
1421 LOG_DEBUG("didr = 0x%08" PRIx32, didr);
1422
1423 cortex_a8_dpm_setup(cortex_a8, didr);
1424
1425 /* Setup Breakpoint Register Pairs */
1426 cortex_a8->brp_num = ((didr >> 24) & 0x0F) + 1;
1427 cortex_a8->brp_num_context = ((didr >> 20) & 0x0F) + 1;
1428 cortex_a8->brp_num_available = cortex_a8->brp_num;
1429 cortex_a8->brp_list = calloc(cortex_a8->brp_num, sizeof(struct cortex_a8_brp));
1430 // cortex_a8->brb_enabled = ????;
1431 for (i = 0; i < cortex_a8->brp_num; i++)
1432 {
1433 cortex_a8->brp_list[i].used = 0;
1434 if (i < (cortex_a8->brp_num-cortex_a8->brp_num_context))
1435 cortex_a8->brp_list[i].type = BRP_NORMAL;
1436 else
1437 cortex_a8->brp_list[i].type = BRP_CONTEXT;
1438 cortex_a8->brp_list[i].value = 0;
1439 cortex_a8->brp_list[i].control = 0;
1440 cortex_a8->brp_list[i].BRPn = i;
1441 }
1442
1443 /* Setup Watchpoint Register Pairs */
1444 cortex_a8->wrp_num = ((didr >> 28) & 0x0F) + 1;
1445 cortex_a8->wrp_num_available = cortex_a8->wrp_num;
1446 cortex_a8->wrp_list = calloc(cortex_a8->wrp_num, sizeof(struct cortex_a8_wrp));
1447 for (i = 0; i < cortex_a8->wrp_num; i++)
1448 {
1449 cortex_a8->wrp_list[i].used = 0;
1450 cortex_a8->wrp_list[i].type = 0;
1451 cortex_a8->wrp_list[i].value = 0;
1452 cortex_a8->wrp_list[i].control = 0;
1453 cortex_a8->wrp_list[i].WRPn = i;
1454 }
1455 LOG_DEBUG("Configured %i hw breakpoint pairs and %i hw watchpoint pairs",
1456 cortex_a8->brp_num , cortex_a8->wrp_num);
1457
1458 target_set_examined(target);
1459 return ERROR_OK;
1460 }
1461
1462 static int cortex_a8_examine(struct target *target)
1463 {
1464 int retval = ERROR_OK;
1465
1466 /* don't re-probe hardware after each reset */
1467 if (!target_was_examined(target))
1468 retval = cortex_a8_examine_first(target);
1469
1470 /* Configure core debug access */
1471 if (retval == ERROR_OK)
1472 retval = cortex_a8_init_debug_access(target);
1473
1474 return retval;
1475 }
1476
1477 /*
1478 * Cortex-A8 target creation and initialization
1479 */
1480
1481 static int cortex_a8_init_target(struct command_context *cmd_ctx,
1482 struct target *target)
1483 {
1484 /* examine_first() does a bunch of this */
1485 return ERROR_OK;
1486 }
1487
1488 static int cortex_a8_init_arch_info(struct target *target,
1489 struct cortex_a8_common *cortex_a8, struct jtag_tap *tap)
1490 {
1491 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
1492 struct arm *armv4_5 = &armv7a->armv4_5_common;
1493 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1494
1495 /* Setup struct cortex_a8_common */
1496 cortex_a8->common_magic = CORTEX_A8_COMMON_MAGIC;
1497 armv4_5->arch_info = armv7a;
1498
1499 /* prepare JTAG information for the new target */
1500 cortex_a8->jtag_info.tap = tap;
1501 cortex_a8->jtag_info.scann_size = 4;
1502
1503 swjdp->dp_select_value = -1;
1504 swjdp->ap_csw_value = -1;
1505 swjdp->ap_tar_value = -1;
1506 swjdp->jtag_info = &cortex_a8->jtag_info;
1507 swjdp->memaccess_tck = 80;
1508
1509 /* Number of bits for tar autoincrement, impl. dep. at least 10 */
1510 swjdp->tar_autoincr_block = (1 << 10);
1511
1512 cortex_a8->fast_reg_read = 0;
1513
1514
1515 /* register arch-specific functions */
1516 armv7a->examine_debug_reason = NULL;
1517
1518 armv7a->post_debug_entry = cortex_a8_post_debug_entry;
1519
1520 armv7a->pre_restore_context = NULL;
1521 armv7a->post_restore_context = NULL;
1522 armv7a->armv4_5_mmu.armv4_5_cache.ctype = -1;
1523 // armv7a->armv4_5_mmu.get_ttb = armv7a_get_ttb;
1524 armv7a->armv4_5_mmu.read_memory = cortex_a8_read_memory;
1525 armv7a->armv4_5_mmu.write_memory = cortex_a8_write_memory;
1526 // armv7a->armv4_5_mmu.disable_mmu_caches = armv7a_disable_mmu_caches;
1527 // armv7a->armv4_5_mmu.enable_mmu_caches = armv7a_enable_mmu_caches;
1528 armv7a->armv4_5_mmu.has_tiny_pages = 1;
1529 armv7a->armv4_5_mmu.mmu_enabled = 0;
1530 armv7a->read_cp15 = cortex_a8_read_cp15;
1531 armv7a->write_cp15 = cortex_a8_write_cp15;
1532
1533
1534 // arm7_9->handle_target_request = cortex_a8_handle_target_request;
1535
1536 /* REVISIT v7a setup should be in a v7a-specific routine */
1537 armv4_5_init_arch_info(target, armv4_5);
1538 armv7a->common_magic = ARMV7_COMMON_MAGIC;
1539
1540 target_register_timer_callback(cortex_a8_handle_target_request, 1, 1, target);
1541
1542 return ERROR_OK;
1543 }
1544
1545 static int cortex_a8_target_create(struct target *target, Jim_Interp *interp)
1546 {
1547 struct cortex_a8_common *cortex_a8 = calloc(1, sizeof(struct cortex_a8_common));
1548
1549 cortex_a8_init_arch_info(target, cortex_a8, target->tap);
1550
1551 return ERROR_OK;
1552 }
1553
1554 COMMAND_HANDLER(cortex_a8_handle_cache_info_command)
1555 {
1556 struct target *target = get_current_target(CMD_CTX);
1557 struct armv7a_common *armv7a = target_to_armv7a(target);
1558
1559 return armv4_5_handle_cache_info_command(CMD_CTX,
1560 &armv7a->armv4_5_mmu.armv4_5_cache);
1561 }
1562
1563
1564 COMMAND_HANDLER(cortex_a8_handle_dbginit_command)
1565 {
1566 struct target *target = get_current_target(CMD_CTX);
1567
1568 cortex_a8_init_debug_access(target);
1569
1570 return ERROR_OK;
1571 }
1572
1573
1574 static int cortex_a8_register_commands(struct command_context *cmd_ctx)
1575 {
1576 struct command *cortex_a8_cmd;
1577 int retval = ERROR_OK;
1578
1579 armv4_5_register_commands(cmd_ctx);
1580 armv7a_register_commands(cmd_ctx);
1581
1582 cortex_a8_cmd = register_command(cmd_ctx, NULL, "cortex_a8",
1583 NULL, COMMAND_ANY,
1584 "cortex_a8 specific commands");
1585
1586 register_command(cmd_ctx, cortex_a8_cmd, "cache_info",
1587 cortex_a8_handle_cache_info_command, COMMAND_EXEC,
1588 "display information about target caches");
1589
1590 register_command(cmd_ctx, cortex_a8_cmd, "dbginit",
1591 cortex_a8_handle_dbginit_command, COMMAND_EXEC,
1592 "Initialize core debug");
1593
1594 return retval;
1595 }
1596
1597 struct target_type cortexa8_target = {
1598 .name = "cortex_a8",
1599
1600 .poll = cortex_a8_poll,
1601 .arch_state = armv7a_arch_state,
1602
1603 .target_request_data = NULL,
1604
1605 .halt = cortex_a8_halt,
1606 .resume = cortex_a8_resume,
1607 .step = cortex_a8_step,
1608
1609 .assert_reset = cortex_a8_assert_reset,
1610 .deassert_reset = cortex_a8_deassert_reset,
1611 .soft_reset_halt = NULL,
1612
1613 .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
1614
1615 .read_memory = cortex_a8_read_memory,
1616 .write_memory = cortex_a8_write_memory,
1617 .bulk_write_memory = cortex_a8_bulk_write_memory,
1618
1619 .checksum_memory = arm_checksum_memory,
1620 .blank_check_memory = arm_blank_check_memory,
1621
1622 .run_algorithm = armv4_5_run_algorithm,
1623
1624 .add_breakpoint = cortex_a8_add_breakpoint,
1625 .remove_breakpoint = cortex_a8_remove_breakpoint,
1626 .add_watchpoint = NULL,
1627 .remove_watchpoint = NULL,
1628
1629 .register_commands = cortex_a8_register_commands,
1630 .target_create = cortex_a8_target_create,
1631 .init_target = cortex_a8_init_target,
1632 .examine = cortex_a8_examine,
1633 .mrc = cortex_a8_mrc,
1634 .mcr = cortex_a8_mcr,
1635 };

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)