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

# The Atheros AR9331 is a highly integrated and cost effective
# IEEE 802.11n 1x1 2.4 GHz System- on-a-Chip (SoC) for wireless
# local area network (WLAN) AP and router platforms.
#
# Notes:
# - MIPS Processor ID (PRId): 0x00019374
# - 24Kc MIPS processor with 64 KB I-Cache and 32 KB D-Cache,
#   operating at up to 400 MHz
# - External 16-bit DDR1, DDR2, or SDRAM memory interface
# - TRST is not available.
# - EJTAG PrRst signal is not supported
# - RESET_L pin A72 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	GPIO6, (B46)	Software configurable, default JTAG
# JTAG_TDO	GPIO7, (A54)	Software configurable, default JTAG
# JTAG_TMS	GPIO8, (A52)	Software configurable, default JTAG
#   Reset
# RESET_L	-, (A72)	Input only
# SYS_RST_L	????????	Output reset request or GPIO
#   Bootstrap
# MEM_TYPE[1]	GPIO28, (A74)	0 - SDRAM, 1 - DDR1 RAM, 2 - DDR2 RAM
# MEM_TYPE[0]	GPIO12, (A56)
# FW_DOWNLOAD	GPIO16, (A75)	Used if BOOT_FROM_SPI = 0. 0 - boot from USB
#                               1 - boot from MDIO.
# JTAG_MODE(JS)	GPIO11, (B48)	0 - JTAG (Default); 1 - EJTAG
# BOOT_FROM_SPI	GPIO1, (A77)	0 - ROM boot; 1 - SPI boot
# SEL_25M_40M	GPIO0, (A78)	0 - 25MHz; 1 - 40MHz
#   UART
# UART0_SOUT	GPIO10, (A79)
# UART0_SIN	GPIO9, (B68)

# 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 srst pulse_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 srst delay 8

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

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
}

proc disable_watchdog { } {
	;# disable watchdog
	mww 0xb8060008 0x0
}

$_TARGETNAME configure -event reset-end { disable_watchdog }

# Section with helpers which can be used by boards
proc ar9331_25mhz_pll_init {} {
	mww 0xb8050008 0x00018004	;# bypass PLL; AHB_POST_DIV - ratio 4
	mww 0xb8050004 0x00000352	;# 34000(ns)/40ns(25MHz) = 0x352 (850)
	mww 0xb8050000 0x40818000	;# Power down control for CPU PLL
					;# OUTDIV | REFDIV | DIV_INT
	mww 0xb8050010 0x001003e8	;# CPU PLL Dither FRAC Register
					;# (disabled?)
	mww 0xb8050000 0x00818000	;# Power on | OUTDIV | REFDIV | DIV_INT
	mww 0xb8050008 0x00008000	;# remove bypass;
					;# AHB_POST_DIV - ratio 2
}

proc ar9331_ddr1_init {} {
	mww 0xb8000000 0x7fbc8cd0       ;# DDR_CONFIG - lots of DRAM confs
	mww 0xb8000004 0x9dd0e6a8	;# DDR_CONFIG2 - more DRAM confs

	mww 0xb8000010 0x8	;# Forces a PRECHARGE ALL cycle
	mww 0xb8000008 0x133	;# mode reg: 0x133 - default
	mww 0xb8000010 0x1	;# Forces an MRS update cycl
	mww 0xb800000c 0x2	;# Extended mode register value.
				;# default 0x2 - Reset to weak driver, DLL on
	mww 0xb8000010 0x2	;# Forces an EMRS update cycle
	mww 0xb8000010 0x8	;# Forces a PRECHARGE ALL cycle
	mww 0xb8000008 0x33	;# mode reg: remove some bit?
	mww 0xb8000010 0x1	;# Forces an MRS update cycl
	mww 0xb8000014 0x4186	;# enable refres: bit(14) - set refresh rate
	mww 0xb800001c 0x8	;# This register is used along with DQ Lane 0,
				;# DQ[7:0], DQS_0
	mww 0xb8000020 0x9	;# This register is used along with DQ Lane 1,
				;# DQ[15:8], DQS_1.
	mww 0xb8000018 0xff	;# DDR read and capture bit mask.
				;# Each bit represents a cycle of valid data.
}

proc ar9331_ddr2_init {} {
	mww 0xb8000000 0x7fbc8cd0	;# DDR_CONFIG - lots of DRAM confs
	mww 0xb8000004 0x9dd0e6a8	;# DDR_CONFIG2 - more DRAM confs

	mww 0xb800008c 0x00000a59
	mww 0xb8000010 0x00000008	;# PRECHARGE ALL cycle

	mww 0xb8000090 0x00000000
	mww 0xb8000010 0x00000010	;# EMR2S update cycle

	mww 0xb8000094 0x00000000
	mww 0xb8000010 0x00000020	;# EMR3S update cycle

	mww 0xb800000c 0x00000000
	mww 0xb8000010 0x00000002	;# EMRS update cycle

	mww 0xb8000008 0x00000100
	mww 0xb8000010 0x00000001	;# MRS update cycle

	mww 0xb8000010 0x00000008	;# PRECHARGE ALL cycle

	mww 0xb8000010 0x00000004
	mww 0xb8000010 0x00000004	;# AUTO REFRESH cycle

	mww 0xb8000008 0x00000a33
	mww 0xb8000010 0x00000001	;# MRS update cycle

	mww 0xb800000c 0x00000382
	mww 0xb8000010 0x00000002	;# EMRS update cycle

	mww 0xb800000c 0x00000402
	mww 0xb8000010 0x00000002	;# EMRS update cycle

	mww 0xb8000014 0x00004186	;# DDR_REFRESH
	mww 0xb800001c 0x00000008	;# DDR_TAP_CTRL0
	mww 0xb8000020 0x00000009	;# DDR_TAP_CTRL1

	;# DDR read and capture bit mask.
	;# Each bit represents a cycle of valid data.
	;# 0xff: use 16-bit DDR
	mww 0xb8000018 0x000000ff
}
