arm: ep9315: Return back Cirrus Logic EDB9315A board support

This patch returns back support for old ep93xx processors family

Signed-off-by: Sergey Kostanbaev <sergey.kostanbaev@gmail.com>
Cc: albert.u.boot@aribaud.net
diff --git a/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S b/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S
index bf2fa2a..cfad206 100644
--- a/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S
+++ b/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S
@@ -2,48 +2,457 @@
  * Low-level initialization for EP93xx
  *
  * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ * Copyright (C) 2013
+ * Sergey Kostanabev <sergey.kostanbaev <at> fairwaves.ru>
  *
  * Copyright (C) 2006 Dominic Rath <Dominic.Rath@gmx.de>
+ * Copyright (C) 2006 Cirrus Logic Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
+
+#include <config.h>
+#include <asm/arch-ep93xx/ep93xx.h>
+
+/*
+/* Configure the SDRAM based on the supplied settings.
+ *
+ * Input:	r0 - SDRAM DEVCFG register
+ *		r2 - configuration for SDRAM chips
+ * Output:	none
+ * Modifies:	r3, r4
+ */
+ep93xx_sdram_config:
+	/* Program the SDRAM device configuration register. */
+	ldr	r3, =SDRAM_BASE
+#ifdef CONFIG_EDB93XX_SDCS0
+	str	r0, [r3, #SDRAM_OFF_DEVCFG0]
+#endif
+#ifdef CONFIG_EDB93XX_SDCS1
+	str	r0, [r3, #SDRAM_OFF_DEVCFG1]
+#endif
+#ifdef CONFIG_EDB93XX_SDCS2
+	str	r0, [r3, #SDRAM_OFF_DEVCFG2]
+#endif
+#ifdef CONFIG_EDB93XX_SDCS3
+	str	r0, [r3, #SDRAM_OFF_DEVCFG3]
+#endif
+
+	/* Set the Initialize and MRS bits (issue continuous NOP commands
+	 * (INIT & MRS set))
+	 */
+	ldr	r4, =(EP93XX_SDRAMCTRL_GLOBALCFG_INIT | \
+			EP93XX_SDRAMCTRL_GLOBALCFG_MRS | \
+			EP93XX_SDRAMCTRL_GLOBALCFG_CKE)
+	str	r4, [r3, #SDRAM_OFF_GLCONFIG]
+
+	/* Delay for 200us. */
+	mov	r4, #0x3000
+delay1:
+	subs	r4, r4, #1
+	bne	delay1
+
+	/* Clear the MRS bit to issue a precharge all. */
+	ldr	r4, =(EP93XX_SDRAMCTRL_GLOBALCFG_INIT | \
+			EP93XX_SDRAMCTRL_GLOBALCFG_CKE)
+	str	r4, [r3, #SDRAM_OFF_GLCONFIG]
+
+	/* Temporarily set the refresh timer to 0x10. Make it really low so
+	 * that refresh cycles are generated.
+	 */
+	ldr	r4, =0x10
+	str	r4, [r3, #SDRAM_OFF_REFRSHTIMR]
+
+	/* Delay for at least 80 SDRAM clock cycles. */
+	mov	r4, #80
+delay2:
+	subs	r4, r4, #1
+	bne	delay2
+
+	/* Set the refresh timer to the fastest required for any device
+	 * that might be used. Set 9.6 ms refresh time.
+	 */
+	ldr	r4, =0x01e0
+	str	r4, [r3, #SDRAM_OFF_REFRSHTIMR]
+
+	/* Select mode register update mode. */
+	ldr	r4, =(EP93XX_SDRAMCTRL_GLOBALCFG_CKE | \
+			EP93XX_SDRAMCTRL_GLOBALCFG_MRS)
+	str	r4, [r3, #SDRAM_OFF_GLCONFIG]
+
+	/* Program the mode register on the SDRAM by performing fake read */
+	ldr	r4, [r2]
+
+	/* Select normal operating mode. */
+	ldr	r4, =EP93XX_SDRAMCTRL_GLOBALCFG_CKE
+	str	r4, [r3, #SDRAM_OFF_GLCONFIG]
+
+	/* Return to the caller. */
+	mov	pc, lr
+
+/*
+ * Test to see if the SDRAM has been configured in a usable mode.
+ *
+ * Input:	r0 - Test address of SDRAM
+ * Output:	r0 - 0 -- Test OK, -1 -- Failed
+ * Modifies:	r0-r5
+ */
+ep93xx_sdram_test:
+	/* Load the test patterns to be written to SDRAM. */
+	ldr	r1, =0xf00dface
+	ldr	r2, =0xdeadbeef
+	ldr	r3, =0x08675309
+	ldr	r4, =0xdeafc0ed
+
+	/* Store the test patterns to SDRAM. */
+	stmia	r0, {r1-r4}
+
+	/* Load the test patterns from SDRAM one at a time and compare them
+	 * to the actual pattern.
+	 */
+	ldr	r5, [r0]
+	cmp	r5, r1
+	ldreq	r5, [r0, #0x0004]
+	cmpeq	r5, r2
+	ldreq	r5, [r0, #0x0008]
+	cmpeq	r5, r3
+	ldreq	r5, [r0, #0x000c]
+	cmpeq	r5, r4
+
+	/* Return -1 if a mismatch was encountered, 0 otherwise. */
+	mvnne	r0, #0xffffffff
+	moveq	r0, #0x00000000
+
+	/* Return to the caller. */
+	mov	pc, lr
+
+/*
+ * Determine the size of the SDRAM. Use data=address for the scan.
+ *
+ * Input:	r0 - Start SDRAM address
+ * Return:	r0 - Single block size
+ *		r1 - Valid block mask
+ *		r2 - Total block count
+ * Modifies:	r0-r5
+ */
+ep93xx_sdram_size:
+	/* Store zero at offset zero. */
+	str	r0, [r0]
+
+	/* Start checking for an alias at 1MB into SDRAM. */
+	ldr	r1, =0x00100000
+
+	/* Store the offset at the current offset. */
+check_block_size:
+	str	r1, [r0, r1]
+
+	/* Read back from zero. */
+	ldr	r2, [r0]
+
+	/* Stop searching of an alias was found. */
+	cmp	r1, r2
+	beq	found_block_size
+
+	/* Advance to the next power of two boundary. */
+	mov	r1, r1, lsl #1
+
+	/* Loop back if the size has not reached 256MB. */
+	cmp	r1, #0x10000000
+	bne	check_block_size
+
+	/* A full 256MB of memory was found, so return it now. */
+	ldr	r0, =0x10000000
+	ldr	r1, =0x00000000
+	ldr	r2, =0x00000001
+	mov	pc, lr
+
+	/* An alias was found. See if the first block is 128MB in size. */
+found_block_size:
+	cmp	r1, #0x08000000
+
+	/* The first block is 128MB, so there is no further memory. Return it
+	 * now.
+	 */
+	ldreq	r0, =0x08000000
+	ldreq	r1, =0x00000000
+	ldreq	r2, =0x00000001
+	moveq	pc, lr
 
-#include <version.h>
-#include <asm/arch/ep93xx.h>
+	/* Save the block size, set the block address bits to zero, and
+	 * initialize the block count to one.
+	 */
+	mov	r3, r1
+	ldr	r4, =0x00000000
+	ldr	r5, =0x00000001
+
+	/* Look for additional blocks of memory by searching for non-aliases. */
+find_blocks:
+	/* Store zero back to address zero. It may be overwritten. */
+	str	r0, [r0]
+
+	/* Advance to the next power of two boundary. */
+	mov	r1, r1, lsl #1
+
+	/* Store the offset at the current offset. */
+	str	r1, [r0, r1]
+
+	/* Read back from zero. */
+	ldr	r2, [r0]
+
+	/* See if a non-alias was found. */
+	cmp	r1, r2
+
+	/* If a non-alias was found, then or in the block address bit and
+	 * multiply the block count by two (since there are two unique
+	 * blocks, one with this bit zero and one with it one).
+	 */
+	orrne	r4, r4, r1
+	movne	r5, r5, lsl #1
+
+	/* Continue searching if there are more address bits to check. */
+	cmp	r1, #0x08000000
+	bne	find_blocks
+
+	/* Return the block size, address mask, and count. */
+	mov	r0, r3
+	mov	r1, r4
+	mov	r2, r5
+
+	/* Return to the caller. */
+	mov	pc, lr
+
 
 .globl lowlevel_init
 lowlevel_init:
-	/* backup return address */
-	ldr r1, =SYSCON_SCRATCH0
-	str lr, [r1]
+
+	mov	r6, lr
+
+	/* Make sure caches are off and invalidated. */
+	ldr	r0, =0x00000000
+	mcr	p15, 0, r0, c1, c0, 0
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	/* Turn off the green LED and turn on the red LED. If the red LED
+	 * is left on for too long, the external reset circuit described
+	 * by application note AN258 will cause the system to reset.
+	 */
+	ldr	r1, =EP93XX_LED_DATA
+	ldr	r0, [r1]
+	bic	r0, r0, #EP93XX_LED_GREEN_ON
+	orr	r0, r0, #EP93XX_LED_RED_ON
+	str	r0, [r1]
+
+	/* Undo the silly static memory controller programming performed
+	 * by the boot rom.
+	 */
+	ldr	r0, =SMC_BASE
+
+	/* Set WST1 and WST2 to 31 HCLK cycles (slowest access) */
+	ldr	r1, =0x0000fbe0
+
+	/* Reset EP93XX_OFF_SMCBCR0 */
+	ldr	r2, [r0]
+	orr	r2, r2, r1
+	str	r2, [r0]
+
+	ldr	r2, [r0, #EP93XX_OFF_SMCBCR1]
+	orr	r2, r2, r1
+	str	r2, [r0, #EP93XX_OFF_SMCBCR1]
 
-	/* Turn on both LEDs */
-	bl red_led_on
-	bl green_led_on
+	ldr	r2, [r0, #EP93XX_OFF_SMCBCR2]
+	orr	r2, r2, r1
+	str	r2, [r0, #EP93XX_OFF_SMCBCR2]
 
-	/* Configure flash wait states before we switch to the PLL */
-	bl flash_cfg
+	ldr	r2, [r0, #EP93XX_OFF_SMCBCR3]
+	orr	r2, r2, r1
+	str	r2, [r0, #EP93XX_OFF_SMCBCR3]
 
-	/* Set up PLL */
-	bl pll_cfg
+	ldr	r2, [r0, #EP93XX_OFF_SMCBCR6]
+	orr	r2, r2, r1
+	str	r2, [r0, #EP93XX_OFF_SMCBCR6]
 
-	/* Turn off the Green LED and leave the Red LED on */
-	bl green_led_off
+	ldr	r2, [r0, #EP93XX_OFF_SMCBCR7]
+	orr	r2, r2, r1
+	str	r2, [r0, #EP93XX_OFF_SMCBCR7]
 
-	/* Setup SDRAM */
-	bl sdram_cfg
+	/* Set the PLL1 and processor clock. */
+	ldr	r0, =SYSCON_BASE
+#ifdef CONFIG_EDB9301
+	/* 332MHz, giving a 166MHz processor clock. */
+	ldr	r1, = 0x02b49907
+#else
 
-	/* Turn on Green LED, Turn off the Red LED */
-	bl green_led_on
-	bl red_led_off
+#ifdef CONFIG_EDB93XX_INDUSTRIAL
+	/* 384MHz, giving a 196MHz processor clock. */
+	ldr	r1, =0x02a4bb38
+#else
+	/* 400MHz, giving a 200MHz processor clock. */
+	ldr	r1, =0x02a4e39e
+#endif
+#endif
+	str	r1, [r0, #SYSCON_OFF_CLKSET1]
 
-	/* FIXME: we use async mode for now */
-	mrc p15, 0, r0, c1, c0, 0
-	orr r0, r0, #0xc0000000
-	mcr p15, 0, r0, c1, c0, 0
+	nop
+	nop
+	nop
+	nop
+	nop
 
-	/* restore return address */
-	ldr r1, =SYSCON_SCRATCH0
-	ldr lr, [r1]
+	/* Need to make sure that SDRAM is configured correctly before
+	 * coping the code into it.
+	 */
+
+#ifdef CONFIG_EDB93XX_SDCS0
+	mov	r11, #SDRAM_DEVCFG0_BASE
+#endif
+#ifdef CONFIG_EDB93XX_SDCS1
+	mov	r11, #SDRAM_DEVCFG1_BASE
+#endif
+#ifdef CONFIG_EDB93XX_SDCS2
+	mov	r11, #SDRAM_DEVCFG2_BASE
+#endif
+#ifdef CONFIG_EDB93XX_SDCS3
+	ldr	r0, =SYSCON_BASE
+	ldr	r0, [r0, #SYSCON_OFF_SYSCFG]
+	ands	r0, r0, #SYSCON_SYSCFG_LASDO
+	moveq	r11, #SDRAM_DEVCFG3_ASD0_BASE
+	movne	r11, #SDRAM_DEVCFG3_ASD1_BASE
+#endif
+	/* See Table 13-5 in EP93xx datasheet for more info about DRAM
+	 * register mapping */
+
+	/* Try a 32-bit wide configuration of SDRAM. */
+	ldr	r0, =(EP93XX_SDRAMCTRL_DEVCFG_BANKCOUNT | \
+			EP93XX_SDRAMCTRL_DEVCFG_SROMLL | \
+			EP93XX_SDRAMCTRL_DEVCFG_CASLAT_2 | \
+			EP93XX_SDRAMCTRL_DEVCFG_RASTOCAS_2)
+
+	/* Set burst count: 4 and CAS: 2
+	 * Burst mode [A11:A10]; CAS [A16:A14]
+	 */
+	orr	r2, r11, #0x00008800
+	bl	ep93xx_sdram_config
+
+	/* Test the SDRAM. */
+	mov	r0, r11
+	bl	ep93xx_sdram_test
+	cmp	r0, #0x00000000
+	beq	ep93xx_sdram_done
+
+	/* Try a 16-bit wide configuration of SDRAM. */
+	ldr	r0, =(EP93XX_SDRAMCTRL_DEVCFG_BANKCOUNT | \
+			EP93XX_SDRAMCTRL_DEVCFG_SROMLL | \
+			EP93XX_SDRAMCTRL_DEVCFG_CASLAT_2 | \
+			EP93XX_SDRAMCTRL_DEVCFG_RASTOCAS_2 | \
+			EP93XX_SDRAMCTRL_DEVCFG_EXTBUSWIDTH)
+
+	/* Set burst count: 8, CAS: 2, sequential burst
+	 * Accoring to Table 13-3 for 16bit operations mapping must be shifted.
+	 * Burst mode [A10:A9]; CAS [A15:A13]
+	 */
+	orr	r2, r11, #0x00004600
+	bl	ep93xx_sdram_config
+
+	/* Test the SDRAM. */
+	mov	r0, r11
+	bl	ep93xx_sdram_test
+	cmp	r0, #0x00000000
+	beq	ep93xx_sdram_done
+
+	/* Turn off the red LED. */
+	ldr	r0, =EP93XX_LED_DATA
+	ldr	r1, [r0]
+	bic	r1, r1, #EP93XX_LED_RED_ON
+	str	r1, [r0]
+
+	/* There is no SDRAM so flash the green LED. */
+flash_green:
+	orr	r1, r1, #EP93XX_LED_GREEN_ON
+	str	r1, [r0]
+	ldr	r2, =0x00010000
+flash_green_delay_1:
+	subs	r2, r2, #1
+	bne	flash_green_delay_1
+	bic	r1, r1, #EP93XX_LED_GREEN_ON
+	str	r1, [r0]
+	ldr	r2, =0x00010000
+flash_green_delay_2:
+	subs	r2, r2, #1
+	bne	flash_green_delay_2
+	orr	r1, r1, #EP93XX_LED_GREEN_ON
+	str	r1, [r0]
+	ldr	r2, =0x00010000
+flash_green_delay_3:
+	subs	r2, r2, #1
+	bne	flash_green_delay_3
+	bic	r1, r1, #EP93XX_LED_GREEN_ON
+	str	r1, [r0]
+	ldr	r2, =0x00050000
+flash_green_delay_4:
+	subs	r2, r2, #1
+	bne	flash_green_delay_4
+	b	flash_green
+
+
+ep93xx_sdram_done:
+	ldr	r1, =EP93XX_LED_DATA
+	ldr	r0, [r1]
+	bic	r0, r0, #EP93XX_LED_RED_ON
+	str	r0, [r1]
+
+	/* Determine the size of the SDRAM. */
+	mov	r0, r11
+	bl	ep93xx_sdram_size
+
+	/* Save the SDRAM characteristics. */
+	mov	r8, r0
+	mov	r9, r1
+	mov	r10, r2
+
+	/* Compute total memory size into r1 */
+	mul	r1, r8, r10
+#ifdef CONFIG_EDB93XX_SDCS0
+	ldr	r2, [r0, #SDRAM_OFF_DEVCFG0]
+#endif
+#ifdef CONFIG_EDB93XX_SDCS1
+	ldr	r2, [r0, #SDRAM_OFF_DEVCFG1]
+#endif
+#ifdef CONFIG_EDB93XX_SDCS2
+	ldr	r2, [r0, #SDRAM_OFF_DEVCFG2]
+#endif
+#ifdef CONFIG_EDB93XX_SDCS3
+	ldr	r2, [r0, #SDRAM_OFF_DEVCFG3]
+#endif
+
+	/* Consider small DRAM size as:
+	 * < 32Mb for 32bit bus
+	 * < 64Mb for 16bit bus
+	 */
+	tst	r2, #EP93XX_SDRAMCTRL_DEVCFG_EXTBUSWIDTH
+	moveq	r1, r1, lsr #1
+	cmp	r1, #0x02000000
+
+#if defined(CONFIG_EDB9301)
+	/* Set refresh counter to 20ms for small DRAM size, otherwise 9.6ms */
+	movlt	r1, #0x03f0
+	movge	r1, #0x01e0
+#else
+	/* Set refresh counter to 30.7ms for small DRAM size, otherwise 15ms */
+	movlt	r1, #0x0600
+	movge	r1, #0x2f0
+#endif
+	str	r1, [r0, #SDRAM_OFF_REFRSHTIMR]
+
+	/* Save the memory configuration information. */
+	orr	r0, r11, #UBOOT_MEMORYCNF_BANK_SIZE
+	stmia	r0, {r8-r11}
 
-	mov pc, lr
+	mov	lr, r6
+	mov	pc, lr