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

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)