123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- /* SPDX-License-Identifier: GPL-2.0+ */
- /*
- * 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.
- */
- #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:
- 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
- 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 lr, r6
- mov pc, lr
|