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

#################################################################################################
#												                                                #
# Author: Lars Poeschel (larsi@wh2.tu-dresden.de)												#
# Generated for In-Circuit ICnova SAM9G45 SODIMM												#
# http://www.ic-board.de/product_info.php?info=p214_ICnova-SAM9G45-SODIMM.html|ICnova			#
#																								#
#################################################################################################

# FIXME use some standard target config, maybe create one from this
#
#	source [find target/...cfg]

source [find target/at91sam9g45.cfg]

# Set reset type.
# reset_config trst_and_srst

# adapter srst delay 200
# jtag_ntrst_delay 200


# If you don't want to execute built-in boot rom code (and there are good reasons at times not to do that) in the
# AT91SAM9 family, the microcontroller is a lump on a log without initialization.  Because this family has
# some powerful features, we want to have a special function that handles "reset init".  To do this we declare
# an event handler where these special activities can take place.

scan_chain
$_TARGETNAME configure -event reset-init {at91sam9g45_init}

# Set fallback clock to 1/6 of worst-case clock speed (which would be the 32.768 kHz slow clock).
# Slow-speed oscillator enabled at reset, so run jtag speed slow.
$_TARGETNAME configure -event reset-start {at91sam9g45_start}


# NandFlash configuration and definition
# Future TBD
# Flash configuration
# flash bank cfi <base> <size> <chip width> <bus width> <target#>
set _FLASHNAME $_CHIPNAME.flash
# set _NANDNAME $_CHIPNAME.nand
flash bank $_FLASHNAME cfi 0x10000000 0x00800000 2 2 $_TARGETNAME
# nand device $_NANDNAME at91sam9 $_TARGETNAME 0x40000000 0xFFFFE800


proc read_register {register} {
	return [read_memory $register 32 1]
}

proc at91sam9g45_start { } {

	# Make sure that the the jtag is running slow, since there are a number of different ways the board
	# can be configured coming into this state that can cause communication problems with the jtag
	# adapter.  Also since this call can be made following a "reset init" where fast memory accesses
	# are enabled, need to temporarily shut this down so that the RSTC_MR register can be written at slower
	# jtag speed without causing GDB keep alive problem.

	arm7_9 fast_memory_access disable
    # Slow-speed oscillator enabled at reset, so run jtag speed slow.
	adapter speed 4
    # Make sure processor is halted, or error will result in following steps.
	halt
	wait_halt 10000
    # RSTC_MR : enable user reset.
	mww 0xfffffd08 0xa5000501
}


