mirror of
https://github.com/openocd-org/openocd.git
synced 2025-10-14 02:58:23 +08:00
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 <gamelaster@outlook.com> Reviewed-on: https://review.openocd.org/c/openocd/+/9145 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:

committed by
Antonio Borneo

parent
34d76b805e
commit
382f067b6e
145
tcl/target/bl616.cfg
Normal file
145
tcl/target/bl616.cfg
Normal file
@@ -0,0 +1,145 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Author: Marek Kraus <gamelaster@gami.ee>
|
||||
|
||||
#
|
||||
# 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
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user