| /* |
| * (C) Copyright 2009 |
| * Juergen Beisert <kernel@pengutronix.de> |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of |
| * the License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
| * MA 02111-1307 USA |
| */ |
| |
| #include <config.h> |
| #include <mach/s3c24x0-iomap.h> |
| |
| .section ".text_bare_init.s3c24x0_disable_wd","ax" |
| |
| /* |
| * Disable the watchdog, else it continues to bark |
| */ |
| .globl s3c24x0_disable_wd |
| s3c24x0_disable_wd: |
| |
| ldr r0, =S3C24X0_WATCHDOG_BASE |
| mov r1, #0x0 |
| str r1, [r0] |
| mov pc, lr |
| |
| /** |
| @page dev_s3c24xx_wd_handling Watchdog handling |
| |
| The watchdog must be disabled very early, because if it resets the system |
| it is still active and will continue to reset the system. So, call this |
| routine very early in your board_init_lowlevel routine. |
| */ |
| |
| /* |
| * S3C2410 PLL configuration |
| * ------------------------- |
| * |
| * Basic frequency calculation |
| * |
| * m * REFclk s = SDIV |
| * PLLclk = ------------ p = PDIV + 2 |
| * p * 2^s m = MDIV + 8 |
| * |
| * After reset the PLL of the s3c2410 processor uses: |
| * |
| * MPLL UPLL |
| * MDIV 0x5c 0x28 |
| * PDIV 0x08 0x08 |
| * SDIV 0x0 0x0 |
| * |
| * 100 * 12MHz 1200MHz |
| * MPLLclk = ------------- = -------- = 120MHz |
| * 10 * 2^0 10 |
| * |
| * 48 * 12MHz 576MHz |
| * UPLLclk = ------------- = -------- = 57,6MHz |
| * 10 * 2^0 10 |
| * |
| * Note: Do not use "r10" here in this code |
| */ |
| |
| #ifdef CONFIG_S3C24XX_PLL_INIT |
| |
| .section ".text_bare_init.s3c24x0_pll_init","ax" |
| |
| .globl s3c24x0_pll_init |
| s3c24x0_pll_init: |
| |
| mov r0, #S3C24X0_CLOCK_POWER_BASE |
| |
| /* configure internal clock ratio */ |
| mov r1, #BOARD_SPECIFIC_CLKDIVN |
| str r1, [r0, #20] |
| |
| /* enable all devices on this chip */ |
| mov r1, #0xFFFFFFF0 |
| str r1, [r0, #12] |
| |
| /* ??????? */ |
| #ifdef CONFIG_CPU_S3C2440 |
| mov r1, #0xFFFFFFFF |
| #endif |
| #ifdef CONFIG_CPU_S3C2410 |
| mov r1, #0x00FFFFFF |
| #endif |
| str r1, [r0, #0] |
| |
| #ifdef CONFIG_CPU_S3C2440 |
| /* |
| * Most of the time HDIVN is not 0, so we must use the |
| * asynchronous bus mode (refer datasheet "Clock and Power Management") |
| */ |
| mrc p15, 0, r1, c1, c0, 0 |
| orr r1, r1, #0xc0000000 |
| mcr p15, 0, r1, c1, c0, 0 |
| #endif |
| |
| /* configure UPLL */ |
| ldr r1, =BOARD_SPECIFIC_UPLL |
| str r1, [r0, #8] |
| |
| nop |
| nop |
| nop |
| nop |
| nop |
| nop |
| nop |
| nop |
| |
| /* configure MPLL */ |
| ldr r1, =BOARD_SPECIFIC_MPLL |
| str r1, [r0, #4] |
| |
| nop |
| nop |
| nop |
| nop |
| nop |
| nop |
| nop |
| nop |
| |
| mov pc, lr |
| |
| #endif |
| |
| /** |
| @page dev_s3c24xx_pll_handling PLL clock handling |
| |
| To control the speed of your machine the PLLs must be reconfigured after reset. |
| |
| For example the S3C2410 CPU wakes up after reset at 120MHz main PLL speed, |
| shared with all other system on chip components. Most of the time this |
| configuration is to slow for the CPU and to fast for the other components. |
| |
| PLL reprogramming can be done in the machine specific manner very early when |
| the CONFIG_S3C24XX_PLL_INIT and CONFIG_MACH_HAS_LOWLEVEL_INIT symbols are |
| defined. The board must provide a board_init_lowlevel() assembler function in |
| this case and calling the s3c24x0_pll_init() assembler function. |
| |
| If the s3c24x0_pll_init() is called a few further symbols must be defined to |
| setup the correct values for the machine. |
| |
| Define in the machine specific config.h the following symbols: |
| |
| - S3C24XX_CLOCK_REFERENCE with the frequency in Hz of your reference crystal. |
| - BOARD_SPECIFIC_CLKDIVN with the value for the main clock ratio register (CLKDIVN) |
| - BOARD_SPECIFIC_MPLL with the value for the main PLL setup register |
| - BOARD_SPECIFIC_UPLL with the value for the USB PLL setup register |
| |
| @note Valid values for the PLL settings can be found in the CPU manual. |
| |
| @par Background: PLL frequency calculation for the S3C2410 CPU (both PLLs) and S3C2440 (UPLL only) |
| |
| @f[ |
| f_{PLL} = \frac{m * f_{Ref}}{p * 2^s} |
| @f] |
| |
| With m = MDIV + 8, p = PDIV + 2 and s = SDIV. |
| |
| @par Background: PLL frequency calculation for the S3C2440 CPU (MPLL only) |
| |
| @f[ |
| f_{PLL} = \frac{2 * m * f_{Ref}}{p * 2^s} |
| @f] |
| |
| With m = MDIV + 8, p = PDIV + 2 and s = SDIV. |
| |
| @note This routine can be used for the S3C2410 and the S3C2440 CPU. |
| |
| */ |
| |
| /* ----------------------------------------------------------------------- */ |
| |
| #ifdef CONFIG_S3C24XX_SDRAM_INIT |
| |
| .section ".text_bare_init.s3c24x0_sdram_init","ax" |
| |
| .globl s3c24x0_sdram_init |
| s3c24x0_sdram_init: |
| |
| adr r0, SDRAMDATA /* get the current relative address of the table */ |
| mov r1, #S3C24X0_MEMCTL_BASE |
| mov r2, #6 /* we *know* it contains 6 entries */ |
| |
| ldr r3, [r0], #4 /* write BSWCON first */ |
| str r3, [r1], #0x1c /* post add register offset for bank6 */ |
| /* |
| * Initializing the SDRAM controller is very simple: |
| * Just write some useful values into the SDRAM controller. |
| */ |
| 0: ldr r3, [r0], #4 |
| str r3, [r1], #4 |
| subs r2, r2, #1 |
| bne 0b |
| |
| mov pc, lr |
| |
| SDRAMDATA: |
| .word BOARD_SPECIFIC_BWSCON |
| .word BOARD_SPECIFIC_BANKCON6 |
| .word BOARD_SPECIFIC_BANKCON7 |
| .word BOARD_SPECIFIC_REFRESH |
| .word BOARD_SPECIFIC_BANKSIZE |
| .word BOARD_SPECIFIC_MRSRB6 |
| .word BOARD_SPECIFIC_MRSRB7 |
| |
| #endif |
| |
| /** |
| @page dev_s3c24xx_sdram_handling SDRAM controller initialisation |
| |
| The SDRAM controller is very simple and its initialisation requires only a |
| few steps. barebox provides a generic routine to do this step. |
| |
| Enable CONFIG_S3C24XX_SDRAM_INIT and CONFIG_MACH_HAS_LOWLEVEL_INIT to be able |
| to call the generic s3c24x0_sdram_init() assembler function from within the |
| machine specific board_init_lowlevel() assembler function. |
| |
| To use the s3c24x0_sdram_init() assembler function a few symbols must be |
| defined to setup correct values for the machine. |
| |
| Define in the machine specific config.h the following list of symbols: |
| |
| - BOARD_SPECIFIC_BWSCON with the values for SDRAM banks 6 and 7 |
| - BOARD_SPECIFIC_BANKCON6 with the value for the BANKCON6 register |
| - BOARD_SPECIFIC_BANKCON7 with the value for the BANKCON7 register |
| - BOARD_SPECIFIC_REFRESH with the value for the REFRESH register |
| - BOARD_SPECIFIC_BANKSIZE with the value for the BANKSIZE register |
| - BOARD_SPECIFIC_MRSRB6 with the value for the MRSRB6 register |
| - BOARD_SPECIFIC_MRSRB7 with the value for the MRSRB7 register |
| */ |
| |
| /* ----------------------------------------------------------------------- */ |
| |
| #ifdef CONFIG_S3C24XX_NAND_BOOT |
| |
| .section ".text_bare_init.s3c24x0_nand_boot","ax" |
| |
| .globl s3c24x0_nand_boot |
| s3c24x0_nand_boot: |
| /* |
| * In the case of NOR boot we are running from the same address space. |
| * Detect this case to handle it correctly. |
| */ |
| mov r1, #S3C24X0_MEMCTL_BASE |
| ldr r3, [r1] |
| and r3, r3, #0x6 |
| cmp r3, #0x0 /* check for NAND case */ |
| beq 2f |
| mov pc, lr /* NOR case: nothing to do here */ |
| |
| 2: ldr sp, =TEXT_BASE /* Setup a temporary stack in SDRAM */ |
| /* |
| * We still run at a location we are not linked to. But lets still running |
| * from the internal SRAM, this may speed up the boot |
| */ |
| push {lr} |
| bl nand_boot |
| pop {lr} |
| /* |
| * Adjust the return address to the correct address in SDRAM |
| */ |
| ldr r1, =TEXT_BASE |
| add lr, lr, r1 |
| |
| mov pc, lr |
| |
| #endif |
| |
| /** |
| @page dev_s3c24xx_nandboot_handling Booting from NAND |
| |
| To be able to boot from NAND memory only, enable the S3C24x0 NAND driver. Also |
| enable CONFIG_S3C24XX_NAND_BOOT and CONFIG_MACH_HAS_LOWLEVEL_INIT to be |
| able to call the s3c24x0_nand_boot() assembler routine from within the |
| machine specific board_init_lowlevel() assembler function. |
| |
| @note This routine assumes an already working SDRAM controller and |
| an initialized stack pointer. |
| |
| @note Basicly this routine runs from inside the internal SRAM. After load of |
| the whole barebox image from the NAND flash memory into the SDRAM it adjusts |
| the link register to the final SDRAM adress and returns. |
| |
| @note In the NAND boot mode, ECC is not checked. So, the first x KBytes used |
| by barebox should have no bit error. |
| |
| Due to the fact the code to load the whole barebox from NAND must fit into |
| the first 4kiB of the barebox image, the shrinked NAND driver is very |
| minimalistic. Setup the NAND access timing is done in a safe manner, what |
| means: Slowest possible values are used. If you want to increase the speed you |
| should define the BOARD_DEFAULT_NAND_TIMING to a valid setting into the |
| NFCONF register and add it to your board specific config.h. Refer S3C24x0's |
| datasheet for further details. The macro #CALC_NFCONF_TIMING could help to |
| calculate the register setting in a hardware independent manner. |
| |
| @note The regular NAND driver uses a platform data structure to define the |
| NAND access timings. |
| |
| @note Its still possible to boot this image from NOR memory. If this routine |
| detects it is running from NOR instead of the internal SRAM it skips any |
| loading and returns immediately. |
| |
| */ |