mips: mips_ejtag_get_impcode error propagation added
[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 int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data)
125 {
126 struct jtag_tap *tap;
127 tap = ejtag_info->tap;
128 assert(tap != NULL);
129
130 struct scan_field field;
131 uint8_t t[4] = {0, 0, 0, 0}, r[4];
132 int retval;
133
134 field.num_bits = 8;
135 field.out_value = t;
136 buf_set_u32(t, 0, field.num_bits, *data);
137 field.in_value = r;
138
139 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
140
141 if ((retval = jtag_execute_queue()) != ERROR_OK)
142 {
143 LOG_ERROR("register read failed");
144 return retval;
145 }
146
147 *data = buf_get_u32(field.in_value, 0, 32);
148
149 keep_alive();
150
151 return ERROR_OK;
152 }
153
154 static int mips_ejtag_step_enable(struct mips_ejtag *ejtag_info)
155 {
156 static const uint32_t code[] = {
157 MIPS32_MTC0(1,31,0), /* move $1 to COP0 DeSave */
158 MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */
159 MIPS32_ORI(1,1,0x0100), /* set SSt bit in debug reg */
160 MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */
161 MIPS32_B(NEG16(5)),
162 MIPS32_MFC0(1,31,0), /* move COP0 DeSave to $1 */
163 };
164
165 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
166 0, NULL, 0, NULL, 1);
167
168 return ERROR_OK;
169 }
170
171 static int mips_ejtag_step_disable(struct mips_ejtag *ejtag_info)
172 {
173 static const uint32_t code[] = {
174 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
175 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
176 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
177 MIPS32_SW(1,0,15), /* sw $1,($15) */
178 MIPS32_SW(2,0,15), /* sw $2,($15) */
179 MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */
180 MIPS32_LUI(2,0xFFFF), /* $2 = 0xfffffeff */
181 MIPS32_ORI(2,2,0xFEFF),
182 MIPS32_AND(1,1,2),
183 MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */
184 MIPS32_LW(2,0,15),
185 MIPS32_LW(1,0,15),
186 MIPS32_B(NEG16(13)),
187 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
188 };
189
190 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
191 0, NULL, 0, NULL, 1);
192
193 return ERROR_OK;
194 }
195
196 int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step)
197 {
198 if (enable_step)
199 return mips_ejtag_step_enable(ejtag_info);
200 return mips_ejtag_step_disable(ejtag_info);
201 }
202
203 int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info)
204 {
205 uint32_t ejtag_ctrl;
206 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
207
208 /* set debug break bit */
209 ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_JTAGBRK;
210 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
211
212 /* break bit will be cleared by hardware */
213 ejtag_ctrl = ejtag_info->ejtag_ctrl;
214 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
215 LOG_DEBUG("ejtag_ctrl: 0x%8.8" PRIx32 "", ejtag_ctrl);
216 if ((ejtag_ctrl & EJTAG_CTRL_BRKST) == 0)
217 {
218 LOG_ERROR("Failed to enter Debug Mode!");
219 return ERROR_FAIL;
220 }
221
222 return ERROR_OK;
223 }
224
225 int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info)
226 {
227 uint32_t inst;
228 inst = MIPS32_DRET;
229
230 /* execute our dret instruction */
231 mips32_pracc_exec(ejtag_info, 1, &inst, 0, NULL, 0, NULL, 0);
232
233 return ERROR_OK;
234 }
235
236 int mips_ejtag_read_debug(struct mips_ejtag *ejtag_info, uint32_t* debug_reg)
237 {
238 /* read ejtag ECR */
239 static const uint32_t code[] = {
240 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
241 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
242 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
243 MIPS32_SW(1,0,15), /* sw $1,($15) */
244 MIPS32_SW(2,0,15), /* sw $2,($15) */
245 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $1 = MIPS32_PRACC_PARAM_OUT */
246 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
247 MIPS32_MFC0(2,23,0), /* move COP0 Debug to $2 */
248 MIPS32_SW(2,0,1),
249 MIPS32_LW(2,0,15),
250 MIPS32_LW(1,0,15),
251 MIPS32_B(NEG16(12)),
252 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
253 };
254
255 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
256 0, NULL, 1, debug_reg, 1);
257
258 return ERROR_OK;
259 }
260
261 int mips_ejtag_init(struct mips_ejtag *ejtag_info)
262 {
263 uint32_t ejtag_version;
264 int retval;
265
266 retval = mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode);
267 if (retval != ERROR_OK)
268 return retval;
269 LOG_DEBUG("impcode: 0x%8.8" PRIx32 "", ejtag_info->impcode);
270
271 /* get ejtag version */
272 ejtag_version = ((ejtag_info->impcode >> 29) & 0x07);
273
274 switch (ejtag_version)
275 {
276 case 0:
277 LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected");
278 break;
279 case 1:
280 LOG_DEBUG("EJTAG: Version 2.5 Detected");
281 break;
282 case 2:
283 LOG_DEBUG("EJTAG: Version 2.6 Detected");
284 break;
285 case 3:
286 LOG_DEBUG("EJTAG: Version 3.1 Detected");
287 break;
288 default:
289 LOG_DEBUG("EJTAG: Unknown Version Detected");
290 break;
291 }
292 LOG_DEBUG("EJTAG: features:%s%s%s%s%s%s%s",
293 ejtag_info->impcode & EJTAG_IMP_R3K ? " R3k" : " R4k",
294 ejtag_info->impcode & EJTAG_IMP_DINT ? " DINT" : "",
295 ejtag_info->impcode & (1 << 22) ? " ASID_8" : "",
296 ejtag_info->impcode & (1 << 21) ? " ASID_6" : "",
297 ejtag_info->impcode & EJTAG_IMP_MIPS16 ? " MIPS16" : "",
298 ejtag_info->impcode & EJTAG_IMP_NODMA ? " noDMA" : " DMA",
299 ejtag_info->impcode & EJTAG_DCR_MIPS64 ? " MIPS64" : " MIPS32");
300
301 if ((ejtag_info->impcode & EJTAG_IMP_NODMA) == 0)
302 LOG_DEBUG("EJTAG: DMA Access Mode Support Enabled");
303
304 /* set initial state for ejtag control reg */
305 ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV;
306 ejtag_info->fast_access_save = -1;
307
308 return ERROR_OK;
309 }
310
311 int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data)
312 {
313 struct jtag_tap *tap;
314 tap = ejtag_info->tap;
315 assert(tap != NULL);
316
317 struct scan_field fields[2];
318 uint8_t spracc = 0;
319 uint8_t t[4] = {0, 0, 0, 0};
320
321 /* fastdata 1-bit register */
322 fields[0].num_bits = 1;
323 fields[0].out_value = &spracc;
324 fields[0].in_value = NULL;
325
326 /* processor access data register 32 bit */
327 fields[1].num_bits = 32;
328 fields[1].out_value = t;
329
330 if (write_t)
331 {
332 fields[1].in_value = NULL;
333 buf_set_u32(t, 0, 32, *data);
334 }
335 else
336 {
337 fields[1].in_value = (uint8_t *) data;
338 }
339
340 jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);
341 keep_alive();
342
343 return ERROR_OK;
344 }

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)