b1fea08e6b72a26eaef09701e2626e858bfa110e
[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, struct jtag_tap *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 COMMAND_HANDLER(arm966e_handle_cp15_command)
166 {
167         int retval;
168         target_t *target = get_current_target(cmd_ctx);
169         struct arm966e_common_s *arm966e = target_to_arm966(target);
170
171         retval = arm966e_verify_pointer(cmd_ctx, arm966e);
172         if (retval != ERROR_OK)
173                 return retval;
174
175         if (target->state != TARGET_HALTED)
176         {
177                 command_print(cmd_ctx, "target must be stopped for \"%s\" command", CMD_NAME);
178                 return ERROR_OK;
179         }
180
181         /* one or more argument, access a single register (write if second argument is given */
182         if (argc >= 1)
183         {
184                 uint32_t address;
185                 COMMAND_PARSE_NUMBER(u32, args[0], address);
186
187                 if (argc == 1)
188                 {
189                         uint32_t value;
190                         if ((retval = arm966e_read_cp15(target, address, &value)) != ERROR_OK)
191                         {
192                                 command_print(cmd_ctx, "couldn't access reg %i", address);
193                                 return ERROR_OK;
194                         }
195                         if ((retval = jtag_execute_queue()) != ERROR_OK)
196                         {
197                                 return retval;
198                         }
199
200                         command_print(cmd_ctx, "%i: %8.8" PRIx32 "", address, value);
201                 }
202                 else if (argc == 2)
203                 {
204                         uint32_t value;
205                         COMMAND_PARSE_NUMBER(u32, args[1], value);
206                         if ((retval = arm966e_write_cp15(target, address, value)) != ERROR_OK)
207                         {
208                                 command_print(cmd_ctx, "couldn't access reg %i", address);
209                                 return ERROR_OK;
210                         }
211                         command_print(cmd_ctx, "%i: %8.8" PRIx32 "", address, value);
212                 }
213         }
214
215         return ERROR_OK;
216 }
217
218 /** Registers commands used to access coprocessor resources. */
219 int arm966e_register_commands(struct command_context_s *cmd_ctx)
220 {
221         int retval;
222         command_t *arm966e_cmd;
223
224         retval = arm9tdmi_register_commands(cmd_ctx);
225         arm966e_cmd = register_command(cmd_ctx, NULL, "arm966e",
226                         NULL, COMMAND_ANY,
227                         "arm966e specific commands");
228         register_command(cmd_ctx, arm966e_cmd, "cp15",
229                         arm966e_handle_cp15_command, COMMAND_EXEC,
230                         "display/modify cp15 register <num> [value]");
231
232         return retval;
233 }
234
235 /** Holds methods for ARM966 targets. */
236 target_type_t arm966e_target =
237 {
238         .name = "arm966e",
239
240         .poll = arm7_9_poll,
241         .arch_state = armv4_5_arch_state,
242
243         .target_request_data = arm7_9_target_request_data,
244
245         .halt = arm7_9_halt,
246         .resume = arm7_9_resume,
247         .step = arm7_9_step,
248
249         .assert_reset = arm7_9_assert_reset,
250         .deassert_reset = arm7_9_deassert_reset,
251         .soft_reset_halt = arm7_9_soft_reset_halt,
252
253         .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
254
255         .read_memory = arm7_9_read_memory,
256         .write_memory = arm7_9_write_memory,
257         .bulk_write_memory = arm7_9_bulk_write_memory,
258         .checksum_memory = arm7_9_checksum_memory,
259         .blank_check_memory = arm7_9_blank_check_memory,
260
261         .run_algorithm = armv4_5_run_algorithm,
262
263         .add_breakpoint = arm7_9_add_breakpoint,
264         .remove_breakpoint = arm7_9_remove_breakpoint,
265         .add_watchpoint = arm7_9_add_watchpoint,
266         .remove_watchpoint = arm7_9_remove_watchpoint,
267
268         .register_commands = arm966e_register_commands,
269         .target_create = arm966e_target_create,
270         .init_target = arm9tdmi_init_target,
271         .examine = arm9tdmi_examine,
272 };