/*
 * (C) Copyright 2010
 * Allied Telesis <www.alliedtelesis.com>
 */

/* based (loosley) on Marvell's board/mv_feroceon/mv_dd/platform.S */

#include <config.h>
#include <asm/arch/discovery.h>
#if defined(CONFIG_SPI_FLASH)
#include "spi/mvSpiSpec.h"
#endif

platform_lowlevel_init_data:
	/* AHB to Mbus Bridge
	 * Change CPU reg base to 0xF1000000
	 *  These *MUST* be first, and it hits
	 *  both potential address to be safe
	 */
	.long 0xD0020080, DISCO_REGS_PHY_BASE
	.long 0xF1020080, DISCO_REGS_PHY_BASE

	/* Configure RGMII-0 interface pad voltage to 1.8V */
	.long DISCO_REGS_PHY_BASE + 0x100E0, 0x1B1B1B9B
	.long DISCO_REGS_PHY_BASE + 0x100E4, 0x011B1B1B

	/* Dram initalization for 4 x x16
	 *  DDR II Micron part number MT47H64M16HR-3
	 *  MClk 333MHz, Size 512MB, ECC disable
	 */
	.long DISCO_REGS_PHY_BASE + 0x01400, 0x43008400	/* DDR Configuration register */
	.long DISCO_REGS_PHY_BASE + 0x01404, 0x37340010	/* DDR Controller Control Low */
	.long DISCO_REGS_PHY_BASE + 0x01408, 0x1101333B	/* DDR Timing (Low) (active cycles value +1) */
	.long DISCO_REGS_PHY_BASE + 0x0140C, 0x00000034	/* DDR Timing (High) */
	.long DISCO_REGS_PHY_BASE + 0x01410, 0x0000DDDD	/* DDR Address Control */
	.long DISCO_REGS_PHY_BASE + 0x01414, 0x00000000	/* DDR Open Pages Control */
	.long DISCO_REGS_PHY_BASE + 0x01418, 0x00000000	/* DDR Operation */
	.long DISCO_REGS_PHY_BASE + 0x0141C, 0x00000642	/* DDR Mode */
	.long DISCO_REGS_PHY_BASE + 0x01420, 0x00000046	/* DDR Extended Mode */
	.long DISCO_REGS_PHY_BASE + 0x01424, 0x0000F1FF	/* DDR Controller Control High */
	.long DISCO_REGS_PHY_BASE + 0x01428, 0x00074410	/* DDR2 ODT Read Timing (default values) */
	.long DISCO_REGS_PHY_BASE + 0x0147C, 0x00007441	/* DDR2 ODT Write Timing (default values) */

	.long DISCO_REGS_PHY_BASE + 0x01500, 0x00000000	/* SDRAM CS[0] Base address at 0x00000000 */
	.long DISCO_REGS_PHY_BASE + 0x01504, 0x1FFFFFF1	/* SDRAM CS[0] Size 512MiB */
	.long DISCO_REGS_PHY_BASE + 0x01508, 0x10000000	/* SDRAM CS[1] Base address */
	.long DISCO_REGS_PHY_BASE + 0x0150C, 0x00FFFFF4	/* SDRAM CS[1] Size, window disabled */
	.long DISCO_REGS_PHY_BASE + 0x01510, 0x20000000	/* SDRAM CS[2] Base address */
	.long DISCO_REGS_PHY_BASE + 0x01514, 0x00FFFFF8	/* SDRAM CS[2] Size, window disabled */
	.long DISCO_REGS_PHY_BASE + 0x01518, 0x30000000	/* SDRAM CS[3] Base address */
	.long DISCO_REGS_PHY_BASE + 0x0151C, 0x00FFFFFC	/* SDRAM CS[3] Size, window disabled */

	.long DISCO_REGS_PHY_BASE + 0x01494, 0x00100000	/* DDR ODT Control (Low) */
	.long DISCO_REGS_PHY_BASE + 0x01498, 0x00000000	/* DDR ODT Control (High) */
	.long DISCO_REGS_PHY_BASE + 0x0149C, 0x0000F801	/* CPU ODT Control */

	.long DISCO_REGS_PHY_BASE + 0x01480, 0x00000001	/* DDR Initialization Control */

	/* End of Header extension */
	.long 0x0, 0x0

.globl lowlevel_init

/************************************************/
/*              lowlevel_init                   *
/************************************************/

lowlevel_init:
	mov	r2, lr

#if defined(CONFIG_MV78200)
	mov	r0, #0
	mrc	p15, 1, r0, c15, c1, 0
        /* Check if we are CPU0 or CPU1 */
	and	r0, r0, #0x4000
	cmp	r0, #0x4000
	bne	cpu0_reg
	b	done_cpu1
#endif

	/* change CPU0 registers according to platform spec */
cpu0_reg:
	adr	r4, platform_lowlevel_init_data
	b	check_next

reg_write:
	/* TODO: This does not yet cater for BigEndian (BE) systems */
	str	r1, [r0]
	add	r4, #8
check_next:
	ldr	r0, [r4]
	ldr	r1, [r4, #4]
	cmp	r0, #0x0
	bne	reg_write

#if defined(CONFIG_SPI_FLASH)
	/* configure the Prescale of SPI clk Tclk = 200MHz */
	MV_REG_READ_ASM (r6, r1, MV_SPI_IF_CONFIG_REG)
	and	r6, r6, #~MV_SPI_CLK_PRESCALE_MASK
	orr	r6, r6, #0x15
	orr	r6, r6, #0x4000
	MV_REG_WRITE_ASM (r6, r1, MV_SPI_IF_CONFIG_REG)
#endif

done:
	mov	lr, r2

done_cpu1:
	mov 	pc, lr

