--- /dev/null
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Script for Bouffalo chips with similar architecture used in BL602
+# based on SiFive E21 core
+
+source [find mem_helper.tcl]
+
+transport select jtag
+
+if { [info exists CPUTAPID ] } {
+ set _CPUTAPID $CPUTAPID
+} else {
+ error "you must specify a tap id"
+}
+
+if { [info exists BL602_CHIPNAME] } {
+ set _CHIPNAME $BL602_CHIPNAME
+} else {
+ error "you must specify a chip name"
+}
+
+if { [info exists WORKAREAADDR] } {
+ set _WORKAREAADDR $WORKAREAADDR
+} else {
+ error "you must specify a work area address"
+}
+
+if { [info exists WORKAREASIZE] } {
+ set _WORKAREASIZE $WORKAREASIZE
+} else {
+ error "you must specify a work area size"
+}
+
+jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id $_CPUTAPID
+
+set _TARGETNAME $_CHIPNAME.cpu
+target create $_TARGETNAME riscv -chain-position $_TARGETNAME
+
+riscv set_mem_access sysbus
+riscv set_enable_virt2phys off
+
+$_TARGETNAME configure -work-area-phys $_WORKAREAADDR -work-area-size $_WORKAREASIZE -work-area-backup 1
+
+# Internal RC ticks on 32 MHz, so this speed should be safe to use.
+adapter speed 8000
+
+# Useful functions
+
+set dmcontrol 0x10
+set dmcontrol_dmactive [expr {1 << 0}]
+set dmcontrol_ndmreset [expr {1 << 1}]
+set dmcontrol_resumereq [expr {1 << 30}]
+set dmcontrol_haltreq [expr {1 << 31}]
+
+proc bl602_restore_clock_defaults { } {
+ # Switch clock to internal RC32M
+ # In HBN_GLB, set ROOT_CLK_SEL = 0
+ mmw 0x4000f030 0x0 0x00000003
+ # Wait for clock switch
+ sleep 10
+
+ # GLB_REG_BCLK_DIS_FALSE
+ mww 0x40000ffc 0x0
+
+ # HCLK is RC32M, so BCLK/HCLK doesn't need divider
+ # In GLB_CLK_CFG0, set BCLK_DIV = 0 and HCLK_DIV = 0
+ mmw 0x40000000 0x0 0x00FFFF00
+ # Wait for clock to stabilize
+ sleep 10
+}
+
+# By spec, ndmreset should reset whole chip. This implementation resets only few parts of the chip.
+# CTRL_PWRON_RESET register in GLB core triggers full "power-on like" reset, so we use it instead
+# for full software reset.
+proc bl602_sw_reset { } {
+ # In GLB_SWRST_CFG2, clear CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET
+ mmw 0x40000018 0x0 0x00000007
+
+ # This Software reset method resets everything, so CPU as well.
+ # It does that in not much good way, resulting in Debug Module being reset as well.
+ # This also means, that right after CPU and Debug Module are turned on, we need to
+ # enable Debug Module and halt CPU if needed. Additionally, we trigger this SW reset
+ # through system bus access directly with DMI commands, to avoid errors printed by
+ # OpenOCD about unsuccessful register write.
+
+ # In GLB_SWRST_CFG2, set CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET to 1
+ riscv dmi_write 0x39 0x40000018
+ riscv dmi_write 0x3c 0x7
+
+ # We need to wait for chip to finish reset and execute BootROM
+ sleep 1
+
+ # JTAG Debug Transport Module is reset as well, so we need to get into RUN/IDLE state
+ runtest 10
+
+ # We need to enable Debug Module and halt the CPU, so we can reset Program Counter
+ # and to do additional clean-ups. If reset was called without halt, resume is handled
+ # by reset-deassert-post event handler.
+
+ # In Debug Module Control (dmcontrol), set dmactive to 1 and then haltreq to 1
+ riscv dmi_write $::dmcontrol $::dmcontrol_dmactive
+ riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_haltreq} ]
+
+ # Set Program Counter to start of BootROM
+ set_reg {pc 0x21000000}
+}
+
+# On BL602 and BL702, the only way to force chip stay in BootROM (until JTAG attaches)
+# is by putting infinity loop into HBN RAM (which is not reset by sw reset), and then
+# configure HBN registers, which will cause BootROM to jump into our code early in BootROM.
+proc bl602_sw_reset_hbn_wait {} {
+ # Restore clocks to defaults
+ bl602_restore_clock_defaults
+
+ # In HBN RAM, write infinity loop instruction
+ # beq zero, zero, 0
+ mww 0x40010000 0x00000063
+ # In HNB, set HBN_RSV0 (Status Flag) to "EHBN" (as uint32_t)
+ mww 0x4000f100 0x4e424845
+ # In HBN, set HBN_RSV1 (WakeUp Address) to HBN RAM address
+ mww 0x4000f104 0x40010000
+
+ # Perform software reset
+ bl602_sw_reset
+
+ # Clear HBN RAM, HBN_RSV0 and HBN_RSV1
+ mww 0x40010000 0x00000000
+ mww 0x4000f100 0x00000000
+ mww 0x4000f104 0x00000000
+
+ # This early jump method locks up BootROM through Trust Zone Controller.
+ # That means any read of BootROM returns 0xDEADBEEF.
+ # Only way to reset it, is through JTAG Reset, thus toggling ndmreset in dmcontrol.
+ riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_ndmreset} ]
+ riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive} ]
+}
+
+$_TARGETNAME configure -event reset-deassert-post {
+ # Resume the processor if reset was triggered without halt request
+ if {$halt == 0} {
+ riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_resumereq} ]
+ }
+}
# TDO - GPIO9
#
-source [find mem_helper.tcl]
-
-transport select jtag
-
if { [info exists CHIPNAME] } {
- set _CHIPNAME $CHIPNAME
+ set BL602_CHIPNAME $CHIPNAME
} else {
- set _CHIPNAME bl702
+ set BL602_CHIPNAME bl702
}
-jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000e05
-
-set _TARGETNAME $_CHIPNAME.cpu
-target create $_TARGETNAME riscv -chain-position $_TARGETNAME
-
-riscv set_mem_access sysbus
+set CPUTAPID 0x20000e05
-$_TARGETNAME configure -work-area-phys 0x22020000 -work-area-size 0x10000 -work-area-backup 1
+# For work-area we use DTCM instead of ITCM, due ITCM is used as buffer for L1 cache and XIP
+set WORKAREAADDR 0x22014000
+set WORKAREASIZE 0xC000
-# Internal RC ticks on 32 MHz, so this speed should be safe to use.
-adapter speed 4000
+source [find target/bl602_common.cfg]
-# Debug Module's ndmreset resets only Trust Zone Controller, so we need to do SW reset instead.
-# CTRL_PWRON_RESET triggers full "power-on like" reset.
-# This means that pinmux configuration to access JTAG is reset as well, and configured back early
-# in BootROM.
-$_TARGETNAME configure -event reset-assert-pre {
+# JTAG reset is broken. Read comment of bl602_sw_reset_hbn_wait function for more information
+$_TARGETNAME configure -event reset-assert {
halt
- # Switch clock to internal RC32M
- # In HBN_GLB, set ROOT_CLK_SEL = 0
- mmw 0x4000f030 0x0 0x00000003
- # Wait for clock switch
- sleep 10
-
- # GLB_REG_BCLK_DIS_FALSE
- mww 0x40000ffc 0x0
-
- # HCLK is RC32M, so BCLK/HCLK doesn't need divider
- # In GLB_CLK_CFG0, set BCLK_DIV = 0 and HCLK_DIV = 0
- mmw 0x40000000 0x0 0x00FFFF00
- # Wait for clock to stabilize
- sleep 10
-
- # Do reset
- # In GLB_SWRST_CFG2, clear CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET
- mmw 0x40000018 0x0 0x00000007
-
- # Since this full software reset resets GPIO pinmux as well, we will lose access
- # to JTAG right away after writing to register. This chip doesn't support abstract
- # memory access, so when this is done by progbuf or sysbus, OpenOCD will fail to read
- # if write was successful or not, and will print error about that. Since receiving of
- # this error is expected, we will turn off log printing for a moment,
- set lvl [lindex [debug_level] 1]
- debug_level -1
- # In GLB_SWRST_CFG2, set CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET to 1
- catch {mmw 0x40000018 0x7 0x0}
- debug_level $lvl
+ bl602_sw_reset_hbn_wait
}
--- /dev/null
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+#
+# Bouffalo Labs BL702L and BL704L target
+#
+# https://en.bouffalolab.com/product/?type=detail&id=26
+#
+# Default JTAG pins: (if not changed by eFuse configuration)
+# TMS - GPIO0
+# TDI - GPIO1
+# TCK - GPIO2
+# TDO - GPIO7
+#
+
+if { [info exists CHIPNAME] } {
+ set BL602_CHIPNAME $CHIPNAME
+} else {
+ set BL602_CHIPNAME bl702l
+}
+
+set CPUTAPID 0x20000e05
+
+# For work-area we use beginning of OCRAM, since BL702L have only ITCM, which can be taken
+# by L1 cache and XIP during runtime.
+set WORKAREAADDR 0x42020000
+set WORKAREASIZE 0x10000
+
+source [find target/bl602_common.cfg]
+
+# JTAG reset is broken. Read comment of bl602_sw_reset function for more information
+# On BL702L, we are forcing boot into ISP mode, so chip stays in BootROM until JTAG re-attach
+$_TARGETNAME configure -event reset-assert {
+ halt
+
+ # Restore clocks to defaults
+ bl602_restore_clock_defaults
+
+ # In HBN_RSV2, set HBN_RELEASE_CORE to HBN_RELEASE_CORE_FLAG (4)
+ # and HBN_USER_BOOT_SEL to 1 (ISP)
+ mww 0x4000f108 0x44000000
+
+ # Perform software reset
+ bl602_sw_reset
+
+ # Reset HBN_RSV2 so BootROM will not force ISP mode again
+ mww 0x4000f108 0x00000000
+}