Dirk Behme <dirk.behme@googlemail.com> Add minimalist Cortex A8 file
[fw/openocd] / src / target / cortex_a8.c
1 /***************************************************************************
2  *   Copyright (C) 2005 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
4  *                                                                         *
5  *   Copyright (C) 2006 by Magnus Lundin                                   *
6  *   lundin@mlu.mine.nu                                                    *
7  *                                                                         *
8  *   Copyright (C) 2008 by Spencer Oliver                                  *
9  *   spen@spen-soft.co.uk                                                  *
10  *                                                                         *
11  *   Copyright (C) 2009 by Dirk Behme                                      *
12  *   dirk.behme@gmail.com - copy from cortex_m3                            *
13  *                                                                         *
14  *   This program is free software; you can redistribute it and/or modify  *
15  *   it under the terms of the GNU General Public License as published by  *
16  *   the Free Software Foundation; either version 2 of the License, or     *
17  *   (at your option) any later version.                                   *
18  *                                                                         *
19  *   This program is distributed in the hope that it will be useful,       *
20  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
21  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
22  *   GNU General Public License for more details.                          *
23  *                                                                         *
24  *   You should have received a copy of the GNU General Public License     *
25  *   along with this program; if not, write to the                         *
26  *   Free Software Foundation, Inc.,                                       *
27  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
28  *                                                                         *
29  *   Cortex-A8(tm) TRM, ARM DDI 0344H                                      *
30  *                                                                         *
31  ***************************************************************************/
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include "replacements.h"
37
38 #include "cortex_a8.h"
39 #include "armv7m.h"
40
41 #include "register.h"
42 #include "target.h"
43 #include "target_request.h"
44 #include "log.h"
45 #include "jtag.h"
46 #include "arm_jtag.h"
47
48 #include <stdlib.h>
49 #include <string.h>
50
51 /* cli handling */
52 int cortex_a8_register_commands(struct command_context_s *cmd_ctx);
53
54 /* forward declarations */
55 int cortex_a8_target_create(struct target_s *target, Jim_Interp *interp);
56
57 target_type_t cortexa8_target =
58 {
59         .name = "cortex_a8",
60
61         .poll = NULL,
62         .arch_state = armv7m_arch_state,
63
64         .target_request_data = NULL,
65
66         .halt = NULL,
67         .resume = NULL,
68         .step = NULL,
69
70         .assert_reset = NULL,
71         .deassert_reset = NULL,
72         .soft_reset_halt = NULL,
73
74         .get_gdb_reg_list = armv7m_get_gdb_reg_list,
75
76         .read_memory = cortex_a8_read_memory,
77         .write_memory = cortex_a8_write_memory,
78         .bulk_write_memory = NULL,
79         .checksum_memory = NULL,
80         .blank_check_memory = NULL,
81
82         .run_algorithm = armv7m_run_algorithm,
83
84         .add_breakpoint = NULL,
85         .remove_breakpoint = NULL,
86         .add_watchpoint = NULL,
87         .remove_watchpoint = NULL,
88
89         .register_commands = cortex_a8_register_commands,
90         .target_create = cortex_a8_target_create,
91         .init_target = NULL,
92         .examine = NULL,
93         .quit = NULL
94 };
95
96 int cortex_a8_dcc_read(swjdp_common_t *swjdp, u8 *value, u8 *ctrl)
97 {
98         u16 dcrdr;
99
100         mem_ap_read_buf_u16( swjdp, (u8*)&dcrdr, 1, DCB_DCRDR);
101         *ctrl = (u8)dcrdr;
102         *value = (u8)(dcrdr >> 8);
103
104         LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl);
105
106         /* write ack back to software dcc register
107          * signify we have read data */
108         if (dcrdr & (1 << 0))
109         {
110                 dcrdr = 0;
111                 mem_ap_write_buf_u16( swjdp, (u8*)&dcrdr, 1, DCB_DCRDR);
112         }
113
114         return ERROR_OK;
115 }
116
117 int cortex_a8_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
118 {
119         /* get pointers to arch-specific information */
120         armv7m_common_t *armv7m = target->arch_info;
121         swjdp_common_t *swjdp = &armv7m->swjdp_info;
122         int retval;
123
124         /* sanitize arguments */
125         if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
126                 return ERROR_INVALID_ARGUMENTS;
127
128         /* cortex_a8 handles unaligned memory access */
129
130         switch (size)
131         {
132                 case 4:
133                         retval = mem_ap_read_buf_u32(swjdp, buffer, 4 * count, address);
134                         break;
135                 case 2:
136                         retval = mem_ap_read_buf_u16(swjdp, buffer, 2 * count, address);
137                         break;
138                 case 1:
139                         retval = mem_ap_read_buf_u8(swjdp, buffer, count, address);
140                         break;
141                 default:
142                         LOG_ERROR("BUG: we shouldn't get here");
143                         exit(-1);
144         }
145
146         return retval;
147 }
148
149 int cortex_a8_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
150 {
151         /* get pointers to arch-specific information */
152         armv7m_common_t *armv7m = target->arch_info;
153         swjdp_common_t *swjdp = &armv7m->swjdp_info;
154         int retval;
155
156         /* sanitize arguments */
157         if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
158                 return ERROR_INVALID_ARGUMENTS;
159
160         switch (size)
161         {
162                 case 4:
163                         retval = mem_ap_write_buf_u32(swjdp, buffer, 4 * count, address);
164                         break;
165                 case 2:
166                         retval = mem_ap_write_buf_u16(swjdp, buffer, 2 * count, address);
167                         break;
168                 case 1:
169                         retval = mem_ap_write_buf_u8(swjdp, buffer, count, address);
170                         break;
171                 default:
172                         LOG_ERROR("BUG: we shouldn't get here");
173                         exit(-1);
174         }
175
176         return retval;
177 }
178
179 int cortex_a8_handle_target_request(void *priv)
180 {
181         target_t *target = priv;
182         if (!target->type->examined)
183                 return ERROR_OK;
184         armv7m_common_t *armv7m = target->arch_info;
185         swjdp_common_t *swjdp = &armv7m->swjdp_info;
186
187         if (!target->dbg_msg_enabled)
188                 return ERROR_OK;
189
190         if (target->state == TARGET_RUNNING)
191         {
192                 u8 data;
193                 u8 ctrl;
194
195                 cortex_a8_dcc_read(swjdp, &data, &ctrl);
196
197                 /* check if we have data */
198                 if (ctrl & (1 << 0))
199                 {
200                         u32 request;
201
202                         /* we assume target is quick enough */
203                         request = data;
204                         cortex_a8_dcc_read(swjdp, &data, &ctrl);
205                         request |= (data << 8);
206                         cortex_a8_dcc_read(swjdp, &data, &ctrl);
207                         request |= (data << 16);
208                         cortex_a8_dcc_read(swjdp, &data, &ctrl);
209                         request |= (data << 24);
210                         target_request(target, request);
211                 }
212         }
213
214         return ERROR_OK;
215 }
216
217 int cortex_a8_init_arch_info(target_t *target, cortex_a8_common_t *cortex_a8, jtag_tap_t *tap)
218 {
219         armv7m_common_t *armv7m;
220         armv7m = &cortex_a8->armv7m;
221
222         /* prepare JTAG information for the new target */
223         cortex_a8->jtag_info.tap = tap;
224         cortex_a8->jtag_info.scann_size = 4;
225
226         armv7m->swjdp_info.dp_select_value = -1;
227         armv7m->swjdp_info.ap_csw_value = -1;
228         armv7m->swjdp_info.ap_tar_value = -1;
229         armv7m->swjdp_info.jtag_info = &cortex_a8->jtag_info;
230
231         /* initialize arch-specific breakpoint handling */
232
233         cortex_a8->common_magic = CORTEX_A8_COMMON_MAGIC;
234         cortex_a8->arch_info = NULL;
235
236         /* register arch-specific functions */
237         armv7m->examine_debug_reason = NULL;
238
239         armv7m->pre_debug_entry = NULL;
240         armv7m->post_debug_entry = NULL;
241
242         armv7m->pre_restore_context = NULL;
243         armv7m->post_restore_context = NULL;
244
245         armv7m_init_arch_info(target, armv7m);
246         armv7m->arch_info = cortex_a8;
247         armv7m->load_core_reg_u32 = NULL;
248         armv7m->store_core_reg_u32 = NULL;
249
250         target_register_timer_callback(cortex_a8_handle_target_request, 1, 1, target);
251
252         return ERROR_OK;
253 }
254
255 int cortex_a8_target_create(struct target_s *target, Jim_Interp *interp)
256 {
257         cortex_a8_common_t *cortex_a8 = calloc(1,sizeof(cortex_a8_common_t));
258
259         cortex_a8_init_arch_info(target, cortex_a8, target->tap);
260
261         return ERROR_OK;
262 }
263
264 int cortex_a8_register_commands(struct command_context_s *cmd_ctx)
265 {
266         int retval;
267
268         retval = armv7m_register_commands(cmd_ctx);
269
270         register_command(cmd_ctx, NULL, "cortex_a8", NULL, COMMAND_ANY, "cortex_a8 specific commands");
271
272         return retval;
273 }