a7de1ad5c9550a39b130a8f6b7cff0318c8b434e
[fw/openocd] / src / target / xtensa / xtensa_debug_module.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Generic Xtensa debug module API for OpenOCD                           *
5  *   Copyright (C) 2019 Espressif Systems Ltd.                             *
6  ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include "xtensa_debug_module.h"
13
14 #define TAPINS_PWRCTL           0x08
15 #define TAPINS_PWRSTAT          0x09
16 #define TAPINS_NARSEL           0x1C
17 #define TAPINS_IDCODE           0x1E
18 #define TAPINS_BYPASS           0x1F
19
20 #define TAPINS_PWRCTL_LEN       8
21 #define TAPINS_PWRSTAT_LEN      8
22 #define TAPINS_NARSEL_ADRLEN    8
23 #define TAPINS_NARSEL_DATALEN   32
24 #define TAPINS_IDCODE_LEN       32
25 #define TAPINS_BYPASS_LEN       1
26
27
28 static void xtensa_dm_add_set_ir(struct xtensa_debug_module *dm, uint8_t value)
29 {
30         struct scan_field field;
31         uint8_t t[4] = { 0 };
32
33         memset(&field, 0, sizeof(field));
34         field.num_bits = dm->tap->ir_length;
35         field.out_value = t;
36         buf_set_u32(t, 0, field.num_bits, value);
37         jtag_add_ir_scan(dm->tap, &field, TAP_IDLE);
38 }
39
40 static void xtensa_dm_add_dr_scan(struct xtensa_debug_module *dm,
41         int len,
42         const uint8_t *src,
43         uint8_t *dest,
44         tap_state_t endstate)
45 {
46         struct scan_field field;
47
48         memset(&field, 0, sizeof(field));
49         field.num_bits = len;
50         field.out_value = src;
51         field.in_value = dest;
52         jtag_add_dr_scan(dm->tap, 1, &field, endstate);
53 }
54
55 int xtensa_dm_init(struct xtensa_debug_module *dm, const struct xtensa_debug_module_config *cfg)
56 {
57         if (!dm || !cfg)
58                 return ERROR_FAIL;
59
60         dm->pwr_ops = cfg->pwr_ops;
61         dm->dbg_ops = cfg->dbg_ops;
62         dm->tap = cfg->tap;
63         dm->queue_tdi_idle = cfg->queue_tdi_idle;
64         dm->queue_tdi_idle_arg = cfg->queue_tdi_idle_arg;
65         return ERROR_OK;
66 }
67
68 int xtensa_dm_queue_enable(struct xtensa_debug_module *dm)
69 {
70         return dm->dbg_ops->queue_reg_write(dm, NARADR_DCRSET, OCDDCR_ENABLEOCD);
71 }
72
73 int xtensa_dm_queue_reg_read(struct xtensa_debug_module *dm, unsigned int reg, uint8_t *value)
74 {
75         uint8_t regdata = (reg << 1) | 0;
76         uint8_t dummy[4] = { 0, 0, 0, 0 };
77
78         if (reg > NARADR_MAX) {
79                 LOG_ERROR("Invalid DBG reg ID %d!", reg);
80                 return ERROR_FAIL;
81         }
82         xtensa_dm_add_set_ir(dm, TAPINS_NARSEL);
83         xtensa_dm_add_dr_scan(dm, TAPINS_NARSEL_ADRLEN, &regdata, NULL, TAP_IDLE);
84         xtensa_dm_add_dr_scan(dm, TAPINS_NARSEL_DATALEN, dummy, value, TAP_IDLE);
85         return ERROR_OK;
86 }
87
88 int xtensa_dm_queue_reg_write(struct xtensa_debug_module *dm, unsigned int reg, uint32_t value)
89 {
90         uint8_t regdata = (reg << 1) | 1;
91         uint8_t valdata[] = { value, value >> 8, value >> 16, value >> 24 };
92
93         if (reg > NARADR_MAX) {
94                 LOG_ERROR("Invalid DBG reg ID %d!", reg);
95                 return ERROR_FAIL;
96         }
97         xtensa_dm_add_set_ir(dm, TAPINS_NARSEL);
98         xtensa_dm_add_dr_scan(dm, TAPINS_NARSEL_ADRLEN, &regdata, NULL, TAP_IDLE);
99         xtensa_dm_add_dr_scan(dm, TAPINS_NARSEL_DATALEN, valdata, NULL, TAP_IDLE);
100         return ERROR_OK;
101 }
102
103 int xtensa_dm_queue_pwr_reg_read(struct xtensa_debug_module *dm, unsigned int reg, uint8_t *data, uint8_t clear)
104 {
105         uint8_t value_clr = clear;
106         uint8_t tap_insn;
107         int tap_insn_sz;
108
109         if (reg == DMREG_PWRCTL) {
110                 tap_insn = TAPINS_PWRCTL;
111                 tap_insn_sz = TAPINS_PWRCTL_LEN;
112         } else if (reg == DMREG_PWRSTAT) {
113                 tap_insn = TAPINS_PWRSTAT;
114                 tap_insn_sz = TAPINS_PWRSTAT_LEN;
115         } else {
116                 LOG_ERROR("Invalid PWR reg ID %d!", reg);
117                 return ERROR_FAIL;
118         }
119         xtensa_dm_add_set_ir(dm, tap_insn);
120         xtensa_dm_add_dr_scan(dm, tap_insn_sz, &value_clr, data, TAP_IDLE);
121         return ERROR_OK;
122 }
123
124 int xtensa_dm_queue_pwr_reg_write(struct xtensa_debug_module *dm, unsigned int reg, uint8_t data)
125 {
126         uint8_t value = data;
127         uint8_t tap_insn;
128         int tap_insn_sz;
129
130         if (reg == DMREG_PWRCTL) {
131                 tap_insn = TAPINS_PWRCTL;
132                 tap_insn_sz = TAPINS_PWRCTL_LEN;
133         } else if (reg == DMREG_PWRSTAT) {
134                 tap_insn = TAPINS_PWRSTAT;
135                 tap_insn_sz = TAPINS_PWRSTAT_LEN;
136         } else {
137                 LOG_ERROR("Invalid PWR reg ID %d!", reg);
138                 return ERROR_FAIL;
139         }
140         xtensa_dm_add_set_ir(dm, tap_insn);
141         xtensa_dm_add_dr_scan(dm, tap_insn_sz, &value, NULL, TAP_IDLE);
142         return ERROR_OK;
143 }
144
145 int xtensa_dm_device_id_read(struct xtensa_debug_module *dm)
146 {
147         uint8_t id_buf[sizeof(uint32_t)];
148
149         dm->dbg_ops->queue_reg_read(dm, NARADR_OCDID, id_buf);
150         xtensa_dm_queue_tdi_idle(dm);
151         int res = jtag_execute_queue();
152         if (res != ERROR_OK)
153                 return res;
154         dm->device_id = buf_get_u32(id_buf, 0, 32);
155         return ERROR_OK;
156 }
157
158 int xtensa_dm_power_status_read(struct xtensa_debug_module *dm, uint32_t clear)
159 {
160         /* uint8_t id_buf[sizeof(uint32_t)]; */
161
162         /* TODO: JTAG does not work when PWRCTL_JTAGDEBUGUSE is not set.
163          * It is set in xtensa_examine(), need to move reading of NARADR_OCDID out of this function */
164         /* dm->dbg_ops->queue_reg_read(dm, NARADR_OCDID, id_buf);
165          *Read reset state */
166         dm->pwr_ops->queue_reg_read(dm, DMREG_PWRSTAT, &dm->power_status.stat, clear);
167         dm->pwr_ops->queue_reg_read(dm, DMREG_PWRSTAT, &dm->power_status.stath, clear);
168         xtensa_dm_queue_tdi_idle(dm);
169         return jtag_execute_queue();
170 }
171
172 int xtensa_dm_core_status_read(struct xtensa_debug_module *dm)
173 {
174         uint8_t dsr_buf[sizeof(uint32_t)];
175
176         xtensa_dm_queue_enable(dm);
177         dm->dbg_ops->queue_reg_read(dm, NARADR_DSR, dsr_buf);
178         xtensa_dm_queue_tdi_idle(dm);
179         int res = jtag_execute_queue();
180         if (res != ERROR_OK)
181                 return res;
182         dm->core_status.dsr = buf_get_u32(dsr_buf, 0, 32);
183         return res;
184 }
185
186 int xtensa_dm_core_status_clear(struct xtensa_debug_module *dm, xtensa_dsr_t bits)
187 {
188         dm->dbg_ops->queue_reg_write(dm, NARADR_DSR, bits);
189         xtensa_dm_queue_tdi_idle(dm);
190         return jtag_execute_queue();
191 }
192
193 int xtensa_dm_trace_start(struct xtensa_debug_module *dm, struct xtensa_trace_start_config *cfg)
194 {
195         /*Turn off trace unit so we can start a new trace. */
196         dm->dbg_ops->queue_reg_write(dm, NARADR_TRAXCTRL, 0);
197         xtensa_dm_queue_tdi_idle(dm);
198         int res = jtag_execute_queue();
199         if (res != ERROR_OK)
200                 return res;
201
202         /*Set up parameters */
203         dm->dbg_ops->queue_reg_write(dm, NARADR_TRAXADDR, 0);
204         if (cfg->stopmask != XTENSA_STOPMASK_DISABLED) {
205                 dm->dbg_ops->queue_reg_write(dm, NARADR_PCMATCHCTRL,
206                         (cfg->stopmask << PCMATCHCTRL_PCML_SHIFT));
207                 dm->dbg_ops->queue_reg_write(dm, NARADR_TRIGGERPC, cfg->stoppc);
208         }
209         dm->dbg_ops->queue_reg_write(dm, NARADR_DELAYCNT, cfg->after);
210         /*Options are mostly hardcoded for now. ToDo: make this more configurable. */
211         dm->dbg_ops->queue_reg_write(
212                 dm,
213                 NARADR_TRAXCTRL,
214                 TRAXCTRL_TREN |
215                 ((cfg->stopmask != XTENSA_STOPMASK_DISABLED) ? TRAXCTRL_PCMEN : 0) | TRAXCTRL_TMEN |
216                 (cfg->after_is_words ? 0 : TRAXCTRL_CNTU) | (0 << TRAXCTRL_SMPER_SHIFT) | TRAXCTRL_PTOWS);
217         xtensa_dm_queue_tdi_idle(dm);
218         return jtag_execute_queue();
219 }
220
221 int xtensa_dm_trace_stop(struct xtensa_debug_module *dm, bool pto_enable)
222 {
223         uint8_t traxctl_buf[sizeof(uint32_t)];
224         uint32_t traxctl;
225         struct xtensa_trace_status trace_status;
226
227         dm->dbg_ops->queue_reg_read(dm, NARADR_TRAXCTRL, traxctl_buf);
228         xtensa_dm_queue_tdi_idle(dm);
229         int res = jtag_execute_queue();
230         if (res != ERROR_OK)
231                 return res;
232         traxctl = buf_get_u32(traxctl_buf, 0, 32);
233
234         if (!pto_enable)
235                 traxctl &= ~(TRAXCTRL_PTOWS | TRAXCTRL_PTOWT);
236
237         dm->dbg_ops->queue_reg_write(dm, NARADR_TRAXCTRL, traxctl | TRAXCTRL_TRSTP);
238         xtensa_dm_queue_tdi_idle(dm);
239         res = jtag_execute_queue();
240         if (res != ERROR_OK)
241                 return res;
242
243         /*Check current status of trace hardware */
244         res = xtensa_dm_trace_status_read(dm, &trace_status);
245         if (res != ERROR_OK)
246                 return res;
247
248         if (trace_status.stat & TRAXSTAT_TRACT) {
249                 LOG_ERROR("Failed to stop tracing (0x%x)!", trace_status.stat);
250                 return ERROR_FAIL;
251         }
252         return ERROR_OK;
253 }
254
255 int xtensa_dm_trace_status_read(struct xtensa_debug_module *dm, struct xtensa_trace_status *status)
256 {
257         uint8_t traxstat_buf[sizeof(uint32_t)];
258
259         dm->dbg_ops->queue_reg_read(dm, NARADR_TRAXSTAT, traxstat_buf);
260         xtensa_dm_queue_tdi_idle(dm);
261         int res = jtag_execute_queue();
262         if (res == ERROR_OK && status)
263                 status->stat = buf_get_u32(traxstat_buf, 0, 32);
264         return res;
265 }
266
267 int xtensa_dm_trace_config_read(struct xtensa_debug_module *dm, struct xtensa_trace_config *config)
268 {
269         uint8_t traxctl_buf[sizeof(uint32_t)];
270         uint8_t memadrstart_buf[sizeof(uint32_t)];
271         uint8_t memadrend_buf[sizeof(uint32_t)];
272         uint8_t adr_buf[sizeof(uint32_t)];
273
274         if (!config)
275                 return ERROR_FAIL;
276
277         dm->dbg_ops->queue_reg_read(dm, NARADR_TRAXCTRL, traxctl_buf);
278         dm->dbg_ops->queue_reg_read(dm, NARADR_MEMADDRSTART, memadrstart_buf);
279         dm->dbg_ops->queue_reg_read(dm, NARADR_MEMADDREND, memadrend_buf);
280         dm->dbg_ops->queue_reg_read(dm, NARADR_TRAXADDR, adr_buf);
281         xtensa_dm_queue_tdi_idle(dm);
282         int res = jtag_execute_queue();
283         if (res == ERROR_OK) {
284                 config->ctrl = buf_get_u32(traxctl_buf, 0, 32);
285                 config->memaddr_start = buf_get_u32(memadrstart_buf, 0, 32);
286                 config->memaddr_end = buf_get_u32(memadrend_buf, 0, 32);
287                 config->addr = buf_get_u32(adr_buf, 0, 32);
288         }
289         return res;
290 }
291
292 int xtensa_dm_trace_data_read(struct xtensa_debug_module *dm, uint8_t *dest, uint32_t size)
293 {
294         if (!dest)
295                 return ERROR_FAIL;
296
297         for (unsigned int i = 0; i < size / 4; i++)
298                 dm->dbg_ops->queue_reg_read(dm, NARADR_TRAXDATA, &dest[i * 4]);
299         xtensa_dm_queue_tdi_idle(dm);
300         return jtag_execute_queue();
301 }
302
303 int xtensa_dm_perfmon_enable(struct xtensa_debug_module *dm, int counter_id,
304         const struct xtensa_perfmon_config *config)
305 {
306         if (!config)
307                 return ERROR_FAIL;
308
309         uint8_t pmstat_buf[4];
310         uint32_t pmctrl = ((config->tracelevel) << 4) +
311                 (config->select << 8) +
312                 (config->mask << 16) +
313                 (config->kernelcnt << 3);
314
315         /* enable performance monitor */
316         dm->dbg_ops->queue_reg_write(dm, NARADR_PMG, 0x1);
317         /* reset counter */
318         dm->dbg_ops->queue_reg_write(dm, NARADR_PM0 + counter_id, 0);
319         dm->dbg_ops->queue_reg_write(dm, NARADR_PMCTRL0 + counter_id, pmctrl);
320         dm->dbg_ops->queue_reg_read(dm, NARADR_PMSTAT0 + counter_id, pmstat_buf);
321         xtensa_dm_queue_tdi_idle(dm);
322         return jtag_execute_queue();
323 }
324
325 int xtensa_dm_perfmon_dump(struct xtensa_debug_module *dm, int counter_id,
326         struct xtensa_perfmon_result *out_result)
327 {
328         uint8_t pmstat_buf[4];
329         uint8_t pmcount_buf[4];
330
331         dm->dbg_ops->queue_reg_read(dm, NARADR_PMSTAT0 + counter_id, pmstat_buf);
332         dm->dbg_ops->queue_reg_read(dm, NARADR_PM0 + counter_id, pmcount_buf);
333         xtensa_dm_queue_tdi_idle(dm);
334         int res = jtag_execute_queue();
335         if (res == ERROR_OK) {
336                 uint32_t stat = buf_get_u32(pmstat_buf, 0, 32);
337                 uint64_t result = buf_get_u32(pmcount_buf, 0, 32);
338
339                 /* TODO: if counter # counter_id+1 has 'select' set to 1, use its value as the
340                 * high 32 bits of the counter. */
341                 if (out_result) {
342                         out_result->overflow = ((stat & 1) != 0);
343                         out_result->value = result;
344                 }
345         }
346
347         return res;
348 }