576be2e195384bf59d903c28728dfe40b191bbed
[fw/openocd] / src / target / arm966e.c
1 /***************************************************************************
2  *   Copyright (C) 2005 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
4  *                                                                         *
5  *   Copyright (C) 2008 by Spencer Oliver                                  *
6  *   spen@spen-soft.co.uk                                                  *
7  *                                                                         *
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.                                   *
12  *                                                                         *
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.                          *
17  *                                                                         *
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  ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "arm966e.h"
28
29 #include "arm7_9_common.h"
30 #include "register.h"
31 #include "target.h"
32 #include "armv4_5.h"
33 #include "embeddedice.h"
34 #include "log.h"
35 #include "jtag.h"
36 #include "arm_jtag.h"
37
38 #include <stdlib.h>
39 #include <string.h>
40
41 #if 0
42 #define _DEBUG_INSTRUCTION_EXECUTION_
43 #endif
44
45 /* cli handling */
46 int arm966e_register_commands(struct command_context_s *cmd_ctx);
47
48 /* forward declarations */
49 int arm966e_target_create(struct target_s *target, Jim_Interp *interp);
50 int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
51 int arm966e_quit(void);
52
53 target_type_t arm966e_target =
54 {
55         .name = "arm966e",
56
57         .poll = arm7_9_poll,
58         .arch_state = armv4_5_arch_state,
59
60         .target_request_data = arm7_9_target_request_data,
61
62         .halt = arm7_9_halt,
63         .resume = arm7_9_resume,
64         .step = arm7_9_step,
65
66         .assert_reset = arm7_9_assert_reset,
67         .deassert_reset = arm7_9_deassert_reset,
68         .soft_reset_halt = arm7_9_soft_reset_halt,
69
70         .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
71
72         .read_memory = arm7_9_read_memory,
73         .write_memory = arm7_9_write_memory,
74         .bulk_write_memory = arm7_9_bulk_write_memory,
75         .checksum_memory = arm7_9_checksum_memory,
76         .blank_check_memory = arm7_9_blank_check_memory,
77         
78         .run_algorithm = armv4_5_run_algorithm,
79         
80         .add_breakpoint = arm7_9_add_breakpoint,
81         .remove_breakpoint = arm7_9_remove_breakpoint,
82         .add_watchpoint = arm7_9_add_watchpoint,
83         .remove_watchpoint = arm7_9_remove_watchpoint,
84
85         .register_commands = arm966e_register_commands,
86         .target_create = arm966e_target_create,
87         .init_target = arm966e_init_target,
88         .examine = arm9tdmi_examine,
89         .quit = arm966e_quit,
90 };
91
92 int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
93 {
94         arm9tdmi_init_target(cmd_ctx, target);
95                 
96         return ERROR_OK;
97 }
98
99 int arm966e_quit(void)
100 {
101         
102         return ERROR_OK;
103 }
104
105 int arm966e_init_arch_info(target_t *target, arm966e_common_t *arm966e, jtag_tap_t *tap, const char *variant)
106 {
107         arm9tdmi_common_t *arm9tdmi = &arm966e->arm9tdmi_common;
108         arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
109         
110         arm9tdmi_init_arch_info(target, arm9tdmi, tap, variant);
111
112         arm9tdmi->arch_info = arm966e;
113         arm966e->common_magic = ARM966E_COMMON_MAGIC;
114         
115         /* The ARM966E-S implements the ARMv5TE architecture which
116          * has the BKPT instruction, so we don't have to use a watchpoint comparator
117          */
118         arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
119         arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
120         
121         return ERROR_OK;
122 }
123
124 int arm966e_target_create( struct target_s *target, Jim_Interp *interp )
125 {
126         arm966e_common_t *arm966e = calloc(1,sizeof(arm966e_common_t));
127         
128         arm966e_init_arch_info(target, arm966e, target->tap, target->variant);
129
130         return ERROR_OK;
131 }
132
133 int arm966e_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, arm966e_common_t **arm966e_p)
134 {
135         armv4_5_common_t *armv4_5 = target->arch_info;
136         arm7_9_common_t *arm7_9;
137         arm9tdmi_common_t *arm9tdmi;
138         arm966e_common_t *arm966e;
139         
140         if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
141         {
142                 return -1;
143         }
144         
145         arm7_9 = armv4_5->arch_info;
146         if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
147         {
148                 return -1;
149         }
150         
151         arm9tdmi = arm7_9->arch_info;
152         if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
153         {
154                 return -1;
155         }
156         
157         arm966e = arm9tdmi->arch_info;
158         if (arm966e->common_magic != ARM966E_COMMON_MAGIC)
159         {
160                 return -1;
161         }
162         
163         *armv4_5_p = armv4_5;
164         *arm7_9_p = arm7_9;
165         *arm9tdmi_p = arm9tdmi;
166         *arm966e_p = arm966e;
167         
168         return ERROR_OK;
169 }
170
171 int arm966e_read_cp15(target_t *target, int reg_addr, u32 *value)
172 {
173         int retval = ERROR_OK;
174         armv4_5_common_t *armv4_5 = target->arch_info;
175         arm7_9_common_t *arm7_9 = armv4_5->arch_info;
176         arm_jtag_t *jtag_info = &arm7_9->jtag_info;
177         scan_field_t fields[3];
178         u8 reg_addr_buf = reg_addr & 0x3f;
179         u8 nr_w_buf = 0;
180         
181         jtag_add_end_state(TAP_RTI);
182         if((retval = arm_jtag_scann(jtag_info, 0xf)) != ERROR_OK)
183         {
184                 return retval;
185         }
186         arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
187
188         fields[0].tap = jtag_info->tap;
189         fields[0].num_bits = 32;
190         fields[0].out_value = NULL;
191         fields[0].out_mask = NULL;
192         fields[0].in_value = NULL;
193         fields[0].in_check_value = NULL;
194         fields[0].in_check_mask = NULL;
195         fields[0].in_handler = NULL;
196         fields[0].in_handler_priv = NULL;
197
198         fields[1].tap = jtag_info->tap;
199         fields[1].num_bits = 6;
200         fields[1].out_value = &reg_addr_buf;
201         fields[1].out_mask = NULL;
202         fields[1].in_value = NULL;
203         fields[1].in_check_value = NULL;
204         fields[1].in_check_mask = NULL;
205         fields[1].in_handler = NULL;
206         fields[1].in_handler_priv = NULL;
207
208         fields[2].tap = jtag_info->tap;
209         fields[2].num_bits = 1;
210         fields[2].out_value = &nr_w_buf;
211         fields[2].out_mask = NULL;
212         fields[2].in_value = NULL;
213         fields[2].in_check_value = NULL;
214         fields[2].in_check_mask = NULL;
215         fields[2].in_handler = NULL;
216         fields[2].in_handler_priv = NULL;
217         
218         jtag_add_dr_scan(3, fields, -1);
219
220         fields[0].in_handler_priv = value;
221         fields[0].in_handler = arm_jtag_buf_to_u32;
222
223         jtag_add_dr_scan(3, fields, -1);
224
225 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
226         if((retval = jtag_execute_queue()) != ERROR_OK)
227         {
228                 return retval;
229         }
230         LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
231 #endif
232
233         return ERROR_OK;
234 }
235
236 int arm966e_write_cp15(target_t *target, int reg_addr, u32 value)
237 {
238         int retval = ERROR_OK;
239         armv4_5_common_t *armv4_5 = target->arch_info;
240         arm7_9_common_t *arm7_9 = armv4_5->arch_info;
241         arm_jtag_t *jtag_info = &arm7_9->jtag_info;
242         scan_field_t fields[3];
243         u8 reg_addr_buf = reg_addr & 0x3f;
244         u8 nr_w_buf = 1;
245         u8 value_buf[4];
246         
247         buf_set_u32(value_buf, 0, 32, value);
248         
249         jtag_add_end_state(TAP_RTI);
250         if((retval = arm_jtag_scann(jtag_info, 0xf)) != ERROR_OK)
251         {
252                 return retval;
253         }
254         arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
255
256         fields[0].tap = jtag_info->tap;
257         fields[0].num_bits = 32;
258         fields[0].out_value = value_buf;
259         fields[0].out_mask = NULL;
260         fields[0].in_value = NULL;
261         fields[0].in_check_value = NULL;
262         fields[0].in_check_mask = NULL;
263         fields[0].in_handler = NULL;
264         fields[0].in_handler_priv = NULL;
265
266         fields[1].tap = jtag_info->tap;
267         fields[1].num_bits = 6;
268         fields[1].out_value = &reg_addr_buf;
269         fields[1].out_mask = NULL;
270         fields[1].in_value = NULL;
271         fields[1].in_check_value = NULL;
272         fields[1].in_check_mask = NULL;
273         fields[1].in_handler = NULL;
274         fields[1].in_handler_priv = NULL;
275
276         fields[2].tap = jtag_info->tap;
277         fields[2].num_bits = 1;
278         fields[2].out_value = &nr_w_buf;
279         fields[2].out_mask = NULL;
280         fields[2].in_value = NULL;
281         fields[2].in_check_value = NULL;
282         fields[2].in_check_mask = NULL;
283         fields[2].in_handler = NULL;
284         fields[2].in_handler_priv = NULL;
285         
286         jtag_add_dr_scan(3, fields, -1);
287
288 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
289         LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
290 #endif
291
292         return ERROR_OK;
293 }
294
295 int arm966e_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
296 {
297         int retval;
298         target_t *target = get_current_target(cmd_ctx);
299         armv4_5_common_t *armv4_5;
300         arm7_9_common_t *arm7_9;
301         arm9tdmi_common_t *arm9tdmi;
302         arm966e_common_t *arm966e;
303         arm_jtag_t *jtag_info;
304
305         if (arm966e_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm966e) != ERROR_OK)
306         {
307                 command_print(cmd_ctx, "current target isn't an ARM966e target");
308                 return ERROR_OK;
309         }
310         
311         jtag_info = &arm7_9->jtag_info;
312         
313         if (target->state != TARGET_HALTED)
314         {
315                 command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
316                 return ERROR_OK;
317         }
318
319         /* one or more argument, access a single register (write if second argument is given */
320         if (argc >= 1)
321         {
322                 int address = strtoul(args[0], NULL, 0);
323
324                 if (argc == 1)
325                 {
326                         u32 value;
327                         if ((retval = arm966e_read_cp15(target, address, &value)) != ERROR_OK)
328                         {
329                                 command_print(cmd_ctx, "couldn't access reg %i", address);
330                                 return ERROR_OK;
331                         }
332                         if((retval = jtag_execute_queue()) != ERROR_OK)
333                         {
334                                 return retval;
335                         }
336                         
337                         command_print(cmd_ctx, "%i: %8.8x", address, value);
338                 }
339                 else if (argc == 2)
340                 {
341                         u32 value = strtoul(args[1], NULL, 0);
342                         if ((retval = arm966e_write_cp15(target, address, value)) != ERROR_OK)
343                         {
344                                 command_print(cmd_ctx, "couldn't access reg %i", address);
345                                 return ERROR_OK;
346                         }
347                         command_print(cmd_ctx, "%i: %8.8x", address, value);
348                 }
349         }
350
351         return ERROR_OK;
352 }
353
354 int arm966e_register_commands(struct command_context_s *cmd_ctx)
355 {
356         int retval;
357         command_t *arm966e_cmd;
358         
359         retval = arm9tdmi_register_commands(cmd_ctx);
360         arm966e_cmd = register_command(cmd_ctx, NULL, "arm966e", NULL, COMMAND_ANY, "arm966e specific commands");
361         register_command(cmd_ctx, arm966e_cmd, "cp15", arm966e_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <num> [value]");
362         
363         return retval;
364 }