diff options
author | Graeme Russ <graeme.russ@gmail.com> | 2011-02-12 15:11:52 +1100 |
---|---|---|
committer | Graeme Russ <graeme.russ@gmail.com> | 2011-02-12 15:11:52 +1100 |
commit | ed4cba79d640daa33806fa228c1a10c6bf9e2101 (patch) | |
tree | b6500012ce46b0cd5ae43fdf0ff136f42e3e7133 /arch/i386/cpu | |
parent | 2e2613d2c4755426cb6bfddf1ca7714b0deec177 (diff) |
x86: Use Cache-As-RAM for initial stack
Diffstat (limited to 'arch/i386/cpu')
-rw-r--r-- | arch/i386/cpu/sc520/Makefile | 1 | ||||
-rw-r--r-- | arch/i386/cpu/sc520/sc520_asm.S | 6 | ||||
-rw-r--r-- | arch/i386/cpu/sc520/sc520_car.S | 94 | ||||
-rw-r--r-- | arch/i386/cpu/start.S | 35 |
4 files changed, 115 insertions, 21 deletions
diff --git a/arch/i386/cpu/sc520/Makefile b/arch/i386/cpu/sc520/Makefile index b962b02327..3c25cbaa51 100644 --- a/arch/i386/cpu/sc520/Makefile +++ b/arch/i386/cpu/sc520/Makefile @@ -37,6 +37,7 @@ COBJS-$(CONFIG_SYS_SC520_SSI) += sc520_ssi.o COBJS-$(CONFIG_SYS_SC520_TIMER) += sc520_timer.o SOBJS-$(CONFIG_SYS_SC520) += sc520_asm.o +SOBJS-$(CONFIG_SYS_SC520) += sc520_car.o SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) diff --git a/arch/i386/cpu/sc520/sc520_asm.S b/arch/i386/cpu/sc520/sc520_asm.S index 9f6cce3188..901aa61fdf 100644 --- a/arch/i386/cpu/sc520/sc520_asm.S +++ b/arch/i386/cpu/sc520/sc520_asm.S @@ -515,7 +515,7 @@ bad_ram: dram_done: /* Restore Boot Flags */ movl %ebx, %ebp - jmp mem_init_ret + ret #if CONFIG_SYS_SDRAM_ECC_ENABLE .globl init_ecc @@ -560,7 +560,7 @@ set_ecc: movb %al,(%edi) out: - jmp init_ecc_ret + ret #endif /* @@ -605,4 +605,4 @@ bank3: movl (%edi), %eax done: movl %edx, %eax - jmp get_mem_size_ret + ret diff --git a/arch/i386/cpu/sc520/sc520_car.S b/arch/i386/cpu/sc520/sc520_car.S new file mode 100644 index 0000000000..22f5225311 --- /dev/null +++ b/arch/i386/cpu/sc520/sc520_car.S @@ -0,0 +1,94 @@ +/* + * (C) Copyright 2010 + * Graeme Russ <graeme.russ@gmail.com>. + * + * 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 <asm/processor-flags.h> +#include <asm/ic/sc520.h> + +.section .text + +.globl car_init +car_init: + /* + * How to enable Cache-As-RAM for the AMD Elan SC520: + * 1. Turn off the CPU Cache (may not be strictly required) + * 2. Set code execution PAR (usually the BOOTCS region) to be + * non-cachable + * 3. Create a Cachable PAR Region for an area of memory which is + * a) NOT where the code is being executed + * b) NOT SDRAM (Controller not initialised yet) + * c) WILL response to read requests + * The easiest way to do this is to create a second BOOTCS + * PAR mappnig with an address != the PAR in step 2 + * 4. Issue a wbinvd to invalidate the CPU cache + * 5. Turn on the CPU Cache + * 6. Read 16kB from the cached PAR region setup in step 3 + * 7. Turn off the CPU Cache (but DO NOT issue a wbinvd) + * + * The following code uses PAR2 as the cached PAR (PAR0 and PAR1 + * are avoided as these are the only two PARs which can be used + * as PCI BUS Memory regions which the board might require) + * + * The configuration of PAR2 must be set in the board configuration + * file as CONFIG_SYS_SC520_CAR_PAR + */ + + /* Configure Cache-As-RAM PAR */ + movl $CONFIG_SYS_SC520_CAR_PAR, %eax + movl $SC520_PAR2, %edi + movl %eax, (%edi) + + /* Trash the cache then turn it on */ + wbinvd + movl %cr0, %eax + andl $~(X86_CR0_NW | X86_CR0_CD), %eax + movl %eax, %cr0 + + /* + * The cache is now enabled and empty. Map a region of memory to + * it by reading that region. + */ + movl $CONFIG_SYS_CAR_ADDR, %esi + movl $CONFIG_SYS_CAR_SIZE, %ecx + shrl $2, %ecx /* we are reading longs */ + cld + rep lodsl + + /* Turn off the cache, but don't trash it */ + movl %cr0, %eax + orl $(X86_CR0_NW | X86_CR0_CD), %eax + movl %eax, %cr0 + + /* Clear the CAR region */ + xorl %eax, %eax + movl $CONFIG_SYS_CAR_ADDR, %edi + movl $CONFIG_SYS_CAR_SIZE, %ecx + shrl $2, %ecx /* we are writing longs */ + rep stosl + + /* + * Done - We should now have CONFIG_SYS_CAR_SIZE bytes of + * Cache-As-RAM + */ + jmp car_init_ret diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index 0ce97134d5..df9ca0d277 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -72,41 +72,40 @@ _start: .globl early_board_init_ret early_board_init_ret: + /* Initialise Cache-As-RAM */ + jmp car_init +.globl car_init_ret +car_init_ret: + /* + * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM, + * or fully initialised SDRAM - we really don't care which) + * starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack + */ + movl $CONFIG_SYS_INIT_SP_ADDR, %esp + /* Skip memory initialization if not starting from cold-reset */ movl %ebx, %ecx andl $GD_FLG_COLD_BOOT, %ecx jz skip_mem_init /* size memory */ - jmp mem_init -.globl mem_init_ret -mem_init_ret: + call mem_init skip_mem_init: /* fetch memory size (into %eax) */ - jmp get_mem_size -.globl get_mem_size_ret -get_mem_size_ret: + call get_mem_size + movl %eax, %esp #if CONFIG_SYS_SDRAM_ECC_ENABLE /* Skip ECC initialization if not starting from cold-reset */ movl %ebx, %ecx andl $GD_FLG_COLD_BOOT, %ecx - jz init_ecc_ret - jmp init_ecc + jz skip_ecc_init + call init_ecc -.globl init_ecc_ret -init_ecc_ret: +skip_init_ecc: #endif - /* Check we have enough memory for stack */ - movl $CONFIG_SYS_STACK_SIZE, %ecx - cmpl %ecx, %eax - jb die -mem_ok: - /* Set stack pointer to upper memory limit*/ - movl %eax, %esp - /* Test the stack */ pushl $0 popl %ecx |