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

#
# Glyn Tonga2 SO-DIMM CPU module (Toshiba TMPA900CMXBG, ARM9)
#
# http://toshiba-mikrocontroller.de/sites/TMPA900CPUBOARDStarter.htm
#
# Hardware on the S0-DIMM module:
#   - Toshiba TMPA900CMXBG (ARM9, ARM926EJ-S, max. 200MHz)
#   - DDR SDRAM: Hynix H5MS5162DFR-J3M (64Mbyte, x16, 1.8V, 166/83MHz at CL3/2)
#   - NAND flash: Samsung K9F2G08U0B-PIB0 (256M x 8 Bit, 3.3V)
#   - Ethernet: SMSC LAN9221I-ABZJ (10/100Mbit, Non-PCI, 16 bit interface)
#

source [find target/tmpa900.cfg]

########################
# Target configuration #
########################

# Initial JTAG speed should not exceed 1/6 of the initial CPU clock
# frequency (24MHz). Be conservative and use 1/8 of the frequency.
# (24MHz / 8 = 3MHz)
adapter speed 3000

$_TARGETNAME configure -event reset-start {
	# Upon reset, set the JTAG frequency to 3MHz again, see above.
	echo "Setting JTAG speed to 3MHz until clocks are initialized."
	adapter speed 3000

	# Halt the CPU.
	halt

	# Disable faster memory access for now.
	arm7_9 fast_memory_access disable
}

$_TARGETNAME configure -event reset-init {
	# Setup clocks, and initialize SRAM and DDR SDRAM.
	tonga2_init

	# At this point the CPU is running at 192MHz, increase JTAG speed.
	# Tests showed that 15MHz works OK, higher speeds can cause problems,
	# though. Not sure if this is a CPU issue or JTAG adapter issue.
	echo "Increasing JTAG speed to 15MHz."
	adapter speed 15000

	# Enable faster memory access.
	arm7_9 fast_memory_access enable
}

