1 /***************************************************************************
2 * Copyright (C) 2008-2009 by Marvell Semiconductors, Inc. *
3 * Written by Nicolas Pitre <nico@marvell.com> *
5 * Copyright (C) 2008 by Hongtao Zheng *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
25 * Marvell Feroceon/Dragonite support.
27 * The Feroceon core, as found in the Orion and Kirkwood SoCs amongst others,
28 * mimics the ARM926 ICE interface with the following differences:
30 * - the MOE (method of entry) reporting is not implemented
32 * - breakpoint/watchpoint comparator #1 is seemingly not implemented
34 * - due to a different pipeline implementation, some injected debug
35 * instruction sequences have to be somewhat different
39 * - asserting DBGRQ doesn't work if target is looping on the undef vector
41 * - the EICE version signature in the COMMS_CTL reg is next to the flow bits
42 * not at the top, and rather meaningless due to existing discrepencies
44 * - the DCC channel is half duplex (only one FIFO for both directions) with
45 * seemingly no proper flow control.
47 * The Dragonite core is the non-mmu version based on the ARM966 model, and
48 * it shares the above issues as well.
55 #include "arm926ejs.h"
57 #include "target_type.h"
59 #include "arm_opcodes.h"
62 static int feroceon_assert_reset(struct target
*target
)
64 struct arm
*armv4_5
= target
->arch_info
;
65 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
66 int ud
= arm7_9
->use_dbgrq
;
68 arm7_9
->use_dbgrq
= 0;
69 if (target
->reset_halt
)
71 arm7_9
->use_dbgrq
= ud
;
72 return arm7_9_assert_reset(target
);
75 static int feroceon_dummy_clock_out(struct arm_jtag
*jtag_info
, uint32_t instr
)
77 struct scan_field fields
[3];
80 uint8_t sysspeed_buf
= 0x0;
83 buf_set_u32(out_buf
, 0, 32, 0);
85 buf_set_u32(instr_buf
, 0, 32, flip_u32(instr
, 32));
87 arm_jtag_scann(jtag_info
, 0x1, TAP_DRPAUSE
);
89 arm_jtag_set_instr(jtag_info
, jtag_info
->intest_instr
, NULL
, TAP_DRPAUSE
);
91 fields
[0].num_bits
= 32;
92 fields
[0].out_value
= out_buf
;
93 fields
[0].in_value
= NULL
;
95 fields
[1].num_bits
= 3;
96 fields
[1].out_value
= &sysspeed_buf
;
97 fields
[1].in_value
= NULL
;
99 fields
[2].num_bits
= 32;
100 fields
[2].out_value
= instr_buf
;
101 fields
[2].in_value
= NULL
;
103 jtag_add_dr_scan(jtag_info
->tap
, 3, fields
, TAP_DRPAUSE
);
105 /* no jtag_add_runtest(0, TAP_DRPAUSE) here */
110 static void feroceon_change_to_arm(struct target
*target
, uint32_t *r0
,
113 struct arm
*armv4_5
= target
->arch_info
;
114 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
115 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
118 * save r0 before using it and put system in ARM state
119 * to allow common handling of ARM and THUMB debugging
122 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
123 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
124 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
126 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
127 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
128 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
129 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, r0
, 0);
130 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
131 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
133 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_MOV(0, 15), 0, NULL
, 0);
134 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
135 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
136 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
137 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, pc
, 0);
138 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
139 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
141 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_BX(15), 0, NULL
, 0);
142 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
143 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
144 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
145 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
147 jtag_execute_queue();
150 * fix program counter:
151 * MOV R0, PC was the 7th instruction (+12)
152 * reading PC in Thumb state gives address of instruction + 4
157 static void feroceon_read_core_regs(struct target
*target
,
158 uint32_t mask
, uint32_t* core_regs
[16])
161 struct arm
*armv4_5
= target
->arch_info
;
162 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
163 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
165 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
166 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
167 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
169 for (i
= 0; i
<= 15; i
++)
171 arm9tdmi_clock_data_in(jtag_info
, core_regs
[i
]);
173 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
174 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
177 static void feroceon_read_core_regs_target_buffer(struct target
*target
,
178 uint32_t mask
, void* buffer
, int size
)
181 struct arm
*armv4_5
= target
->arch_info
;
182 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
183 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
184 int be
= (target
->endianness
== TARGET_BIG_ENDIAN
) ? 1 : 0;
185 uint32_t *buf_u32
= buffer
;
186 uint16_t *buf_u16
= buffer
;
187 uint8_t *buf_u8
= buffer
;
189 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
190 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
191 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
193 for (i
= 0; i
<= 15; i
++)
195 if (mask
& (1 << i
)) {
199 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u32
++, 4, be
);
202 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u16
++, 2, be
);
205 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u8
++, 1, be
);
211 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
212 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
215 static void feroceon_read_xpsr(struct target
*target
, uint32_t *xpsr
, int spsr
)
217 struct arm
*armv4_5
= target
->arch_info
;
218 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
219 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
221 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRS(0, spsr
& 1), 0, NULL
, 0);
222 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
223 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
224 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
225 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
226 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
227 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
229 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
230 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
231 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
232 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, xpsr
, 0);
234 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
235 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
238 static void feroceon_write_xpsr(struct target
*target
, uint32_t xpsr
, int spsr
)
240 struct arm
*armv4_5
= target
->arch_info
;
241 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
242 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
244 LOG_DEBUG("xpsr: %8.8" PRIx32
", spsr: %i", xpsr
, spsr
);
246 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr
& 0xff, 0, 1, spsr
), 0, NULL
, 0);
247 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
248 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
249 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
250 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
251 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
252 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
254 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff00) >> 8, 0xc, 2, spsr
), 0, NULL
, 0);
255 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
256 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
257 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
258 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
259 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
260 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
262 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff0000) >> 16, 0x8, 4, spsr
), 0, NULL
, 0);
263 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
264 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
265 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
266 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
267 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
268 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
270 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff000000) >> 24, 0x4, 8, spsr
), 0, NULL
, 0);
271 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
272 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
273 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
274 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
275 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
276 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
279 static void feroceon_write_xpsr_im8(struct target
*target
,
280 uint8_t xpsr_im
, int rot
, int spsr
)
282 struct arm
*armv4_5
= target
->arch_info
;
283 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
284 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
286 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im
, rot
, spsr
);
288 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr_im
, rot
, 1, spsr
), 0, NULL
, 0);
289 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
290 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
291 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
292 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
293 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
294 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
297 static void feroceon_write_core_regs(struct target
*target
,
298 uint32_t mask
, uint32_t core_regs
[16])
301 struct arm
*armv4_5
= target
->arch_info
;
302 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
303 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
305 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
306 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
307 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
309 for (i
= 0; i
<= 15; i
++)
311 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, core_regs
[i
], NULL
, 0);
313 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
314 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
315 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
318 static void feroceon_branch_resume(struct target
*target
)
320 struct arm
*armv4_5
= target
->arch_info
;
321 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
322 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
324 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
325 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
326 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
327 arm9tdmi_clock_out(jtag_info
, ARMV4_5_B(0xfffff9, 0), 0, NULL
, 0);
328 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
330 arm7_9
->need_bypass_before_restart
= 1;
333 static void feroceon_branch_resume_thumb(struct target
*target
)
337 struct arm
*armv4_5
= target
->arch_info
;
338 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
339 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
340 uint32_t r0
= buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
341 uint32_t pc
= buf_get_u32(armv4_5
->pc
->value
, 0, 32);
343 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
344 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
345 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
346 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
348 arm9tdmi_clock_out(jtag_info
, 0xE28F0001, 0, NULL
, 0); // add r0,pc,#1
349 arm9tdmi_clock_out(jtag_info
, ARMV4_5_BX(0), 0, NULL
, 0);
350 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
351 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
353 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL
, 0);
354 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
355 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
357 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, r0
, NULL
, 0);
358 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
359 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
362 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_B(0x7e9 + pc
), 0, NULL
, 0);
363 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 1);
365 arm7_9
->need_bypass_before_restart
= 1;
368 static int feroceon_read_cp15(struct target
*target
, uint32_t op1
,
369 uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t *value
)
371 struct arm
*armv4_5
= target
->arch_info
;
372 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
373 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
376 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRC(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
377 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
378 err
= arm7_9_execute_sys_speed(target
);
382 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
383 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
384 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
385 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, value
, 0);
386 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
387 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
388 return jtag_execute_queue();
391 static int feroceon_write_cp15(struct target
*target
, uint32_t op1
,
392 uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t value
)
394 struct arm
*armv4_5
= target
->arch_info
;
395 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
396 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
398 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL
, 0);
399 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
400 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
401 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, value
, NULL
, 0);
402 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
403 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
404 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
406 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MCR(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
407 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
408 return arm7_9_execute_sys_speed(target
);
411 static void feroceon_set_dbgrq(struct target
*target
)
413 struct arm
*armv4_5
= target
->arch_info
;
414 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
415 struct reg
*dbg_ctrl
= &arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
];
417 buf_set_u32(dbg_ctrl
->value
, 0, 8, 2);
418 embeddedice_store_reg(dbg_ctrl
);
421 static void feroceon_enable_single_step(struct target
*target
, uint32_t next_pc
)
423 struct arm
*armv4_5
= target
->arch_info
;
424 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
426 /* set a breakpoint there */
427 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
], next_pc
);
428 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
], 0);
429 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
], 0xffffffff);
430 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
], 0x100);
431 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
], 0xf7);
434 static void feroceon_disable_single_step(struct target
*target
)
436 struct arm
*armv4_5
= target
->arch_info
;
437 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
439 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
]);
440 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
]);
441 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
]);
442 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
]);
443 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
]);
446 static int feroceon_examine_debug_reason(struct target
*target
)
448 /* the MOE is not implemented */
449 if (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)
451 target
->debug_reason
= DBG_REASON_DBGRQ
;
457 static int feroceon_bulk_write_memory(struct target
*target
,
458 uint32_t address
, uint32_t count
, uint8_t *buffer
)
461 struct arm
*armv4_5
= target
->arch_info
;
462 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
463 enum arm_state core_state
= armv4_5
->core_state
;
464 uint32_t x
, flip
, shift
, save
[7];
468 * We can't use the dcc flow control bits, so let's transfer data
469 * with 31 bits and flip the MSB each time a new data word is sent.
471 static uint32_t dcc_code
[] =
473 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
474 0xe3a0301e, /* 1: mov r3, #30 */
475 0xe3a04002, /* mov r4, #2 */
476 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
477 0xe1310005, /* teq r1, r5 */
478 0x0afffffc, /* beq 1b */
479 0xe1a05001, /* mov r5, r1 */
480 0xe1a01081, /* mov r1, r1, lsl #1 */
481 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
482 0xe1320005, /* teq r2, r5 */
483 0x0afffffc, /* beq 3b */
484 0xe1a05002, /* mov r5, r2 */
485 0xe3c22102, /* bic r2, r2, #0x80000000 */
486 0xe1811332, /* orr r1, r1, r2, lsr r3 */
487 0xe2533001, /* subs r3, r3, #1 */
488 0xe4801004, /* str r1, [r0], #4 */
489 0xe1a01412, /* mov r1, r2, lsl r4 */
490 0xe2844001, /* add r4, r4, #1 */
491 0x4affffed, /* bmi 1b */
492 0xeafffff3, /* b 3b */
495 uint32_t dcc_size
= sizeof(dcc_code
);
497 if (!arm7_9
->dcc_downloads
)
498 return target_write_memory(target
, address
, 4, count
, buffer
);
500 /* regrab previously allocated working_area, or allocate a new one */
501 if (!arm7_9
->dcc_working_area
)
503 uint8_t dcc_code_buf
[dcc_size
];
505 /* make sure we have a working area */
506 if (target_alloc_working_area(target
, dcc_size
, &arm7_9
->dcc_working_area
) != ERROR_OK
)
508 LOG_INFO("no working area available, falling back to memory writes");
509 return target_write_memory(target
, address
, 4, count
, buffer
);
512 /* copy target instructions to target endianness */
513 for (i
= 0; i
< dcc_size
/4; i
++)
514 target_buffer_set_u32(target
, dcc_code_buf
+ i
*4, dcc_code
[i
]);
516 /* write DCC code to working area */
517 if ((retval
= target_write_memory(target
, arm7_9
->dcc_working_area
->address
, 4, dcc_size
/4, dcc_code_buf
)) != ERROR_OK
)
523 /* backup clobbered processor state */
524 for (i
= 0; i
<= 5; i
++)
525 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32);
526 save
[i
] = buf_get_u32(armv4_5
->pc
->value
, 0, 32);
528 /* set up target address in r0 */
529 buf_set_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32, address
);
530 armv4_5
->core_cache
->reg_list
[0].valid
= 1;
531 armv4_5
->core_cache
->reg_list
[0].dirty
= 1;
532 armv4_5
->core_state
= ARM_STATE_ARM
;
534 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], 0);
535 arm7_9_resume(target
, 0, arm7_9
->dcc_working_area
->address
, 1, 1);
541 for (i
= 0; i
< count
; i
++)
543 uint32_t y
= target_buffer_get_u32(target
, buffer
);
544 uint32_t z
= (x
>> 1) | (y
>> shift
) | (flip
^= 0x80000000);
545 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
546 x
= y
<< (32 - shift
);
547 if (++shift
>= 32 || i
+ 1 >= count
)
549 z
= (x
>> 1) | (flip
^= 0x80000000);
550 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
557 retval
= target_halt(target
);
558 if (retval
== ERROR_OK
)
559 retval
= target_wait_state(target
, TARGET_HALTED
, 500);
560 if (retval
== ERROR_OK
) {
561 uint32_t endaddress
=
562 buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
563 if (endaddress
!= address
+ count
*4) {
564 LOG_ERROR("DCC write failed,"
565 " expected end address 0x%08" PRIx32
566 " got 0x%0" PRIx32
"",
567 address
+ count
*4, endaddress
);
572 /* restore target state */
573 for (i
= 0; i
<= 5; i
++)
575 buf_set_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32, save
[i
]);
576 armv4_5
->core_cache
->reg_list
[i
].valid
= 1;
577 armv4_5
->core_cache
->reg_list
[i
].dirty
= 1;
579 buf_set_u32(armv4_5
->pc
->value
, 0, 32, save
[i
]);
580 armv4_5
->pc
->valid
= 1;
581 armv4_5
->pc
->dirty
= 1;
582 armv4_5
->core_state
= core_state
;
587 static int feroceon_init_target(struct command_context
*cmd_ctx
,
588 struct target
*target
)
590 arm9tdmi_init_target(cmd_ctx
, target
);
594 static void feroceon_common_setup(struct target
*target
)
596 struct arm
*armv4_5
= target
->arch_info
;
597 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
599 /* override some insn sequence functions */
600 arm7_9
->change_to_arm
= feroceon_change_to_arm
;
601 arm7_9
->read_core_regs
= feroceon_read_core_regs
;
602 arm7_9
->read_core_regs_target_buffer
= feroceon_read_core_regs_target_buffer
;
603 arm7_9
->read_xpsr
= feroceon_read_xpsr
;
604 arm7_9
->write_xpsr
= feroceon_write_xpsr
;
605 arm7_9
->write_xpsr_im8
= feroceon_write_xpsr_im8
;
606 arm7_9
->write_core_regs
= feroceon_write_core_regs
;
607 arm7_9
->branch_resume
= feroceon_branch_resume
;
608 arm7_9
->branch_resume_thumb
= feroceon_branch_resume_thumb
;
610 /* must be implemented with only one comparator */
611 arm7_9
->enable_single_step
= feroceon_enable_single_step
;
612 arm7_9
->disable_single_step
= feroceon_disable_single_step
;
614 /* MOE is not implemented */
615 arm7_9
->examine_debug_reason
= feroceon_examine_debug_reason
;
617 /* Note: asserting DBGRQ might not win over the undef exception.
618 If that happens then just use "arm7_9 dbgrq disable". */
619 arm7_9
->use_dbgrq
= 1;
620 arm7_9
->set_special_dbgrq
= feroceon_set_dbgrq
;
622 /* only one working comparator */
623 arm7_9
->wp_available_max
= 1;
624 arm7_9
->wp1_used_default
= -1;
627 static int feroceon_target_create(struct target
*target
, Jim_Interp
*interp
)
629 struct arm926ejs_common
*arm926ejs
= calloc(1,sizeof(struct arm926ejs_common
));
631 arm926ejs_init_arch_info(target
, arm926ejs
, target
->tap
);
632 feroceon_common_setup(target
);
634 /* the standard ARM926 methods don't always work (don't ask...) */
635 arm926ejs
->read_cp15
= feroceon_read_cp15
;
636 arm926ejs
->write_cp15
= feroceon_write_cp15
;
641 static int dragonite_target_create(struct target
*target
, Jim_Interp
*interp
)
643 struct arm966e_common
*arm966e
= calloc(1,sizeof(struct arm966e_common
));
645 arm966e_init_arch_info(target
, arm966e
, target
->tap
);
646 feroceon_common_setup(target
);
651 static int feroceon_examine(struct target
*target
)
654 struct arm7_9_common
*arm7_9
;
657 retval
= arm7_9_examine(target
);
658 if (retval
!= ERROR_OK
)
661 armv4_5
= target
->arch_info
;
662 arm7_9
= armv4_5
->arch_info
;
664 /* the COMMS_CTRL bits are all contiguous */
665 if (buf_get_u32(arm7_9
->eice_cache
->reg_list
[EICE_COMMS_CTRL
].value
, 2, 4) != 6)
666 LOG_ERROR("unexpected Feroceon EICE version signature");
668 arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].size
= 6;
669 arm7_9
->eice_cache
->reg_list
[EICE_DBG_STAT
].size
= 5;
670 arm7_9
->has_monitor_mode
= 1;
672 /* vector catch reg is not initialized on reset */
673 embeddedice_set_reg(&arm7_9
->eice_cache
->reg_list
[EICE_VEC_CATCH
], 0);
675 /* clear monitor mode, enable comparators */
676 embeddedice_read_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
677 jtag_execute_queue();
678 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 4, 1, 0);
679 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 5, 1, 0);
680 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
685 struct target_type feroceon_target
=
690 .arch_state
= arm926ejs_arch_state
,
692 .target_request_data
= arm7_9_target_request_data
,
695 .resume
= arm7_9_resume
,
698 .assert_reset
= feroceon_assert_reset
,
699 .deassert_reset
= arm7_9_deassert_reset
,
700 .soft_reset_halt
= arm926ejs_soft_reset_halt
,
702 .get_gdb_reg_list
= arm_get_gdb_reg_list
,
704 .read_memory
= arm7_9_read_memory
,
705 .write_memory
= arm926ejs_write_memory
,
706 .bulk_write_memory
= feroceon_bulk_write_memory
,
708 .checksum_memory
= arm_checksum_memory
,
709 .blank_check_memory
= arm_blank_check_memory
,
711 .run_algorithm
= armv4_5_run_algorithm
,
713 .add_breakpoint
= arm7_9_add_breakpoint
,
714 .remove_breakpoint
= arm7_9_remove_breakpoint
,
715 .add_watchpoint
= arm7_9_add_watchpoint
,
716 .remove_watchpoint
= arm7_9_remove_watchpoint
,
718 .commands
= arm926ejs_command_handlers
,
719 .target_create
= feroceon_target_create
,
720 .init_target
= feroceon_init_target
,
721 .examine
= feroceon_examine
,
724 struct target_type dragonite_target
=
729 .arch_state
= arm_arch_state
,
731 .target_request_data
= arm7_9_target_request_data
,
734 .resume
= arm7_9_resume
,
737 .assert_reset
= feroceon_assert_reset
,
738 .deassert_reset
= arm7_9_deassert_reset
,
739 .soft_reset_halt
= arm7_9_soft_reset_halt
,
741 .get_gdb_reg_list
= arm_get_gdb_reg_list
,
743 .read_memory
= arm7_9_read_memory
,
744 .write_memory
= arm7_9_write_memory
,
745 .bulk_write_memory
= feroceon_bulk_write_memory
,
747 .checksum_memory
= arm_checksum_memory
,
748 .blank_check_memory
= arm_blank_check_memory
,
750 .run_algorithm
= armv4_5_run_algorithm
,
752 .add_breakpoint
= arm7_9_add_breakpoint
,
753 .remove_breakpoint
= arm7_9_remove_breakpoint
,
754 .add_watchpoint
= arm7_9_add_watchpoint
,
755 .remove_watchpoint
= arm7_9_remove_watchpoint
,
757 .commands
= arm966e_command_handlers
,
758 .target_create
= dragonite_target_create
,
759 .init_target
= feroceon_init_target
,
760 .examine
= feroceon_examine
,
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)