proc at91sam9g45_init { } {

	# At reset AT91SAM9G45 chip runs on slow clock (32.768 kHz).  To shift over to a normal clock requires
	# a number of steps that must be carefully performed.  The process outline below follows the
	# recommended procedure outlined in the AT91SAM9G45 technical manual.
	#
	# Several key and very important things to keep in mind:
	# The SDRAM parts used currently on the board are -75 grade parts.  This
	# means the master clock (MCLK) must be at or below 133 MHz or timing errors will occur.  The processor
	# core can operate up to 400 MHz and therefore PCLK must be at or below this to function properly.

	# Make sure processor is halted, or error will result in following steps.
	halt
	# RSTC_MR : enable user reset.
	mww 0xfffffd08 0xa5000501
	# WDT_MR : disable watchdog.
	mww 0xfffffd44 0x00008000

	# Enable the main 15.000 MHz oscillator in CKGR_MOR register.
	# Wait for MOSCS in PMC_SR to assert indicating oscillator is again stable after change to CKGR_MOR.

	mww 0xfffffc20 0x00004001
	while { [expr {[read_register 0xfffffc68] & 0x01}] != 1 } { sleep 1 }

	# Set PLLA Register for 792.576 MHz (divider: bypass, multiplier: 43).
	# Wait for LOCKA signal in PMC_SR to assert indicating PLLA is stable.

	#mww 0xfffffc28 0x202a3f01
	mww 0xfffffc28 0x20c73f03
	while { [expr {[read_register 0xfffffc68] & 0x02}] != 2 } { sleep 1 }

	# Set master system clock prescaler divide by 6 and processor clock divide by 2 in PMC_MCKR.
	# Wait for MCKRDY signal from PMC_SR to assert.

	#mww 0xfffffc30 0x00000101
	mww 0xfffffc30 0x00001301
	while { [expr {[read_register 0xfffffc68] & 0x08}] != 8 } { sleep 1 }

	# Now change PMC_MCKR register to select PLLA.
	# Wait for MCKRDY signal from PMC_SR to assert.

	mww 0xfffffc30 0x00001302
	while { [expr {[read_register 0xfffffc68] & 0x08}] != 8 } { sleep 1 }

	# Processor and master clocks are now operating and stable at maximum frequency possible:
	#	-> MCLK = 132.096 MHz
	#	-> PCLK = 396.288 MHz

	# Switch over to adaptive clocking.

	adapter speed 6000

	# Enable faster DCC downloads.

	arm7_9 dcc_downloads enable

	# To be able to use external SDRAM, several peripheral configuration registers must
	# be modified.  The first change is made to PIO_ASR to select peripheral functions
	# for D15 through D31.  The second change is made to the PIO_PDR register to disable
	# this for D15 through D31.

#	mww 0xfffff870 0xffff0000
#	mww 0xfffff804 0xffff0000

	# The EBI chip select register EBI_CS must be specifically configured to enable the internal SDRAM controller
	# using CS1.  Additionally we want CS3 assigned to NandFlash.  Also VDDIO is connected physically on
	# the board to the 3.3 VDC power supply so set the appropriate register bit to notify the micrcontroller.

	# mww 0xffffef1c 0x000100a

	# The ICnova SAM9G45 SODIMM has built-in NandFlash.  The exact physical timing characteristics
	# for the memory type used on the current board (MT29F2G08AACWP) can be established by setting
	# four registers in order:  SMC_SETUP3, SMC_PULSE3, SMC_CYCLE3, and SMC_MODE3.

	# mww 0xffffec30 0x00020002
	# mww 0xffffec34 0x04040404
	# mww 0xffffec38 0x00070007
	# mww 0xffffec3c 0x00030003

	# Identify NandFlash bank 0.  Disabled at the moment because a memory driver is not yet complete.

#	nand probe 0

    # SMC_SETUP0 : Setup SMC for NOR Flash
	mww 0xffffe800 0x0012000a
    # SMC_PULSE0
	mww 0xffffe804 0x3b38343b
    # SMC_CYCLE0
	mww 0xffffe808 0x003f003f
    # SMC_MODE0
	mww 0xffffe80c 0x00001000
    # Identify flash bank 0
	flash probe 0

	# Now setup SDRAM.  This is tricky and configuration is very important for reliability!  The current calculations
	# are based on 2 x Samsung K4T51083QG memory.

	# 0. Enable DDR2 Clock
	mww 0xfffffc00 0x4
	# 1. Program memory device type
	# 1.1 configure the DDR controller
	mww 0xffffe620 0x16
	# 1.2 program the DDR controller
	mww 0xffffe608 0x3d

	# 2. program memory device features
	# 2.1 assume timings for 7.5ns min clock period
	mww 0xffffe60c 0x21128226
	# 2.2 pSDDRC->HDDRSDRC2_T1PR
	mww 0xffffe610 0x02c8100e
	# 2.3 pSDDRC->HDDRSDRC2_T2PR
	mww 0xffffe614 0x01000702
	# 3. NOP
	mww 0xffffe600 0x1
	mww 0x70000000 0x1
	# 3.1 delay 200us
	sleep 1
	# jim tcl alternative: after ms
	# after 0.2

	# 4. NOP
	mww 0xffffe600 0x1
	mww 0x70000000 0x1
	# 4.1 delay 400ns

	# 5. set all bank precharge
	mww 0xffffe600 0x2
	mww 0x70000000 0x1
	# 5.1 delay 400ns

	# 6. set EMR operation (EMRS2)
	mww 0xffffe600 0x5
	mww 0x74000000 0x1
	# 6.1 delay 2 cycles

	# 7. set EMR operation (EMRS3)
	mww 0xffffe600 0x5
	mww 0x76000000 0x1
	# 7.1 delay 2 cycles

	# 8. set EMR operation (EMRS1)
	mww 0xffffe600 0x5
	mww 0x72000000 0x1
	# 8.1 delay 200 cycles (400Mhz -> 5 * 10^-7s)
	sleep 1

	# 9. Enable DLL Reset (set DLL bit)
	set CR  [expr {[read_register 0xffffe608] | 0x80}]
	mww 0xffffe608 $CR

	# 10. mode register cycle to reset the DLL
	mww 0xffffe600 0x5
	mww 0x70000000 0x1
	# 10.1 delay 2 cycles

	# 11. set all bank precharge
	mww 0xffffe600 0x2
	mww 0x70000000 0x1
	# 11.1 delay 400 ns

	# 12. two auto-refresh (CBR) cycles are provided.
	mww 0xffffe600 0x4
	mww 0x70000000 0x1
	# 12.1 delay 10 cycles
	# 12.2 2nd cycle (schreiben des Mode Register sparen wir uns)
	mww 0x70000000 0x1
	# 12.3 delay 10 cycles

	# 13. disable DLL reset (clear DLL bit)
	set CR  [expr {[read_register 0xffffe608] & 0xffffff7f}]
	mww 0xffffe608 $CR

	# 14. mode register set cycle
	mww 0xffffe600 0x3
	mww 0x70000000 0x1

	# 15. program OCD field (set OCD bits)
	set CR  [expr {[read_register 0xffffe608] | 0x7000}]
	mww 0xffffe608 $CR

	# 16. (EMRS1)
	mww 0xffffe600 0x5
	mww 0x72000000 0x1
	# 16.1 delay 2 cycles

	# 17. disable OCD field (clear OCD bits)
	set CR  [expr {[read_register 0xffffe608] & 0xffff8fff}]
	mww 0xffffe608 $CR

	# 18. (EMRS1)
	mww 0xffffe600 0x5
	mww 0x76000000 0x1
	# 18.1 delay 2 cycles

	# 19. normal mode command
	mww 0xffffe600 0x0
	mww 0x70000000 0x1

	# 20. perform write to any address
	#mww 0x70000000 0x1

	# 21. write refresh rate into the count field of the refresh rate register
	mww 0xffffe604 0x24b
	# 21.1 delay (500 * 6 cycles)

	arm7_9 fast_memory_access enable
}