Add FTDI SWD driver
[openocd.git] / src / target / fa526.c
1 /***************************************************************************
2 * Copyright (C) 2009 by Paulius Zaleckas *
3 * paulius.zaleckas@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
19 ***************************************************************************/
20
21 /*
22 * FA526 is very similar to ARM920T with following differences:
23 *
24 * - execution pipeline is 6 steps
25 * - Unified TLB
26 * - has Branch Target Buffer
27 * - does not support reading of I/D cache contents
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "arm920t.h"
35 #include "target_type.h"
36 #include "arm_opcodes.h"
37
38 static void fa526_change_to_arm(struct target *target, uint32_t *r0, uint32_t *pc)
39 {
40 LOG_ERROR("%s: there is no Thumb state on FA526", __func__);
41 }
42
43 static void fa526_read_core_regs(struct target *target,
44 uint32_t mask, uint32_t *core_regs[16])
45 {
46 int i;
47 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
48 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
49
50 /* STMIA r0-15, [r0] at debug speed
51 * register values will start to appear on 4th DCLK
52 */
53 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
54
55 /* fetch NOP, STM in DECODE stage */
56 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
57 /* fetch NOP, STM in SHIFT stage */
58 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
59 /* fetch NOP, STM in EXECUTE stage (1st cycle) */
60 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
61
62 for (i = 0; i <= 15; i++) {
63 if (mask & (1 << i))
64 /* nothing fetched, STM in MEMORY (i'th cycle) */
65 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
66 }
67 }
68
69 static void fa526_read_core_regs_target_buffer(struct target *target,
70 uint32_t mask, void *buffer, int size)
71 {
72 int i;
73 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
74 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
75 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
76 uint32_t *buf_u32 = buffer;
77 uint16_t *buf_u16 = buffer;
78 uint8_t *buf_u8 = buffer;
79
80 /* STMIA r0-15, [r0] at debug speed
81 * register values will start to appear on 4th DCLK
82 */
83 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
84
85 /* fetch NOP, STM in DECODE stage */
86 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
87 /* fetch NOP, STM in SHIFT stage */
88 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
89 /* fetch NOP, STM in EXECUTE stage (1st cycle) */
90 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
91
92 for (i = 0; i <= 15; i++) {
93 if (mask & (1 << i))
94 /* nothing fetched, STM in MEMORY (i'th cycle) */
95 switch (size) {
96 case 4:
97 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
98 break;
99 case 2:
100 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
101 break;
102 case 1:
103 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
104 break;
105 }
106 }
107 }
108
109 static void fa526_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
110 {
111 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
112 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
113
114 /* MRS r0, cpsr */
115 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
116 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
117 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
118 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
119 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
120 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
121
122 /* STR r0, [r15] */
123 arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);
124 /* fetch NOP, STR in DECODE stage */
125 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
126 /* fetch NOP, STR in SHIFT stage */
127 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
128 /* fetch NOP, STR in EXECUTE stage (1st cycle) */
129 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
130 /* nothing fetched, STR in MEMORY */
131 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
132 }
133
134 static void fa526_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
135 {
136 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
137 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
138
139 LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
140
141 /* MSR1 fetched */
142 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
143 /* MSR2 fetched, MSR1 in DECODE */
144 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
145 /* MSR3 fetched, MSR1 in SHIFT, MSR2 in DECODE */
146 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
147 /* MSR4 fetched, MSR1 in EXECUTE (1), MSR2 in SHIFT, MSR3 in DECODE */
148 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
149 /* nothing fetched, MSR1 in EXECUTE (2) */
150 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
151 /* nothing fetched, MSR1 in EXECUTE (3) */
152 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
153 /* nothing fetched, MSR2 in EXECUTE (1), MSR3 in SHIFT, MSR4 in DECODE */
154 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
155 /* nothing fetched, MSR2 in EXECUTE (2) */
156 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
157 /* nothing fetched, MSR2 in EXECUTE (3) */
158 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
159 /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in SHIFT */
160 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
161 /* nothing fetched, MSR3 in EXECUTE (2) */
162 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
163 /* nothing fetched, MSR3 in EXECUTE (3) */
164 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
165 /* NOP fetched, MSR4 in EXECUTE (1) */
166 /* last MSR writes flags, which takes only one cycle */
167 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
168 }
169
170 static void fa526_write_xpsr_im8(struct target *target,
171 uint8_t xpsr_im, int rot, int spsr)
172 {
173 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
174 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
175
176 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
177
178 /* MSR fetched */
179 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
180 /* NOP fetched, MSR in DECODE */
181 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
182 /* NOP fetched, MSR in SHIFT */
183 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
184 /* NOP fetched, MSR in EXECUTE (1) */
185 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
186
187 /* rot == 4 writes flags, which takes only one cycle */
188 if (rot != 4) {
189 /* nothing fetched, MSR in EXECUTE (2) */
190 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
191 /* nothing fetched, MSR in EXECUTE (3) */
192 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
193 }
194 }
195
196 static void fa526_write_core_regs(struct target *target,
197 uint32_t mask, uint32_t core_regs[16])
198 {
199 int i;
200 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
201 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
202
203 /* LDMIA r0-15, [r0] at debug speed
204 * register values will start to appear on 4th DCLK
205 */
206 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
207
208 /* fetch NOP, LDM in DECODE stage */
209 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
210 /* fetch NOP, LDM in SHIFT stage */
211 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
212 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
213 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
214
215 for (i = 0; i <= 15; i++) {
216 if (mask & (1 << i))
217 /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
218 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
219 }
220 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
221 }
222
223 static void fa526_write_pc(struct target *target, uint32_t pc)
224 {
225 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
226 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
227
228 /* LDMIA r0-15, [r0] at debug speed
229 * register values will start to appear on 4th DCLK
230 */
231 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);
232
233 /* fetch NOP, LDM in DECODE stage */
234 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
235 /* fetch NOP, LDM in SHIFT stage */
236 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
237 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
238 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
239 /* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */
240 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);
241 /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
242 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
243 /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
244 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
245 /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
246 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
247 }
248
249 static void fa526_branch_resume_thumb(struct target *target)
250 {
251 LOG_ERROR("%s: there is no Thumb state on FA526", __func__);
252 }
253
254 static int fa526_init_arch_info_2(struct target *target,
255 struct arm7_9_common *arm7_9, struct jtag_tap *tap)
256 {
257 /* prepare JTAG information for the new target */
258 arm7_9->jtag_info.tap = tap;
259 arm7_9->jtag_info.scann_size = 5;
260
261 /* register arch-specific functions */
262 arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;
263 arm7_9->change_to_arm = fa526_change_to_arm;
264 arm7_9->read_core_regs = fa526_read_core_regs;
265 arm7_9->read_core_regs_target_buffer = fa526_read_core_regs_target_buffer;
266 arm7_9->read_xpsr = fa526_read_xpsr;
267
268 arm7_9->write_xpsr = fa526_write_xpsr;
269 arm7_9->write_xpsr_im8 = fa526_write_xpsr_im8;
270 arm7_9->write_core_regs = fa526_write_core_regs;
271
272 arm7_9->load_word_regs = arm9tdmi_load_word_regs;
273 arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;
274 arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;
275
276 arm7_9->store_word_regs = arm9tdmi_store_word_regs;
277 arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;
278 arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;
279
280 arm7_9->write_pc = fa526_write_pc;
281 arm7_9->branch_resume = arm9tdmi_branch_resume;
282 arm7_9->branch_resume_thumb = fa526_branch_resume_thumb;
283
284 arm7_9->enable_single_step = arm9tdmi_enable_single_step;
285 arm7_9->disable_single_step = arm9tdmi_disable_single_step;
286
287 arm7_9->write_memory = arm920t_write_memory;
288 arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
289
290 arm7_9->post_debug_entry = NULL;
291
292 arm7_9->pre_restore_context = NULL;
293
294 /* initialize arch-specific breakpoint handling */
295 arm7_9->arm_bkpt = 0xdeeedeee;
296 arm7_9->thumb_bkpt = 0xdeee;
297
298 arm7_9->dbgreq_adjust_pc = 3;
299
300 arm7_9_init_arch_info(target, arm7_9);
301
302 /* override use of DBGRQ, this is safe on ARM9TDMI */
303 arm7_9->use_dbgrq = 1;
304
305 /* all ARM9s have the vector catch register */
306 arm7_9->has_vector_catch = 1;
307
308 return ERROR_OK;
309 }
310
311 static int fa526_init_arch_info(struct target *target,
312 struct arm920t_common *arm920t, struct jtag_tap *tap)
313 {
314 struct arm7_9_common *arm7_9 = &arm920t->arm7_9_common;
315
316 /* initialize arm7/arm9 specific info (including armv4_5) */
317 fa526_init_arch_info_2(target, arm7_9, tap);
318
319 arm920t->common_magic = ARM920T_COMMON_MAGIC;
320
321 arm7_9->post_debug_entry = arm920t_post_debug_entry;
322 arm7_9->pre_restore_context = arm920t_pre_restore_context;
323
324 arm920t->armv4_5_mmu.armv4_5_cache.ctype = -1;
325 arm920t->armv4_5_mmu.get_ttb = arm920t_get_ttb;
326 arm920t->armv4_5_mmu.read_memory = arm7_9_read_memory;
327 arm920t->armv4_5_mmu.write_memory = arm7_9_write_memory;
328 arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches;
329 arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches;
330 arm920t->armv4_5_mmu.has_tiny_pages = 1;
331 arm920t->armv4_5_mmu.mmu_enabled = 0;
332
333 /* disabling linefills leads to lockups, so keep them enabled for now
334 * this doesn't affect correctness, but might affect timing issues, if
335 * important data is evicted from the cache during the debug session
336 * */
337 arm920t->preserve_cache = 0;
338
339 /* override hw single-step capability from ARM9TDMI */
340 arm7_9->has_single_step = 1;
341
342 return ERROR_OK;
343 }
344
345 static int fa526_target_create(struct target *target, Jim_Interp *interp)
346 {
347 struct arm920t_common *arm920t = calloc(1, sizeof(struct arm920t_common));
348
349 return fa526_init_arch_info(target, arm920t, target->tap);
350 }
351
352 /** Holds methods for FA526 targets. */
353 struct target_type fa526_target = {
354 .name = "fa526",
355
356 .poll = arm7_9_poll,
357 .arch_state = arm920t_arch_state,
358
359 .target_request_data = arm7_9_target_request_data,
360
361 .halt = arm7_9_halt,
362 .resume = arm7_9_resume,
363 .step = arm7_9_step,
364
365 .assert_reset = arm7_9_assert_reset,
366 .deassert_reset = arm7_9_deassert_reset,
367 .soft_reset_halt = arm920t_soft_reset_halt,
368
369 .get_gdb_reg_list = arm_get_gdb_reg_list,
370
371 .read_memory = arm920t_read_memory,
372 .write_memory = arm7_9_write_memory_opt,
373
374 .checksum_memory = arm_checksum_memory,
375 .blank_check_memory = arm_blank_check_memory,
376
377 .run_algorithm = armv4_5_run_algorithm,
378
379 .add_breakpoint = arm7_9_add_breakpoint,
380 .remove_breakpoint = arm7_9_remove_breakpoint,
381 .add_watchpoint = arm7_9_add_watchpoint,
382 .remove_watchpoint = arm7_9_remove_watchpoint,
383
384 .commands = arm920t_command_handlers,
385 .target_create = fa526_target_create,
386 .init_target = arm9tdmi_init_target,
387 .examine = arm7_9_examine,
388 .check_reset = arm7_9_check_reset,
389 };

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)