# The QCA4531 is a two stream (2x2) 802.11b/g/n single-band programmable
# Wi-Fi System-on-Chip (SoC) for the Internet of Things (IoT).
#
# Product page:
# https://www.qualcomm.com/products/qca4531
#
# Notes:
# - MIPS Processor ID (PRId): 0x00019374
# - 24Kc MIPS processor with 64 KB I-Cache and 32 KB D-Cache,
#   operating at up to 650 MHz
# - External 16-bit DDR1, operating at up to 200 MHz, DDR2 operating at up
#   to 300 MHz
# - TRST is not available.
# - EJTAG PrRst signal is not supported
# - RESET_L pin B56 on the SoC will reset internal JTAG logic.
#
# Pins related for debug and bootstrap:
# Name		Pin		Description
#   JTAG
# JTAG_TCK	GPIO0, (A27)	Software configurable, default JTAG
# JTAG_TDI	GPIO1, (B23)	Software configurable, default JTAG
# JTAG_TDO	GPIO2, (A28)	Software configurable, default JTAG
# JTAG_TMS	GPIO3, (A29)	Software configurable, default JTAG
#   Reset
# RESET_L	-, (B56)	Input only
# SYS_RST_L	GPIO17, (A79)	Output reset request or GPIO
#   Bootstrap
# JTAG_MODE	GPIO16, (A78)	0 - JTAG (Default); 1 - EJTAG
# DDR_SELECT	GPIO10, (A57)	0 - DDR2; 1 - DDR1
#   UART
# UART0_SOUT	GPIO10, (A57)
# UART0_SIN	GPIO9, (B49)

# Per default we need to use "none" variant to be able properly "reset init"
# or "reset halt" the CPU.
reset_config none srst_pulls_trst

# For SRST based variant we still need proper timings.
# For ETH part the reset should be asserted at least for 10ms
# Since there is no other information let's take 100ms to be sure.
adapter_nsrst_assert_width 100

# according to the SoC documentation it should take at least 5ms from
# reset end till bootstrap end. In the practice we need 8ms to get JTAG back
# to live.
adapter_nsrst_delay 8

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

jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00000001

set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME mips_m4k -endian big -chain-position $_TARGETNAME

# provide watchdog helper.
proc disable_watchdog { } {
	mww 0xb8060008 0x0
}

$_TARGETNAME configure -event halted { disable_watchdog }

# Since PrRst is not supported and SRST will reset complete chip
# with JTAG engine, we need to reset CPU from CPU itself.
$_TARGETNAME configure -event reset-assert-pre {
	halt
}

$_TARGETNAME configure -event reset-assert {
	catch "mww 0xb806001C 0x01000000"
}

# To be able to trigger complete chip reset, in case JTAG is blocked
# or CPU not responding, we still can use this helper.
proc full_reset { } {
	reset_config srst_only
	reset
	halt
	reset_config none
}

# Section with helpers which can be used by boards
proc qca4531_ddr2_550_550_init {} {
	# Clear reset flags for different SoC components
	mww 0xb806001c 0xfeceffff
	mww 0xb806001c 0xeeceffff
	mww 0xb806001c 0xe6ceffff

	# PMU configurations
	# Internal Switcher
	mww 0xb8116c40 0x633c8176
	# Increase the DDR voltage
	mww 0xb8116c44 0x10200000
	# XTAL Configurations
	mww 0xb81162c0 0x4b962100
	mww 0xb81162c4 0x480
	mww 0xb81162c8 0x04000144
	# Recommended PLL configurations
	mww 0xb81161c4 0x54086000
	mww 0xb8116244 0x54086000

	# PLL init
	mww 0xb8050008 0x0131001c
	mww 0xb8050000 0x40001580
	mww 0xb8050004 0x40015800
	mww 0xb8050008 0x0131001c
	mww 0xb8050000 0x00001580
	mww 0xb8050004 0x00015800
	mww 0xb8050008 0x01310000
	mww 0xb8050044 0x781003ff
	mww 0xb8050048 0x003c103f

	# DDR2 init
	mww 0xb8000108 0x401f0042
	mww 0xb80000b8 0x0000166d
	mww 0xb8000000 0xcfaaf33b
	mww 0xb800015c 0x0000000f
	mww 0xb8000004 0xa272efa8
	mww 0xb8000018 0x0000ffff
	mww 0xb80000c4 0x74444444
	mww 0xb80000c8 0x00000444
	mww 0xb8000004 0xa210ee28
	mww 0xb8000004 0xa2b2e1a8
	mww 0xb8000010 0x8
	mww 0xb80000bc 0x0
	mww 0xb8000010 0x10
	mww 0xb80000c0 0x0
	mww 0xb8000010 0x40
	mww 0xb800000c 0x2
	mww 0xb8000010 0x2
	mww 0xb8000008 0xb43
	mww 0xb8000010 0x1
	mww 0xb8000010 0x8
	mww 0xb8000010 0x4
	mww 0xb8000010 0x4
	mww 0xb8000008 0xa43
	mww 0xb8000010 0x1
	mww 0xb800000c 0x382
	mww 0xb8000010 0x2
	mww 0xb800000c 0x402
	mww 0xb8000010 0x2
	mww 0xb8000014 0x40be
	mww 0xb800001C 0x20
	mww 0xb8000020 0x20
	mww 0xb80000cc 0xfffff

	# UART GPIO programming
	mww 0xb8040000 0xff30b
	mww 0xb8040044 0x908
	mww 0xb8040034 0x160000
}
