diff options
Diffstat (limited to 'tcl')
-rw-r--r-- | tcl/target/nrf52.cfg | 29 | ||||
-rw-r--r-- | tcl/target/xilinx_zynqmp.cfg | 134 |
2 files changed, 157 insertions, 6 deletions
diff --git a/tcl/target/nrf52.cfg b/tcl/target/nrf52.cfg index 0c82c57..0703b18 100644 --- a/tcl/target/nrf52.cfg +++ b/tcl/target/nrf52.cfg @@ -131,10 +131,29 @@ proc _proc_pre_enable_$_CHIPNAME.tpiu {_targetname _chipname} { 0x52840 - 0x52833 - 0x52832 { + # Configuration values for all supported trace port speeds, see + # TRACECONFIG.TRACEPORTSPEED + set trace_port_speeds { + 32000000 0 + 16000000 1 + 8000000 2 + 4000000 3 + } + + # Note that trace port clock stands for what is referred to as + # TRACECLKIN in the Arm CoreSight documentation. + set trace_port_clock [$_chipname.tpiu cget -traceclk] + + if { ![dict exists $trace_port_speeds $trace_port_clock] } { + error "Trace clock speed is not supported" + } + + # Set TRACECONFIG.TRACEPORTSPEED + mmw 0x4000055C [dict get $trace_port_speeds $trace_port_clock] 0x3 + if { [$_chipname.tpiu cget -protocol] eq "sync" } { if { [$_chipname.tpiu cget -port-width] != 4 } { - echo "Error. Device only supports 4-bit sync traces." - return + error "Device only supports 4-bit sync traces" } # Set TRACECONFIG.TRACEMUX to enable synchronous trace @@ -154,12 +173,10 @@ proc _proc_pre_enable_$_CHIPNAME.tpiu {_targetname _chipname} { 0x52811 - 0x52810 - 0x52805 { - echo "Error: Device does not support TPIU" - return + error "Device does not support TPIU" } default { - echo "Error: Unknown device" - return + error "Unknown device, cannot configure TPIU" } } } diff --git a/tcl/target/xilinx_zynqmp.cfg b/tcl/target/xilinx_zynqmp.cfg index 9734a18..e8224be 100644 --- a/tcl/target/xilinx_zynqmp.cfg +++ b/tcl/target/xilinx_zynqmp.cfg @@ -104,3 +104,137 @@ proc core_up { args } { $_TARGETNAME.$core arp_examine } } + +proc BIT {n} { + return [expr {1 << $n}] +} + +set IPI_BASE 0xff300000 +set IPI_PMU_0_TRIG [expr {$IPI_BASE + 0x30000}] +set IPI_PMU_0_IER [expr {$IPI_BASE + 0x30018}] +set IPI_PMU_0 [BIT 16] + +set CRF_APB_BASE 0xfd1a0000 +set CRF_APB_RST_FPD_APU [expr {$CRF_APB_BASE + 0x104}] +set CRF_APB_RST_FPD_APU_ACPU0_PWRON_RESET [BIT 10] +set CRF_APB_RST_FPD_APU_L2_RESET [BIT 8] +set CRF_APB_RST_FPD_APU_ACPU0_RESET [BIT 0] + +set APU_BASE 0xfd5c0000 +set APU_RVBARADDR_BASE [expr {$APU_BASE + 0x40}] + +set PMU_BASE 0xffd80000 +set PMU_GLOBAL $PMU_BASE +set PMU_GLOBAL_MB_SLEEP [BIT 16] +set PMU_GLOBAL_FW_IS_PRESENT [BIT 4] +set PMU_GLOBAL_DONT_SLEEP [BIT 0] + +set PMU_RAM_BASE 0xffdc0000 + +set OCM_RAM_BASE 0xfffc0000 + +rename BIT {} + +add_help_text halt_pmu "Halt the PMU in preparation for loading new firmware.\ + This should be matched with a call to resume_pmu." +proc halt_pmu {} { + set axi $::_CHIPNAME.axi + set val [$axi read_memory $::IPI_PMU_0_IER 32 1] + $axi write_memory $::IPI_PMU_0_IER 32 [expr {$val | $::IPI_PMU_0}] + + set val [$axi read_memory $::IPI_PMU_0_TRIG 32 1] + $axi write_memory $::IPI_PMU_0_TRIG 32 [expr {$val | $::IPI_PMU_0}] + + set start [ms] + while {!([$axi read_memory $::PMU_GLOBAL 32 1] & $::PMU_GLOBAL_MB_SLEEP)} { + if {[ms] - $start > 1000} { + error "Timed out waiting for PMU to halt" + } + } +} + +add_help_text resume_pmu "Resume the PMU after loading new firmware. This\ + should be matched with a call to halt_pmu." +proc resume_pmu {} { + set axi $::_CHIPNAME.axi + set val [$axi read_memory $::PMU_GLOBAL 32 1] + $axi write_memory $::PMU_GLOBAL 32 [expr {$val | $::PMU_GLOBAL_DONT_SLEEP}] + + set start [ms] + while {!([$axi read_memory $::PMU_GLOBAL 32 1] & $::PMU_GLOBAL_FW_IS_PRESENT)} { + if {[ms] - $start > 5000} { + error "Timed out waiting for PMU firmware" + } + } +} + +add_usage_text release_apu {apu} +add_help_text release_apu "Release an APU from reset. It will start executing\ + at RVBARADDR. You probably want resume_apu or start_apu instead." +proc release_apu {apu} { + set axi $::_CHIPNAME.axi + set val [$axi read_memory $::CRF_APB_RST_FPD_APU 32 1] + set mask [expr { + (($::CRF_APB_RST_FPD_APU_ACPU0_PWRON_RESET | \ + $::CRF_APB_RST_FPD_APU_ACPU0_RESET) << $apu) | \ + $::CRF_APB_RST_FPD_APU_L2_RESET + }] + $axi write_memory $::CRF_APB_RST_FPD_APU 32 [expr {$val & ~$mask}] + + core_up $apu + $::_TARGETNAME.$apu aarch64 dbginit +} + +proc _rvbaraddr {apu} { + return [expr {$::APU_RVBARADDR_BASE + 8 * $apu}] +} + +add_usage_text resume_apu {apu addr} +add_help_text resume_apu "Resume an APU at a given address." +proc resume_apu {apu addr} { + set addrl [expr {$addr & 0xffffffff}] + set addrh [expr {$addr >> 32}] + $::_CHIPNAME.axi write_memory [_rvbaraddr $apu] 32 [list $addrl $addrh] + + release_apu $apu +} + +add_usage_text start_apu {apu} +add_help_text start_apu "Start an APU and put it into an infinite loop at\ + RVBARADDR. This can be convenient if you just want to halt the APU\ + (since it won't execute anything unusual)." +proc start_apu {apu} { + set axi $::_CHIPNAME.axi + foreach {addrl addrh} [$axi read_memory [_rvbaraddr $apu] 32 2] { + set addr [expr {($addrh << 32) | $addrl}] + } + # write the infinite loop instruction + $axi write_memory $addr 32 0x14000000 + + release_apu $apu +} + +add_usage_text boot_pmu {image} +add_help_text boot_pmu "Boot the PMU with a given firmware image, loading it\ + to the beginning of PMU RAM. The PMU ROM will jump to this location\ + after we resume it." +proc boot_pmu {image} { + halt_pmu + echo "Info : Loading PMU firmware $image to $::PMU_RAM_BASE" + load_image $image $::PMU_RAM_BASE + resume_pmu +} + +add_usage_text boot_apu "image \[apu=0 \[addr=$OCM_RAM_BASE\]\]" +add_help_text boot_apu "Boot an APU with a given firmware image. The default\ + address is the beginning of OCM RAM. Upon success, the default target\ + will be changed to the (running) apu." +proc boot_apu [list image {apu 0} [list addr $OCM_RAM_BASE]] { + start_apu $apu + targets $::_TARGETNAME.$apu + halt + + echo "Info : Loading APU$apu firmware $image to $addr" + load_image $image $addr + resume $addr +} |