| /* |
| * Memory Setup stuff - taken from blob memsetup.S |
| * |
| * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and |
| * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) |
| * |
| * Modified for the Samsung SMDK2410 by |
| * (C) Copyright 2002 |
| * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> |
| * |
| * (C) Copyright 2008 |
| * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> |
| * |
| * See file CREDITS for list of people who contributed to this |
| * project. |
| * |
| * 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 <version.h> |
| |
| #include <asm/arch/s3c6400.h> |
| |
| #ifdef CONFIG_SERIAL1 |
| #define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART0_OFFSET) |
| #elif defined(CONFIG_SERIAL2) |
| #define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART1_OFFSET) |
| #else |
| #define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART2_OFFSET) |
| #endif |
| |
| _TEXT_BASE: |
| .word TEXT_BASE |
| |
| .globl lowlevel_init |
| lowlevel_init: |
| mov r12, lr |
| |
| /* LED on only #8 */ |
| ldr r0, =ELFIN_GPIO_BASE |
| ldr r1, =0x55540000 |
| str r1, [r0, #GPNCON_OFFSET] |
| |
| ldr r1, =0x55555555 |
| str r1, [r0, #GPNPUD_OFFSET] |
| |
| ldr r1, =0xf000 |
| str r1, [r0, #GPNDAT_OFFSET] |
| |
| /* Disable Watchdog */ |
| ldr r0, =0x7e000000 @0x7e004000 |
| orr r0, r0, #0x4000 |
| mov r1, #0 |
| str r1, [r0] |
| |
| /* External interrupt pending clear */ |
| ldr r0, =(ELFIN_GPIO_BASE+EINTPEND_OFFSET) /*EINTPEND*/ |
| ldr r1, [r0] |
| str r1, [r0] |
| |
| ldr r0, =ELFIN_VIC0_BASE_ADDR @0x71200000 |
| ldr r1, =ELFIN_VIC1_BASE_ADDR @0x71300000 |
| |
| /* Disable all interrupts (VIC0 and VIC1) */ |
| mvn r3, #0x0 |
| str r3, [r0, #oINTMSK] |
| str r3, [r1, #oINTMSK] |
| |
| /* Set all interrupts as IRQ */ |
| mov r3, #0x0 |
| str r3, [r0, #oINTMOD] |
| str r3, [r1, #oINTMOD] |
| |
| /* Pending Interrupt Clear */ |
| mov r3, #0x0 |
| str r3, [r0, #oVECTADDR] |
| str r3, [r1, #oVECTADDR] |
| |
| /* init system clock */ |
| bl system_clock_init |
| |
| #ifndef CONFIG_NAND_SPL |
| /* for UART */ |
| bl uart_asm_init |
| #endif |
| |
| #ifdef CONFIG_BOOT_NAND |
| /* simple init for NAND */ |
| bl nand_asm_init |
| #endif |
| |
| /* Memory subsystem address 0x7e00f120 */ |
| ldr r0, =ELFIN_MEM_SYS_CFG |
| |
| /* Xm0CSn2 = NFCON CS0, Xm0CSn3 = NFCON CS1 */ |
| mov r1, #S3C64XX_MEM_SYS_CFG_NAND |
| str r1, [r0] |
| |
| bl mem_ctrl_asm_init |
| |
| /* Wakeup support. Don't know if it's going to be used, untested. */ |
| ldr r0, =(ELFIN_CLOCK_POWER_BASE + RST_STAT_OFFSET) |
| ldr r1, [r0] |
| bic r1, r1, #0xfffffff7 |
| cmp r1, #0x8 |
| beq wakeup_reset |
| |
| 1: |
| mov lr, r12 |
| mov pc, lr |
| |
| wakeup_reset: |
| |
| /* Clear wakeup status register */ |
| ldr r0, =(ELFIN_CLOCK_POWER_BASE + WAKEUP_STAT_OFFSET) |
| ldr r1, [r0] |
| str r1, [r0] |
| |
| /* LED test */ |
| ldr r0, =ELFIN_GPIO_BASE |
| ldr r1, =0x3000 |
| str r1, [r0, #GPNDAT_OFFSET] |
| |
| /* Load return address and jump to kernel */ |
| ldr r0, =(ELFIN_CLOCK_POWER_BASE + INF_REG0_OFFSET) |
| /* r1 = physical address of s3c6400_cpu_resume function */ |
| ldr r1, [r0] |
| /* Jump to kernel (sleep-s3c6400.S) */ |
| mov pc, r1 |
| nop |
| nop |
| /* |
| * system_clock_init: Initialize core clock and bus clock. |
| * void system_clock_init(void) |
| */ |
| system_clock_init: |
| ldr r0, =ELFIN_CLOCK_POWER_BASE /* 0x7e00f000 */ |
| |
| #ifdef CONFIG_SYNC_MODE |
| ldr r1, [r0, #OTHERS_OFFSET] |
| mov r2, #0x40 |
| orr r1, r1, r2 |
| str r1, [r0, #OTHERS_OFFSET] |
| |
| nop |
| nop |
| nop |
| nop |
| nop |
| |
| ldr r2, =0x80 |
| orr r1, r1, r2 |
| str r1, [r0, #OTHERS_OFFSET] |
| |
| check_syncack: |
| ldr r1, [r0, #OTHERS_OFFSET] |
| ldr r2, =0xf00 |
| and r1, r1, r2 |
| cmp r1, #0xf00 |
| bne check_syncack |
| #else /* ASYNC Mode */ |
| nop |
| nop |
| nop |
| nop |
| nop |
| |
| /* |
| * This was unconditional in original Samsung sources, but it doesn't |
| * seem to make much sense on S3C6400. |
| */ |
| #ifndef CONFIG_S3C6400 |
| ldr r1, [r0, #OTHERS_OFFSET] |
| bic r1, r1, #0xC0 |
| orr r1, r1, #0x40 |
| str r1, [r0, #OTHERS_OFFSET] |
| |
| wait_for_async: |
| ldr r1, [r0, #OTHERS_OFFSET] |
| and r1, r1, #0xf00 |
| cmp r1, #0x0 |
| bne wait_for_async |
| #endif |
| |
| ldr r1, [r0, #OTHERS_OFFSET] |
| bic r1, r1, #0x40 |
| str r1, [r0, #OTHERS_OFFSET] |
| #endif |
| |
| mov r1, #0xff00 |
| orr r1, r1, #0xff |
| str r1, [r0, #APLL_LOCK_OFFSET] |
| str r1, [r0, #MPLL_LOCK_OFFSET] |
| |
| /* Set Clock Divider */ |
| ldr r1, [r0, #CLK_DIV0_OFFSET] |
| bic r1, r1, #0x30000 |
| bic r1, r1, #0xff00 |
| bic r1, r1, #0xff |
| ldr r2, =CLK_DIV_VAL |
| orr r1, r1, r2 |
| str r1, [r0, #CLK_DIV0_OFFSET] |
| |
| ldr r1, =APLL_VAL |
| str r1, [r0, #APLL_CON_OFFSET] |
| ldr r1, =MPLL_VAL |
| str r1, [r0, #MPLL_CON_OFFSET] |
| |
| /* FOUT of EPLL is 96MHz */ |
| ldr r1, =0x200203 |
| str r1, [r0, #EPLL_CON0_OFFSET] |
| ldr r1, =0x0 |
| str r1, [r0, #EPLL_CON1_OFFSET] |
| |
| /* APLL, MPLL, EPLL select to Fout */ |
| ldr r1, [r0, #CLK_SRC_OFFSET] |
| orr r1, r1, #0x7 |
| str r1, [r0, #CLK_SRC_OFFSET] |
| |
| /* wait at least 200us to stablize all clock */ |
| mov r1, #0x10000 |
| 1: subs r1, r1, #1 |
| bne 1b |
| |
| /* Synchronization for VIC port */ |
| #if defined(CONFIG_SYNC_MODE) |
| ldr r1, [r0, #OTHERS_OFFSET] |
| orr r1, r1, #0x20 |
| str r1, [r0, #OTHERS_OFFSET] |
| #elif !defined(CONFIG_S3C6400) |
| /* According to 661558um_S3C6400X_rev10.pdf 0x20 is reserved */ |
| ldr r1, [r0, #OTHERS_OFFSET] |
| bic r1, r1, #0x20 |
| str r1, [r0, #OTHERS_OFFSET] |
| #endif |
| mov pc, lr |
| |
| |
| #ifndef CONFIG_NAND_SPL |
| /* |
| * uart_asm_init: Initialize UART's pins |
| */ |
| uart_asm_init: |
| /* set GPIO to enable UART */ |
| ldr r0, =ELFIN_GPIO_BASE |
| ldr r1, =0x220022 |
| str r1, [r0, #GPACON_OFFSET] |
| mov pc, lr |
| #endif |
| |
| #ifdef CONFIG_BOOT_NAND |
| /* |
| * NAND Interface init for SMDK6400 |
| */ |
| nand_asm_init: |
| ldr r0, =ELFIN_NAND_BASE |
| ldr r1, [r0, #NFCONF_OFFSET] |
| orr r1, r1, #0x70 |
| orr r1, r1, #0x7700 |
| str r1, [r0, #NFCONF_OFFSET] |
| |
| ldr r1, [r0, #NFCONT_OFFSET] |
| orr r1, r1, #0x07 |
| str r1, [r0, #NFCONT_OFFSET] |
| |
| mov pc, lr |
| #endif |
| |
| #ifdef CONFIG_ENABLE_MMU |
| /* |
| * MMU Table for SMDK6400 |
| */ |
| |
| /* form a first-level section entry */ |
| .macro FL_SECTION_ENTRY base,ap,d,c,b |
| .word (\base << 20) | (\ap << 10) | \ |
| (\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1) |
| .endm |
| |
| .section .mmudata, "a" |
| .align 14 |
| /* the following alignment creates the mmu table at address 0x4000. */ |
| .globl mmu_table |
| mmu_table: |
| .set __base, 0 |
| /* 1:1 mapping for debugging */ |
| .rept 0xA00 |
| FL_SECTION_ENTRY __base, 3, 0, 0, 0 |
| .set __base, __base + 1 |
| .endr |
| |
| /* access is not allowed. */ |
| .rept 0xC00 - 0xA00 |
| .word 0x00000000 |
| .endr |
| |
| /* 128MB for SDRAM 0xC0000000 -> 0x50000000 */ |
| .set __base, 0x500 |
| .rept 0xC80 - 0xC00 |
| FL_SECTION_ENTRY __base, 3, 0, 1, 1 |
| .set __base, __base + 1 |
| .endr |
| |
| /* access is not allowed. */ |
| .rept 0x1000 - 0xc80 |
| .word 0x00000000 |
| .endr |
| #endif |