# SPDX-License-Identifier: GPL-2.0-or-later # cn9130 -- support for the Marvell Octeon TX2 / CN9130 CPU family # # henrik.nordstorm@addiva.se, Nov 2023 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME cn9130 } if { [info exists MASTERTAPID] } { set _MASTERTAPID $MASTERTAPID } else { set _MASTERTAPID 0x07025357 } if { [info exists APTAPID] } { set _APTAPID $APTAPID } else { set _APTAPID 0x4ba00477 } if { [info exists SBTAPID] } { set _SBTAPID $SBTAPID } else { set _SBTAPID 0x4ba00477 } if { [info exists CORES] } { set _CORES $CORES } else { set _CORES 4 } # CTI base address should be possible to read from the CoreSight # ROM table like how the DBG base address is when not specified. if { [info exists CTIBASE] } { set _CTIBASE $CTIBASE } else { set _CTIBASE {0x80420000 0x80520000 0x80620000 0x80720000} } # CN9130 is a multi-die chip and has a multi level hierarchical # JTAG TAP, where all the DAPs are disabled at reset, requiring # both configuration to enable access to the chip DAPs, and a # vendor specific bypass IR instruction to access the slave TAPs # via the master TAP. In addition there is a number of sample # bits that should be ignored. # # The default BYPASS instruction in the master TAP bypasses the # whole chip and not only the master TAP. And similarly on # IDCODE the master TAP only responds with it's own ID and # bypasses the other TAPs on the chip, while OpenOCD expects # ID from all enabled TAPs in the chain. # Bootstrap with the default boundary scan oriented TAP configuration # where the master,ap,sb TAPs are seen as one big fat TAP, which matches # what OpenOCD expects from IDCODE and BYPASS. jtag newtap $_CHIPNAME bs -irlen 19 -enable -expected-id $_MASTERTAPID # Declare the full JTAG chain, but in disabled state during setup jtag newtap $_CHIPNAME sample4 -irlen 1 -disable jtag newtap $_CHIPNAME sample3 -irlen 1 -disable jtag newtap $_CHIPNAME sample2 -irlen 1 -disable jtag newtap $_CHIPNAME ap.cpu -irlen 4 -disable -expected-id $_APTAPID jtag newtap $_CHIPNAME ap -irlen 5 -disable jtag newtap $_CHIPNAME sample1 -irlen 1 -disable jtag newtap $_CHIPNAME sb.cpu -irlen 4 -disable -expected-id $_SBTAPID jtag newtap $_CHIPNAME sb -irlen 5 -disable jtag newtap $_CHIPNAME master -irlen 5 -disable -ir-bypass 0x11 -expected-id $_MASTERTAPID # Once the iniial IDCODE scan has completed switch to more detailed # scan chain giving access to the individual chip TAPs. jtag configure $_CHIPNAME.bs -event setup "cn9130_enable_full_chain $_CHIPNAME" proc cn9130_enable_full_chain { _CHIPNAME } { # Switch to detailed TAP declaration jtag tapdisable $_CHIPNAME.bs jtag tapenable $_CHIPNAME.master jtag tapenable $_CHIPNAME.sb jtag tapenable $_CHIPNAME.sample1 jtag tapenable $_CHIPNAME.ap jtag tapenable $_CHIPNAME.sample2 jtag tapenable $_CHIPNAME.sample3 jtag tapenable $_CHIPNAME.sample4 } # AP & SB TAPs have a config register to enable/disable access to # the auxilary DAP TAP. Default off which hides the DAP TAP from # the scan chain. proc cn9130_dap_config { chip tap state } { irscan $chip.$tap 0x12 drscan $chip.$tap 32 $state } jtag configure $_CHIPNAME.bs -event tap-disable "" jtag configure $_CHIPNAME.bs -event tap-enable "" jtag configure $_CHIPNAME.sample4 -event tap-enable "" jtag configure $_CHIPNAME.sample3 -event tap-enable "" jtag configure $_CHIPNAME.sample2 -event tap-enable "" jtag configure $_CHIPNAME.ap.cpu -event tap-disable "cn9130_dap_config $_CHIPNAME ap 0" jtag configure cn9130.ap.cpu -event tap-enable "cn9130_dap_config $_CHIPNAME ap 1" jtag configure $_CHIPNAME.ap -event tap-enable "" jtag configure $_CHIPNAME.sample1 -event tap-enable "" jtag configure $_CHIPNAME.sb.cpu -event tap-disable "cn9130_dap_config $_CHIPNAME sb 0" jtag configure cn9130.sb.cpu -event tap-enable "cn9130_dap_config $_CHIPNAME sb 1" jtag configure $_CHIPNAME.sb -event tap-enable "" jtag configure $_CHIPNAME.master -event tap-enable "" dap create $_CHIPNAME.ap.dap -chain-position $_CHIPNAME.ap.cpu # Main bus target create $_CHIPNAME.ap.axi mem_ap \ -dap $_CHIPNAME.ap.dap \ -ap-num 0 # Periperials bus target create $_CHIPNAME.ap.apb mem_ap \ -dap $_CHIPNAME.ap.dap \ -ap-num 1 # MSS bus target create $_CHIPNAME.ap.ahb mem_ap \ -dap $_CHIPNAME.ap.dap \ -ap-num 2 # AP A72 CPU cores set _smp_command "" for { set _core 0 } { $_core < $_CORES } { incr _core 1 } { cti create $_CHIPNAME.ap.cti.$_core \ -dap $_CHIPNAME.ap.dap \ -baseaddr [ lindex $_CTIBASE $_core ] \ -ap-num 1 if { $_core == 0 } { target create $_CHIPNAME.ap.a72.$_core aarch64 \ -dap $_CHIPNAME.ap.dap \ -ap-num 1 \ -cti $_CHIPNAME.ap.cti.$_core \ -coreid $_core \ -rtos hwthread set _smp_command "target smp $_CHIPNAME.ap.a72.$_core" } else { # Defer non-boot cores. Held hard in reset until # SMP is activated. target create $_CHIPNAME.ap.a72.$_core aarch64 \ -dap $_CHIPNAME.ap.dap \ -ap-num 1 \ -cti $_CHIPNAME.ap.cti.$_core \ -coreid $_core \ -defer-examine set _smp_command "$_smp_command $_CHIPNAME.ap.a72.$_core" } } # Set up the A72 cluster as SMP # Note: Only the boot core is active by default. The other core DAPs can # be enabled by arp_examine after they have been released from hard reset. eval $_smp_command # AP MSS M3 CPU core. Defer as it is held in reset until firmware is loaded. target create $_CHIPNAME.ap.mss cortex_m -dap $_CHIPNAME.ap.dap -ap-num 2 -defer-examine # Why is this needed? reset fails with "Debug regions are unpowered" otherwise $_CHIPNAME.ap.axi configure -event examine-start "dap init" # Automate enabling the AP A72 DAP once the full scan chain is enabled proc cn9130_ap_setup { _CHIPNAME } { jtag tapenable $_CHIPNAME.ap.cpu targets $_CHIPNAME.ap.a72.0 } jtag configure $_CHIPNAME.ap -event setup "cn9130_ap_setup $_CHIPNAME"