1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * Generic Xtensa debug module API for OpenOCD *
5 * Copyright (C) 2019 Espressif Systems Ltd. *
6 ***************************************************************************/
12 #include "xtensa_debug_module.h"
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
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
28 static void xtensa_dm_add_set_ir(struct xtensa_debug_module *dm, uint8_t value)
30 struct scan_field field;
33 memset(&field, 0, sizeof(field));
34 field.num_bits = dm->tap->ir_length;
36 buf_set_u32(t, 0, field.num_bits, value);
37 jtag_add_ir_scan(dm->tap, &field, TAP_IDLE);
40 static void xtensa_dm_add_dr_scan(struct xtensa_debug_module *dm,
46 struct scan_field field;
48 memset(&field, 0, sizeof(field));
50 field.out_value = src;
51 field.in_value = dest;
52 jtag_add_dr_scan(dm->tap, 1, &field, endstate);
55 int xtensa_dm_init(struct xtensa_debug_module *dm, const struct xtensa_debug_module_config *cfg)
60 dm->pwr_ops = cfg->pwr_ops;
61 dm->dbg_ops = cfg->dbg_ops;
63 dm->queue_tdi_idle = cfg->queue_tdi_idle;
64 dm->queue_tdi_idle_arg = cfg->queue_tdi_idle_arg;
68 int xtensa_dm_queue_enable(struct xtensa_debug_module *dm)
70 return dm->dbg_ops->queue_reg_write(dm, NARADR_DCRSET, OCDDCR_ENABLEOCD);
73 int xtensa_dm_queue_reg_read(struct xtensa_debug_module *dm, unsigned int reg, uint8_t *value)
75 uint8_t regdata = (reg << 1) | 0;
76 uint8_t dummy[4] = { 0, 0, 0, 0 };
78 if (reg > NARADR_MAX) {
79 LOG_ERROR("Invalid DBG reg ID %d!", reg);
82 xtensa_dm_add_set_ir(dm, TAPINS_NARSEL);
83 xtensa_dm_add_dr_scan(dm, TAPINS_NARSEL_ADRLEN, ®data, NULL, TAP_IDLE);
84 xtensa_dm_add_dr_scan(dm, TAPINS_NARSEL_DATALEN, dummy, value, TAP_IDLE);
88 int xtensa_dm_queue_reg_write(struct xtensa_debug_module *dm, unsigned int reg, uint32_t value)
90 uint8_t regdata = (reg << 1) | 1;
91 uint8_t valdata[] = { value, value >> 8, value >> 16, value >> 24 };
93 if (reg > NARADR_MAX) {
94 LOG_ERROR("Invalid DBG reg ID %d!", reg);
97 xtensa_dm_add_set_ir(dm, TAPINS_NARSEL);
98 xtensa_dm_add_dr_scan(dm, TAPINS_NARSEL_ADRLEN, ®data, NULL, TAP_IDLE);
99 xtensa_dm_add_dr_scan(dm, TAPINS_NARSEL_DATALEN, valdata, NULL, TAP_IDLE);
103 int xtensa_dm_queue_pwr_reg_read(struct xtensa_debug_module *dm, unsigned int reg, uint8_t *data, uint8_t clear)
105 uint8_t value_clr = clear;
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;
116 LOG_ERROR("Invalid PWR reg ID %d!", reg);
119 xtensa_dm_add_set_ir(dm, tap_insn);
120 xtensa_dm_add_dr_scan(dm, tap_insn_sz, &value_clr, data, TAP_IDLE);
124 int xtensa_dm_queue_pwr_reg_write(struct xtensa_debug_module *dm, unsigned int reg, uint8_t data)
126 uint8_t value = data;
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;
137 LOG_ERROR("Invalid PWR reg ID %d!", reg);
140 xtensa_dm_add_set_ir(dm, tap_insn);
141 xtensa_dm_add_dr_scan(dm, tap_insn_sz, &value, NULL, TAP_IDLE);
145 int xtensa_dm_device_id_read(struct xtensa_debug_module *dm)
147 uint8_t id_buf[sizeof(uint32_t)];
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();
154 dm->device_id = buf_get_u32(id_buf, 0, 32);
158 int xtensa_dm_power_status_read(struct xtensa_debug_module *dm, uint32_t clear)
160 /* uint8_t id_buf[sizeof(uint32_t)]; */
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);
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();
172 int xtensa_dm_core_status_read(struct xtensa_debug_module *dm)
174 uint8_t dsr_buf[sizeof(uint32_t)];
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();
182 dm->core_status.dsr = buf_get_u32(dsr_buf, 0, 32);
186 int xtensa_dm_core_status_clear(struct xtensa_debug_module *dm, xtensa_dsr_t bits)
188 dm->dbg_ops->queue_reg_write(dm, NARADR_DSR, bits);
189 xtensa_dm_queue_tdi_idle(dm);
190 return jtag_execute_queue();
193 int xtensa_dm_trace_start(struct xtensa_debug_module *dm, struct xtensa_trace_start_config *cfg)
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();
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);
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(
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();
221 int xtensa_dm_trace_stop(struct xtensa_debug_module *dm, bool pto_enable)
223 uint8_t traxctl_buf[sizeof(uint32_t)];
225 struct xtensa_trace_status trace_status;
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();
232 traxctl = buf_get_u32(traxctl_buf, 0, 32);
235 traxctl &= ~(TRAXCTRL_PTOWS | TRAXCTRL_PTOWT);
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();
243 /*Check current status of trace hardware */
244 res = xtensa_dm_trace_status_read(dm, &trace_status);
248 if (trace_status.stat & TRAXSTAT_TRACT) {
249 LOG_ERROR("Failed to stop tracing (0x%x)!", trace_status.stat);
255 int xtensa_dm_trace_status_read(struct xtensa_debug_module *dm, struct xtensa_trace_status *status)
257 uint8_t traxstat_buf[sizeof(uint32_t)];
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);
267 int xtensa_dm_trace_config_read(struct xtensa_debug_module *dm, struct xtensa_trace_config *config)
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)];
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);
292 int xtensa_dm_trace_data_read(struct xtensa_debug_module *dm, uint8_t *dest, uint32_t size)
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();
303 int xtensa_dm_perfmon_enable(struct xtensa_debug_module *dm, int counter_id,
304 const struct xtensa_perfmon_config *config)
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);
315 /* enable performance monitor */
316 dm->dbg_ops->queue_reg_write(dm, NARADR_PMG, 0x1);
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();
325 int xtensa_dm_perfmon_dump(struct xtensa_debug_module *dm, int counter_id,
326 struct xtensa_perfmon_result *out_result)
328 uint8_t pmstat_buf[4];
329 uint8_t pmcount_buf[4];
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);
339 /* TODO: if counter # counter_id+1 has 'select' set to 1, use its value as the
340 * high 32 bits of the counter. */
342 out_result->overflow = ((stat & 1) != 0);
343 out_result->value = result;