cleanup: rename armv4_5 to arm for readability
[openocd.git] / src / target / mips_ejtag.c
1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
4 * *
5 * Copyright (C) 2008 by David T.L. Wong *
6 * *
7 * Copyright (C) 2009 by David N. Claffey <dnclaffey@gmail.com> *
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 * This program is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU General Public License *
20 * along with this program; if not, write to the *
21 * Free Software Foundation, Inc., *
22 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
23 ***************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "mips32.h"
29 #include "mips_ejtag.h"
30
31 void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, int new_instr)
32 {
33 struct jtag_tap *tap;
34
35 tap = ejtag_info->tap;
36 assert(tap != NULL);
37
38 if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr)
39 {
40 struct scan_field field;
41 uint8_t t[4];
42
43 field.num_bits = tap->ir_length;
44 field.out_value = t;
45 buf_set_u32(t, 0, field.num_bits, new_instr);
46 field.in_value = NULL;
47
48 jtag_add_ir_scan(tap, &field, TAP_IDLE);
49 }
50 }
51
52 int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode)
53 {
54 struct scan_field field;
55 uint8_t r[4];
56
57 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IDCODE);
58
59 field.num_bits = 32;
60 field.out_value = NULL;
61 field.in_value = r;
62
63 jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE);
64
65 int retval;
66 if ((retval = jtag_execute_queue()) != ERROR_OK)
67 {
68 LOG_ERROR("register read failed");
69 return retval;
70 }
71
72 *idcode = buf_get_u32(field.in_value, 0, 32);
73
74 return ERROR_OK;
75 }
76
77 static int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info, uint32_t *impcode)
78 {
79 struct scan_field field;
80 uint8_t r[4];
81
82 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IMPCODE);
83
84 field.num_bits = 32;
85 field.out_value = NULL;
86 field.in_value = r;
87
88 jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE);
89
90 int retval;
91 if ((retval = jtag_execute_queue()) != ERROR_OK)
92 {
93 LOG_ERROR("register read failed");
94 return retval;
95 }
96
97 *impcode = buf_get_u32(field.in_value, 0, 32);
98
99 return ERROR_OK;
100 }
101
102 int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data)
103 {
104 struct jtag_tap *tap;
105 tap = ejtag_info->tap;
106 assert(tap != NULL);
107
108 struct scan_field field;
109 uint8_t t[4], r[4];
110 int retval;
111
112 field.num_bits = 32;
113 field.out_value = t;
114 buf_set_u32(t, 0, field.num_bits, *data);
115 field.in_value = r;
116
117 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
118
119 if ((retval = jtag_execute_queue()) != ERROR_OK)
120 {
121 LOG_ERROR("register read failed");
122 return retval;
123 }
124
125 *data = buf_get_u32(field.in_value, 0, 32);
126
127 keep_alive();
128
129 return ERROR_OK;
130 }
131
132 void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data)
133 {
134 uint8_t t[4];
135 struct jtag_tap *tap;
136 tap = ejtag_info->tap;
137 assert(tap != NULL);
138
139 struct scan_field field;
140
141 field.num_bits = 32;
142 field.out_value = t;
143 buf_set_u32(t, 0, field.num_bits, data);
144
145 field.in_value = NULL;
146
147 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
148 }
149
150 int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data)
151 {
152 struct jtag_tap *tap;
153 tap = ejtag_info->tap;
154 assert(tap != NULL);
155
156 struct scan_field field;
157 uint8_t t[4] = {0, 0, 0, 0}, r[4];
158 int retval;
159
160 field.num_bits = 8;
161 field.out_value = t;
162 buf_set_u32(t, 0, field.num_bits, *data);
163 field.in_value = r;
164
165 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
166
167 if ((retval = jtag_execute_queue()) != ERROR_OK)
168 {
169 LOG_ERROR("register read failed");
170 return retval;
171 }
172
173 *data = buf_get_u32(field.in_value, 0, 32);
174
175 return ERROR_OK;
176 }
177
178 void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data)
179 {
180 struct jtag_tap *tap;
181 tap = ejtag_info->tap;
182 assert(tap != NULL);
183
184 struct scan_field field;
185
186 field.num_bits = 8;
187 field.out_value = &data;
188 field.in_value = NULL;
189
190 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
191 }
192
193 static int mips_ejtag_step_enable(struct mips_ejtag *ejtag_info)
194 {
195 static const uint32_t code[] = {
196 MIPS32_MTC0(1,31,0), /* move $1 to COP0 DeSave */
197 MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */
198 MIPS32_ORI(1,1,0x0100), /* set SSt bit in debug reg */
199 MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */
200 MIPS32_B(NEG16(5)),
201 MIPS32_MFC0(1,31,0), /* move COP0 DeSave to $1 */
202 };
203
204 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
205 0, NULL, 0, NULL, 1);
206 }
207
208 static int mips_ejtag_step_disable(struct mips_ejtag *ejtag_info)
209 {
210 static const uint32_t code[] = {
211 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
212 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
213 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
214 MIPS32_SW(1,0,15), /* sw $1,($15) */
215 MIPS32_SW(2,0,15), /* sw $2,($15) */
216 MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */
217 MIPS32_LUI(2,0xFFFF), /* $2 = 0xfffffeff */
218 MIPS32_ORI(2,2,0xFEFF),
219 MIPS32_AND(1,1,2),
220 MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */
221 MIPS32_LW(2,0,15),
222 MIPS32_LW(1,0,15),
223 MIPS32_B(NEG16(13)),
224 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
225 };
226
227 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
228 0, NULL, 0, NULL, 1);
229 }
230
231 int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step)
232 {
233 if (enable_step)
234 return mips_ejtag_step_enable(ejtag_info);
235 return mips_ejtag_step_disable(ejtag_info);
236 }
237
238 int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info)
239 {
240 uint32_t ejtag_ctrl;
241 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
242
243 /* set debug break bit */
244 ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_JTAGBRK;
245 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
246
247 /* break bit will be cleared by hardware */
248 ejtag_ctrl = ejtag_info->ejtag_ctrl;
249 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
250 LOG_DEBUG("ejtag_ctrl: 0x%8.8" PRIx32 "", ejtag_ctrl);
251 if ((ejtag_ctrl & EJTAG_CTRL_BRKST) == 0)
252 {
253 LOG_ERROR("Failed to enter Debug Mode!");
254 return ERROR_FAIL;
255 }
256
257 return ERROR_OK;
258 }
259
260 int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info)
261 {
262 uint32_t inst;
263 inst = MIPS32_DRET;
264
265 /* execute our dret instruction */
266 return mips32_pracc_exec(ejtag_info, 1, &inst, 0, NULL, 0, NULL, 0);
267 }
268
269 int mips_ejtag_read_debug(struct mips_ejtag *ejtag_info, uint32_t* debug_reg)
270 {
271 /* read ejtag ECR */
272 static const uint32_t code[] = {
273 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
274 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
275 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
276 MIPS32_SW(1,0,15), /* sw $1,($15) */
277 MIPS32_SW(2,0,15), /* sw $2,($15) */
278 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $1 = MIPS32_PRACC_PARAM_OUT */
279 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
280 MIPS32_MFC0(2,23,0), /* move COP0 Debug to $2 */
281 MIPS32_SW(2,0,1),
282 MIPS32_LW(2,0,15),
283 MIPS32_LW(1,0,15),
284 MIPS32_B(NEG16(12)),
285 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
286 };
287
288 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
289 0, NULL, 1, debug_reg, 1);
290 }
291
292 int mips_ejtag_init(struct mips_ejtag *ejtag_info)
293 {
294 uint32_t ejtag_version;
295 int retval;
296
297 retval = mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode);
298 if (retval != ERROR_OK)
299 return retval;
300 LOG_DEBUG("impcode: 0x%8.8" PRIx32 "", ejtag_info->impcode);
301
302 /* get ejtag version */
303 ejtag_version = ((ejtag_info->impcode >> 29) & 0x07);
304
305 switch (ejtag_version)
306 {
307 case 0:
308 LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected");
309 break;
310 case 1:
311 LOG_DEBUG("EJTAG: Version 2.5 Detected");
312 break;
313 case 2:
314 LOG_DEBUG("EJTAG: Version 2.6 Detected");
315 break;
316 case 3:
317 LOG_DEBUG("EJTAG: Version 3.1 Detected");
318 break;
319 default:
320 LOG_DEBUG("EJTAG: Unknown Version Detected");
321 break;
322 }
323 LOG_DEBUG("EJTAG: features:%s%s%s%s%s%s%s",
324 ejtag_info->impcode & EJTAG_IMP_R3K ? " R3k" : " R4k",
325 ejtag_info->impcode & EJTAG_IMP_DINT ? " DINT" : "",
326 ejtag_info->impcode & (1 << 22) ? " ASID_8" : "",
327 ejtag_info->impcode & (1 << 21) ? " ASID_6" : "",
328 ejtag_info->impcode & EJTAG_IMP_MIPS16 ? " MIPS16" : "",
329 ejtag_info->impcode & EJTAG_IMP_NODMA ? " noDMA" : " DMA",
330 ejtag_info->impcode & EJTAG_DCR_MIPS64 ? " MIPS64" : " MIPS32");
331
332 if ((ejtag_info->impcode & EJTAG_IMP_NODMA) == 0)
333 LOG_DEBUG("EJTAG: DMA Access Mode Support Enabled");
334
335 /* set initial state for ejtag control reg */
336 ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV;
337 ejtag_info->fast_access_save = -1;
338
339 return ERROR_OK;
340 }
341
342 int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data)
343 {
344 struct jtag_tap *tap;
345
346 tap = ejtag_info->tap;
347 assert(tap != NULL);
348
349 struct scan_field fields[2];
350 uint8_t spracc = 0;
351 uint8_t t[4] = {0, 0, 0, 0};
352
353 /* fastdata 1-bit register */
354 fields[0].num_bits = 1;
355 fields[0].out_value = &spracc;
356 fields[0].in_value = NULL;
357
358 /* processor access data register 32 bit */
359 fields[1].num_bits = 32;
360 fields[1].out_value = t;
361
362 if (write_t)
363 {
364 fields[1].in_value = NULL;
365 buf_set_u32(t, 0, 32, *data);
366 }
367 else
368 {
369 fields[1].in_value = (void *) data;
370 }
371
372 jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);
373
374 if ( (!write_t) && (data) )
375 jtag_add_callback(mips_le_to_h_u32,
376 (jtag_callback_data_t) data);
377
378 keep_alive();
379
380 return ERROR_OK;
381 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)