# SPDX-License-Identifier: GPL-2.0-or-later

#
# Configuration script for Cypress PSoC6 family of microcontrollers (CY8C6xxx)
# PSoC6 is a dual-core device with CM0+ and CM4 cores. Both cores share
# the same Flash/RAM/MMIO address space.
#

source [find target/swj-dp.tcl]

adapter speed 1000

global _CHIPNAME
if { [info exists CHIPNAME] } {
	set _CHIPNAME $CHIPNAME
} else {
	set _CHIPNAME psoc6
}

global TARGET
set TARGET $_CHIPNAME.cpu

swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu

# Is CM0 Debugging enabled ?
global _ENABLE_CM0
if { [info exists ENABLE_CM0] } {
	set _ENABLE_CM0 $ENABLE_CM0
} else {
	set _ENABLE_CM0 1
}

# Is CM4 Debugging enabled ?
global _ENABLE_CM4
if { [info exists ENABLE_CM4] } {
	set _ENABLE_CM4 $ENABLE_CM4
} else {
	set _ENABLE_CM4 1
}

global _WORKAREASIZE_CM0
if { [info exists WORKAREASIZE_CM0] } {
	set _WORKAREASIZE_CM0 $WORKAREASIZE_CM0
} else {
	set _WORKAREASIZE_CM0 0x4000
}

global _WORKAREASIZE_CM4
if { [info exists WORKAREASIZE_CM4] } {
	set _WORKAREASIZE_CM4 $WORKAREASIZE_CM4
} else {
	set _WORKAREASIZE_CM4 0x4000
}

global _WORKAREAADDR_CM0
if { [info exists WORKAREAADDR_CM0] } {
	set _WORKAREAADDR_CM0 $WORKAREAADDR_CM0
} else {
	set _WORKAREAADDR_CM0 0x08000000
}

global _WORKAREAADDR_CM4
if { [info exists WORKAREAADDR_CM4] } {
	set _WORKAREAADDR_CM4 $WORKAREAADDR_CM4
} else {
	set _WORKAREAADDR_CM4 0x08000000
}

proc init_reset { mode } {
	global RESET_MODE
	set RESET_MODE $mode

	if {[using_jtag]} {
		jtag arp_init-reset
	}
}

# Utility to make 'reset halt' work as reset;halt on a target
# It does not prevent running code after reset
proc psoc6_deassert_post { target } {
	# PSoC6 cleared AP registers including TAR during reset
	# Force examine to synchronize OpenOCD target status
	$target arp_examine

	global RESET_MODE
	global TARGET

	if { $RESET_MODE ne "run" } {
		$target arp_poll
		$target arp_poll
		set st [$target curstate]

		if { $st eq "reset" } {
			# we assume running state follows
			# if reset accidentally halts, waiting is useless
			catch { $target arp_waitstate running 100 }
			set st [$target curstate]
		}

		if { $st eq "running" } {
			echo "$target: Ran after reset and before halt..."
			if { $target eq "${TARGET}.cm0" } {
				# Try to cleanly reset whole system
				# and halt the CM0 at entry point
				psoc6 reset_halt
				$target arp_waitstate halted 100
			} else {
				$target arp_halt
			}
		}
	}
}

if { $_ENABLE_CM0 } {
	target create ${TARGET}.cm0 cortex_m -dap $_CHIPNAME.dap -ap-num 1 -coreid 0
	${TARGET}.cm0 configure -work-area-phys $_WORKAREAADDR_CM0 -work-area-size $_WORKAREASIZE_CM0 -work-area-backup 0

	flash bank main_flash_cm0		psoc6 0x10000000 0 0 0 ${TARGET}.cm0
	flash bank work_flash_cm0		psoc6 0x14000000 0 0 0 ${TARGET}.cm0
	flash bank super_flash_user_cm0	psoc6 0x16000800 0 0 0 ${TARGET}.cm0
	flash bank super_flash_nar_cm0	psoc6 0x16001A00 0 0 0 ${TARGET}.cm0
	flash bank super_flash_key_cm0	psoc6 0x16005A00 0 0 0 ${TARGET}.cm0
	flash bank super_flash_toc2_cm0	psoc6 0x16007C00 0 0 0 ${TARGET}.cm0

	${TARGET}.cm0 cortex_m reset_config sysresetreq
	${TARGET}.cm0 configure -event reset-deassert-post "psoc6_deassert_post ${TARGET}.cm0"
}

if { $_ENABLE_CM4 } {
	target create ${TARGET}.cm4 cortex_m -dap $_CHIPNAME.dap -ap-num 2 -coreid 1
	${TARGET}.cm4 configure -work-area-phys $_WORKAREAADDR_CM4 -work-area-size $_WORKAREASIZE_CM4 -work-area-backup 0

	flash bank main_flash_cm4		psoc6 0x10000000 0 0 0 ${TARGET}.cm4
	flash bank work_flash_cm4		psoc6 0x14000000 0 0 0 ${TARGET}.cm4
	flash bank super_flash_user_cm4	psoc6 0x16000800 0 0 0 ${TARGET}.cm4
	flash bank super_flash_nar_cm4	psoc6 0x16001A00 0 0 0 ${TARGET}.cm4
	flash bank super_flash_key_cm4	psoc6 0x16005A00 0 0 0 ${TARGET}.cm4
	flash bank super_flash_toc2_cm4	psoc6 0x16007C00 0 0 0 ${TARGET}.cm4

	${TARGET}.cm4 cortex_m reset_config vectreset
	${TARGET}.cm4 configure -event reset-deassert-post "psoc6_deassert_post ${TARGET}.cm4"
}

if { $_ENABLE_CM0 } {
	# Use CM0+ by default on dual-core devices
	targets ${TARGET}.cm0
}

if {[using_jtag]} {
	jtag newtap $_CHIPNAME bs -irlen 18 -expected-id 0x2e200069
}
