This is an automated email from Gerrit.

"Marek Kraus <[email protected]>" just uploaded a new patch set to Gerrit, 
which you can find at https://review.openocd.org/c/openocd/+/9145

-- gerrit

commit df2a7cbb3acfd7a6412659929e11fdbaabf1f1a8
Author: Marek Kraus <[email protected]>
Date:   Sat Mar 22 15:36:45 2025 +0100

    tcl/target: add Bouffalo Lab BL616 chip series support
    
    Adds support for BL616 series of chips, BL616 and BL618.
    No flash bank support yet.
    
    BL616 in comparison with BL602-series have new architecture,
    using T-Head E907 RISC-V cores, instead of SiFive ones.
    
    As BL602-series, the ndmreset bit in RISC-V Debug Module
    does not reset the chip as it should, so we need to do it
    manually with registers almost the same way as in BL602.
    
    Additionally, JTAG Debug Transport Module in the chip have wrongly
    implemented Test-Logic-Reset state, causing automatic chain scan
    not working at all after initial JTAG usage. This is because
    Test-Logic-State do not set IR instruction to IDCODE,
    as it should by JTAG spec. We can fix this by getting state machine
    to known state and configure IR instruction manually to IDCODE.
    This bug was so far found in T-Head C906 and E907 IP cores.
    
    This patch was tested heavily and works reliably on
    BL616, BL618 and QCC74X.
    
    Change-Id: Idc80a702e817d78fc0ca925572c68d4d0c28ce4e
    Signed-off-by: Marek Kraus <[email protected]>

diff --git a/tcl/target/bl616.cfg b/tcl/target/bl616.cfg
new file mode 100644
index 0000000000..ee59f18508
--- /dev/null
+++ b/tcl/target/bl616.cfg
@@ -0,0 +1,145 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Author: Marek Kraus <[email protected]>
+
+#
+# Bouffalo Labs BL616 and BL618 target
+#
+# Default JTAG pins: (if not changed by eFuse configuration)
+# TMS - GPIO0
+# TCK - GPIO1
+# TDO - GPIO2
+# TDI - GPIO3
+#
+
+source [find mem_helper.tcl]
+
+transport select jtag
+
+if { [info exists CHIPNAME] } {
+       set _CHIPNAME $CHIPNAME
+} else {
+       set _CHIPNAME bl616
+}
+
+jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10000b6f
+
+set _TARGETNAME $_CHIPNAME.cpu
+target create $_TARGETNAME riscv -chain-position $_TARGETNAME
+
+riscv set_mem_access progbuf
+riscv set_enable_virt2phys off
+
+$_TARGETNAME configure -work-area-phys 0x40000000 -work-area-size 0x10000 
-work-area-backup 1
+
+adapter speed 4000
+
+# Useful functions
+set dmcontrol          0x10
+set dmcontrol_dmactive [expr {1 << 0}]
+set dmcontrol_haltreq  [expr {1 << 31}]
+
+# 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.
+$_TARGETNAME configure -event reset-assert {
+       halt
+
+       # To stay in BootROM until JTAG re-attaches, we are using BootROM 
functionality
+       # to force ISP mode, so BootROM looks out for external ISP 
communication.
+
+       # In HBN_RSV2, set HBN_RELEASE_CORE to HBN_RELEASE_CORE_FLAG (4)
+       # and HBN_USER_BOOT_SEL to 1 (ISP)
+       mww 0x2000f108 0x44000000
+
+       # Switch clock to internal RC32M
+       # In HBN_GLB, set ROOT_CLK_SEL = 0
+       mmw 0x2000f030 0x0 0x00000002
+
+       # In GLB_SYS_CFG0, set REG_BCLK_DIV and REG_HCLK_DIV = 0
+       mmw 0x20000090 0x0 0x00FFFF00
+
+       # Trigger BCLK ACT pulse
+       # In GLB_SYS_CFG1, set BCLK_DIV_ACT_PULSE = 1
+       mmw 0x20000094 0x1 0x00000001
+       # In GLB_SYS_CFG1, wait for GLB_STS_BCLK_PROT_DONE to become 1
+       while { [expr {[mrw 0x20000094] & 4}] == 0 } { sleep 1 }
+
+       # In GLB_SWRST_CFG2, clear CTRL_PWRON_RESET
+       mmw 0x20000548 0x0 0x00000001
+
+       # 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 program buffer access directly with DMI commands, to avoid 
errors printed by
+       # OpenOCD about unsuccessful register write.
+
+       # In GLB_SWRST_CFG2, set CTRL_PWRON_RESET to 1
+       set_reg {fp 0x20000548 s1 0x01}
+       riscv dmi_write 0x20 0x00942023
+       riscv dmi_write 0x17 0x40000
+
+       # We need to wait for chip to finish reset and execute BootROM
+       sleep 10
+
+       # 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} ]
+}
+
+$_TARGETNAME configure -event reset-deassert-post {
+       # Set Program Counter to start of BootROM and execute one instruction
+       step 0x90000000
+
+       # When using default JTAG pinout, BOOT pin is the same as JTAG TDO pin.
+       # Since after reset we set PC to start of the BootROM,
+       # BootROM will execute also check of BOOT pin, which will disable TDO 
pin,
+       # to check the BOOT pin state. This leads to temporary loss of JTAG 
access
+       # and causes (recoverable) errors in OpenOCD. We can bypass the BOOT 
pin check
+       # function, by forcing booting from Media/SPI Flash.
+
+       # In HBN_RSV2, set HBN_RELEASE_CORE to HBN_RELEASE_CORE_FLAG (4)
+       # and HBN_USER_BOOT_SEL to 2 (Media/SPI Flash)
+       mww 0x2000f108 0x48000000
+
+       # Resume the processor if reset was triggered without halt request
+       if {$halt == 0} {
+               resume
+       }
+}
+
+# According to JTAG spec (IEEE 1149.1), when chip enters "Test-Logic-Reset" 
state,
+# the IR instruction should be set to "IDCODE" or "BYPASS" (when chip does not 
have IDCODE).
+# This is done so automatic chain scan can detect all the chips within JTAG 
chain without knowing IDCODE.
+# JTAG Debug Transport Module (DTM) used in this chip, developed by T-Head 
(formerly C-Sky)
+# does not implement this, so OpenOCD can't detect the chip anymore after the 
IR instruction is changed.
+# This workaround gets chip into known state, and manually set IR instruction 
to IDCODE,
+# which is 0x01, standardized by RISC-V Debug Specification.
+proc init_reset { mode } {
+       if {[using_jtag]} {
+               # Get JTAG SM to known state
+               runtest 10
+               # Set IR to IDCODE
+               irscan $::_CHIPNAME.cpu 0x01
+               jtag arp_init-reset
+       }
+}
+
+proc jtag_init {} {
+       # Get JTAG SM to known state
+       runtest 10
+       # Set IR to IDCODE
+       irscan $::_CHIPNAME.cpu 0x01
+
+       if {[catch {jtag arp_init} err]!=0} {
+               # try resetting additionally
+               init_reset startup
+       }
+}

-- 

Reply via email to