]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S
arm: ep9315: Return back Cirrus Logic EDB9315A board support
[karo-tx-uboot.git] / arch / arm / cpu / arm920t / ep93xx / lowlevel_init.S
index bf2fa2ac320b989b050d92e98550b5b09fe0b12d..cfad206eddbf7f24f9907f02939ad68f14d0ea1d 100644 (file)
  * 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 <version.h>
-#include <asm/arch/ep93xx.h>
+#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
+
+       /* 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]
 
-       /* Turn on both LEDs */
-       bl red_led_on
-       bl green_led_on
+       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]
+
+       ldr     r2, [r0, #EP93XX_OFF_SMCBCR2]
+       orr     r2, r2, r1
+       str     r2, [r0, #EP93XX_OFF_SMCBCR2]
+
+       ldr     r2, [r0, #EP93XX_OFF_SMCBCR3]
+       orr     r2, r2, r1
+       str     r2, [r0, #EP93XX_OFF_SMCBCR3]
+
+       ldr     r2, [r0, #EP93XX_OFF_SMCBCR6]
+       orr     r2, r2, r1
+       str     r2, [r0, #EP93XX_OFF_SMCBCR6]
+
+       ldr     r2, [r0, #EP93XX_OFF_SMCBCR7]
+       orr     r2, r2, r1
+       str     r2, [r0, #EP93XX_OFF_SMCBCR7]
+
+       /* Set the PLL1 and processor clock. */
+       ldr     r0, =SYSCON_BASE
+#ifdef CONFIG_EDB9301
+       /* 332MHz, giving a 166MHz processor clock. */
+       ldr     r1, = 0x02b49907
+#else
+
+#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]
+
+       nop
+       nop
+       nop
+       nop
+       nop
+
+       /* 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
+
 
-       /* Configure flash wait states before we switch to the PLL */
-       bl flash_cfg
+ep93xx_sdram_done:
+       ldr     r1, =EP93XX_LED_DATA
+       ldr     r0, [r1]
+       bic     r0, r0, #EP93XX_LED_RED_ON
+       str     r0, [r1]
 
-       /* Set up PLL */
-       bl pll_cfg
+       /* Determine the size of the SDRAM. */
+       mov     r0, r11
+       bl      ep93xx_sdram_size
 
-       /* Turn off the Green LED and leave the Red LED on */
-       bl green_led_off
+       /* Save the SDRAM characteristics. */
+       mov     r8, r0
+       mov     r9, r1
+       mov     r10, r2
 
-       /* Setup SDRAM */
-       bl sdram_cfg
+       /* 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
 
-       /* Turn on Green LED, Turn off the Red LED */
-       bl green_led_on
-       bl red_led_off
+       /* 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
 
-       /* 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
+#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]
 
-       /* restore return address */
-       ldr r1, =SYSCON_SCRATCH0
-       ldr lr, [r1]
+       /* 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