proc tonga2_init { } {
	######################
	# PLL initialization #
	######################

	# Clock overview (see datasheet chapter 3.5.2, page 57):
	#   - fs: Low-frequency oscillator
	#   - fOSCH: High-frequency oscillator (24MHz on this board)
	#   - fPLL = fOSCH * multiplier (where multiplier can be 6 or 8)
	#   - fFCLK = fPLL / gear (where gear can be 1/2/4/8)
	#   - fHCLK is always fFCLK/2. fPCLK is also fFCLK/2.
	#
	# We select multiplier = 8 and gear = 1, so
	#   fFCLK = fOSCH * 8 / 1 = 192MHz.

	# SYSCR3 (System Control Register 3): Disable and configure PLL.
	#   - PLL operation control: off
	#   - PLL constant value setting 1: always 0, as per datasheet
	#   - PLL constant value setting 2: x8 (multiplier = 8)
	mww 0xf005000c 0x00000007

	# SYSCR4 (System Control Register 4): Configure PLL.
	#   - PLL constant value setting 3: 140MHz or more
	#   - PLL constant value setting 4: always 1, as per datasheet
	#   - PLL constant value setting 5: 140MHz or more
	mww 0xf0050010 0x00000065

	# SYSCR3 (System Control Register 3): Enable PLL.
	#   - PLL operation control: on
	#   - All other bits remain set as above.
	mww 0xf005000c 0x00000087

	# Wait for PLL to stabilize.
	sleep 10

	# SYSCR2 (System Control Register 2): Switch from fOSCH to fPLL.
	#   - Selection of the PLL output clock: fPLL
	mww 0xf0050008 0x00000002

	# SYSCR1 (System Control Register 1):
	#   - Clock gear programming: fc/1 (i.e., gear = 1, don't divide).
	mww 0xf0050004 0x00000000

	# CLKCR5 (Clock Control Register 5): Set bits 3 and 6. The datasheet
	# says the bits are reserved, but also recommends "Write as one".
	mww 0xf0050054 0x00000048


	##############################################################
	# Dynamic Memory Controller (DMC) / DDR SDRAM initialization #
	##############################################################

	# PMC (Power Management Controller):
	# PMCDRV (External Port "Driverbility" control register):
	# Bits DRV_MEM0/DRV_MEM1 (memory relation port drive power):
	mww 0xf0020260 0x00000003	;# Select 1.8V +/- 0.1V

	# Setup DDR SDRAM timing parameters for our specific chip.
	mww 0xf4310014 0x00000004	;# cas_latency = 2
	mww 0xf4310018 0x00000001	;# t_dqss = 1
	mww 0xf431001c 0x00000002	;# t_mrd = 2
	mww 0xf4310020 0x0000000a	;# t_ras = 10
	mww 0xf4310024 0x0000000a	;# t_rc = 10
	mww 0xf4310028 0x00000013	;# t_rcd = 3, schedule_rcd = 2
	mww 0xf431002c 0x0000010a	;# t_rfc = 10, schedule_rfc = 8
	mww 0xf4310030 0x00000013	;# t_rp = 3, schedule_rp = 2
	mww 0xf4310034 0x00000002	;# t_rrd = 2
	mww 0xf4310038 0x00000002	;# t_wr = 2
	mww 0xf431003c 0x00000001	;# t_wtr = 1
	mww 0xf4310040 0x0000000a	;# t_xp = 10
	mww 0xf4310044 0x0000000c	;# t_xsr = 12
	mww 0xf4310048 0x00000014	;# t_esr = 20

	# dmc_memory_cfg_5 (DMC Memory Configuration register):
	# Set memory configuration:
	# column_bits = 10, row_bits = 13, ap-bit = 10, power_down_prd = 0,
	# auto_power_down = disable, stop_mem_clock = disable, memory_burst = 4
	mww 0xf431000c 0x00010012

	# dmc_user_config_5 (DMC user_config register):
	# Data bus width of DDR SDRAM: 16 bit
	mww 0xf4310304 0x00000058

	# dmc_refresh_prd_5 (DMC Refresh Period register):
	# Auto refresh: every 2656 (0xa60) DMCSCLK periods.
	mww 0xf4310010 0x00000a60

	# dmc_chip_0_cfg_5 (DMC chip_0_cfg registers):
	#   - SDRAM address structure: bank, row, column
	#   - address_match = 01000000 (start address [31:24])
	#   - address_mask  = 11111100 (start address [31:24] mask value)
	mww 0xf4310200 0x000140fc

	# Initialize the DDR SDRAM chip.
	# dmc_direct_cmd_5 (DMC Direct Command register).
	# See datasheet chapter 3.10.5.1, page 268.
	mww 0xf4310008 0x000c0000	;# RAM init: NOP
	mww 0xf4310008 0x00000000	;# RAM init: Precharge all
	mww 0xf4310008 0x00040000	;# RAM init: Autorefresh
	mww 0xf4310008 0x00040000	;# RAM init: Autorefresh
	mww 0xf4310008 0x00080032	;# RAM init: addr_13_to_0 = 0x32
	mww 0xf4310008 0x000c0000	;# RAM init: NOP
	mww 0xf4310008 0x000a0000	;# RAM init: bank_addr = bank 2

	# dmc_id_<0-5>_cfg_5 (DMC id_<0-5>_cfg registers):
	# Set min./max. QoS values.
	#   - 0x5: Enable QoS, max. QoS = 1
	#   - 0xb: Enable QoS, min. QoS = 2
	mww 0xf4310100 0x00000005	;# AHB0: CPU Data
	mww 0xf4310104 0x00000005	;# AHB1: CPU Inst
	mww 0xf4310108 0x0000000b	;# AHB2: LCDC
	mww 0xf431010c 0x00000005	;# AHB3: LCDDA, USB
	mww 0xf4310110 0x00000005	;# AHB4: DMA1
	mww 0xf4310114 0x00000005	;# AHB5: DMA2

	# dmc_memc_cmd_5 (DMC Memory Controller Command register):
	# Change DMC state to ready.
	mww 0xf4310004 0x00000000	;# memc_cmd = "Go"

	# EBI: SMC Timeout register
	mww 0xf00a0050 0x00000001	;# smc_timeout = 1


	########################################################
	# Static Memory Controller (SMC) / SRAM initialization #
	########################################################

	# smc_set_cycles_5 (SMC Set Cycles register):
	# tRC = 10, tWC = 10, tCEOE = 7, tWP = 5, tPC=2, tTR=2
	mww 0xf4311014 0x0004afaa

	# smc_set_opmode_5 (SMC Set Opmode register):
	# Memory data bus width = 16 bits, async read mode, read burst
	# length = 1 beat, async write mode, write burst length = 1 beat,
	# byte enable (SMCBE0-1) timing = SMCCSn timing, memory burst boundary
	# split setting = burst can cross any address boundary
	mww 0xf4311018 0x00000001

	# smc_direct_cmd_5 (SMC Direct Command register):
	# cmd_type = UpdateRegs, chip_select = CS1
	mww 0xf4311010 0x00c00000

	echo "Clocks, SRAM, and DDR SDRAM are now initialized."
}

#######################
# Flash configuration #
#######################

# TODO: Implement NAND support.