mips: fix swapping if openocd is running on big endian host
[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
56 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IDCODE);
57
58 field.num_bits = 32;
59 field.out_value = NULL;
60 field.in_value = (void*)idcode;
61
62 jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE);
63
64 int retval;
65 if ((retval = jtag_execute_queue()) != ERROR_OK)
66 {
67 LOG_ERROR("register read failed");
68 return retval;
69 }
70 return ERROR_OK;
71 }
72
73 static int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info, uint32_t *impcode)
74 {
75 struct scan_field field;
76
77 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IMPCODE);
78
79 field.num_bits = 32;
80 field.out_value = NULL;
81 field.in_value = (void*)impcode;
82
83 jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE);
84
85 int retval;
86 if ((retval = jtag_execute_queue()) != ERROR_OK)
87 {
88 LOG_ERROR("register read failed");
89 return retval;
90 }
91 return ERROR_OK;
92 }
93
94 int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data)
95 {
96 struct jtag_tap *tap;
97 tap = ejtag_info->tap;
98 assert(tap != NULL);
99
100 struct scan_field field;
101 uint8_t t[4], r[4];
102 int retval;
103
104 field.num_bits = 32;
105 field.out_value = t;
106 buf_set_u32(t, 0, field.num_bits, *data);
107 field.in_value = r;
108
109 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
110
111 if ((retval = jtag_execute_queue()) != ERROR_OK)
112 {
113 LOG_ERROR("register read failed");
114 return retval;
115 }
116
117 *data = buf_get_u32(field.in_value, 0, 32);
118
119 keep_alive();
120
121 return ERROR_OK;
122 }
123
124 void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data)
125 {
126 uint8_t t[4];
127 struct jtag_tap *tap;
128 tap = ejtag_info->tap;
129 assert(tap != NULL);
130
131 struct scan_field field;
132
133 field.num_bits = 32;
134 field.out_value = t;
135 buf_set_u32(t, 0, field.num_bits, data);
136
137 field.in_value = NULL;
138
139 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
140 }
141
142 int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data)
143 {
144 struct jtag_tap *tap;
145 tap = ejtag_info->tap;
146 assert(tap != NULL);
147
148 struct scan_field field;
149 uint8_t t[4] = {0, 0, 0, 0}, r[4];
150 int retval;
151
152 field.num_bits = 8;
153 field.out_value = t;
154 buf_set_u32(t, 0, field.num_bits, *data);
155 field.in_value = r;
156
157 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
158
159 if ((retval = jtag_execute_queue()) != ERROR_OK)
160 {
161 LOG_ERROR("register read failed");
162 return retval;
163 }
164
165 *data = buf_get_u32(field.in_value, 0, 32);
166
167 return ERROR_OK;
168 }
169
170 void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data)
171 {
172 struct jtag_tap *tap;
173 tap = ejtag_info->tap;
174 assert(tap != NULL);
175
176 struct scan_field field;
177
178 field.num_bits = 8;
179 field.out_value = &data;
180 field.in_value = NULL;
181
182 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
183 }
184
185 static int mips_ejtag_step_enable(struct mips_ejtag *ejtag_info)
186 {
187 static const uint32_t code[] = {
188 MIPS32_MTC0(1,31,0), /* move $1 to COP0 DeSave */
189 MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */
190 MIPS32_ORI(1,1,0x0100), /* set SSt bit in debug reg */
191 MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */
192 MIPS32_B(NEG16(5)),
193 MIPS32_MFC0(1,31,0), /* move COP0 DeSave to $1 */
194 };
195
196 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
197 0, NULL, 0, NULL, 1);
198 }
199
200 static int mips_ejtag_step_disable(struct mips_ejtag *ejtag_info)
201 {
202 static const uint32_t code[] = {
203 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
204 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
205 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
206 MIPS32_SW(1,0,15), /* sw $1,($15) */
207 MIPS32_SW(2,0,15), /* sw $2,($15) */
208 MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */
209 MIPS32_LUI(2,0xFFFF), /* $2 = 0xfffffeff */
210 MIPS32_ORI(2,2,0xFEFF),
211 MIPS32_AND(1,1,2),
212 MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */
213 MIPS32_LW(2,0,15),
214 MIPS32_LW(1,0,15),
215 MIPS32_B(NEG16(13)),
216 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
217 };
218
219 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
220 0, NULL, 0, NULL, 1);
221 }
222
223 int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step)
224 {
225 if (enable_step)
226 return mips_ejtag_step_enable(ejtag_info);
227 return mips_ejtag_step_disable(ejtag_info);
228 }
229
230 int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info)
231 {
232 uint32_t ejtag_ctrl;
233 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
234
235 /* set debug break bit */
236 ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_JTAGBRK;
237 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
238
239 /* break bit will be cleared by hardware */
240 ejtag_ctrl = ejtag_info->ejtag_ctrl;
241 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
242 LOG_DEBUG("ejtag_ctrl: 0x%8.8" PRIx32 "", ejtag_ctrl);
243 if ((ejtag_ctrl & EJTAG_CTRL_BRKST) == 0)
244 {
245 LOG_ERROR("Failed to enter Debug Mode!");
246 return ERROR_FAIL;
247 }
248
249 return ERROR_OK;
250 }
251
252 int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info)
253 {
254 uint32_t inst;
255 inst = MIPS32_DRET;
256
257 /* execute our dret instruction */
258 return mips32_pracc_exec(ejtag_info, 1, &inst, 0, NULL, 0, NULL, 0);
259 }
260
261 int mips_ejtag_read_debug(struct mips_ejtag *ejtag_info, uint32_t* debug_reg)
262 {
263 /* read ejtag ECR */
264 static const uint32_t code[] = {
265 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
266 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
267 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
268 MIPS32_SW(1,0,15), /* sw $1,($15) */
269 MIPS32_SW(2,0,15), /* sw $2,($15) */
270 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $1 = MIPS32_PRACC_PARAM_OUT */
271 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
272 MIPS32_MFC0(2,23,0), /* move COP0 Debug to $2 */
273 MIPS32_SW(2,0,1),
274 MIPS32_LW(2,0,15),
275 MIPS32_LW(1,0,15),
276 MIPS32_B(NEG16(12)),
277 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
278 };
279
280 return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
281 0, NULL, 1, debug_reg, 1);
282 }
283
284 int mips_ejtag_init(struct mips_ejtag *ejtag_info)
285 {
286 uint32_t ejtag_version;
287 int retval;
288
289 retval = mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode);
290 if (retval != ERROR_OK)
291 return retval;
292 LOG_DEBUG("impcode: 0x%8.8" PRIx32 "", ejtag_info->impcode);
293
294 /* get ejtag version */
295 ejtag_version = ((ejtag_info->impcode >> 29) & 0x07);
296
297 switch (ejtag_version)
298 {
299 case 0:
300 LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected");
301 break;
302 case 1:
303 LOG_DEBUG("EJTAG: Version 2.5 Detected");
304 break;
305 case 2:
306 LOG_DEBUG("EJTAG: Version 2.6 Detected");
307 break;
308 case 3:
309 LOG_DEBUG("EJTAG: Version 3.1 Detected");
310 break;
311 default:
312 LOG_DEBUG("EJTAG: Unknown Version Detected");
313 break;
314 }
315 LOG_DEBUG("EJTAG: features:%s%s%s%s%s%s%s",
316 ejtag_info->impcode & EJTAG_IMP_R3K ? " R3k" : " R4k",
317 ejtag_info->impcode & EJTAG_IMP_DINT ? " DINT" : "",
318 ejtag_info->impcode & (1 << 22) ? " ASID_8" : "",
319 ejtag_info->impcode & (1 << 21) ? " ASID_6" : "",
320 ejtag_info->impcode & EJTAG_IMP_MIPS16 ? " MIPS16" : "",
321 ejtag_info->impcode & EJTAG_IMP_NODMA ? " noDMA" : " DMA",
322 ejtag_info->impcode & EJTAG_DCR_MIPS64 ? " MIPS64" : " MIPS32");
323
324 if ((ejtag_info->impcode & EJTAG_IMP_NODMA) == 0)
325 LOG_DEBUG("EJTAG: DMA Access Mode Support Enabled");
326
327 /* set initial state for ejtag control reg */
328 ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV;
329 ejtag_info->fast_access_save = -1;
330
331 return ERROR_OK;
332 }
333
334 int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data)
335 {
336 struct jtag_tap *tap;
337 tap = ejtag_info->tap;
338 assert(tap != NULL);
339
340 struct scan_field fields[2];
341 uint8_t spracc = 0;
342 uint8_t t[4] = {0, 0, 0, 0};
343
344 /* fastdata 1-bit register */
345 fields[0].num_bits = 1;
346 fields[0].out_value = &spracc;
347 fields[0].in_value = NULL;
348
349 /* processor access data register 32 bit */
350 fields[1].num_bits = 32;
351 fields[1].out_value = t;
352
353 if (write_t)
354 {
355 fields[1].in_value = NULL;
356 buf_set_u32(t, 0, 32, *data);
357 }
358 else
359 {
360 fields[1].in_value = (uint8_t *) data;
361 }
362
363 jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);
364 keep_alive();
365
366 return ERROR_OK;
367 }

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)