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

# Renesas RZ/G2 SOCs
# - There are a combination of Cortex-A57s, Cortex-A53s, Cortex-A55, Cortex-R7
# and Cortex-M33 for each SOC
# - Each SOC can boot through the Cortex-A5x cores

# Supported RZ/G2 SOCs and their cores:
# RZ/G2H:   Cortex-A57 x4, Cortex-A53 x4, Cortex-R7
# RZ/G2M:   Cortex-A57 x2, Cortex-A53 x4, Cortex-R7
# RZ/G2N:   Cortex-A57 x2,                Cortex-R7
# RZ/G2E:                  Cortex-A53 x2, Cortex-R7
# RZ/G2L:                  Cortex-A55 x2, Cortex-M33
# RZ/G2LC:                 Cortex-A55 x2, Cortex-M33
# RZ/G2UL:                 Cortex-A55 x1, Cortex-M33

# Usage:
# There are 2 configuration options:
# SOC:       Selects the supported SOC. (Default 'G2L')
# BOOT_CORE: Selects the booting core. 'CA57', 'CA53' or 'CA55'

transport select jtag
reset_config trst_and_srst srst_gates_jtag
adapter speed 4000
adapter srst delay 500

if { [info exists SOC] } {
	set _soc $SOC
} else {
	set _soc G2L
}

set _num_ca57 0
set _num_ca55 0
set _num_ca53 0
set _num_cr7 0
set _num_cm33 0

# Set configuration for each SOC and the default 'BOOT_CORE'
switch $_soc {
	G2H {
		set _CHIPNAME r8a774ex
		set _num_ca57 4
		set _num_ca53 4
		set _num_cr7 1
		set _boot_core CA57
		set _ap_num 1
	}
	G2M {
		set _CHIPNAME r8a774ax
		set _num_ca57 2
		set _num_ca53 4
		set _num_cr7 1
		set _boot_core CA57
		set _ap_num 1
	}
	G2N {
		set _CHIPNAME r8a774bx
		set _num_ca57 2
		set _num_ca53 0
		set _num_cr7 1
		set _boot_core CA57
		set _ap_num 1
	}
	G2E {
		set _CHIPNAME r8a774c0
		set _num_ca57 0
		set _num_ca53 2
		set _num_cr7 1
		set _boot_core CA53
		set _ap_num 1
	}
	G2L {
		set _CHIPNAME r9a07g044l
		set _num_ca55 2
		set _num_cm33 1
		set _boot_core CA55
		set _ap_num 0
	}
	G2LC {
		set _CHIPNAME r9a07g044c
		set _num_ca55 2
		set _num_cm33 1
		set _boot_core CA55
		set _ap_num 0
	}
	G2UL {
		set _CHIPNAME r9a07g043u
		set _num_ca55 1
		set _num_cm33 1
		set _boot_core CA55
		set _ap_num 0
	}
	default {
		error "'$_soc' is invalid!"
	}
}

# If configured, override the default 'CHIPNAME'
if { [info exists CHIPNAME] } {
	set _CHIPNAME $CHIPNAME
}

# If configured, override the default 'BOOT_CORE'
if { [info exists BOOT_CORE] } {
	set _boot_core $BOOT_CORE
}

if { [info exists DAP_TAPID] } {
	set _DAP_TAPID $DAP_TAPID
} else {
	set _DAP_TAPID 0x6ba00477
}

echo "\t$_soc - $_num_ca57 CA57(s), $_num_ca55 CA55(s), $_num_ca53 CA53(s), $_num_cr7 CR7(s), \
	$_num_cm33 CM33(s)"
echo "\tBoot Core - $_boot_core\n"

set _DAPNAME $_CHIPNAME.dap


# TAP and DAP
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID \
	-ignore-version
dap create $_DAPNAME -chain-position $_CHIPNAME.cpu
echo "$_CHIPNAME.cpu"

