5b464efb7e4f7c74dbcba401674448113309a2a9
[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 #include "target_type.h"
29
30
31 #if 0
32 #define _DEBUG_INSTRUCTION_EXECUTION_
33 #endif
34
35 int arm966e_init_arch_info(target_t *target, arm966e_common_t *arm966e, jtag_tap_t *tap)
36 {
37         arm9tdmi_common_t *arm9tdmi = &arm966e->arm9tdmi_common;
38         arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
39
40         arm9tdmi_init_arch_info(target, arm9tdmi, tap);
41
42         arm966e->common_magic = ARM966E_COMMON_MAGIC;
43
44         /* The ARM966E-S implements the ARMv5TE architecture which
45          * has the BKPT instruction, so we don't have to use a watchpoint comparator
46          */
47         arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
48         arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
49
50         return ERROR_OK;
51 }
52
53 static int arm966e_target_create(struct target_s *target, Jim_Interp *interp)
54 {
55         arm966e_common_t *arm966e = calloc(1,sizeof(arm966e_common_t));
56
57         return arm966e_init_arch_info(target, arm966e, target->tap);
58 }
59
60 static int arm966e_verify_pointer(struct command_context_s *cmd_ctx,
61                 struct arm966e_common_s *arm966e)
62 {
63         if (arm966e->common_magic != ARM966E_COMMON_MAGIC) {
64                 command_print(cmd_ctx, "target is not an ARM966");
65                 return ERROR_TARGET_INVALID;
66         }
67         return ERROR_OK;
68 }
69
70 static int arm966e_read_cp15(target_t *target, int reg_addr, uint32_t *value)
71 {
72         int retval = ERROR_OK;
73         struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
74         arm_jtag_t *jtag_info = &arm7_9->jtag_info;
75         scan_field_t fields[3];
76         uint8_t reg_addr_buf = reg_addr & 0x3f;
77         uint8_t nr_w_buf = 0;
78
79         jtag_set_end_state(TAP_IDLE);
80         if ((retval = arm_jtag_scann(jtag_info, 0xf)) != ERROR_OK)
81         {
82                 return retval;
83         }
84         arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
85
86         fields[0].tap = jtag_info->tap;
87         fields[0].num_bits = 32;
88         fields[0].out_value = NULL;
89         fields[0].in_value = NULL;
90
91         fields[1].tap = jtag_info->tap;
92         fields[1].num_bits = 6;
93         fields[1].out_value = &reg_addr_buf;
94         fields[1].in_value = NULL;
95
96         fields[2].tap = jtag_info->tap;
97         fields[2].num_bits = 1;
98         fields[2].out_value = &nr_w_buf;
99         fields[2].in_value = NULL;
100
101         jtag_add_dr_scan(3, fields, jtag_get_end_state());
102
103         fields[1].in_value = (uint8_t *)value;
104
105         jtag_add_dr_scan(3, fields, jtag_get_end_state());
106
107         jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);
108
109
110 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
111         if ((retval = jtag_execute_queue()) != ERROR_OK)
112         {
113                 return retval;
114         }
115         LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
116 #endif
117
118         return ERROR_OK;
119 }
120
121 // EXPORTED to str9x (flash)
122 int arm966e_write_cp15(target_t *target, int reg_addr, uint32_t value)
123 {
124         int retval = ERROR_OK;
125         struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
126         arm_jtag_t *jtag_info = &arm7_9->jtag_info;
127         scan_field_t fields[3];
128         uint8_t reg_addr_buf = reg_addr & 0x3f;
129         uint8_t nr_w_buf = 1;
130         uint8_t value_buf[4];
131
132         buf_set_u32(value_buf, 0, 32, value);
133
134         jtag_set_end_state(TAP_IDLE);
135         if ((retval = arm_jtag_scann(jtag_info, 0xf)) != ERROR_OK)
136         {
137                 return retval;
138         }
139         arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
140
141         fields[0].tap = jtag_info->tap;
142         fields[0].num_bits = 32;
143         fields[0].out_value = value_buf;
144         fields[0].in_value = NULL;
145
146         fields[1].tap = jtag_info->tap;
147         fields[1].num_bits = 6;
148         fields[1].out_value = &reg_addr_buf;
149         fields[1].in_value = NULL;
150
151         fields[2].tap = jtag_info->tap;
152         fields[2].num_bits = 1;
153         fields[2].out_value = &nr_w_buf;
154         fields[2].in_value = NULL;
155
156         jtag_add_dr_scan(3, fields, jtag_get_end_state());
157
158 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
159         LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
160 #endif
161
162         return ERROR_OK;
163 }
164
165 static int arm966e_handle_cp15_command(struct command_context_s *cmd_ctx,
166                 char *cmd, char **args, int argc)
167 {
168         int retval;
169         target_t *target = get_current_target(cmd_ctx);
170         struct arm966e_common_s *arm966e = target_to_arm966(target);
171
172         retval = arm966e_verify_pointer(cmd_ctx, arm966e);
173         if (retval != ERROR_OK)
174                 return retval;
175
176         if (target->state != TARGET_HALTED)
177         {
178                 command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
179                 return ERROR_OK;
180         }
181
182         /* one or more argument, access a single register (write if second argument is given */
183         if (argc >= 1)
184         {
185                 uint32_t address;
186                 COMMAND_PARSE_NUMBER(u32, args[0], address);
187
188                 if (argc == 1)
189                 {
190                         uint32_t value;
191                         if ((retval = arm966e_read_cp15(target, address, &value)) != ERROR_OK)
192                         {
193                                 command_print(cmd_ctx, "couldn't access reg %i", address);
194                                 return ERROR_OK;
195                         }
196                         if ((retval = jtag_execute_queue()) != ERROR_OK)
197                         {
198                                 return retval;
199                         }
200
201                         command_print(cmd_ctx, "%i: %8.8" PRIx32 "", address, value);
202                 }
203                 else if (argc == 2)
204                 {
205                         uint32_t value;
206                         COMMAND_PARSE_NUMBER(u32, args[1], value);
207                         if ((retval = arm966e_write_cp15(target, address, value)) != ERROR_OK)
208                         {
209                                 command_print(cmd_ctx, "couldn't access reg %i", address);
210                                 return ERROR_OK;
211                         }
212                         command_print(cmd_ctx, "%i: %8.8" PRIx32 "", address, value);
213                 }
214         }
215
216         return ERROR_OK;
217 }
218
219 /** Registers commands used to access coprocessor resources. */
220 int arm966e_register_commands(struct command_context_s *cmd_ctx)
221 {
222         int retval;
223         command_t *arm966e_cmd;
224
225         retval = arm9tdmi_register_commands(cmd_ctx);
226         arm966e_cmd = register_command(cmd_ctx, NULL, "arm966e",
227                         NULL, COMMAND_ANY,
228                         "arm966e specific commands");
229         register_command(cmd_ctx, arm966e_cmd, "cp15",
230                         arm966e_handle_cp15_command, COMMAND_EXEC,
231                         "display/modify cp15 register <num> [value]");
232
233         return retval;
234 }
235
236 /** Holds methods for ARM966 targets. */
237 target_type_t arm966e_target =
238 {
239         .name = "arm966e",
240
241         .poll = arm7_9_poll,
242         .arch_state = armv4_5_arch_state,
243
244         .target_request_data = arm7_9_target_request_data,
245
246         .halt = arm7_9_halt,
247         .resume = arm7_9_resume,
248         .step = arm7_9_step,
249
250         .assert_reset = arm7_9_assert_reset,
251         .deassert_reset = arm7_9_deassert_reset,
252         .soft_reset_halt = arm7_9_soft_reset_halt,
253
254         .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
255
256         .read_memory = arm7_9_read_memory,
257         .write_memory = arm7_9_write_memory,
258         .bulk_write_memory = arm7_9_bulk_write_memory,
259         .checksum_memory = arm7_9_checksum_memory,
260         .blank_check_memory = arm7_9_blank_check_memory,
261
262         .run_algorithm = armv4_5_run_algorithm,
263
264         .add_breakpoint = arm7_9_add_breakpoint,
265         .remove_breakpoint = arm7_9_remove_breakpoint,
266         .add_watchpoint = arm7_9_add_watchpoint,
267         .remove_watchpoint = arm7_9_remove_watchpoint,
268
269         .register_commands = arm966e_register_commands,
270         .target_create = arm966e_target_create,
271         .init_target = arm9tdmi_init_target,
272         .examine = arm9tdmi_examine,
273 };