68a39faf3d6a81c732d9e2f0612f7d0a96db4956
[fw/openocd] / 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  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
21  ***************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "mips32.h"
27 #include "mips_ejtag.h"
28
29
30 int mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, int new_instr, void *delete_me_and_submit_patch)
31 {
32         struct jtag_tap *tap;
33
34         tap = ejtag_info->tap;
35         if (tap == NULL)
36                 return ERROR_FAIL;
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.tap = tap;
44                 field.num_bits = tap->ir_length;
45                 field.out_value = t;
46                 buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
47                 field.in_value = NULL;
48
49                 jtag_add_ir_scan(1, &field, jtag_get_end_state());
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         jtag_set_end_state(TAP_IDLE);
60
61         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IDCODE, NULL);
62
63         field.tap = ejtag_info->tap;
64         field.num_bits = 32;
65         field.out_value = NULL;
66         field.in_value = (void*)idcode;
67
68         jtag_add_dr_scan(1, &field, jtag_get_end_state());
69
70         if (jtag_execute_queue() != ERROR_OK)
71         {
72                 LOG_ERROR("register read failed");
73         }
74
75         return ERROR_OK;
76 }
77
78 int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info, uint32_t *impcode)
79 {
80         struct scan_field field;
81
82         jtag_set_end_state(TAP_IDLE);
83
84         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IMPCODE, NULL);
85
86         field.tap = ejtag_info->tap;
87         field.num_bits = 32;
88         field.out_value = NULL;
89         field.in_value = (void*)impcode;
90
91         jtag_add_dr_scan(1, &field, jtag_get_end_state());
92
93         if (jtag_execute_queue() != ERROR_OK)
94         {
95                 LOG_ERROR("register read failed");
96         }
97
98         return ERROR_OK;
99 }
100
101 int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data)
102 {
103         struct jtag_tap *tap;
104         tap  = ejtag_info->tap;
105
106         if (tap == NULL)
107                 return ERROR_FAIL;
108         struct scan_field field;
109         uint8_t t[4], r[4];
110         int retval;
111
112         field.tap = tap;
113         field.num_bits = 32;
114         field.out_value = t;
115         buf_set_u32(field.out_value, 0, field.num_bits, *data);
116         field.in_value = r;
117
118         jtag_add_dr_scan(1, &field, jtag_get_end_state());
119
120         if ((retval = jtag_execute_queue()) != ERROR_OK)
121         {
122                 LOG_ERROR("register read failed");
123                 return retval;
124         }
125
126         *data = buf_get_u32(field.in_value, 0, 32);
127
128         keep_alive();
129
130         return ERROR_OK;
131 }
132
133 int mips_ejtag_step_enable(struct mips_ejtag *ejtag_info)
134 {
135         uint32_t code[] = {
136                         MIPS32_MTC0(1,31,0),                    /* move $1 to COP0 DeSave */
137                         MIPS32_MFC0(1,23,0),                    /* move COP0 Debug to $1 */
138                         MIPS32_ORI(1,1,0x0100),                 /* set SSt bit in debug reg */
139                         MIPS32_MTC0(1,23,0),                    /* move $1 to COP0 Debug */
140                         MIPS32_MFC0(1,31,0),                    /* move COP0 DeSave to $1 */
141                         MIPS32_NOP,
142                         MIPS32_B(NEG16(7)),
143                         MIPS32_NOP,
144         };
145
146         mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
147                 0, NULL, 0, NULL, 1);
148
149         return ERROR_OK;
150 }
151 int mips_ejtag_step_disable(struct mips_ejtag *ejtag_info)
152 {
153         uint32_t code[] = {
154                         MIPS32_MTC0(15,31,0),                                                   /* move $15 to COP0 DeSave */
155                         MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),     /* $15 = MIPS32_PRACC_STACK */
156                         MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
157                         MIPS32_SW(1,0,15),                                                              /* sw $1,($15) */
158                         MIPS32_SW(2,0,15),                                                              /* sw $2,($15) */
159                         MIPS32_MFC0(1,23,0),                                                    /* move COP0 Debug to $1 */
160                         MIPS32_LUI(2,0xFFFF),                                                   /* $2 = 0xfffffeff */
161                         MIPS32_ORI(2,2,0xFEFF),
162                         MIPS32_AND(1,1,2),
163                         MIPS32_MTC0(1,23,0),                                                    /* move $1 to COP0 Debug */
164                         MIPS32_LW(2,0,15),
165                         MIPS32_LW(1,0,15),
166                         MIPS32_MFC0(15,31,0),                                                   /* move COP0 DeSave to $15 */
167                         MIPS32_NOP,
168                         MIPS32_B(NEG16(15)),
169                         MIPS32_NOP,
170         };
171
172         mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
173                 0, NULL, 0, NULL, 1);
174
175         return ERROR_OK;
176 }
177
178 int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step)
179 {
180         if (enable_step)
181                 return mips_ejtag_step_enable(ejtag_info);
182         return mips_ejtag_step_disable(ejtag_info);
183 }
184
185 int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info)
186 {
187         uint32_t ejtag_ctrl;
188         jtag_set_end_state(TAP_IDLE);
189         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
190
191         /* set debug break bit */
192         ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_JTAGBRK;
193         mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
194
195         /* break bit will be cleared by hardware */
196         ejtag_ctrl = ejtag_info->ejtag_ctrl;
197         mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
198         LOG_DEBUG("ejtag_ctrl: 0x%8.8" PRIx32 "", ejtag_ctrl);
199         if ((ejtag_ctrl & EJTAG_CTRL_BRKST) == 0)
200                 LOG_DEBUG("Failed to enter Debug Mode!");
201
202         return ERROR_OK;
203 }
204
205 int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info)
206 {
207         uint32_t inst;
208         inst = MIPS32_DRET;
209
210         /* execute our dret instruction */
211         mips32_pracc_exec(ejtag_info, 1, &inst, 0, NULL, 0, NULL, 0);
212
213         return ERROR_OK;
214 }
215
216 int mips_ejtag_read_debug(struct mips_ejtag *ejtag_info, uint32_t* debug_reg)
217 {
218         /* read ejtag ECR */
219         uint32_t code[] = {
220                         MIPS32_MTC0(15,31,0),                                                   /* move $15 to COP0 DeSave */
221                         MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),     /* $15 = MIPS32_PRACC_STACK */
222                         MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
223                         MIPS32_SW(1,0,15),                                                              /* sw $1,($15) */
224                         MIPS32_SW(2,0,15),                                                              /* sw $2,($15) */
225                         MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)),  /* $1 = MIPS32_PRACC_PARAM_OUT */
226                         MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
227                         MIPS32_MFC0(2,23,0),                                                    /* move COP0 Debug to $2 */
228                         MIPS32_SW(2,0,1),
229                         MIPS32_LW(2,0,15),
230                         MIPS32_LW(1,0,15),
231                         MIPS32_MFC0(15,31,0),                                                   /* move COP0 DeSave to $15 */
232                         MIPS32_NOP,
233                         MIPS32_B(NEG16(14)),
234                         MIPS32_NOP,
235         };
236
237         mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
238                 0, NULL, 1, debug_reg, 1);
239
240         return ERROR_OK;
241 }
242
243 int mips_ejtag_init(struct mips_ejtag *ejtag_info)
244 {
245         uint32_t ejtag_version;
246
247         mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode);
248         LOG_DEBUG("impcode: 0x%8.8" PRIx32 "", ejtag_info->impcode);
249
250         /* get ejtag version */
251         ejtag_version = ((ejtag_info->impcode >> 29) & 0x07);
252
253         switch (ejtag_version)
254         {
255                 case 0:
256                         LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected");
257                         break;
258                 case 1:
259                         LOG_DEBUG("EJTAG: Version 2.5 Detected");
260                         break;
261                 case 2:
262                         LOG_DEBUG("EJTAG: Version 2.6 Detected");
263                         break;
264                 case 3:
265                         LOG_DEBUG("EJTAG: Version 3.1 Detected");
266                         break;
267                 default:
268                         LOG_DEBUG("EJTAG: Unknown Version Detected");
269                         break;
270         }
271         LOG_DEBUG("EJTAG: features:%s%s%s%s%s%s%s",
272                 ejtag_info->impcode & (1 << 28) ? " R3k":    " R4k",
273                 ejtag_info->impcode & (1 << 24) ? " DINT":   "",
274                 ejtag_info->impcode & (1 << 22) ? " ASID_8": "",
275                 ejtag_info->impcode & (1 << 21) ? " ASID_6": "",
276                 ejtag_info->impcode & (1 << 16) ? " MIPS16": "",
277                 ejtag_info->impcode & (1 << 14) ? " noDMA":  " DMA",
278                 ejtag_info->impcode & (1 << 0)  ? " MIPS64": " MIPS32"
279 );
280
281         if ((ejtag_info->impcode & (1 << 14)) == 0)
282                 LOG_DEBUG("EJTAG: DMA Access Mode Support Enabled");
283
284         /* set initial state for ejtag control reg */
285         ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV;
286
287         return ERROR_OK;
288 }