|
| 1 | +# SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | +# Author: Marek Kraus <[email protected]> |
| 3 | + |
| 4 | +# |
| 5 | +# Bouffalo Labs BL616 and BL618 target |
| 6 | +# |
| 7 | +# Default JTAG pins: (if not changed by eFuse configuration) |
| 8 | +# TMS - GPIO0 |
| 9 | +# TCK - GPIO1 |
| 10 | +# TDO - GPIO2 |
| 11 | +# TDI - GPIO3 |
| 12 | +# |
| 13 | + |
| 14 | +source [find mem_helper.tcl] |
| 15 | + |
| 16 | +transport select jtag |
| 17 | + |
| 18 | +if { [info exists CHIPNAME] } { |
| 19 | + set _CHIPNAME $CHIPNAME |
| 20 | +} else { |
| 21 | + set _CHIPNAME bl616 |
| 22 | +} |
| 23 | + |
| 24 | +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10000b6f |
| 25 | + |
| 26 | +set _TARGETNAME $_CHIPNAME.cpu |
| 27 | +target create $_TARGETNAME riscv -chain-position $_TARGETNAME |
| 28 | + |
| 29 | +riscv set_mem_access progbuf |
| 30 | +riscv set_enable_virt2phys off |
| 31 | + |
| 32 | +$_TARGETNAME configure -work-area-phys 0x40000000 -work-area-size 0x10000 -work-area-backup 1 |
| 33 | + |
| 34 | +adapter speed 4000 |
| 35 | + |
| 36 | +# Useful functions |
| 37 | +set dmcontrol 0x10 |
| 38 | +set dmcontrol_dmactive [expr {1 << 0}] |
| 39 | +set dmcontrol_haltreq [expr {1 << 31}] |
| 40 | + |
| 41 | +# By spec, ndmreset should reset whole chip. This implementation resets only few parts of the chip. |
| 42 | +# CTRL_PWRON_RESET register in GLB core triggers full "power-on like" reset, so we use it instead |
| 43 | +# for full software reset. |
| 44 | +$_TARGETNAME configure -event reset-assert { |
| 45 | + halt |
| 46 | + |
| 47 | + # To stay in BootROM until JTAG re-attaches, we are using BootROM functionality |
| 48 | + # to force ISP mode, so BootROM looks out for external ISP communication. |
| 49 | + |
| 50 | + # In HBN_RSV2, set HBN_RELEASE_CORE to HBN_RELEASE_CORE_FLAG (4) |
| 51 | + # and HBN_USER_BOOT_SEL to 1 (ISP) |
| 52 | + mww 0x2000f108 0x44000000 |
| 53 | + |
| 54 | + # Switch clock to internal RC32M |
| 55 | + # In HBN_GLB, set ROOT_CLK_SEL = 0 |
| 56 | + mmw 0x2000f030 0x0 0x00000002 |
| 57 | + |
| 58 | + # In GLB_SYS_CFG0, set REG_BCLK_DIV and REG_HCLK_DIV = 0 |
| 59 | + mmw 0x20000090 0x0 0x00FFFF00 |
| 60 | + |
| 61 | + # Trigger BCLK ACT pulse |
| 62 | + # In GLB_SYS_CFG1, set BCLK_DIV_ACT_PULSE = 1 |
| 63 | + mmw 0x20000094 0x1 0x00000001 |
| 64 | + # In GLB_SYS_CFG1, wait for GLB_STS_BCLK_PROT_DONE to become 1 |
| 65 | + while { [expr {[mrw 0x20000094] & 4}] == 0 } { sleep 1 } |
| 66 | + |
| 67 | + # In GLB_SWRST_CFG2, clear CTRL_PWRON_RESET |
| 68 | + mmw 0x20000548 0x0 0x00000001 |
| 69 | + |
| 70 | + # This Software reset method resets everything, so CPU as well. |
| 71 | + # It does that in not much good way, resulting in Debug Module being reset as well. |
| 72 | + # This also means, that right after CPU and Debug Module are turned on, we need to |
| 73 | + # enable Debug Module and halt CPU if needed. Additionally, we trigger this SW reset |
| 74 | + # through program buffer access directly with DMI commands, to avoid errors printed by |
| 75 | + # OpenOCD about unsuccessful register write. |
| 76 | + |
| 77 | + # In GLB_SWRST_CFG2, set CTRL_PWRON_RESET to 1 |
| 78 | + set_reg {fp 0x20000548 s1 0x01} |
| 79 | + riscv dmi_write 0x20 0x00942023 |
| 80 | + riscv dmi_write 0x17 0x40000 |
| 81 | + |
| 82 | + # We need to wait for chip to finish reset and execute BootROM |
| 83 | + sleep 10 |
| 84 | + |
| 85 | + # JTAG Debug Transport Module is reset as well, so we need to get into RUN/IDLE state |
| 86 | + runtest 10 |
| 87 | + |
| 88 | + # We need to enable Debug Module and halt the CPU, so we can reset Program Counter |
| 89 | + # and to do additional clean-ups. If reset was called without halt, resume is handled |
| 90 | + # by reset-deassert-post event handler. |
| 91 | + |
| 92 | + # In Debug Module Control (dmcontrol), set dmactive to 1 and then haltreq to 1 |
| 93 | + riscv dmi_write $::dmcontrol $::dmcontrol_dmactive |
| 94 | + riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_haltreq} ] |
| 95 | +} |
| 96 | + |
| 97 | +$_TARGETNAME configure -event reset-deassert-post { |
| 98 | + # Set Program Counter to start of BootROM and execute one instruction |
| 99 | + step 0x90000000 |
| 100 | + |
| 101 | + # When using default JTAG pinout, BOOT pin is the same as JTAG TDO pin. |
| 102 | + # Since after reset we set PC to start of the BootROM, |
| 103 | + # BootROM will execute also check of BOOT pin, which will disable TDO pin, |
| 104 | + # to check the BOOT pin state. This leads to temporary loss of JTAG access |
| 105 | + # and causes (recoverable) errors in OpenOCD. We can bypass the BOOT pin check |
| 106 | + # function, by forcing booting from Media/SPI Flash. |
| 107 | + |
| 108 | + # In HBN_RSV2, set HBN_RELEASE_CORE to HBN_RELEASE_CORE_FLAG (4) |
| 109 | + # and HBN_USER_BOOT_SEL to 2 (Media/SPI Flash) |
| 110 | + mww 0x2000f108 0x48000000 |
| 111 | + |
| 112 | + # Resume the processor if reset was triggered without halt request |
| 113 | + if {$halt == 0} { |
| 114 | + resume |
| 115 | + } |
| 116 | +} |
| 117 | + |
| 118 | +# According to JTAG spec (IEEE 1149.1), when chip enters "Test-Logic-Reset" state, |
| 119 | +# the IR instruction should be set to "IDCODE" or "BYPASS" (when chip does not have IDCODE). |
| 120 | +# This is done so automatic chain scan can detect all the chips within JTAG chain without knowing IDCODE. |
| 121 | +# JTAG Debug Transport Module (DTM) used in this chip, developed by T-Head (formerly C-Sky) |
| 122 | +# does not implement this, so OpenOCD can't detect the chip anymore after the IR instruction is changed. |
| 123 | +# This workaround gets chip into known state, and manually set IR instruction to IDCODE, |
| 124 | +# which is 0x01, standardized by RISC-V Debug Specification. |
| 125 | +proc init_reset { mode } { |
| 126 | + if {[using_jtag]} { |
| 127 | + # Get JTAG SM to known state |
| 128 | + runtest 10 |
| 129 | + # Set IR to IDCODE |
| 130 | + irscan $::_CHIPNAME.cpu 0x01 |
| 131 | + jtag arp_init-reset |
| 132 | + } |
| 133 | +} |
| 134 | + |
| 135 | +proc jtag_init {} { |
| 136 | + # Get JTAG SM to known state |
| 137 | + runtest 10 |
| 138 | + # Set IR to IDCODE |
| 139 | + irscan $::_CHIPNAME.cpu 0x01 |
| 140 | + |
| 141 | + if {[catch {jtag arp_init} err]!=0} { |
| 142 | + # try resetting additionally |
| 143 | + init_reset startup |
| 144 | + } |
| 145 | +} |
0 commit comments