--- /dev/null
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# RP2350 is a microcontroller with dual Cortex-M33 cores or dual Hazard3 RISC-V cores.
+# https://www.raspberrypi.com/documentation/microcontrollers/rp2350.html
+
+transport select swd
+
+source [find target/swj-dp.tcl]
+
+if { [info exists CHIPNAME] } {
+ set _CHIPNAME $CHIPNAME
+} else {
+ set _CHIPNAME rp2350
+}
+
+if { [info exists WORKAREASIZE] } {
+ set _WORKAREASIZE $WORKAREASIZE
+} else {
+ set _WORKAREASIZE 0x10000
+}
+
+if { [info exists CPUTAPID] } {
+ set _CPUTAPID $CPUTAPID
+} else {
+ set _CPUTAPID 0x00040927
+}
+
+# Set to '1' to start rescue mode
+if { [info exists RESCUE] } {
+ set _RESCUE $RESCUE
+} else {
+ set _RESCUE 0
+}
+
+# Set to 'cm0' or 'cm1' for Cortex-M33 single core configuration
+# To keep compatibility with RP2040 aliases '0' and '1' are provided for Cortex-M33 cores
+# Use 'rv0' or 'rv1' for RISC-V single core configuration
+# List more for a multicore configuration
+if { [info exists USE_CORE] } {
+ set _USE_CORE $USE_CORE
+} else {
+ # defaults to both Cortex-M33 cores
+ set _USE_CORE { cm0 cm1 }
+}
+
+swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID
+
+if { [info exists SWD_MULTIDROP] } {
+ dap create $_CHIPNAME.dap -adiv6 -chain-position $_CHIPNAME.cpu -dp-id 0x0040927 -instance-id 0
+} else {
+ dap create $_CHIPNAME.dap -adiv6 -chain-position $_CHIPNAME.cpu
+}
+
+# Cortex-M33 core 0
+if { [lsearch $_USE_CORE cm0] >= 0 || [lsearch $_USE_CORE 0] >= 0 } {
+ set _TARGETNAME_CM0 $_CHIPNAME.cm0
+ set _TARGETNAME_0 $_TARGETNAME_CM0
+}
+
+# RISC-V core 0
+if { [lsearch $_USE_CORE rv0] >= 0 } {
+ set _TARGETNAME_RV0 $_CHIPNAME.rv0
+ if { ![info exists _TARGETNAME_0] } {
+ set _TARGETNAME_0 $_TARGETNAME_RV0
+ }
+}
+
+# Cortex-M33 core 1
+if { [lsearch $_USE_CORE cm1] >= 0 || [lsearch $_USE_CORE 1] >= 0 } {
+ set _TARGETNAME_CM1 $_CHIPNAME.cm1
+ set _TARGETNAME_1 $_TARGETNAME_CM1
+}
+
+# RISC-V core 1
+if { [lsearch $_USE_CORE rv1] >= 0 } {
+ set _TARGETNAME_RV1 $_CHIPNAME.rv1
+ if { ![info exists _TARGETNAME_1] } {
+ set _TARGETNAME_1 $_TARGETNAME_RV1
+ }
+}
+
+
+if { [info exists _TARGETNAME_CM0] } {
+ target create $_TARGETNAME_CM0 cortex_m -dap $_CHIPNAME.dap -ap-num 0x2000
+ # srst does not exist; use SYSRESETREQ to perform a soft reset
+ $_TARGETNAME_CM0 cortex_m reset_config sysresetreq
+
+ # After a rescue reset the cache requires invalidate to allow SPI flash
+ # reads from the XIP cached mapping area
+ $_TARGETNAME_CM0 configure -event reset-init { rp2xxx rom_api_call FC }
+}
+
+if { [info exists _TARGETNAME_RV0] } {
+ target create $_TARGETNAME_RV0 riscv -dap $_CHIPNAME.dap -ap-num 0xa000 -coreid 0
+ $_TARGETNAME_RV0 riscv set_enable_virt2phys off
+
+ # Workaround for stray IO_QSPI: GPIO_QSPI_SD1_CTRL: INOVER bit in RISC-V BOOTSEL
+ $_TARGETNAME_RV0 configure -event reset-init { mww 0x4003002c 0 }
+
+ if { [info exists _TARGETNAME_CM0] } {
+ # just for setting after init when the event become-available is not fired
+ $_TARGETNAME_RV0 configure -event examine-end "rp2xxx _switch_target $_TARGETNAME_CM0 $_TARGETNAME_RV0"
+ }
+}
+
+if { [info exists _TARGETNAME_CM1] } {
+ target create $_TARGETNAME_CM1 cortex_m -dap $_CHIPNAME.dap -ap-num 0x4000
+ $_TARGETNAME_CM1 cortex_m reset_config sysresetreq
+}
+
+if { [info exists _TARGETNAME_RV1] } {
+ target create $_TARGETNAME_RV1 riscv -dap $_CHIPNAME.dap -ap-num 0xa000 -coreid 1
+ $_TARGETNAME_RV1 riscv set_enable_virt2phys off
+}
+
+if { [info exists USE_SMP] } {
+ set _USE_SMP $USE_SMP
+} elseif { [info exists _TARGETNAME_CM0] == [info exists _TARGETNAME_CM1]
+ && [info exists _TARGETNAME_RV0] == [info exists _TARGETNAME_RV1] } {
+ set _USE_SMP 1
+} else {
+ set _USE_SMP 0
+}
+if { $_USE_SMP } {
+ if { [info exists _TARGETNAME_CM0] && [info exists _TARGETNAME_CM1] } {
+ $_TARGETNAME_CM0 configure -rtos hwthread
+ $_TARGETNAME_CM1 configure -rtos hwthread
+ target smp $_TARGETNAME_CM0 $_TARGETNAME_CM1
+ }
+ if { [info exists _TARGETNAME_RV0] && [info exists _TARGETNAME_RV1] } {
+ $_TARGETNAME_RV0 configure -rtos hwthread
+ $_TARGETNAME_RV1 configure -rtos hwthread
+ target smp $_TARGETNAME_RV0 $_TARGETNAME_RV1
+ }
+}
+
+if { [info exists _TARGETNAME_0] } {
+ set _FLASH_TARGET $_TARGETNAME_0
+}
+if { ![info exists _FLASH_TARGET] && [info exists _TARGETNAME_1] } {
+ set _FLASH_TARGET $_TARGETNAME_1
+ if { [info exists _TARGETNAME_CM1] && [info exists _TARGETNAME_RV1] } {
+ echo "Info : $_CHIPNAME.flash will be handled by $_TARGETNAME_1 without switching"
+ }
+}
+if { [info exists _FLASH_TARGET] } {
+ $_FLASH_TARGET configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE
+ if { [info exists _TARGETNAME_CM0] && [info exists _TARGETNAME_RV0] } {
+ $_TARGETNAME_RV0 configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE
+ echo "Info : $_CHIPNAME.flash will be handled by the active one of $_FLASH_TARGET and $_TARGETNAME_RV0 cores"
+ }
+ set _FLASHNAME $_CHIPNAME.flash
+ set _FLASHSIZE 0x00400000
+ flash bank $_FLASHNAME rp2040_flash 0x10000000 $_FLASHSIZE 0 0 $_FLASH_TARGET
+}
+
+if { [info exists _TARGETNAME_1] } {
+ # Alias to ensure gdb connecting to core 1 gets the correct memory map
+ flash bank $_CHIPNAME.alias virtual 0x10000000 0 0 0 $_TARGETNAME_1 $_FLASHNAME
+}
+
+if { [info exists _TARGETNAME_0] } {
+ # Select core 0
+ targets $_TARGETNAME_0
+}
+
+# Cold reset resets everything except DP
+proc cold_reset { { __CHIPNAME "" } } {
+ if { $__CHIPNAME == "" } {
+ global _CHIPNAME
+ set __CHIPNAME $_CHIPNAME
+ }
+ poll off
+ # set CDBGRSTREQ (and keep set CSYSPWRUPREQ and CDBGPWRUPREQ)
+ $__CHIPNAME.dap dpreg 4 0x54000000
+ set dpstat [$__CHIPNAME.dap dpreg 4]
+ if { [expr { $dpstat & 0xcc000000 }] != 0xcc000000 } {
+ echo "Warn : dpstat_reset failed, DP STAT $dpstat"
+ }
+ $__CHIPNAME.dap dpreg 4 0x50000000
+ dap init
+ poll on
+}
+
+# Rescue reset resets everything except DP and RP_AP
+# Both Cortex-M33 cores stop in bootrom
+proc rescue_reset { { __CHIPNAME "" } } {
+ if { $__CHIPNAME == "" } {
+ global _CHIPNAME
+ set __CHIPNAME $_CHIPNAME
+ }
+ poll off
+ # set bit RESCUE_RESTART in RP_AP: CTRL register
+ $__CHIPNAME.dap apreg 0x80000 0 0x80000000
+ $__CHIPNAME.dap apreg 0x80000 0 0
+ dap init
+ poll on
+ if { [lsearch [target names] $__CHIPNAME.cm0] < 0 } {
+ echo "Info : restart OpenOCD with 'set USE_CORE { cm0 cm1 }' to debug after rescue"
+ }
+}
+
+if { $_RESCUE } {
+ init
+ rescue_reset
+}