From Michael Bruck
[fw/openocd] / src / target / arm926ejs.c
1 /***************************************************************************\r
2  *   Copyright (C) 2007 by Dominic Rath                                    *\r
3  *   Dominic.Rath@gmx.de                                                   *\r
4  *                                                                         *\r
5  *   This program is free software; you can redistribute it and/or modify  *\r
6  *   it under the terms of the GNU General Public License as published by  *\r
7  *   the Free Software Foundation; either version 2 of the License, or     *\r
8  *   (at your option) any later version.                                   *\r
9  *                                                                         *\r
10  *   This program is distributed in the hope that it will be useful,       *\r
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
13  *   GNU General Public License for more details.                          *\r
14  *                                                                         *\r
15  *   You should have received a copy of the GNU General Public License     *\r
16  *   along with this program; if not, write to the                         *\r
17  *   Free Software Foundation, Inc.,                                       *\r
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
19  ***************************************************************************/\r
20 #ifdef HAVE_CONFIG_H\r
21 #include "config.h"\r
22 #endif\r
23 \r
24 #include "arm926ejs.h"\r
25 #include "jtag.h"\r
26 #include "log.h"\r
27 \r
28 #include <stdlib.h>\r
29 #include <string.h>\r
30 \r
31 #if 1\r
32 #define _DEBUG_INSTRUCTION_EXECUTION_\r
33 #endif\r
34 \r
35 /* cli handling */\r
36 int arm926ejs_register_commands(struct command_context_s *cmd_ctx);\r
37 \r
38 int arm926ejs_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
39 int arm926ejs_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
40 int arm926ejs_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
41 int arm926ejs_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
42 int arm926ejs_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
43 int arm926ejs_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
44 \r
45 int arm926ejs_handle_read_cache_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
46 int arm926ejs_handle_read_mmu_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
47 \r
48 /* forward declarations */\r
49 int arm926ejs_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);\r
50 int arm926ejs_init_target(struct command_context_s *cmd_ctx, struct target_s *target);\r
51 int arm926ejs_quit();\r
52 int arm926ejs_arch_state(struct target_s *target);\r
53 int arm926ejs_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);\r
54 int arm926ejs_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);\r
55 int arm926ejs_soft_reset_halt(struct target_s *target);\r
56 static int arm926ejs_virt2phys(struct target_s *target, u32 virtual, u32 *physical);\r
57 static int arm926ejs_mmu(struct target_s *target, int *enabled);\r
58 \r
59 target_type_t arm926ejs_target =\r
60 {\r
61         .name = "arm926ejs",\r
62 \r
63         .poll = arm7_9_poll,\r
64         .arch_state = arm926ejs_arch_state,\r
65 \r
66         .target_request_data = arm7_9_target_request_data,\r
67 \r
68         .halt = arm7_9_halt,\r
69         .resume = arm7_9_resume,\r
70         .step = arm7_9_step,\r
71 \r
72         .assert_reset = arm7_9_assert_reset,\r
73         .deassert_reset = arm7_9_deassert_reset,\r
74         .soft_reset_halt = arm926ejs_soft_reset_halt,\r
75         .prepare_reset_halt = arm7_9_prepare_reset_halt,\r
76         \r
77         .get_gdb_reg_list = armv4_5_get_gdb_reg_list,\r
78 \r
79         .read_memory = arm7_9_read_memory,\r
80         .write_memory = arm926ejs_write_memory,\r
81         .bulk_write_memory = arm7_9_bulk_write_memory,\r
82         .checksum_memory = arm7_9_checksum_memory,\r
83         \r
84         .run_algorithm = armv4_5_run_algorithm,\r
85 \r
86         .add_breakpoint = arm7_9_add_breakpoint,\r
87         .remove_breakpoint = arm7_9_remove_breakpoint,\r
88         .add_watchpoint = arm7_9_add_watchpoint,\r
89         .remove_watchpoint = arm7_9_remove_watchpoint,\r
90 \r
91         .register_commands = arm926ejs_register_commands,\r
92         .target_command = arm926ejs_target_command,\r
93         .init_target = arm926ejs_init_target,\r
94         .quit = arm926ejs_quit,\r
95         .virt2phys = arm926ejs_virt2phys,\r
96         .mmu = arm926ejs_mmu\r
97 };\r
98 \r
99 \r
100 int arm926ejs_catch_broken_irscan(u8 *captured, void *priv, scan_field_t *field)\r
101 {\r
102         /* The ARM926EJ-S' instruction register is 4 bits wide */\r
103         u8 t = *captured & 0xf;\r
104         u8 t2 = *field->in_check_value & 0xf;\r
105         if (t == t2)\r
106         {\r
107                 return ERROR_OK;\r
108         }\r
109         else if ((t == 0x0f) || (t == 0x00))\r
110         {\r
111                 DEBUG("caught ARM926EJ-S invalid Capture-IR result after CP15 access");\r
112                 return ERROR_OK;\r
113         }\r
114         return ERROR_JTAG_QUEUE_FAILED;;\r
115 }\r
116 \r
117 #define ARM926EJS_CP15_ADDR(opcode_1, opcode_2, CRn, CRm) ((opcode_1 << 11) | (opcode_2 << 8) | (CRn << 4) | (CRm << 0))\r
118 \r
119 int arm926ejs_cp15_read(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 *value)\r
120 {\r
121         armv4_5_common_t *armv4_5 = target->arch_info;\r
122         arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
123         arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
124         u32 address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);\r
125         scan_field_t fields[4];\r
126         u8 address_buf[2];\r
127         u8 nr_w_buf = 0;\r
128         u8 access = 1;\r
129         \r
130         buf_set_u32(address_buf, 0, 14, address);\r
131         \r
132         jtag_add_end_state(TAP_RTI);\r
133         arm_jtag_scann(jtag_info, 0xf);\r
134         arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
135 \r
136         fields[0].device = jtag_info->chain_pos;\r
137         fields[0].num_bits = 32;\r
138         fields[0].out_value = NULL;\r
139         fields[0].out_mask = NULL;\r
140         fields[0].in_value = NULL;\r
141         fields[0].in_check_value = NULL;\r
142         fields[0].in_check_mask = NULL;\r
143         fields[0].in_handler = NULL;\r
144         fields[0].in_handler_priv = NULL;\r
145 \r
146         fields[1].device = jtag_info->chain_pos;\r
147         fields[1].num_bits = 1;\r
148         fields[1].out_value = &access;\r
149         fields[1].out_mask = NULL;\r
150         fields[1].in_value = &access;\r
151         fields[1].in_check_value = NULL;\r
152         fields[1].in_check_mask = NULL;\r
153         fields[1].in_handler = NULL;\r
154         fields[1].in_handler_priv = NULL;\r
155 \r
156         fields[2].device = jtag_info->chain_pos;\r
157         fields[2].num_bits = 14;\r
158         fields[2].out_value = address_buf;\r
159         fields[2].out_mask = NULL;\r
160         fields[2].in_value = NULL;\r
161         fields[2].in_check_value = NULL;\r
162         fields[2].in_check_mask = NULL;\r
163         fields[2].in_handler = NULL;\r
164         fields[2].in_handler_priv = NULL;\r
165 \r
166         fields[3].device = jtag_info->chain_pos;\r
167         fields[3].num_bits = 1;\r
168         fields[3].out_value = &nr_w_buf;\r
169         fields[3].out_mask = NULL;\r
170         fields[3].in_value = NULL;\r
171         fields[3].in_check_value = NULL;\r
172         fields[3].in_check_mask = NULL;\r
173         fields[3].in_handler = NULL;\r
174         fields[3].in_handler_priv = NULL;\r
175         \r
176         jtag_add_dr_scan(4, fields, -1);\r
177 \r
178         fields[0].in_handler_priv = value;\r
179         fields[0].in_handler = arm_jtag_buf_to_u32;\r
180         \r
181         do\r
182         {\r
183                 /* rescan with NOP, to wait for the access to complete */\r
184                 access = 0;\r
185                 nr_w_buf = 0;\r
186                 jtag_add_dr_scan(4, fields, -1);\r
187                 jtag_execute_queue();\r
188         } while (buf_get_u32(&access, 0, 1) != 1);\r
189 \r
190 #ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
191         DEBUG("addr: 0x%x value: %8.8x", address, *value);\r
192 #endif\r
193         \r
194         arm_jtag_set_instr(jtag_info, 0xc, &arm926ejs_catch_broken_irscan);\r
195 \r
196         return ERROR_OK;\r
197 }\r
198 \r
199 int arm926ejs_cp15_write(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 value)\r
200 {\r
201         armv4_5_common_t *armv4_5 = target->arch_info;\r
202         arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
203         arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
204         u32 address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);\r
205         scan_field_t fields[4];\r
206         u8 value_buf[4];\r
207         u8 address_buf[2];\r
208         u8 nr_w_buf = 1;\r
209         u8 access = 1;\r
210         \r
211         buf_set_u32(address_buf, 0, 14, address);\r
212         buf_set_u32(value_buf, 0, 32, value);\r
213         \r
214         jtag_add_end_state(TAP_RTI);\r
215         arm_jtag_scann(jtag_info, 0xf);\r
216         arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
217 \r
218         fields[0].device = jtag_info->chain_pos;\r
219         fields[0].num_bits = 32;\r
220         fields[0].out_value = value_buf;\r
221         fields[0].out_mask = NULL;\r
222         fields[0].in_value = NULL;\r
223         fields[0].in_check_value = NULL;\r
224         fields[0].in_check_mask = NULL;\r
225         fields[0].in_handler = NULL;\r
226         fields[0].in_handler_priv = NULL;\r
227 \r
228         fields[1].device = jtag_info->chain_pos;\r
229         fields[1].num_bits = 1;\r
230         fields[1].out_value = &access;\r
231         fields[1].out_mask = NULL;\r
232         fields[1].in_value = &access;\r
233         fields[1].in_check_value = NULL;\r
234         fields[1].in_check_mask = NULL;\r
235         fields[1].in_handler = NULL;\r
236         fields[1].in_handler_priv = NULL;\r
237 \r
238         fields[2].device = jtag_info->chain_pos;\r
239         fields[2].num_bits = 14;\r
240         fields[2].out_value = address_buf;\r
241         fields[2].out_mask = NULL;\r
242         fields[2].in_value = NULL;\r
243         fields[2].in_check_value = NULL;\r
244         fields[2].in_check_mask = NULL;\r
245         fields[2].in_handler = NULL;\r
246         fields[2].in_handler_priv = NULL;\r
247 \r
248         fields[3].device = jtag_info->chain_pos;\r
249         fields[3].num_bits = 1;\r
250         fields[3].out_value = &nr_w_buf;\r
251         fields[3].out_mask = NULL;\r
252         fields[3].in_value = NULL;\r
253         fields[3].in_check_value = NULL;\r
254         fields[3].in_check_mask = NULL;\r
255         fields[3].in_handler = NULL;\r
256         fields[3].in_handler_priv = NULL;\r
257         \r
258         jtag_add_dr_scan(4, fields, -1);\r
259 \r
260         do\r
261         {\r
262                 /* rescan with NOP, to wait for the access to complete */\r
263                 access = 0;\r
264                 nr_w_buf = 0;\r
265                 jtag_add_dr_scan(4, fields, -1);\r
266                 jtag_execute_queue();\r
267         } while (buf_get_u32(&access, 0, 1) != 1);\r
268 \r
269 #ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
270         DEBUG("addr: 0x%x value: %8.8x", address, value);\r
271 #endif\r
272 \r
273         arm_jtag_set_instr(jtag_info, 0xf, &arm926ejs_catch_broken_irscan);\r
274 \r
275         return ERROR_OK;\r
276 }\r
277 \r
278 int arm926ejs_examine_debug_reason(target_t *target)\r
279 {\r
280         armv4_5_common_t *armv4_5 = target->arch_info;\r
281         arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
282         reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];\r
283         int debug_reason;\r
284         int retval;\r
285 \r
286         embeddedice_read_reg(dbg_stat);\r
287         if ((retval = jtag_execute_queue()) != ERROR_OK)\r
288                 return retval;\r
289         \r
290         debug_reason = buf_get_u32(dbg_stat->value, 6, 4);\r
291         \r
292         switch (debug_reason)\r
293         {\r
294                 case 1:\r
295                         DEBUG("breakpoint from EICE unit 0");\r
296                         target->debug_reason = DBG_REASON_BREAKPOINT;\r
297                         break;\r
298                 case 2:\r
299                         DEBUG("breakpoint from EICE unit 1");\r
300                         target->debug_reason = DBG_REASON_BREAKPOINT;\r
301                         break;\r
302                 case 3:\r
303                         DEBUG("soft breakpoint (BKPT instruction)");\r
304                         target->debug_reason = DBG_REASON_BREAKPOINT;\r
305                         break;\r
306                 case 4:\r
307                         DEBUG("vector catch breakpoint");\r
308                         target->debug_reason = DBG_REASON_BREAKPOINT;\r
309                         break;\r
310                 case 5:\r
311                         DEBUG("external breakpoint");\r
312                         target->debug_reason = DBG_REASON_BREAKPOINT;\r
313                         break;\r
314                 case 6:\r
315                         DEBUG("watchpoint from EICE unit 0");\r
316                         target->debug_reason = DBG_REASON_WATCHPOINT;\r
317                         break;\r
318                 case 7:\r
319                         DEBUG("watchpoint from EICE unit 1");\r
320                         target->debug_reason = DBG_REASON_WATCHPOINT;\r
321                         break;\r
322                 case 8:\r
323                         DEBUG("external watchpoint");\r
324                         target->debug_reason = DBG_REASON_WATCHPOINT;\r
325                         break;\r
326                 case 9:\r
327                         DEBUG("internal debug request");\r
328                         target->debug_reason = DBG_REASON_DBGRQ;\r
329                         break;\r
330                 case 10:\r
331                         DEBUG("external debug request");\r
332                         target->debug_reason = DBG_REASON_DBGRQ;\r
333                         break;\r
334                 case 11:\r
335                         ERROR("BUG: debug re-entry from system speed access shouldn't be handled here");\r
336                         break;\r
337                 default:\r
338                         ERROR("BUG: unknown debug reason: 0x%x", debug_reason);\r
339                         target->debug_reason = DBG_REASON_DBGRQ;\r
340         }\r
341         \r
342         return ERROR_OK;\r
343 }\r
344 \r
345 u32 arm926ejs_get_ttb(target_t *target)\r
346 {\r
347         armv4_5_common_t *armv4_5 = target->arch_info;\r
348         arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
349         arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
350         arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
351         int retval;\r
352         u32 ttb = 0x0;\r
353 \r
354         if ((retval = arm926ejs->read_cp15(target, 0, 0, 2, 0, &ttb)) != ERROR_OK)\r
355                 return retval;\r
356 \r
357         return ttb;\r
358 }\r
359 \r
360 void arm926ejs_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)\r
361 {\r
362         armv4_5_common_t *armv4_5 = target->arch_info;\r
363         arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
364         arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
365         arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
366         u32 cp15_control;\r
367 \r
368         /* read cp15 control register */\r
369         arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);\r
370         jtag_execute_queue();\r
371         \r
372         if (mmu)\r
373         {\r
374                 /* invalidate TLB */\r
375                 arm926ejs->write_cp15(target, 0, 0, 8, 7, 0x0);\r
376                 \r
377                 cp15_control &= ~0x1U;\r
378         }\r
379         \r
380         if (d_u_cache)\r
381         {\r
382                 u32 debug_override;\r
383                 /* read-modify-write CP15 debug override register \r
384                  * to enable "test and clean all" */\r
385                 arm926ejs->read_cp15(target, 0, 0, 15, 0, &debug_override);\r
386                 debug_override |= 0x80000;\r
387                 arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);\r
388                 \r
389                 /* clean and invalidate DCache */\r
390                 arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);\r
391 \r
392                 /* write CP15 debug override register \r
393                  * to disable "test and clean all" */\r
394                 debug_override &= ~0x80000;\r
395                 arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);\r
396                 \r
397                 cp15_control &= ~0x4U;\r
398         }\r
399         \r
400         if (i_cache)\r
401         {\r
402                 /* invalidate ICache */\r
403                 arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);\r
404                 \r
405                 cp15_control &= ~0x1000U;\r
406         }\r
407         \r
408         arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);\r
409 }\r
410 \r
411 void arm926ejs_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)\r
412 {\r
413         armv4_5_common_t *armv4_5 = target->arch_info;\r
414         arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
415         arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
416         arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
417         u32 cp15_control;\r
418 \r
419         /* read cp15 control register */\r
420         arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);\r
421         jtag_execute_queue();\r
422                 \r
423         if (mmu)\r
424                 cp15_control |= 0x1U;\r
425         \r
426         if (d_u_cache)\r
427                 cp15_control |= 0x4U;\r
428         \r
429         if (i_cache)\r
430                 cp15_control |= 0x1000U;\r
431         \r
432         arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);\r
433 }\r
434 \r
435 void arm926ejs_post_debug_entry(target_t *target)\r
436 {\r
437         armv4_5_common_t *armv4_5 = target->arch_info;\r
438         arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
439         arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
440         arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
441 \r
442         /* examine cp15 control reg */\r
443         arm926ejs->read_cp15(target, 0, 0, 1, 0, &arm926ejs->cp15_control_reg);\r
444         jtag_execute_queue();\r
445         DEBUG("cp15_control_reg: %8.8x", arm926ejs->cp15_control_reg);\r
446 \r
447         if (arm926ejs->armv4_5_mmu.armv4_5_cache.ctype == -1)\r
448         {\r
449                 u32 cache_type_reg;\r
450                 /* identify caches */\r
451                 arm926ejs->read_cp15(target, 0, 1, 0, 0, &cache_type_reg);\r
452                 jtag_execute_queue();\r
453                 armv4_5_identify_cache(cache_type_reg, &arm926ejs->armv4_5_mmu.armv4_5_cache);\r
454         }\r
455 \r
456         arm926ejs->armv4_5_mmu.mmu_enabled = (arm926ejs->cp15_control_reg & 0x1U) ? 1 : 0;\r
457         arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm926ejs->cp15_control_reg & 0x4U) ? 1 : 0;\r
458         arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm926ejs->cp15_control_reg & 0x1000U) ? 1 : 0;\r
459 \r
460         /* save i/d fault status and address register */\r
461         arm926ejs->read_cp15(target, 0, 0, 5, 0, &arm926ejs->d_fsr);\r
462         arm926ejs->read_cp15(target, 0, 1, 5, 0, &arm926ejs->i_fsr);\r
463         arm926ejs->read_cp15(target, 0, 0, 6, 0, &arm926ejs->d_far);\r
464         \r
465         DEBUG("D FSR: 0x%8.8x, D FAR: 0x%8.8x, I FSR: 0x%8.8x",\r
466                 arm926ejs->d_fsr, arm926ejs->d_far, arm926ejs->i_fsr);  \r
467 \r
468 \r
469         u32 cache_dbg_ctrl;\r
470         \r
471         /* read-modify-write CP15 cache debug control register \r
472          * to disable I/D-cache linefills and force WT */\r
473         arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);\r
474         cache_dbg_ctrl |= 0x7;\r
475         arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);\r
476 }\r
477 \r
478 void arm926ejs_pre_restore_context(target_t *target)\r
479 {\r
480         armv4_5_common_t *armv4_5 = target->arch_info;\r
481         arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
482         arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
483         arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
484 \r
485         /* restore i/d fault status and address register */\r
486         arm926ejs->write_cp15(target, 0, 0, 5, 0, arm926ejs->d_fsr);\r
487         arm926ejs->write_cp15(target, 0, 1, 5, 0, arm926ejs->i_fsr);\r
488         arm926ejs->write_cp15(target, 0, 0, 6, 0, arm926ejs->d_far);\r
489         \r
490         u32 cache_dbg_ctrl;\r
491         \r
492         /* read-modify-write CP15 cache debug control register \r
493          * to reenable I/D-cache linefills and disable WT */\r
494         arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);\r
495         cache_dbg_ctrl &= ~0x7;\r
496         arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);\r
497 }\r
498 \r
499 int arm926ejs_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm926ejs_common_t **arm926ejs_p)\r
500 {\r
501         armv4_5_common_t *armv4_5 = target->arch_info;\r
502         arm7_9_common_t *arm7_9;\r
503         arm9tdmi_common_t *arm9tdmi;\r
504         arm926ejs_common_t *arm926ejs;\r
505         \r
506         if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)\r
507         {\r
508                 return -1;\r
509         }\r
510         \r
511         arm7_9 = armv4_5->arch_info;\r
512         if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)\r
513         {\r
514                 return -1;\r
515         }\r
516         \r
517         arm9tdmi = arm7_9->arch_info;\r
518         if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)\r
519         {\r
520                 return -1;\r
521         }\r
522         \r
523         arm926ejs = arm9tdmi->arch_info;\r
524         if (arm926ejs->common_magic != ARM926EJS_COMMON_MAGIC)\r
525         {\r
526                 return -1;\r
527         }\r
528         \r
529         *armv4_5_p = armv4_5;\r
530         *arm7_9_p = arm7_9;\r
531         *arm9tdmi_p = arm9tdmi;\r
532         *arm926ejs_p = arm926ejs;\r
533         \r
534         return ERROR_OK;\r
535 }\r
536 \r
537 int arm926ejs_arch_state(struct target_s *target)\r
538 {\r
539         armv4_5_common_t *armv4_5 = target->arch_info;\r
540         arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
541         arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
542         arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
543         \r
544         char *state[] = \r
545         {\r
546                 "disabled", "enabled"\r
547         };\r
548         \r
549         if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)\r
550         {\r
551                 ERROR("BUG: called for a non-ARMv4/5 target");\r
552                 exit(-1);\r
553         }\r
554         \r
555         USER(\r
556                         "target halted in %s state due to %s, current mode: %s\n"\r
557                         "cpsr: 0x%8.8x pc: 0x%8.8x\n"\r
558                         "MMU: %s, D-Cache: %s, I-Cache: %s",\r
559                          armv4_5_state_strings[armv4_5->core_state],\r
560                          target_debug_reason_strings[target->debug_reason],\r
561                          armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],\r
562                          buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),\r
563                          buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),\r
564                          state[arm926ejs->armv4_5_mmu.mmu_enabled],\r
565                          state[arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], \r
566                          state[arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);\r
567         \r
568         return ERROR_OK;\r
569 }\r
570 \r
571 int arm926ejs_soft_reset_halt(struct target_s *target)\r
572 {\r
573         armv4_5_common_t *armv4_5 = target->arch_info;\r
574         arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
575         arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
576         arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
577         reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];\r
578         \r
579         if (target->state == TARGET_RUNNING)\r
580         {\r
581                 target->type->halt(target);\r
582         }\r
583         \r
584         while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)\r
585         {\r
586                 embeddedice_read_reg(dbg_stat);\r
587                 jtag_execute_queue();\r
588         }\r
589         \r
590         target->state = TARGET_HALTED;\r
591         \r
592         /* SVC, ARM state, IRQ and FIQ disabled */\r
593         buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);\r
594         armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;\r
595         armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;\r
596         \r
597         /* start fetching from 0x0 */\r
598         buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);\r
599         armv4_5->core_cache->reg_list[15].dirty = 1;\r
600         armv4_5->core_cache->reg_list[15].valid = 1;\r
601         \r
602         armv4_5->core_mode = ARMV4_5_MODE_SVC;\r
603         armv4_5->core_state = ARMV4_5_STATE_ARM;\r
604         \r
605         arm926ejs_disable_mmu_caches(target, 1, 1, 1);\r
606         arm926ejs->armv4_5_mmu.mmu_enabled = 0;\r
607         arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;\r
608         arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;\r
609 \r
610         target_call_event_callbacks(target, TARGET_EVENT_HALTED);\r
611         \r
612         return ERROR_OK;\r
613 }\r
614 \r
615 int arm926ejs_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)\r
616 {\r
617         int retval;\r
618         armv4_5_common_t *armv4_5 = target->arch_info;\r
619         arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
620         arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
621         arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
622         \r
623         if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)\r
624                 return retval;\r
625 \r
626         /* If ICache is enabled, we have to invalidate affected ICache lines\r
627          * the DCache is forced to write-through, so we don't have to clean it here\r
628          */\r
629         if (arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled)\r
630         {\r
631                 if (count <= 1)\r
632                 {\r
633                         /* invalidate ICache single entry with MVA */\r
634                         arm926ejs->write_cp15(target, 0, 1, 7, 5, address);\r
635                 }\r
636                 else\r
637                 {\r
638                         /* invalidate ICache */\r
639                         arm926ejs->write_cp15(target, 0, 0, 7, 5, address);\r
640                 }\r
641         }\r
642 \r
643         return retval;\r
644 }\r
645 \r
646 int arm926ejs_init_target(struct command_context_s *cmd_ctx, struct target_s *target)\r
647 {\r
648         arm9tdmi_init_target(cmd_ctx, target);\r
649                 \r
650         return ERROR_OK;\r
651         \r
652 }\r
653 \r
654 int arm926ejs_quit()\r
655 {\r
656         \r
657         return ERROR_OK;\r
658 }\r
659 \r
660 int arm926ejs_init_arch_info(target_t *target, arm926ejs_common_t *arm926ejs, int chain_pos, char *variant)\r
661 {\r
662         arm9tdmi_common_t *arm9tdmi = &arm926ejs->arm9tdmi_common;\r
663         arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;\r
664         \r
665         /* initialize arm9tdmi specific info (including arm7_9 and armv4_5)\r
666          */\r
667         arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);\r
668 \r
669         arm9tdmi->arch_info = arm926ejs;\r
670         arm926ejs->common_magic = ARM926EJS_COMMON_MAGIC;\r
671         \r
672         arm7_9->post_debug_entry = arm926ejs_post_debug_entry;\r
673         arm7_9->pre_restore_context = arm926ejs_pre_restore_context;\r
674         \r
675         arm926ejs->read_cp15 = arm926ejs_cp15_read;\r
676         arm926ejs->write_cp15 = arm926ejs_cp15_write;\r
677         arm926ejs->armv4_5_mmu.armv4_5_cache.ctype = -1;\r
678         arm926ejs->armv4_5_mmu.get_ttb = arm926ejs_get_ttb;\r
679         arm926ejs->armv4_5_mmu.read_memory = arm7_9_read_memory;\r
680         arm926ejs->armv4_5_mmu.write_memory = arm7_9_write_memory;\r
681         arm926ejs->armv4_5_mmu.disable_mmu_caches = arm926ejs_disable_mmu_caches;\r
682         arm926ejs->armv4_5_mmu.enable_mmu_caches = arm926ejs_enable_mmu_caches;\r
683         arm926ejs->armv4_5_mmu.has_tiny_pages = 1;\r
684         arm926ejs->armv4_5_mmu.mmu_enabled = 0;\r
685         \r
686         arm7_9->examine_debug_reason = arm926ejs_examine_debug_reason;\r
687         \r
688         /* The ARM926EJ-S implements the ARMv5TE architecture which\r
689          * has the BKPT instruction, so we don't have to use a watchpoint comparator\r
690          */\r
691         arm7_9->arm_bkpt = ARMV5_BKPT(0x0);\r
692         arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;\r
693         \r
694         arm7_9->sw_bkpts_use_wp = 0;\r
695         arm7_9->sw_bkpts_enabled = 1;\r
696         \r
697         return ERROR_OK;\r
698 }\r
699 \r
700 int arm926ejs_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)\r
701 {\r
702         int chain_pos;\r
703         char *variant = NULL;\r
704         arm926ejs_common_t *arm926ejs = malloc(sizeof(arm926ejs_common_t));\r
705         \r
706         if (argc < 4)\r
707         {\r
708                 ERROR("'target arm926ejs' requires at least one additional argument");\r
709                 exit(-1);\r
710         }\r
711         \r
712         chain_pos = strtoul(args[3], NULL, 0);\r
713         \r
714         if (argc >= 5)\r
715                 variant = args[4];\r
716         \r
717         DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);\r
718         \r
719         arm926ejs_init_arch_info(target, arm926ejs, chain_pos, variant);\r
720 \r
721         return ERROR_OK;\r
722 }\r
723 \r
724 int arm926ejs_register_commands(struct command_context_s *cmd_ctx)\r
725 {\r
726         int retval;\r
727         command_t *arm926ejs_cmd;\r
728         \r
729                 \r
730         retval = arm9tdmi_register_commands(cmd_ctx);\r
731         \r
732         arm926ejs_cmd = register_command(cmd_ctx, NULL, "arm926ejs", NULL, COMMAND_ANY, "arm926ejs specific commands");\r
733 \r
734         register_command(cmd_ctx, arm926ejs_cmd, "cp15", arm926ejs_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <opcode_1> <opcode_2> <CRn> <CRm> [value]");\r
735         \r
736         register_command(cmd_ctx, arm926ejs_cmd, "cache_info", arm926ejs_handle_cache_info_command, COMMAND_EXEC, "display information about target caches");\r
737         register_command(cmd_ctx, arm926ejs_cmd, "virt2phys", arm926ejs_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");\r
738 \r
739         register_command(cmd_ctx, arm926ejs_cmd, "mdw_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");\r
740         register_command(cmd_ctx, arm926ejs_cmd, "mdh_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");\r
741         register_command(cmd_ctx, arm926ejs_cmd, "mdb_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");\r
742 \r
743         register_command(cmd_ctx, arm926ejs_cmd, "mww_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");\r
744         register_command(cmd_ctx, arm926ejs_cmd, "mwh_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");\r
745         register_command(cmd_ctx, arm926ejs_cmd, "mwb_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");\r
746 \r
747         return ERROR_OK;\r
748 }\r
749 \r
750 int arm926ejs_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
751 {\r
752         int retval;\r
753         target_t *target = get_current_target(cmd_ctx);\r
754         armv4_5_common_t *armv4_5;\r
755         arm7_9_common_t *arm7_9;\r
756         arm9tdmi_common_t *arm9tdmi;\r
757         arm926ejs_common_t *arm926ejs;\r
758         int opcode_1;\r
759         int opcode_2;\r
760         int CRn;\r
761         int CRm;\r
762 \r
763         if ((argc < 4) || (argc > 5))\r
764         {\r
765                 command_print(cmd_ctx, "usage: arm926ejs cp15 <opcode_1> <opcode_2> <CRn> <CRm> [value]");\r
766                 return ERROR_OK;\r
767         }\r
768         \r
769         opcode_1 = strtoul(args[0], NULL, 0);\r
770         opcode_2 = strtoul(args[1], NULL, 0);\r
771         CRn = strtoul(args[2], NULL, 0);\r
772         CRm = strtoul(args[3], NULL, 0);\r
773 \r
774         if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)\r
775         {\r
776                 command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");\r
777                 return ERROR_OK;\r
778         }\r
779         \r
780         if (target->state != TARGET_HALTED)\r
781         {\r
782                 command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
783                 return ERROR_OK;\r
784         }\r
785         \r
786         if (argc == 4)\r
787         {\r
788                 u32 value;\r
789                 if ((retval = arm926ejs->read_cp15(target, opcode_1, opcode_2, CRn, CRm, &value)) != ERROR_OK)\r
790                 {\r
791                         command_print(cmd_ctx, "couldn't access register");\r
792                         return ERROR_OK;\r
793                 }\r
794                 jtag_execute_queue();\r
795                 \r
796                 command_print(cmd_ctx, "%i %i %i %i: %8.8x", opcode_1, opcode_2, CRn, CRm, value);\r
797         }\r
798         else\r
799         {\r
800                 u32 value = strtoul(args[4], NULL, 0);\r
801                 if ((retval = arm926ejs->write_cp15(target, opcode_1, opcode_2, CRn, CRm, value)) != ERROR_OK)\r
802                 {\r
803                         command_print(cmd_ctx, "couldn't access register");\r
804                         return ERROR_OK;\r
805                 }\r
806                 command_print(cmd_ctx, "%i %i %i %i: %8.8x", opcode_1, opcode_2, CRn, CRm, value);\r
807         }\r
808 \r
809         return ERROR_OK;\r
810 }\r
811 \r
812 int arm926ejs_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
813 {\r
814         target_t *target = get_current_target(cmd_ctx);\r
815         armv4_5_common_t *armv4_5;\r
816         arm7_9_common_t *arm7_9;\r
817         arm9tdmi_common_t *arm9tdmi;\r
818         arm926ejs_common_t *arm926ejs;\r
819         \r
820         if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)\r
821         {\r
822                 command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");\r
823                 return ERROR_OK;\r
824         }\r
825         \r
826         return armv4_5_handle_cache_info_command(cmd_ctx, &arm926ejs->armv4_5_mmu.armv4_5_cache);\r
827 }\r
828 \r
829 int arm926ejs_handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
830 {       \r
831         target_t *target = get_current_target(cmd_ctx);\r
832         armv4_5_common_t *armv4_5;\r
833         arm7_9_common_t *arm7_9;\r
834         arm9tdmi_common_t *arm9tdmi;\r
835         arm926ejs_common_t *arm926ejs;\r
836         arm_jtag_t *jtag_info;\r
837 \r
838         if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)\r
839         {\r
840                 command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");\r
841                 return ERROR_OK;\r
842         }\r
843         \r
844         jtag_info = &arm7_9->jtag_info;\r
845         \r
846         if (target->state != TARGET_HALTED)\r
847         {\r
848                 command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
849                 return ERROR_OK;\r
850         }\r
851                 \r
852         return armv4_5_mmu_handle_virt2phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);\r
853 }\r
854 \r
855 int arm926ejs_handle_md_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
856 {       \r
857         target_t *target = get_current_target(cmd_ctx);\r
858         armv4_5_common_t *armv4_5;\r
859         arm7_9_common_t *arm7_9;\r
860         arm9tdmi_common_t *arm9tdmi;\r
861         arm926ejs_common_t *arm926ejs;\r
862         arm_jtag_t *jtag_info;\r
863 \r
864         if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)\r
865         {\r
866                 command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");\r
867                 return ERROR_OK;\r
868         }\r
869         \r
870         jtag_info = &arm7_9->jtag_info;\r
871         \r
872         if (target->state != TARGET_HALTED)\r
873         {\r
874                 command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
875                 return ERROR_OK;\r
876         }\r
877         \r
878         return armv4_5_mmu_handle_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);\r
879 }\r
880 \r
881 int arm926ejs_handle_mw_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
882 {       \r
883         target_t *target = get_current_target(cmd_ctx);\r
884         armv4_5_common_t *armv4_5;\r
885         arm7_9_common_t *arm7_9;\r
886         arm9tdmi_common_t *arm9tdmi;\r
887         arm926ejs_common_t *arm926ejs;\r
888         arm_jtag_t *jtag_info;\r
889 \r
890         if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)\r
891         {\r
892                 command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");\r
893                 return ERROR_OK;\r
894         }\r
895         \r
896         jtag_info = &arm7_9->jtag_info;\r
897         \r
898         if (target->state != TARGET_HALTED)\r
899         {\r
900                 command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
901                 return ERROR_OK;\r
902         }\r
903         \r
904         return armv4_5_mmu_handle_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);\r
905 }\r
906 static int arm926ejs_virt2phys(struct target_s *target, u32 virtual, u32 *physical)\r
907 {\r
908         int retval;\r
909         int type;\r
910         u32 cb;\r
911         int domain;\r
912         u32 ap;\r
913         \r
914         armv4_5_common_t *armv4_5;\r
915         arm7_9_common_t *arm7_9;\r
916         arm9tdmi_common_t *arm9tdmi;\r
917         arm926ejs_common_t *arm926ejs;\r
918         retval= arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs);\r
919         if (retval != ERROR_OK)\r
920         {\r
921                 return retval;\r
922         }\r
923         u32 ret = armv4_5_mmu_translate_va(target, &arm926ejs->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);\r
924         if (type == -1)\r
925         {\r
926                 return ret;\r
927         }\r
928         *physical = ret;\r
929         return ERROR_OK;\r
930 }\r
931 \r
932 static int arm926ejs_mmu(struct target_s *target, int *enabled)\r
933 {\r
934         armv4_5_common_t *armv4_5 = target->arch_info;\r
935         arm926ejs_common_t *arm926ejs = armv4_5->arch_info;\r
936         \r
937         if (target->state != TARGET_HALTED)\r
938         {\r
939                 ERROR("Target not halted");\r
940                 return ERROR_TARGET_INVALID;\r
941         }\r
942         *enabled = arm926ejs->armv4_5_mmu.mmu_enabled;\r
943         return ERROR_OK;\r
944 }\r