jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / target / feroceon.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2008-2009 by Marvell Semiconductors, Inc. *
5 * Written by Nicolas Pitre <nico@marvell.com> *
6 * *
7 * Copyright (C) 2008 by Hongtao Zheng *
8 * hontor@126.com *
9 ***************************************************************************/
10
11 /*
12 * Marvell Feroceon/Dragonite support.
13 *
14 * The Feroceon core, as found in the Orion and Kirkwood SoCs amongst others,
15 * mimics the ARM926 ICE interface with the following differences:
16 *
17 * - the MOE (method of entry) reporting is not implemented
18 *
19 * - breakpoint/watchpoint comparator #1 is seemingly not implemented
20 *
21 * - due to a different pipeline implementation, some injected debug
22 * instruction sequences have to be somewhat different
23 *
24 * Other issues:
25 *
26 * - asserting DBGRQ doesn't work if target is looping on the undef vector
27 *
28 * - the EICE version signature in the COMMS_CTL reg is next to the flow bits
29 * not at the top, and rather meaningless due to existing discrepancies
30 *
31 * - the DCC channel is half duplex (only one FIFO for both directions) with
32 * seemingly no proper flow control.
33 *
34 * The Dragonite core is the non-mmu version based on the ARM966 model, and
35 * it shares the above issues as well.
36 */
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #include "arm926ejs.h"
43 #include "arm966e.h"
44 #include "target_type.h"
45 #include "register.h"
46 #include "arm_opcodes.h"
47
48 static int feroceon_assert_reset(struct target *target)
49 {
50 struct arm *arm = target->arch_info;
51 struct arm7_9_common *arm7_9 = arm->arch_info;
52 int ud = arm7_9->use_dbgrq;
53
54 /* TODO: apply hw reset signal in not examined state */
55 if (!(target_was_examined(target))) {
56 LOG_WARNING("Reset is not asserted because the target is not examined.");
57 LOG_WARNING("Use a reset button or power cycle the target.");
58 return ERROR_TARGET_NOT_EXAMINED;
59 }
60
61 arm7_9->use_dbgrq = 0;
62 if (target->reset_halt)
63 arm7_9_halt(target);
64 arm7_9->use_dbgrq = ud;
65 return arm7_9_assert_reset(target);
66 }
67
68 static int feroceon_dummy_clock_out(struct arm_jtag *jtag_info, uint32_t instr)
69 {
70 struct scan_field fields[3];
71 uint8_t out_buf[4];
72 uint8_t instr_buf[4];
73 uint8_t sysspeed_buf = 0x0;
74 int retval;
75
76 /* prepare buffer */
77 buf_set_u32(out_buf, 0, 32, 0);
78
79 buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
80
81 retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
82 if (retval != ERROR_OK)
83 return retval;
84
85 retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
86 if (retval != ERROR_OK)
87 return retval;
88
89 fields[0].num_bits = 32;
90 fields[0].out_value = out_buf;
91 fields[0].in_value = NULL;
92
93 fields[1].num_bits = 3;
94 fields[1].out_value = &sysspeed_buf;
95 fields[1].in_value = NULL;
96
97 fields[2].num_bits = 32;
98 fields[2].out_value = instr_buf;
99 fields[2].in_value = NULL;
100
101 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
102
103 /* no jtag_add_runtest(0, TAP_DRPAUSE) here */
104
105 return ERROR_OK;
106 }
107
108 static void feroceon_change_to_arm(struct target *target, uint32_t *r0,
109 uint32_t *pc)
110 {
111 struct arm *arm = target->arch_info;
112 struct arm7_9_common *arm7_9 = arm->arch_info;
113 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
114
115 /*
116 * save r0 before using it and put system in ARM state
117 * to allow common handling of ARM and THUMB debugging
118 */
119
120 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
121 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
122 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
123
124 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
125 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
126 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
127 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 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, NULL, 0);
130
131 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
132 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
133 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
134 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
135 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 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, NULL, 0);
138
139 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(15), 0, NULL, 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);
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
145 jtag_execute_queue();
146
147 /*
148 * fix program counter:
149 * MOV R0, PC was the 7th instruction (+12)
150 * reading PC in Thumb state gives address of instruction + 4
151 */
152 *pc -= (12 + 4);
153 }
154
155 static void feroceon_read_core_regs(struct target *target,
156 uint32_t mask, uint32_t *core_regs[16])
157 {
158 int i;
159 struct arm *arm = target->arch_info;
160 struct arm7_9_common *arm7_9 = arm->arch_info;
161 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
162
163 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
164 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
165 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
166
167 for (i = 0; i <= 15; i++)
168 if (mask & (1 << i))
169 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
170
171 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
172 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
173 }
174
175 static void feroceon_read_core_regs_target_buffer(struct target *target,
176 uint32_t mask, void *buffer, int size)
177 {
178 int i;
179 struct arm *arm = target->arch_info;
180 struct arm7_9_common *arm7_9 = arm->arch_info;
181 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
182 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
183 uint32_t *buf_u32 = buffer;
184 uint16_t *buf_u16 = buffer;
185 uint8_t *buf_u8 = buffer;
186
187 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
188 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
189 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
190
191 for (i = 0; i <= 15; i++) {
192 if (mask & (1 << i)) {
193 switch (size) {
194 case 4:
195 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
196 break;
197 case 2:
198 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
199 break;
200 case 1:
201 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
202 break;
203 }
204 }
205 }
206
207 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
208 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
209 }
210
211 static void feroceon_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
212 {
213 struct arm *arm = target->arch_info;
214 struct arm7_9_common *arm7_9 = arm->arch_info;
215 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
216
217 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
218 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
219 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
220 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
221 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 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
225 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 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);
228 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
229
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 }
233
234 static void feroceon_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
235 {
236 struct arm *arm = target->arch_info;
237 struct arm7_9_common *arm7_9 = arm->arch_info;
238 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
239
240 LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
241
242 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
243 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
244 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
245 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
246 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 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
250 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 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);
253 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
254 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 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
258 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 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);
261 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
262 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 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
266 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 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);
269 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
270 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 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 }
274
275 static void feroceon_write_xpsr_im8(struct target *target,
276 uint8_t xpsr_im, int rot, int spsr)
277 {
278 struct arm *arm = target->arch_info;
279 struct arm7_9_common *arm7_9 = arm->arch_info;
280 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
281
282 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
283
284 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
285 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
286 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
287 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 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 }
292
293 static void feroceon_write_core_regs(struct target *target,
294 uint32_t mask, uint32_t core_regs[16])
295 {
296 int i;
297 struct arm *arm = target->arch_info;
298 struct arm7_9_common *arm7_9 = arm->arch_info;
299 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
300
301 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
302 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
303 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
304
305 for (i = 0; i <= 15; i++)
306 if (mask & (1 << i))
307 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
308
309 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
310 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
311 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
312 }
313
314 static void feroceon_branch_resume(struct target *target)
315 {
316 struct arm *arm = target->arch_info;
317 struct arm7_9_common *arm7_9 = arm->arch_info;
318 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
319
320 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
321 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
322 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
323 arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffff9, 0), 0, NULL, 0);
324 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
325
326 arm7_9->need_bypass_before_restart = 1;
327 }
328
329 static void feroceon_branch_resume_thumb(struct target *target)
330 {
331 LOG_DEBUG("-");
332
333 struct arm *arm = target->arch_info;
334 struct arm7_9_common *arm7_9 = arm->arch_info;
335 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
336 uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32);
337 uint32_t pc = buf_get_u32(arm->pc->value, 0, 32);
338
339 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
340 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
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
344 arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); /* add r0,pc,#1 */
345 arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
346 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
347 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
348
349 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL, 0);
350 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
351 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
352
353 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, r0, 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);
356
357 pc = (pc & 2) >> 1;
358 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7e9 + pc), 0, NULL, 0);
359 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 1);
360
361 arm7_9->need_bypass_before_restart = 1;
362 }
363
364 static int feroceon_read_cp15(struct target *target, uint32_t op1,
365 uint32_t op2, uint32_t crn, uint32_t crm, uint32_t *value)
366 {
367 struct arm *arm = target->arch_info;
368 struct arm7_9_common *arm7_9 = arm->arch_info;
369 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
370 int err;
371
372 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRC(15, op1, 0, crn, crm, op2), 0, NULL, 0);
373 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
374 err = arm7_9_execute_sys_speed(target);
375 if (err != ERROR_OK)
376 return err;
377
378 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
379 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 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, value, 0);
382 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
383 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
384 return jtag_execute_queue();
385 }
386
387 static int feroceon_write_cp15(struct target *target, uint32_t op1,
388 uint32_t op2, uint32_t crn, uint32_t crm, uint32_t value)
389 {
390 struct arm *arm = target->arch_info;
391 struct arm7_9_common *arm7_9 = arm->arch_info;
392 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
393
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);
401
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);
405 }
406
407 static void feroceon_set_dbgrq(struct target *target)
408 {
409 struct arm *arm = target->arch_info;
410 struct arm7_9_common *arm7_9 = arm->arch_info;
411 struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
412
413 buf_set_u32(dbg_ctrl->value, 0, 8, 2);
414 embeddedice_store_reg(dbg_ctrl);
415 }
416
417 static void feroceon_enable_single_step(struct target *target, uint32_t next_pc)
418 {
419 struct arm *arm = target->arch_info;
420 struct arm7_9_common *arm7_9 = arm->arch_info;
421
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);
428 }
429
430 static void feroceon_disable_single_step(struct target *target)
431 {
432 struct arm *arm = target->arch_info;
433 struct arm7_9_common *arm7_9 = arm->arch_info;
434
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]);
440 }
441
442 static int feroceon_examine_debug_reason(struct target *target)
443 {
444 /* the MOE is not implemented */
445 if (target->debug_reason != DBG_REASON_SINGLESTEP)
446 target->debug_reason = DBG_REASON_DBGRQ;
447
448 return ERROR_OK;
449 }
450
451 static int feroceon_bulk_write_memory(struct target *target,
452 target_addr_t address, uint32_t count, const uint8_t *buffer)
453 {
454 int retval;
455 struct arm *arm = target->arch_info;
456 struct arm7_9_common *arm7_9 = arm->arch_info;
457 enum arm_state core_state = arm->core_state;
458 uint32_t x, flip, shift, save[7];
459 uint32_t i;
460
461 /*
462 * We can't use the dcc flow control bits, so let's transfer data
463 * with 31 bits and flip the MSB each time a new data word is sent.
464 */
465 static uint32_t dcc_code[] = {
466 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
467 0xe3a0301e, /* 1: mov r3, #30 */
468 0xe3a04002, /* mov r4, #2 */
469 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
470 0xe1310005, /* teq r1, r5 */
471 0x0afffffc, /* beq 1b */
472 0xe1a05001, /* mov r5, r1 */
473 0xe1a01081, /* mov r1, r1, lsl #1 */
474 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
475 0xe1320005, /* teq r2, r5 */
476 0x0afffffc, /* beq 3b */
477 0xe1a05002, /* mov r5, r2 */
478 0xe3c22102, /* bic r2, r2, #0x80000000 */
479 0xe1811332, /* orr r1, r1, r2, lsr r3 */
480 0xe2533001, /* subs r3, r3, #1 */
481 0xe4801004, /* str r1, [r0], #4 */
482 0xe1a01412, /* mov r1, r2, lsl r4 */
483 0xe2844001, /* add r4, r4, #1 */
484 0x4affffed, /* bmi 1b */
485 0xeafffff3, /* b 3b */
486 };
487
488 uint32_t dcc_size = sizeof(dcc_code);
489
490 if (address % 4 != 0)
491 return ERROR_TARGET_UNALIGNED_ACCESS;
492
493 if (!arm7_9->dcc_downloads)
494 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
495
496 /* regrab previously allocated working_area, or allocate a new one */
497 if (!arm7_9->dcc_working_area) {
498 uint8_t dcc_code_buf[dcc_size];
499
500 /* make sure we have a working area */
501 if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK) {
502 LOG_INFO("no working area available, falling back to memory writes");
503 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
504 }
505
506 /* copy target instructions to target endianness */
507 target_buffer_set_u32_array(target, dcc_code_buf, ARRAY_SIZE(dcc_code), dcc_code);
508
509 /* write DCC code to working area, using the non-optimized
510 * memory write to avoid ending up here again */
511 retval = arm7_9_write_memory_no_opt(target,
512 arm7_9->dcc_working_area->address, 4, dcc_size/4, dcc_code_buf);
513 if (retval != ERROR_OK)
514 return retval;
515 }
516
517 /* backup clobbered processor state */
518 for (i = 0; i <= 5; i++)
519 save[i] = buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32);
520 save[i] = buf_get_u32(arm->pc->value, 0, 32);
521
522 /* set up target address in r0 */
523 buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, address);
524 arm->core_cache->reg_list[0].valid = true;
525 arm->core_cache->reg_list[0].dirty = true;
526 arm->core_state = ARM_STATE_ARM;
527
528 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0);
529 arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1);
530
531 /* send data over */
532 x = 0;
533 flip = 0;
534 shift = 1;
535 for (i = 0; i < count; i++) {
536 uint32_t y = target_buffer_get_u32(target, buffer);
537 uint32_t z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000);
538 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
539 x = y << (32 - shift);
540 if (++shift >= 32 || i + 1 >= count) {
541 z = (x >> 1) | (flip ^= 0x80000000);
542 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
543 x = 0;
544 shift = 1;
545 }
546 buffer += 4;
547 }
548
549 retval = target_halt(target);
550 if (retval == ERROR_OK)
551 retval = target_wait_state(target, TARGET_HALTED, 500);
552 if (retval == ERROR_OK) {
553 uint32_t endaddress =
554 buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32);
555 if (endaddress != address + count*4) {
556 LOG_ERROR("DCC write failed,"
557 " expected end address 0x%08" TARGET_PRIxADDR
558 " got 0x%0" PRIx32 "",
559 address + count*4, endaddress);
560 retval = ERROR_FAIL;
561 }
562 }
563
564 /* restore target state */
565 for (i = 0; i <= 5; i++) {
566 buf_set_u32(arm->core_cache->reg_list[i].value, 0, 32, save[i]);
567 arm->core_cache->reg_list[i].valid = true;
568 arm->core_cache->reg_list[i].dirty = true;
569 }
570 buf_set_u32(arm->pc->value, 0, 32, save[i]);
571 arm->pc->valid = true;
572 arm->pc->dirty = true;
573 arm->core_state = core_state;
574
575 return retval;
576 }
577
578 static int feroceon_init_target(struct command_context *cmd_ctx,
579 struct target *target)
580 {
581 arm9tdmi_init_target(cmd_ctx, target);
582 return ERROR_OK;
583 }
584
585 static void feroceon_deinit_target(struct target *target)
586 {
587 arm9tdmi_deinit_target(target);
588 }
589
590 static void feroceon_common_setup(struct target *target)
591 {
592 struct arm *arm = target->arch_info;
593 struct arm7_9_common *arm7_9 = arm->arch_info;
594
595 /* override some insn sequence functions */
596 arm7_9->change_to_arm = feroceon_change_to_arm;
597 arm7_9->read_core_regs = feroceon_read_core_regs;
598 arm7_9->read_core_regs_target_buffer = feroceon_read_core_regs_target_buffer;
599 arm7_9->read_xpsr = feroceon_read_xpsr;
600 arm7_9->write_xpsr = feroceon_write_xpsr;
601 arm7_9->write_xpsr_im8 = feroceon_write_xpsr_im8;
602 arm7_9->write_core_regs = feroceon_write_core_regs;
603 arm7_9->branch_resume = feroceon_branch_resume;
604 arm7_9->branch_resume_thumb = feroceon_branch_resume_thumb;
605
606 /* must be implemented with only one comparator */
607 arm7_9->enable_single_step = feroceon_enable_single_step;
608 arm7_9->disable_single_step = feroceon_disable_single_step;
609
610 arm7_9->bulk_write_memory = feroceon_bulk_write_memory;
611
612 /* MOE is not implemented */
613 arm7_9->examine_debug_reason = feroceon_examine_debug_reason;
614
615 /* Note: asserting DBGRQ might not win over the undef exception.
616 If that happens then just use "arm7_9 dbgrq disable". */
617 arm7_9->use_dbgrq = 1;
618 arm7_9->set_special_dbgrq = feroceon_set_dbgrq;
619
620 /* only one working comparator */
621 arm7_9->wp_available_max = 1;
622 arm7_9->wp1_used_default = -1;
623 }
624
625 static int feroceon_target_create(struct target *target, Jim_Interp *interp)
626 {
627 struct arm926ejs_common *arm926ejs = calloc(1, sizeof(struct arm926ejs_common));
628
629 arm926ejs_init_arch_info(target, arm926ejs, target->tap);
630 feroceon_common_setup(target);
631
632 struct arm *arm = target->arch_info;
633 struct arm7_9_common *arm7_9 = arm->arch_info;
634 arm7_9->write_memory = arm926ejs_write_memory;
635
636 /* the standard ARM926 methods don't always work (don't ask...) */
637 arm926ejs->read_cp15 = feroceon_read_cp15;
638 arm926ejs->write_cp15 = feroceon_write_cp15;
639
640 return ERROR_OK;
641 }
642
643 static int dragonite_target_create(struct target *target, Jim_Interp *interp)
644 {
645 struct arm966e_common *arm966e = calloc(1, sizeof(struct arm966e_common));
646
647 arm966e_init_arch_info(target, arm966e, target->tap);
648 feroceon_common_setup(target);
649
650 struct arm *arm = target->arch_info;
651 struct arm7_9_common *arm7_9 = arm->arch_info;
652 arm7_9->write_memory = arm7_9_write_memory;
653
654 return ERROR_OK;
655 }
656
657 static int feroceon_examine(struct target *target)
658 {
659 struct arm *arm;
660 struct arm7_9_common *arm7_9;
661 int retval;
662
663 retval = arm7_9_examine(target);
664 if (retval != ERROR_OK)
665 return retval;
666
667 arm = target->arch_info;
668 arm7_9 = arm->arch_info;
669
670 /* the COMMS_CTRL bits are all contiguous */
671 if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6)
672 LOG_ERROR("unexpected Feroceon EICE version signature");
673
674 arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6;
675 arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5;
676 arm7_9->has_monitor_mode = 1;
677
678 /* vector catch reg is not initialized on reset */
679 embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0);
680
681 /* clear monitor mode, enable comparators */
682 embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
683 jtag_execute_queue();
684 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
685 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0);
686 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
687
688 return ERROR_OK;
689 }
690
691 struct target_type feroceon_target = {
692 .name = "feroceon",
693
694 .poll = arm7_9_poll,
695 .arch_state = arm926ejs_arch_state,
696
697 .target_request_data = arm7_9_target_request_data,
698
699 .halt = arm7_9_halt,
700 .resume = arm7_9_resume,
701 .step = arm7_9_step,
702
703 .assert_reset = feroceon_assert_reset,
704 .deassert_reset = arm7_9_deassert_reset,
705 .soft_reset_halt = arm926ejs_soft_reset_halt,
706
707 .get_gdb_arch = arm_get_gdb_arch,
708 .get_gdb_reg_list = arm_get_gdb_reg_list,
709
710 .read_memory = arm7_9_read_memory,
711 .write_memory = arm7_9_write_memory_opt,
712
713 .checksum_memory = arm_checksum_memory,
714 .blank_check_memory = arm_blank_check_memory,
715
716 .run_algorithm = armv4_5_run_algorithm,
717
718 .add_breakpoint = arm7_9_add_breakpoint,
719 .remove_breakpoint = arm7_9_remove_breakpoint,
720 .add_watchpoint = arm7_9_add_watchpoint,
721 .remove_watchpoint = arm7_9_remove_watchpoint,
722
723 .commands = arm926ejs_command_handlers,
724 .target_create = feroceon_target_create,
725 .init_target = feroceon_init_target,
726 .deinit_target = feroceon_deinit_target,
727 .examine = feroceon_examine,
728 };
729
730 struct target_type dragonite_target = {
731 .name = "dragonite",
732
733 .poll = arm7_9_poll,
734 .arch_state = arm_arch_state,
735
736 .target_request_data = arm7_9_target_request_data,
737
738 .halt = arm7_9_halt,
739 .resume = arm7_9_resume,
740 .step = arm7_9_step,
741
742 .assert_reset = feroceon_assert_reset,
743 .deassert_reset = arm7_9_deassert_reset,
744 .soft_reset_halt = arm7_9_soft_reset_halt,
745
746 .get_gdb_arch = arm_get_gdb_arch,
747 .get_gdb_reg_list = arm_get_gdb_reg_list,
748
749 .read_memory = arm7_9_read_memory,
750 .write_memory = arm7_9_write_memory_opt,
751
752 .checksum_memory = arm_checksum_memory,
753 .blank_check_memory = arm_blank_check_memory,
754
755 .run_algorithm = armv4_5_run_algorithm,
756
757 .add_breakpoint = arm7_9_add_breakpoint,
758 .remove_breakpoint = arm7_9_remove_breakpoint,
759 .add_watchpoint = arm7_9_add_watchpoint,
760 .remove_watchpoint = arm7_9_remove_watchpoint,
761
762 .commands = arm966e_command_handlers,
763 .target_create = dragonite_target_create,
764 .init_target = feroceon_init_target,
765 .examine = feroceon_examine,
766 };

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)