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

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)