84ad5294b0655ab65e80573bd1c313a0a89a74d4
[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 int 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 if (tap == NULL)
37 return ERROR_FAIL;
38
39 if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr)
40 {
41 struct scan_field field;
42 uint8_t t[4];
43
44 field.num_bits = tap->ir_length;
45 field.out_value = t;
46 buf_set_u32(t, 0, field.num_bits, new_instr);
47 field.in_value = NULL;
48
49 jtag_add_ir_scan(tap, &field, TAP_IDLE);
50 }
51
52 return ERROR_OK;
53 }
54
55 int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode)
56 {
57 struct scan_field field;
58
59 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IDCODE);
60
61 field.num_bits = 32;
62 field.out_value = NULL;
63 field.in_value = (void*)idcode;
64
65 jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE);
66
67 if (jtag_execute_queue() != ERROR_OK)
68 {
69 LOG_ERROR("register read failed");
70 }
71
72 return ERROR_OK;
73 }
74
75 static int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info, uint32_t *impcode)
76 {
77 struct scan_field field;
78
79 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IMPCODE);
80
81 field.num_bits = 32;
82 field.out_value = NULL;
83 field.in_value = (void*)impcode;
84
85 jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE);
86
87 if (jtag_execute_queue() != ERROR_OK)
88 {
89 LOG_ERROR("register read failed");
90 }
91
92 return ERROR_OK;
93 }
94
95 int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data)
96 {
97 struct jtag_tap *tap;
98 tap = ejtag_info->tap;
99
100 if (tap == NULL)
101 return ERROR_FAIL;
102 struct scan_field field;
103 uint8_t t[4], r[4];
104 int retval;
105
106 field.num_bits = 32;
107 field.out_value = t;
108 buf_set_u32(t, 0, field.num_bits, *data);
109 field.in_value = r;
110
111 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
112
113 if ((retval = jtag_execute_queue()) != ERROR_OK)
114 {
115 LOG_ERROR("register read failed");
116 return retval;
117 }
118
119 *data = buf_get_u32(field.in_value, 0, 32);
120
121 keep_alive();
122
123 return ERROR_OK;
124 }
125
126 int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data)
127 {
128 struct jtag_tap *tap;
129 tap = ejtag_info->tap;
130
131 if (tap == NULL)
132 return ERROR_FAIL;
133 struct scan_field field;
134 uint8_t t[4] = {0, 0, 0, 0}, r[4];
135 int retval;
136
137 field.num_bits = 8;
138 field.out_value = t;
139 buf_set_u32(t, 0, field.num_bits, *data);
140 field.in_value = r;
141
142 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
143
144 if ((retval = jtag_execute_queue()) != ERROR_OK)
145 {
146 LOG_ERROR("register read failed");
147 return retval;
148 }
149
150 *data = buf_get_u32(field.in_value, 0, 32);
151
152 keep_alive();
153
154 return ERROR_OK;
155 }
156
157 static int mips_ejtag_step_enable(struct mips_ejtag *ejtag_info)
158 {
159 static const uint32_t code[] = {
160 MIPS32_MTC0(1,31,0), /* move $1 to COP0 DeSave */
161 MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */
162 MIPS32_ORI(1,1,0x0100), /* set SSt bit in debug reg */
163 MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */
164 MIPS32_B(NEG16(5)),
165 MIPS32_MFC0(1,31,0), /* move COP0 DeSave to $1 */
166 };
167
168 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
169 0, NULL, 0, NULL, 1);
170
171 return ERROR_OK;
172 }
173
174 static int mips_ejtag_step_disable(struct mips_ejtag *ejtag_info)
175 {
176 static const uint32_t code[] = {
177 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
178 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
179 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
180 MIPS32_SW(1,0,15), /* sw $1,($15) */
181 MIPS32_SW(2,0,15), /* sw $2,($15) */
182 MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */
183 MIPS32_LUI(2,0xFFFF), /* $2 = 0xfffffeff */
184 MIPS32_ORI(2,2,0xFEFF),
185 MIPS32_AND(1,1,2),
186 MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */
187 MIPS32_LW(2,0,15),
188 MIPS32_LW(1,0,15),
189 MIPS32_B(NEG16(13)),
190 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
191 };
192
193 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
194 0, NULL, 0, NULL, 1);
195
196 return ERROR_OK;
197 }
198
199 int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step)
200 {
201 if (enable_step)
202 return mips_ejtag_step_enable(ejtag_info);
203 return mips_ejtag_step_disable(ejtag_info);
204 }
205
206 int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info)
207 {
208 uint32_t ejtag_ctrl;
209 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
210
211 /* set debug break bit */
212 ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_JTAGBRK;
213 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
214
215 /* break bit will be cleared by hardware */
216 ejtag_ctrl = ejtag_info->ejtag_ctrl;
217 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
218 LOG_DEBUG("ejtag_ctrl: 0x%8.8" PRIx32 "", ejtag_ctrl);
219 if ((ejtag_ctrl & EJTAG_CTRL_BRKST) == 0)
220 LOG_DEBUG("Failed to enter Debug Mode!");
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
265 mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode);
266 LOG_DEBUG("impcode: 0x%8.8" PRIx32 "", ejtag_info->impcode);
267
268 /* get ejtag version */
269 ejtag_version = ((ejtag_info->impcode >> 29) & 0x07);
270
271 switch (ejtag_version)
272 {
273 case 0:
274 LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected");
275 break;
276 case 1:
277 LOG_DEBUG("EJTAG: Version 2.5 Detected");
278 break;
279 case 2:
280 LOG_DEBUG("EJTAG: Version 2.6 Detected");
281 break;
282 case 3:
283 LOG_DEBUG("EJTAG: Version 3.1 Detected");
284 break;
285 default:
286 LOG_DEBUG("EJTAG: Unknown Version Detected");
287 break;
288 }
289 LOG_DEBUG("EJTAG: features:%s%s%s%s%s%s%s",
290 ejtag_info->impcode & EJTAG_IMP_R3K ? " R3k" : " R4k",
291 ejtag_info->impcode & EJTAG_IMP_DINT ? " DINT" : "",
292 ejtag_info->impcode & (1 << 22) ? " ASID_8" : "",
293 ejtag_info->impcode & (1 << 21) ? " ASID_6" : "",
294 ejtag_info->impcode & EJTAG_IMP_MIPS16 ? " MIPS16" : "",
295 ejtag_info->impcode & EJTAG_IMP_NODMA ? " noDMA" : " DMA",
296 ejtag_info->impcode & EJTAG_DCR_MIPS64 ? " MIPS64" : " MIPS32");
297
298 if ((ejtag_info->impcode & EJTAG_IMP_NODMA) == 0)
299 LOG_DEBUG("EJTAG: DMA Access Mode Support Enabled");
300
301 /* set initial state for ejtag control reg */
302 ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV;
303
304 return ERROR_OK;
305 }
306
307 int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write, uint32_t *data)
308 {
309 struct jtag_tap *tap;
310 tap = ejtag_info->tap;
311
312 if (tap == NULL)
313 return ERROR_FAIL;
314
315 struct scan_field fields[2];
316 uint8_t spracc = 0;
317 uint8_t t[4] = {0, 0, 0, 0};
318
319 /* fastdata 1-bit register */
320 fields[0].num_bits = 1;
321 fields[0].out_value = &spracc;
322 fields[0].in_value = NULL;
323
324 /* processor access data register 32 bit */
325 fields[1].num_bits = 32;
326 fields[1].out_value = t;
327
328 if (write)
329 {
330 fields[1].in_value = NULL;
331 buf_set_u32(t, 0, 32, *data);
332 }
333 else
334 {
335 fields[1].in_value = (uint8_t *) data;
336 }
337
338 jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);
339 keep_alive();
340
341 return ERROR_OK;
342 }

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)