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"
61 int feroceon_assert_reset(struct target
*target
)
63 struct arm
*armv4_5
= target
->arch_info
;
64 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
65 int ud
= arm7_9
->use_dbgrq
;
67 arm7_9
->use_dbgrq
= 0;
68 if (target
->reset_halt
)
70 arm7_9
->use_dbgrq
= ud
;
71 return arm7_9_assert_reset(target
);
74 int feroceon_dummy_clock_out(struct arm_jtag
*jtag_info
, uint32_t instr
)
76 struct scan_field fields
[3];
79 uint8_t sysspeed_buf
= 0x0;
82 buf_set_u32(out_buf
, 0, 32, 0);
84 buf_set_u32(instr_buf
, 0, 32, flip_u32(instr
, 32));
86 jtag_set_end_state(TAP_DRPAUSE
);
87 arm_jtag_scann(jtag_info
, 0x1);
89 arm_jtag_set_instr(jtag_info
, jtag_info
->intest_instr
, NULL
);
91 fields
[0].tap
= jtag_info
->tap
;
92 fields
[0].num_bits
= 32;
93 fields
[0].out_value
= out_buf
;
94 fields
[0].in_value
= NULL
;
96 fields
[1].tap
= jtag_info
->tap
;
97 fields
[1].num_bits
= 3;
98 fields
[1].out_value
= &sysspeed_buf
;
99 fields
[1].in_value
= NULL
;
101 fields
[2].tap
= jtag_info
->tap
;
102 fields
[2].num_bits
= 32;
103 fields
[2].out_value
= instr_buf
;
104 fields
[2].in_value
= NULL
;
106 jtag_add_dr_scan(3, fields
, jtag_get_end_state());
108 /* no jtag_add_runtest(0, jtag_get_end_state()) here */
113 void feroceon_change_to_arm(struct target
*target
, uint32_t *r0
, uint32_t *pc
)
115 struct arm
*armv4_5
= target
->arch_info
;
116 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
117 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
120 * save r0 before using it and put system in ARM state
121 * to allow common handling of ARM and THUMB debugging
124 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
125 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
126 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
128 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
129 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 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, r0
, 0);
132 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
133 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
135 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_MOV(0, 15), 0, NULL
, 0);
136 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
137 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 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, pc
, 0);
140 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
141 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
143 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_BX(15), 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);
146 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
147 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
149 jtag_execute_queue();
152 * fix program counter:
153 * MOV R0, PC was the 7th instruction (+12)
154 * reading PC in Thumb state gives address of instruction + 4
159 void feroceon_read_core_regs(struct target
*target
, uint32_t mask
, uint32_t* core_regs
[16])
162 struct arm
*armv4_5
= target
->arch_info
;
163 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
164 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
166 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
167 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
168 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
170 for (i
= 0; i
<= 15; i
++)
172 arm9tdmi_clock_data_in(jtag_info
, core_regs
[i
]);
174 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
175 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
178 void feroceon_read_core_regs_target_buffer(struct target
*target
, 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 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 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 void feroceon_write_xpsr_im8(struct target
*target
, uint8_t xpsr_im
, int rot
, int spsr
)
281 struct arm
*armv4_5
= target
->arch_info
;
282 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
283 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
285 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im
, rot
, spsr
);
287 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr_im
, rot
, 1, spsr
), 0, NULL
, 0);
288 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
296 void feroceon_write_core_regs(struct target
*target
, uint32_t mask
, uint32_t core_regs
[16])
299 struct arm
*armv4_5
= target
->arch_info
;
300 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
301 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
303 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
304 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
305 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
307 for (i
= 0; i
<= 15; i
++)
309 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, core_regs
[i
], NULL
, 0);
311 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
312 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
313 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
316 void feroceon_branch_resume(struct target
*target
)
318 struct arm
*armv4_5
= target
->arch_info
;
319 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
320 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
322 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
323 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
324 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
325 arm9tdmi_clock_out(jtag_info
, ARMV4_5_B(0xfffff9, 0), 0, NULL
, 0);
326 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
328 arm7_9
->need_bypass_before_restart
= 1;
331 void feroceon_branch_resume_thumb(struct target
*target
)
335 struct arm
*armv4_5
= target
->arch_info
;
336 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
337 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
338 uint32_t r0
= buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
339 uint32_t pc
= buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
341 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
342 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
343 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
344 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
346 arm9tdmi_clock_out(jtag_info
, 0xE28F0001, 0, NULL
, 0); // add r0,pc,#1
347 arm9tdmi_clock_out(jtag_info
, ARMV4_5_BX(0), 0, NULL
, 0);
348 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
349 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
351 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL
, 0);
352 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
353 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
355 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, r0
, NULL
, 0);
356 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
357 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
360 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_B(0x7e9 + pc
), 0, NULL
, 0);
361 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 1);
363 arm7_9
->need_bypass_before_restart
= 1;
366 int feroceon_read_cp15(struct target
*target
, uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t *value
)
368 struct arm
*armv4_5
= target
->arch_info
;
369 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
370 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
373 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRC(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
374 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
375 err
= arm7_9_execute_sys_speed(target
);
379 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
380 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
381 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
382 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, value
, 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 return jtag_execute_queue();
388 int feroceon_write_cp15(struct target
*target
, uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t value
)
390 struct arm
*armv4_5
= target
->arch_info
;
391 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
392 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
394 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL
, 0);
395 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
396 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
397 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, value
, NULL
, 0);
398 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
402 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MCR(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
403 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
404 return arm7_9_execute_sys_speed(target
);
407 void feroceon_set_dbgrq(struct target
*target
)
409 struct arm
*armv4_5
= target
->arch_info
;
410 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
411 struct reg
*dbg_ctrl
= &arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
];
413 buf_set_u32(dbg_ctrl
->value
, 0, 8, 2);
414 embeddedice_store_reg(dbg_ctrl
);
417 void feroceon_enable_single_step(struct target
*target
, uint32_t next_pc
)
419 struct arm
*armv4_5
= target
->arch_info
;
420 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
422 /* set a breakpoint there */
423 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
], next_pc
);
424 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
], 0);
425 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
], 0xffffffff);
426 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
], 0x100);
427 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
], 0xf7);
430 void feroceon_disable_single_step(struct target
*target
)
432 struct arm
*armv4_5
= target
->arch_info
;
433 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
435 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
]);
436 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
]);
437 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
]);
438 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
]);
439 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
]);
442 int feroceon_examine_debug_reason(struct target
*target
)
444 /* the MOE is not implemented */
445 if (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)
447 target
->debug_reason
= DBG_REASON_DBGRQ
;
453 int feroceon_bulk_write_memory(struct target
*target
, uint32_t address
, uint32_t count
, uint8_t *buffer
)
456 struct arm
*armv4_5
= target
->arch_info
;
457 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
458 enum arm_state core_state
= armv4_5
->core_state
;
459 uint32_t x
, flip
, shift
, save
[7];
463 * We can't use the dcc flow control bits, so let's transfer data
464 * with 31 bits and flip the MSB each time a new data word is sent.
466 static uint32_t dcc_code
[] =
468 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
469 0xe3a0301e, /* 1: mov r3, #30 */
470 0xe3a04002, /* mov r4, #2 */
471 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
472 0xe1310005, /* teq r1, r5 */
473 0x0afffffc, /* beq 1b */
474 0xe1a05001, /* mov r5, r1 */
475 0xe1a01081, /* mov r1, r1, lsl #1 */
476 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
477 0xe1320005, /* teq r2, r5 */
478 0x0afffffc, /* beq 3b */
479 0xe1a05002, /* mov r5, r2 */
480 0xe3c22102, /* bic r2, r2, #0x80000000 */
481 0xe1811332, /* orr r1, r1, r2, lsr r3 */
482 0xe2533001, /* subs r3, r3, #1 */
483 0xe4801004, /* str r1, [r0], #4 */
484 0xe1a01412, /* mov r1, r2, lsl r4 */
485 0xe2844001, /* add r4, r4, #1 */
486 0x4affffed, /* bmi 1b */
487 0xeafffff3, /* b 3b */
490 uint32_t dcc_size
= sizeof(dcc_code
);
492 if (!arm7_9
->dcc_downloads
)
493 return target_write_memory(target
, address
, 4, count
, buffer
);
495 /* regrab previously allocated working_area, or allocate a new one */
496 if (!arm7_9
->dcc_working_area
)
498 uint8_t dcc_code_buf
[dcc_size
];
500 /* make sure we have a working area */
501 if (target_alloc_working_area(target
, dcc_size
, &arm7_9
->dcc_working_area
) != ERROR_OK
)
503 LOG_INFO("no working area available, falling back to memory writes");
504 return target_write_memory(target
, address
, 4, count
, buffer
);
507 /* copy target instructions to target endianness */
508 for (i
= 0; i
< dcc_size
/4; i
++)
509 target_buffer_set_u32(target
, dcc_code_buf
+ i
*4, dcc_code
[i
]);
511 /* write DCC code to working area */
512 if ((retval
= target_write_memory(target
, arm7_9
->dcc_working_area
->address
, 4, dcc_size
/4, dcc_code_buf
)) != ERROR_OK
)
518 /* backup clobbered processor state */
519 for (i
= 0; i
<= 5; i
++)
520 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32);
521 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
523 /* set up target address in r0 */
524 buf_set_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32, address
);
525 armv4_5
->core_cache
->reg_list
[0].valid
= 1;
526 armv4_5
->core_cache
->reg_list
[0].dirty
= 1;
527 armv4_5
->core_state
= ARM_STATE_ARM
;
529 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], 0);
530 arm7_9_resume(target
, 0, arm7_9
->dcc_working_area
->address
, 1, 1);
536 for (i
= 0; i
< count
; i
++)
538 uint32_t y
= target_buffer_get_u32(target
, buffer
);
539 uint32_t z
= (x
>> 1) | (y
>> shift
) | (flip
^= 0x80000000);
540 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
541 x
= y
<< (32 - shift
);
542 if (++shift
>= 32 || i
+ 1 >= count
)
544 z
= (x
>> 1) | (flip
^= 0x80000000);
545 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
552 retval
= target_halt(target
);
553 if (retval
== ERROR_OK
)
554 retval
= target_wait_state(target
, TARGET_HALTED
, 500);
555 if (retval
== ERROR_OK
) {
556 uint32_t endaddress
=
557 buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
558 if (endaddress
!= address
+ count
*4) {
559 LOG_ERROR("DCC write failed,"
560 " expected end address 0x%08" PRIx32
561 " got 0x%0" PRIx32
"",
562 address
+ count
*4, endaddress
);
567 /* restore target state */
568 for (i
= 0; i
<= 5; i
++)
570 buf_set_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32, save
[i
]);
571 armv4_5
->core_cache
->reg_list
[i
].valid
= 1;
572 armv4_5
->core_cache
->reg_list
[i
].dirty
= 1;
574 buf_set_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32, save
[i
]);
575 armv4_5
->core_cache
->reg_list
[15].valid
= 1;
576 armv4_5
->core_cache
->reg_list
[15].dirty
= 1;
577 armv4_5
->core_state
= core_state
;
582 int feroceon_init_target(struct command_context
*cmd_ctx
, struct target
*target
)
584 arm9tdmi_init_target(cmd_ctx
, target
);
588 void feroceon_common_setup(struct target
*target
)
590 struct arm
*armv4_5
= target
->arch_info
;
591 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
593 /* override some insn sequence functions */
594 arm7_9
->change_to_arm
= feroceon_change_to_arm
;
595 arm7_9
->read_core_regs
= feroceon_read_core_regs
;
596 arm7_9
->read_core_regs_target_buffer
= feroceon_read_core_regs_target_buffer
;
597 arm7_9
->read_xpsr
= feroceon_read_xpsr
;
598 arm7_9
->write_xpsr
= feroceon_write_xpsr
;
599 arm7_9
->write_xpsr_im8
= feroceon_write_xpsr_im8
;
600 arm7_9
->write_core_regs
= feroceon_write_core_regs
;
601 arm7_9
->branch_resume
= feroceon_branch_resume
;
602 arm7_9
->branch_resume_thumb
= feroceon_branch_resume_thumb
;
604 /* must be implemented with only one comparator */
605 arm7_9
->enable_single_step
= feroceon_enable_single_step
;
606 arm7_9
->disable_single_step
= feroceon_disable_single_step
;
608 /* MOE is not implemented */
609 arm7_9
->examine_debug_reason
= feroceon_examine_debug_reason
;
611 /* Note: asserting DBGRQ might not win over the undef exception.
612 If that happens then just use "arm7_9 dbgrq disable". */
613 arm7_9
->use_dbgrq
= 1;
614 arm7_9
->set_special_dbgrq
= feroceon_set_dbgrq
;
616 /* only one working comparator */
617 arm7_9
->wp_available_max
= 1;
618 arm7_9
->wp1_used_default
= -1;
621 int feroceon_target_create(struct target
*target
, Jim_Interp
*interp
)
623 struct arm926ejs_common
*arm926ejs
= calloc(1,sizeof(struct arm926ejs_common
));
625 arm926ejs_init_arch_info(target
, arm926ejs
, target
->tap
);
626 feroceon_common_setup(target
);
628 /* the standard ARM926 methods don't always work (don't ask...) */
629 arm926ejs
->read_cp15
= feroceon_read_cp15
;
630 arm926ejs
->write_cp15
= feroceon_write_cp15
;
635 int dragonite_target_create(struct target
*target
, Jim_Interp
*interp
)
637 struct arm966e_common
*arm966e
= calloc(1,sizeof(struct arm966e_common
));
639 arm966e_init_arch_info(target
, arm966e
, target
->tap
);
640 feroceon_common_setup(target
);
645 int feroceon_examine(struct target
*target
)
648 struct arm7_9_common
*arm7_9
;
651 retval
= arm7_9_examine(target
);
652 if (retval
!= ERROR_OK
)
655 armv4_5
= target
->arch_info
;
656 arm7_9
= armv4_5
->arch_info
;
658 /* the COMMS_CTRL bits are all contiguous */
659 if (buf_get_u32(arm7_9
->eice_cache
->reg_list
[EICE_COMMS_CTRL
].value
, 2, 4) != 6)
660 LOG_ERROR("unexpected Feroceon EICE version signature");
662 arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].size
= 6;
663 arm7_9
->eice_cache
->reg_list
[EICE_DBG_STAT
].size
= 5;
664 arm7_9
->has_monitor_mode
= 1;
666 /* vector catch reg is not initialized on reset */
667 embeddedice_set_reg(&arm7_9
->eice_cache
->reg_list
[EICE_VEC_CATCH
], 0);
669 /* clear monitor mode, enable comparators */
670 embeddedice_read_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
671 jtag_execute_queue();
672 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 4, 1, 0);
673 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 5, 1, 0);
674 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
679 struct target_type feroceon_target
=
684 .arch_state
= arm926ejs_arch_state
,
686 .target_request_data
= arm7_9_target_request_data
,
689 .resume
= arm7_9_resume
,
692 .assert_reset
= feroceon_assert_reset
,
693 .deassert_reset
= arm7_9_deassert_reset
,
694 .soft_reset_halt
= arm926ejs_soft_reset_halt
,
696 .get_gdb_reg_list
= armv4_5_get_gdb_reg_list
,
698 .read_memory
= arm7_9_read_memory
,
699 .write_memory
= arm926ejs_write_memory
,
700 .bulk_write_memory
= feroceon_bulk_write_memory
,
702 .checksum_memory
= arm_checksum_memory
,
703 .blank_check_memory
= arm_blank_check_memory
,
705 .run_algorithm
= armv4_5_run_algorithm
,
707 .add_breakpoint
= arm7_9_add_breakpoint
,
708 .remove_breakpoint
= arm7_9_remove_breakpoint
,
709 .add_watchpoint
= arm7_9_add_watchpoint
,
710 .remove_watchpoint
= arm7_9_remove_watchpoint
,
712 .commands
= arm926ejs_command_handlers
,
713 .target_create
= feroceon_target_create
,
714 .init_target
= feroceon_init_target
,
715 .examine
= feroceon_examine
,
718 struct target_type dragonite_target
=
723 .arch_state
= armv4_5_arch_state
,
725 .target_request_data
= arm7_9_target_request_data
,
728 .resume
= arm7_9_resume
,
731 .assert_reset
= feroceon_assert_reset
,
732 .deassert_reset
= arm7_9_deassert_reset
,
733 .soft_reset_halt
= arm7_9_soft_reset_halt
,
735 .get_gdb_reg_list
= armv4_5_get_gdb_reg_list
,
737 .read_memory
= arm7_9_read_memory
,
738 .write_memory
= arm7_9_write_memory
,
739 .bulk_write_memory
= feroceon_bulk_write_memory
,
741 .checksum_memory
= arm_checksum_memory
,
742 .blank_check_memory
= arm_blank_check_memory
,
744 .run_algorithm
= armv4_5_run_algorithm
,
746 .add_breakpoint
= arm7_9_add_breakpoint
,
747 .remove_breakpoint
= arm7_9_remove_breakpoint
,
748 .add_watchpoint
= arm7_9_add_watchpoint
,
749 .remove_watchpoint
= arm7_9_remove_watchpoint
,
751 .commands
= arm966e_command_handlers
,
752 .target_create
= dragonite_target_create
,
753 .init_target
= feroceon_init_target
,
754 .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)