set CA57_DBGBASE {0x80410000 0x80510000 0x80610000 0x80710000}
set CA57_CTIBASE {0x80420000 0x80520000 0x80620000 0x80720000}
set CA55_DBGBASE {0x10E10000 0x10F10000}
set CA55_CTIBASE {0x10E20000 0x10F20000}
set CA53_DBGBASE {0x80C10000 0x80D10000 0x80E10000 0x80F10000}
set CA53_CTIBASE {0x80C20000 0x80D20000 0x80E20000 0x80F20000}
set  CR7_DBGBASE 0x80910000
set  CR7_CTIBASE 0x80918000
set CM33_DBGBASE 0xE000E000
set CM33_CTIBASE 0xE0042000

set smp_targets ""

proc setup_a5x {core_name dbgbase ctibase num boot} {
	for { set _core 0 } { $_core < $num } { incr _core } {
		set _TARGETNAME $::_CHIPNAME.$core_name.$_core
		set _CTINAME $_TARGETNAME.cti
		cti create $_CTINAME -dap $::_DAPNAME -ap-num $::_ap_num \
			-baseaddr [lindex $ctibase $_core]
		target create $_TARGETNAME aarch64 -dap $::_DAPNAME \
			-ap-num $::_ap_num -dbgbase [lindex $dbgbase $_core] -cti $_CTINAME
		if { $_core > 0 || $boot == 0 } {
			$_TARGETNAME configure -defer-examine
		}
		set ::smp_targets "$::smp_targets $_TARGETNAME"
	}
}

proc setup_cr7 {dbgbase ctibase} {
	set _TARGETNAME $::_CHIPNAME.r7
	set _CTINAME $_TARGETNAME.cti
	cti create $_CTINAME -dap $::_DAPNAME -ap-num 1 -baseaddr $ctibase
	target create $_TARGETNAME cortex_r4 -dap $::_DAPNAME \
		-ap-num 1 -dbgbase $dbgbase -defer-examine
}

proc setup_cm33 {dbgbase ctibase} {
        set _TARGETNAME $::_CHIPNAME.m33
        set _CTINAME $_TARGETNAME.cti
        cti create $_CTINAME -dap $::_DAPNAME -ap-num 2 -baseaddr $ctibase
        target create $_TARGETNAME cortex_m -dap $::_DAPNAME \
                -ap-num 2 -dbgbase $dbgbase -defer-examine
}

# Organize target list based on the boot core
if { $_boot_core == "CA57" } {
	setup_a5x a57 $CA57_DBGBASE $CA57_CTIBASE $_num_ca57 1
	setup_a5x a53 $CA53_DBGBASE $CA53_CTIBASE $_num_ca53 0
	setup_cr7 $CR7_DBGBASE $CR7_CTIBASE
} elseif { $_boot_core == "CA53" } {
	setup_a5x a53 $CA53_DBGBASE $CA53_CTIBASE $_num_ca53 1
	setup_a5x a57 $CA57_DBGBASE $CA57_CTIBASE $_num_ca57 0
	setup_cr7 $CR7_DBGBASE $CR7_CTIBASE
} elseif { $_boot_core == "CA55" } {
	setup_a5x a55 $CA55_DBGBASE $CA55_CTIBASE $_num_ca55 1
	setup_cm33 $CM33_DBGBASE $CM33_CTIBASE
}
echo "SMP targets:$smp_targets"
eval "target smp $smp_targets"

if { $_soc == "G2L" || $_soc == "G2LC" || $_soc == "G2UL" } {
	target create $_CHIPNAME.axi_ap mem_ap -dap $_DAPNAME -ap-num 1
}

proc init_reset {mode} {
    # Assert both resets: equivalent to a power-on reset
    adapter assert trst assert srst

    # Deassert TRST to begin TAP communication
    adapter deassert trst assert srst

    # TAP should now be responsive, validate the scan-chain
    jtag arp_init
}