jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / target / espressif / esp32s3.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * ESP32-S3 target API for OpenOCD *
5 * Copyright (C) 2020 Espressif Systems Ltd. *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <helper/time_support.h>
13 #include <target/target.h>
14 #include <target/target_type.h>
15 #include <target/smp.h>
16 #include <target/semihosting_common.h>
17 #include "assert.h"
18 #include "esp_xtensa_smp.h"
19
20 /*
21 This is a JTAG driver for the ESP32_S3, the are two Tensilica cores inside
22 the ESP32_S3 chip. For more information please have a look into ESP32_S3 target
23 implementation.
24 */
25
26 /* ESP32_S3 memory map */
27 #define ESP32_S3_RTC_DATA_LOW 0x50000000
28 #define ESP32_S3_RTC_DATA_HIGH 0x50002000
29 #define ESP32_S3_EXTRAM_DATA_LOW 0x3D000000
30 #define ESP32_S3_EXTRAM_DATA_HIGH 0x3E000000
31 #define ESP32_S3_SYS_RAM_LOW 0x60000000UL
32 #define ESP32_S3_SYS_RAM_HIGH (ESP32_S3_SYS_RAM_LOW + 0x10000000UL)
33 #define ESP32_S3_RTC_SLOW_MEM_BASE ESP32_S3_RTC_DATA_LOW
34
35 /* ESP32_S3 WDT */
36 #define ESP32_S3_WDT_WKEY_VALUE 0x50D83AA1
37 #define ESP32_S3_TIMG0_BASE 0x6001F000
38 #define ESP32_S3_TIMG1_BASE 0x60020000
39 #define ESP32_S3_TIMGWDT_CFG0_OFF 0x48
40 #define ESP32_S3_TIMGWDT_PROTECT_OFF 0x64
41 #define ESP32_S3_TIMG0WDT_CFG0 (ESP32_S3_TIMG0_BASE + ESP32_S3_TIMGWDT_CFG0_OFF)
42 #define ESP32_S3_TIMG1WDT_CFG0 (ESP32_S3_TIMG1_BASE + ESP32_S3_TIMGWDT_CFG0_OFF)
43 #define ESP32_S3_TIMG0WDT_PROTECT (ESP32_S3_TIMG0_BASE + ESP32_S3_TIMGWDT_PROTECT_OFF)
44 #define ESP32_S3_TIMG1WDT_PROTECT (ESP32_S3_TIMG1_BASE + ESP32_S3_TIMGWDT_PROTECT_OFF)
45 #define ESP32_S3_RTCCNTL_BASE 0x60008000
46 #define ESP32_S3_RTCWDT_CFG_OFF 0x98
47 #define ESP32_S3_RTCWDT_PROTECT_OFF 0xB0
48 #define ESP32_S3_SWD_CONF_OFF 0xB0
49 #define ESP32_S3_SWD_WPROTECT_OFF 0xB4
50 #define ESP32_S3_RTCWDT_CFG (ESP32_S3_RTCCNTL_BASE + ESP32_S3_RTCWDT_CFG_OFF)
51 #define ESP32_S3_RTCWDT_PROTECT (ESP32_S3_RTCCNTL_BASE + ESP32_S3_RTCWDT_PROTECT_OFF)
52 #define ESP32_S3_SWD_CONF_REG (ESP32_S3_RTCCNTL_BASE + ESP32_S3_SWD_CONF_OFF)
53 #define ESP32_S3_SWD_WPROTECT_REG (ESP32_S3_RTCCNTL_BASE + ESP32_S3_SWD_WPROTECT_OFF)
54 #define ESP32_S3_SWD_AUTO_FEED_EN_M BIT(31)
55 #define ESP32_S3_SWD_WKEY_VALUE 0x8F1D312AU
56
57 #define ESP32_S3_TRACEMEM_BLOCK_SZ 0x4000
58
59 /* ESP32_S3 dport regs */
60 #define ESP32_S3_DR_REG_SYSTEM_BASE 0x600c0000
61 #define ESP32_S3_SYSTEM_CORE_1_CONTROL_0_REG (ESP32_S3_DR_REG_SYSTEM_BASE + 0x014)
62 #define ESP32_S3_SYSTEM_CONTROL_CORE_1_CLKGATE_EN BIT(1)
63
64 /* ESP32_S3 RTC regs */
65 #define ESP32_S3_RTC_CNTL_SW_CPU_STALL_REG (ESP32_S3_RTCCNTL_BASE + 0xBC)
66 #define ESP32_S3_RTC_CNTL_SW_CPU_STALL_DEF 0x0
67
68 struct esp32s3_common {
69 struct esp_xtensa_smp_common esp_xtensa_smp;
70 };
71
72 /* Reset ESP32-S3's peripherals.
73 * 1. OpenOCD makes sure the target is halted; if not, tries to halt it.
74 * If that fails, tries to reset it (via OCD) and then halt.
75 * 2. OpenOCD loads the stub code into RTC_SLOW_MEM.
76 * 3. Executes the stub code from address 0x50000004.
77 * 4. The stub code changes the reset vector to 0x50000000, and triggers
78 * a system reset using RTC_CNTL_SW_SYS_RST bit.
79 * 5. Once the PRO CPU is out of reset, it executes the stub code from address 0x50000000.
80 * The stub code disables the watchdog, re-enables JTAG and the APP CPU,
81 * restores the reset vector, and enters an infinite loop.
82 * 6. OpenOCD waits until it can talk to the OCD module again, then halts the target.
83 * 7. OpenOCD restores the contents of RTC_SLOW_MEM.
84 *
85 * End result: all the peripherals except RTC_CNTL are reset, CPU's PC is undefined,
86 * PRO CPU is halted, APP CPU is in reset.
87 */
88
89 static const uint8_t esp32s3_reset_stub_code[] = {
90 #include "../../../contrib/loaders/reset/espressif/esp32s3/cpu_reset_handler_code.inc"
91 };
92
93 static int esp32s3_soc_reset(struct target *target)
94 {
95 int res;
96 struct target_list *head;
97 struct xtensa *xtensa;
98
99 LOG_DEBUG("start");
100 /* In order to write to peripheral registers, target must be halted first */
101 if (target->state != TARGET_HALTED) {
102 LOG_DEBUG("Target not halted before SoC reset, trying to halt it first");
103 xtensa_halt(target);
104 res = target_wait_state(target, TARGET_HALTED, 1000);
105 if (res != ERROR_OK) {
106 LOG_DEBUG("Couldn't halt target before SoC reset, trying to do reset-halt");
107 res = xtensa_assert_reset(target);
108 if (res != ERROR_OK) {
109 LOG_ERROR(
110 "Couldn't halt target before SoC reset! (xtensa_assert_reset returned %d)",
111 res);
112 return res;
113 }
114 alive_sleep(10);
115 xtensa_poll(target);
116 bool reset_halt_save = target->reset_halt;
117 target->reset_halt = true;
118 res = xtensa_deassert_reset(target);
119 target->reset_halt = reset_halt_save;
120 if (res != ERROR_OK) {
121 LOG_ERROR(
122 "Couldn't halt target before SoC reset! (xtensa_deassert_reset returned %d)",
123 res);
124 return res;
125 }
126 alive_sleep(10);
127 xtensa_poll(target);
128 xtensa_halt(target);
129 res = target_wait_state(target, TARGET_HALTED, 1000);
130 if (res != ERROR_OK) {
131 LOG_ERROR("Couldn't halt target before SoC reset");
132 return res;
133 }
134 }
135 }
136
137 if (target->smp) {
138 foreach_smp_target(head, target->smp_targets) {
139 xtensa = target_to_xtensa(head->target);
140 /* if any of the cores is stalled unstall them */
141 if (xtensa_dm_core_is_stalled(&xtensa->dbg_mod)) {
142 LOG_TARGET_DEBUG(head->target, "Unstall CPUs before SW reset!");
143 res = target_write_u32(target,
144 ESP32_S3_RTC_CNTL_SW_CPU_STALL_REG,
145 ESP32_S3_RTC_CNTL_SW_CPU_STALL_DEF);
146 if (res != ERROR_OK) {
147 LOG_TARGET_ERROR(head->target, "Failed to unstall CPUs before SW reset!");
148 return res;
149 }
150 break; /* both cores are unstalled now, so exit the loop */
151 }
152 }
153 }
154
155 LOG_DEBUG("Loading stub code into RTC RAM");
156 uint8_t slow_mem_save[sizeof(esp32s3_reset_stub_code)];
157
158 /* Save contents of RTC_SLOW_MEM which we are about to overwrite */
159 res = target_read_buffer(target, ESP32_S3_RTC_SLOW_MEM_BASE, sizeof(slow_mem_save), slow_mem_save);
160 if (res != ERROR_OK) {
161 LOG_ERROR("Failed to save contents of RTC_SLOW_MEM (%d)!", res);
162 return res;
163 }
164
165 /* Write stub code into RTC_SLOW_MEM */
166 res = target_write_buffer(target,
167 ESP32_S3_RTC_SLOW_MEM_BASE,
168 sizeof(esp32s3_reset_stub_code),
169 esp32s3_reset_stub_code);
170 if (res != ERROR_OK) {
171 LOG_ERROR("Failed to write stub (%d)!", res);
172 return res;
173 }
174
175 LOG_DEBUG("Resuming the target");
176 xtensa = target_to_xtensa(target);
177 xtensa->suppress_dsr_errors = true;
178 res = xtensa_resume(target, 0, ESP32_S3_RTC_SLOW_MEM_BASE + 4, 0, 0);
179 xtensa->suppress_dsr_errors = false;
180 if (res != ERROR_OK) {
181 LOG_ERROR("Failed to run stub (%d)!", res);
182 return res;
183 }
184 LOG_DEBUG("resume done, waiting for the target to come alive");
185
186 /* Wait for SoC to reset */
187 alive_sleep(100);
188 int64_t timeout = timeval_ms() + 100;
189 bool get_timeout = false;
190 while (target->state != TARGET_RESET && target->state != TARGET_RUNNING) {
191 alive_sleep(10);
192 xtensa_poll(target);
193 if (timeval_ms() >= timeout) {
194 LOG_TARGET_ERROR(target,
195 "Timed out waiting for CPU to be reset, target state=%d",
196 target->state);
197 get_timeout = true;
198 break;
199 }
200 }
201
202 /* Halt the CPU again */
203 LOG_DEBUG("halting the target");
204 xtensa_halt(target);
205 res = target_wait_state(target, TARGET_HALTED, 1000);
206 if (res == ERROR_OK) {
207 LOG_DEBUG("restoring RTC_SLOW_MEM");
208 res = target_write_buffer(target, ESP32_S3_RTC_SLOW_MEM_BASE, sizeof(slow_mem_save), slow_mem_save);
209 if (res != ERROR_OK)
210 LOG_TARGET_ERROR(target, "Failed to restore contents of RTC_SLOW_MEM (%d)!", res);
211 } else {
212 LOG_TARGET_ERROR(target, "Timed out waiting for CPU to be halted after SoC reset");
213 }
214
215 return get_timeout ? ERROR_TARGET_TIMEOUT : res;
216 }
217
218 static int esp32s3_disable_wdts(struct target *target)
219 {
220 /* TIMG1 WDT */
221 int res = target_write_u32(target, ESP32_S3_TIMG0WDT_PROTECT, ESP32_S3_WDT_WKEY_VALUE);
222 if (res != ERROR_OK) {
223 LOG_ERROR("Failed to write ESP32_S3_TIMG0WDT_PROTECT (%d)!", res);
224 return res;
225 }
226 res = target_write_u32(target, ESP32_S3_TIMG0WDT_CFG0, 0);
227 if (res != ERROR_OK) {
228 LOG_ERROR("Failed to write ESP32_S3_TIMG0WDT_CFG0 (%d)!", res);
229 return res;
230 }
231 /* TIMG2 WDT */
232 res = target_write_u32(target, ESP32_S3_TIMG1WDT_PROTECT, ESP32_S3_WDT_WKEY_VALUE);
233 if (res != ERROR_OK) {
234 LOG_ERROR("Failed to write ESP32_S3_TIMG1WDT_PROTECT (%d)!", res);
235 return res;
236 }
237 res = target_write_u32(target, ESP32_S3_TIMG1WDT_CFG0, 0);
238 if (res != ERROR_OK) {
239 LOG_ERROR("Failed to write ESP32_S3_TIMG1WDT_CFG0 (%d)!", res);
240 return res;
241 }
242 /* RTC WDT */
243 res = target_write_u32(target, ESP32_S3_RTCWDT_PROTECT, ESP32_S3_WDT_WKEY_VALUE);
244 if (res != ERROR_OK) {
245 LOG_ERROR("Failed to write ESP32_S3_RTCWDT_PROTECT (%d)!", res);
246 return res;
247 }
248 res = target_write_u32(target, ESP32_S3_RTCWDT_CFG, 0);
249 if (res != ERROR_OK) {
250 LOG_ERROR("Failed to write ESP32_S3_RTCWDT_CFG (%d)!", res);
251 return res;
252 }
253 /* Enable SWD auto-feed */
254 res = target_write_u32(target, ESP32_S3_SWD_WPROTECT_REG, ESP32_S3_SWD_WKEY_VALUE);
255 if (res != ERROR_OK) {
256 LOG_ERROR("Failed to write ESP32_S3_SWD_WPROTECT_REG (%d)!", res);
257 return res;
258 }
259 uint32_t swd_conf_reg = 0;
260 res = target_read_u32(target, ESP32_S3_SWD_CONF_REG, &swd_conf_reg);
261 if (res != ERROR_OK) {
262 LOG_ERROR("Failed to read ESP32_S3_SWD_CONF_REG (%d)!", res);
263 return res;
264 }
265 swd_conf_reg |= ESP32_S3_SWD_AUTO_FEED_EN_M;
266 res = target_write_u32(target, ESP32_S3_SWD_CONF_REG, swd_conf_reg);
267 if (res != ERROR_OK) {
268 LOG_ERROR("Failed to write ESP32_S3_SWD_CONF_REG (%d)!", res);
269 return res;
270 }
271 return ERROR_OK;
272 }
273
274 static int esp32s3_on_halt(struct target *target)
275 {
276 int ret = esp32s3_disable_wdts(target);
277 if (ret == ERROR_OK)
278 ret = esp_xtensa_smp_on_halt(target);
279 return ret;
280 }
281
282 static int esp32s3_arch_state(struct target *target)
283 {
284 return ERROR_OK;
285 }
286
287 static int esp32s3_virt2phys(struct target *target,
288 target_addr_t virtual, target_addr_t *physical)
289 {
290 if (physical) {
291 *physical = virtual;
292 return ERROR_OK;
293 }
294 return ERROR_FAIL;
295 }
296
297 static int esp32s3_target_init(struct command_context *cmd_ctx, struct target *target)
298 {
299 return esp_xtensa_smp_target_init(cmd_ctx, target);
300 }
301
302 static const struct xtensa_debug_ops esp32s3_dbg_ops = {
303 .queue_enable = xtensa_dm_queue_enable,
304 .queue_reg_read = xtensa_dm_queue_reg_read,
305 .queue_reg_write = xtensa_dm_queue_reg_write
306 };
307
308 static const struct xtensa_power_ops esp32s3_pwr_ops = {
309 .queue_reg_read = xtensa_dm_queue_pwr_reg_read,
310 .queue_reg_write = xtensa_dm_queue_pwr_reg_write
311 };
312
313 static const struct esp_xtensa_smp_chip_ops esp32s3_chip_ops = {
314 .reset = esp32s3_soc_reset,
315 .on_halt = esp32s3_on_halt
316 };
317
318 static const struct esp_semihost_ops esp32s3_semihost_ops = {
319 .prepare = esp32s3_disable_wdts
320 };
321
322 static int esp32s3_target_create(struct target *target, Jim_Interp *interp)
323 {
324 struct xtensa_debug_module_config esp32s3_dm_cfg = {
325 .dbg_ops = &esp32s3_dbg_ops,
326 .pwr_ops = &esp32s3_pwr_ops,
327 .tap = target->tap,
328 .queue_tdi_idle = NULL,
329 .queue_tdi_idle_arg = NULL
330 };
331
332 struct esp32s3_common *esp32s3 = calloc(1, sizeof(struct esp32s3_common));
333 if (!esp32s3) {
334 LOG_ERROR("Failed to alloc memory for arch info!");
335 return ERROR_FAIL;
336 }
337
338 int ret = esp_xtensa_smp_init_arch_info(target,
339 &esp32s3->esp_xtensa_smp,
340 &esp32s3_dm_cfg,
341 &esp32s3_chip_ops,
342 &esp32s3_semihost_ops);
343 if (ret != ERROR_OK) {
344 LOG_ERROR("Failed to init arch info!");
345 free(esp32s3);
346 return ret;
347 }
348
349 /* Assume running target. If different, the first poll will fix this. */
350 target->state = TARGET_RUNNING;
351 target->debug_reason = DBG_REASON_NOTHALTED;
352 return ERROR_OK;
353 }
354
355 static const struct command_registration esp32s3_command_handlers[] = {
356 {
357 .usage = "",
358 .chain = esp_xtensa_smp_command_handlers,
359 },
360 {
361 .name = "esp",
362 .usage = "",
363 .chain = esp32_apptrace_command_handlers,
364 },
365 {
366 .name = "esp32",
367 .usage = "",
368 .chain = smp_command_handlers,
369 },
370 {
371 .name = "arm",
372 .mode = COMMAND_ANY,
373 .help = "ARM Command Group",
374 .usage = "",
375 .chain = semihosting_common_handlers
376 },
377 COMMAND_REGISTRATION_DONE
378 };
379
380 /** Holds methods for Xtensa targets. */
381 struct target_type esp32s3_target = {
382 .name = "esp32s3",
383
384 .poll = esp_xtensa_smp_poll,
385 .arch_state = esp32s3_arch_state,
386
387 .halt = xtensa_halt,
388 .resume = esp_xtensa_smp_resume,
389 .step = esp_xtensa_smp_step,
390
391 .assert_reset = esp_xtensa_smp_assert_reset,
392 .deassert_reset = esp_xtensa_smp_deassert_reset,
393 .soft_reset_halt = esp_xtensa_smp_soft_reset_halt,
394
395 .virt2phys = esp32s3_virt2phys,
396 .mmu = xtensa_mmu_is_enabled,
397 .read_memory = xtensa_read_memory,
398 .write_memory = xtensa_write_memory,
399
400 .read_buffer = xtensa_read_buffer,
401 .write_buffer = xtensa_write_buffer,
402
403 .checksum_memory = xtensa_checksum_memory,
404
405 .get_gdb_arch = xtensa_get_gdb_arch,
406 .get_gdb_reg_list = xtensa_get_gdb_reg_list,
407
408 .run_algorithm = xtensa_run_algorithm,
409 .start_algorithm = xtensa_start_algorithm,
410 .wait_algorithm = xtensa_wait_algorithm,
411
412 .add_breakpoint = esp_xtensa_breakpoint_add,
413 .remove_breakpoint = esp_xtensa_breakpoint_remove,
414
415 .add_watchpoint = esp_xtensa_smp_watchpoint_add,
416 .remove_watchpoint = esp_xtensa_smp_watchpoint_remove,
417
418 .target_create = esp32s3_target_create,
419 .init_target = esp32s3_target_init,
420 .examine = xtensa_examine,
421 .deinit_target = esp_xtensa_target_deinit,
422
423 .commands = esp32s3_command_handlers,
424 };

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)