From c9b981ba013582d8c65d94aed8230f6e446c3556 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=BB=84=E6=B6=9B?= Date: Tue, 25 Jan 2011 20:30:13 +0800 Subject: [PATCH] rk29: add sram support --- arch/arm/kernel/vmlinux.lds.S | 56 ++++++++++++ arch/arm/mach-rk29/Makefile | 2 +- arch/arm/mach-rk29/board-rk29-aigo.c | 2 + arch/arm/mach-rk29/board-rk29-winaccord.c | 2 + arch/arm/mach-rk29/board-rk29sdk.c | 2 + arch/arm/mach-rk29/include/mach/memory.h | 8 ++ arch/arm/mach-rk29/include/mach/sram.h | 37 ++++++++ arch/arm/mach-rk29/sram.c | 102 ++++++++++++++++++++++ 8 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-rk29/include/mach/sram.h create mode 100644 arch/arm/mach-rk29/sram.c diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index aecf87dfbaec..5d972f1c9770 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -255,6 +255,62 @@ SECTIONS __tcm_end = .; } #endif +#ifdef CONFIG_ARCH_RK29 + /* + * We align everything to a page boundary so we can + * free it after init has commenced and SRAM contents have + * been copied to its destination. + */ + .sram_start : { + . = ALIGN(PAGE_SIZE); + __sram_start = .; + __sram_code_start = .; + } + + /* + * Link these to the ITCM RAM + * Put VMA to the TCM address and LMA to the common RAM + * and we'll upload the contents from RAM to TCM and free + * the used RAM after that. + */ + .text_sram_code SRAM_CODE_OFFSET : AT(__sram_code_start) + { + __ssram_code_text = .; + *(.sram.text) + *(.sram.rodata) + . = ALIGN(4); + __esram_code_text = .; + } + + /* + * Reset the dot pointer, this is needed to create the + * relative __dtcm_start below (to be used as extern in code). + */ + . = ADDR(.sram_start) + SIZEOF(.sram_start) + SIZEOF(.text_sram_code); + + .sram_data_start : { + __sram_data_start = .; + } + + /* TODO: add remainder of ITCM as well, that can be used for data! */ + .data_sram SRAM_DATA_OFFSET : AT(__sram_data_start) + { + . = ALIGN(4); + __ssram_data = .; + *(.sram.data) + . = ALIGN(4); + __esram_data = .; + } + + /* Reset the dot pointer or the linker gets confused */ + . = ADDR(.sram_data_start) + SIZEOF(.data_sram); + + /* End marker for freeing TCM copy in linked object */ + .sram_end : AT(ADDR(.sram_data_start) + SIZEOF(.data_sram)){ + . = ALIGN(PAGE_SIZE); + __sram_end = .; + } +#endif .bss : { __bss_start = .; /* BSS */ diff --git a/arch/arm/mach-rk29/Makefile b/arch/arm/mach-rk29/Makefile index e8dab6f06307..4d91315eb97a 100755 --- a/arch/arm/mach-rk29/Makefile +++ b/arch/arm/mach-rk29/Makefile @@ -1,4 +1,4 @@ -obj-y += timer.o io.o devices.o iomux.o clock.o rk29-pl330.o dma.o gpio.o +obj-y += timer.o io.o devices.o iomux.o clock.o rk29-pl330.o dma.o gpio.o sram.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_RK29_VPU) += vpu.o vpu_mem.o obj-$(CONFIG_MACH_RK29SDK) += board-rk29sdk.o board-rk29sdk-key.o board-rk29sdk-rfkill.o diff --git a/arch/arm/mach-rk29/board-rk29-aigo.c b/arch/arm/mach-rk29/board-rk29-aigo.c index 6018c6bba7b9..e0fb50d881e5 100644 --- a/arch/arm/mach-rk29/board-rk29-aigo.c +++ b/arch/arm/mach-rk29/board-rk29-aigo.c @@ -42,6 +42,7 @@ #include /* ddl@rock-chips.com : camera support */ #include /* ddl@rock-chips.com : camera support */ #include +#include #include #include @@ -1816,6 +1817,7 @@ static void __init machine_rk29_fixup(struct machine_desc *desc, struct tag *tag static void __init machine_rk29_mapio(void) { rk29_map_common_io(); + rk29_sram_init(); rk29_clock_init(); rk29_iomux_init(); } diff --git a/arch/arm/mach-rk29/board-rk29-winaccord.c b/arch/arm/mach-rk29/board-rk29-winaccord.c index ea21ea7c7dd7..39cc2e81640c 100644 --- a/arch/arm/mach-rk29/board-rk29-winaccord.c +++ b/arch/arm/mach-rk29/board-rk29-winaccord.c @@ -42,6 +42,7 @@ #include /* ddl@rock-chips.com : camera support */ #include /* ddl@rock-chips.com : camera support */ #include +#include #include #include @@ -1719,6 +1720,7 @@ static void __init machine_rk29_fixup(struct machine_desc *desc, struct tag *tag static void __init machine_rk29_mapio(void) { rk29_map_common_io(); + rk29_sram_init(); rk29_clock_init(); rk29_iomux_init(); } diff --git a/arch/arm/mach-rk29/board-rk29sdk.c b/arch/arm/mach-rk29/board-rk29sdk.c index 46d7998aa8ab..0f9d9d8a92ad 100755 --- a/arch/arm/mach-rk29/board-rk29sdk.c +++ b/arch/arm/mach-rk29/board-rk29sdk.c @@ -42,6 +42,7 @@ #include /* ddl@rock-chips.com : camera support */ #include /* ddl@rock-chips.com : camera support */ #include +#include #include #include @@ -1793,6 +1794,7 @@ static void __init machine_rk29_fixup(struct machine_desc *desc, struct tag *tag static void __init machine_rk29_mapio(void) { rk29_map_common_io(); + rk29_sram_init(); rk29_clock_init(); rk29_iomux_init(); } diff --git a/arch/arm/mach-rk29/include/mach/memory.h b/arch/arm/mach-rk29/include/mach/memory.h index 3dfc5036818a..7492e70ee306 100644 --- a/arch/arm/mach-rk29/include/mach/memory.h +++ b/arch/arm/mach-rk29/include/mach/memory.h @@ -25,5 +25,13 @@ #define CONSISTENT_DMA_SIZE SZ_8M +/* + * SRAM memory whereabouts + */ +#define SRAM_CODE_OFFSET 0xff400000 +#define SRAM_CODE_END 0xff401fff +#define SRAM_DATA_OFFSET 0xff402000 +#define SRAM_DATA_END 0xff403fff + #endif diff --git a/arch/arm/mach-rk29/include/mach/sram.h b/arch/arm/mach-rk29/include/mach/sram.h new file mode 100644 index 000000000000..a7f91498420c --- /dev/null +++ b/arch/arm/mach-rk29/include/mach/sram.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2008-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * TCM memory handling for ARM systems + * + * Author: Linus Walleij + * Author: Rickard Andersson + */ + +#ifdef CONFIG_ARCH_RK29 + +/* Tag variables with this */ +#define __sramdata __section(.sram.data) +/* Tag constants with this */ +#define __sramconst __section(.sram.rodata) +/* Tag functions inside SRAM called from outside SRAM with this */ +#define __sramfunc __attribute__((long_call)) __section(.sram.text) noinline +/* Tag function inside SRAM called from inside SRAM with this */ +#define __sramlocalfunc __section(.sram.text) + +void __init rk29_sram_init(void); + +static inline unsigned long ddr_save_sp(unsigned long new_sp) +{ + unsigned long old_sp; + + asm volatile ("mov %0, sp" : "=r" (old_sp)); + asm volatile ("mov sp, %0" :: "r" (new_sp)); + return old_sp; +} + +// save_sp ±ØÐ붨ÒåΪȫ¾Ö±äÁ¿ +#define DDR_SAVE_SP(save_sp) do { save_sp = ddr_save_sp((SRAM_DATA_END&(~7))); } while (0) +#define DDR_RESTORE_SP(save_sp) do { ddr_save_sp(save_sp); } while (0) + +#endif + diff --git a/arch/arm/mach-rk29/sram.c b/arch/arm/mach-rk29/sram.c new file mode 100644 index 000000000000..5d9bd09fd67e --- /dev/null +++ b/arch/arm/mach-rk29/sram.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2008-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * TCM memory handling for ARM systems + * + * Author: Linus Walleij + * Author: Rickard Andersson + */ +#include +#include +#include +#include +#include +#include +#include /* memcpy */ +#include /* PAGE_SHIFT */ +#include +#include +#include +#include +#include +#include + + +/* SRAM section definitions from the linker */ +extern char __sram_code_start, __ssram_code_text, __esram_code_text; +extern char __sram_data_start, __ssram_data, __esram_data; + +static struct map_desc sram_code_iomap[] __initdata = { + { + .virtual = SRAM_CODE_OFFSET, +// .pfn = __phys_to_pfn(RK29_SRAM_PHYS), + .pfn = __phys_to_pfn(0x0), + // .length = (SRAM_CODE_END - SRAM_CODE_OFFSET + 1), + .length = 1024*1024, // (SRAM_CODE_END - SRAM_CODE_OFFSET + 1), + .type = MT_MEMORY//MT_MEMORY //MT_HIGH_VECTORS//MT_MEMORY //MT_UNCACHED + } +}; + +static struct map_desc sram_data_iomap[] __initdata = { + { + .virtual = SRAM_DATA_OFFSET, + // .pfn = __phys_to_pfn(RK29_SRAM_PHYS+0x2000), + .pfn = __phys_to_pfn(0x2000), + .length = (SRAM_DATA_END - SRAM_DATA_OFFSET + 1), + .type = MT_HIGH_VECTORS //MT_MEMORY //MT_UNCACHED + } +}; + + +int __init rk29_sram_init(void) +{ + char *start; + char *end; + char *ram; + + iotable_init(sram_code_iomap, 1); +// iotable_init(sram_data_iomap, 1); + + /* + * Normally devicemaps_init() would flush caches and tlb after + * mdesc->map_io(), but since we're called from map_io(), we + * must do it here. + */ + local_flush_tlb_all(); + flush_cache_all(); + + memset((char *)SRAM_CODE_OFFSET,0x0,(SRAM_CODE_END - SRAM_CODE_OFFSET + 1)); + memset((char *)SRAM_DATA_OFFSET,0x0,(SRAM_DATA_END - SRAM_DATA_OFFSET + 1)); + + /* Copy code from RAM to SRAM CODE */ + start = &__ssram_code_text; + end = &__esram_code_text; + ram = &__sram_code_start; + memcpy(start, ram, (end-start)); + flush_icache_range((unsigned long) start, (unsigned long) end); + + printk("CPU SRAM: copied sram code from %p to %p - %p \n", ram, start, end); + printk("%08x %08x\n", *(u32 *)0xFF400628, *(u32 *)0xFF40062C); +// extern void DDR_EnterSelfRefresh(); +// DDR_EnterSelfRefresh(); + + printk("CPU SRAM: start = [%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x]\n", + start[0],start[1],start[2],start[3],start[4],start[5],start[6],start[7],start[8],start[9],start[10],start[11],start[12],start[13],start[14],start[15]); + start += 0x10; + printk("CPU SRAM: start = [%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x]\n", + start[0],start[1],start[2],start[3],start[4],start[5],start[6],start[7],start[8],start[9],start[10],start[11],start[12],start[13],start[14],start[15]); + + printk("CPU SRAM: ram = [%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x]\n", + ram[0],ram[1],ram[2],ram[3],ram[4],ram[5],ram[6],ram[7],ram[8],ram[9],ram[10],ram[11],ram[12],ram[13],ram[14],ram[15]); + + + /* Copy data from RAM to SRAM DATA */ + start = &__ssram_data; + end = &__esram_data; + ram = &__sram_data_start; + memcpy(start, ram, (end-start)); + + printk("CPU SRAM: copied sram data from %p to %p - %p\n", ram,start, end); + + return 0; +} -- 2.34.1