diff options
author | Tony Lindgren <tony@atomide.com> | 2006-04-02 17:46:25 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-04-02 17:46:25 +0100 |
commit | 670c104ae8e7bcc28be0289a16dac2ddfb88b285 (patch) | |
tree | 1c55f3a466775fd1d3b73ca28947500221e47134 /arch/arm/plat-omap | |
parent | 6e60e79a1d46eaa3369febc2f6c31e0acfaaae3f (diff) | |
download | blackbird-op-linux-670c104ae8e7bcc28be0289a16dac2ddfb88b285.tar.gz blackbird-op-linux-670c104ae8e7bcc28be0289a16dac2ddfb88b285.zip |
[ARM] 3430/1: ARM: OMAP: 5/8 Update PM
Patch from Tony Lindgren
Update OMAP PM code from linux-omap tree:
- Move PM code from plat-omap to mach-omap1 and mach-omap2
by Tony Lindgren
- Add minimal PM support for omap24xx by Tony Lindgren and
Richard Woodruff
- Misc updates to omap1 PM code by Tuukka Tikkanen et al
- Updates to the SRAM code needed for PM and FB by Imre Deak
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r-- | arch/arm/plat-omap/pm.c | 1 | ||||
-rw-r--r-- | arch/arm/plat-omap/sleep.S | 452 | ||||
-rw-r--r-- | arch/arm/plat-omap/sram.c | 143 |
3 files changed, 122 insertions, 474 deletions
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c index 093efd786f21..1a24e2c10714 100644 --- a/arch/arm/plat-omap/pm.c +++ b/arch/arm/plat-omap/pm.c @@ -38,6 +38,7 @@ #include <linux/pm.h> #include <linux/sched.h> #include <linux/proc_fs.h> +#include <linux/pm.h> #include <linux/interrupt.h> #include <asm/io.h> diff --git a/arch/arm/plat-omap/sleep.S b/arch/arm/plat-omap/sleep.S deleted file mode 100644 index 4cd7d292f854..000000000000 --- a/arch/arm/plat-omap/sleep.S +++ /dev/null @@ -1,452 +0,0 @@ -/* - * linux/arch/arm/plat-omap/sleep.S - * - * Low-level OMAP730/1510/1610 sleep/wakeUp support - * - * Initial SA1110 code: - * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> - * - * Adapted for PXA by Nicolas Pitre: - * Copyright (c) 2002 Monta Vista Software, Inc. - * - * Support for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com> - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/config.h> -#include <linux/linkage.h> -#include <asm/assembler.h> -#include <asm/arch/io.h> -#include <asm/arch/pm.h> - - .text - -/* - * Forces OMAP into idle state - * - * omapXXXX_idle_loop_suspend() - * - * Note: This code get's copied to internal SRAM at boot. When the OMAP - * wakes up it continues execution at the point it went to sleep. - * - * Note: Because of slightly different configuration values we have - * processor specific functions here. - */ - -#if defined(CONFIG_ARCH_OMAP730) -ENTRY(omap730_idle_loop_suspend) - - stmfd sp!, {r0 - r12, lr} @ save registers on stack - - @ load base address of ARM_IDLECT1 and ARM_IDLECT2 - mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 - - @ turn off clock domains - @ get ARM_IDLECT2 into r2 - ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - mov r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff - orr r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00 - strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - - @ request ARM idle - @ get ARM_IDLECT1 into r1 - ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - orr r3, r1, #OMAP730_IDLE_LOOP_REQUEST & 0xffff - strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - mov r5, #IDLE_WAIT_CYCLES & 0xff - orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 -l_730: subs r5, r5, #1 - bne l_730 -/* - * Let's wait for the next clock tick to wake us up. - */ - mov r0, #0 - mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt -/* - * omap730_idle_loop_suspend()'s resume point. - * - * It will just start executing here, so we'll restore stuff from the - * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. - */ - - @ restore ARM_IDLECT1 and ARM_IDLECT2 and return - @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 - strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - ldmfd sp!, {r0 - r12, pc} @ restore regs and return - -ENTRY(omap730_idle_loop_suspend_sz) - .word . - omap730_idle_loop_suspend -#endif /* CONFIG_ARCH_OMAP730 */ - -#ifdef CONFIG_ARCH_OMAP15XX -ENTRY(omap1510_idle_loop_suspend) - - stmfd sp!, {r0 - r12, lr} @ save registers on stack - - @ load base address of ARM_IDLECT1 and ARM_IDLECT2 - mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 - - @ turn off clock domains - @ get ARM_IDLECT2 into r2 - ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff - orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00 - strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - - @ request ARM idle - @ get ARM_IDLECT1 into r1 - ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - orr r3, r1, #OMAP1510_IDLE_LOOP_REQUEST & 0xffff - strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - mov r5, #IDLE_WAIT_CYCLES & 0xff - orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 -l_1510: subs r5, r5, #1 - bne l_1510 -/* - * Let's wait for the next clock tick to wake us up. - */ - mov r0, #0 - mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt -/* - * omap1510_idle_loop_suspend()'s resume point. - * - * It will just start executing here, so we'll restore stuff from the - * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. - */ - - @ restore ARM_IDLECT1 and ARM_IDLECT2 and return - @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 - strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - ldmfd sp!, {r0 - r12, pc} @ restore regs and return - -ENTRY(omap1510_idle_loop_suspend_sz) - .word . - omap1510_idle_loop_suspend -#endif /* CONFIG_ARCH_OMAP15XX */ - -#if defined(CONFIG_ARCH_OMAP16XX) -ENTRY(omap1610_idle_loop_suspend) - - stmfd sp!, {r0 - r12, lr} @ save registers on stack - - @ load base address of ARM_IDLECT1 and ARM_IDLECT2 - mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 - - @ turn off clock domains - @ get ARM_IDLECT2 into r2 - ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff - orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00 - strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - - @ request ARM idle - @ get ARM_IDLECT1 into r1 - ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - orr r3, r1, #OMAP1610_IDLE_LOOP_REQUEST & 0xffff - strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - mov r5, #IDLE_WAIT_CYCLES & 0xff - orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 -l_1610: subs r5, r5, #1 - bne l_1610 -/* - * Let's wait for the next clock tick to wake us up. - */ - mov r0, #0 - mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt -/* - * omap1610_idle_loop_suspend()'s resume point. - * - * It will just start executing here, so we'll restore stuff from the - * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. - */ - - @ restore ARM_IDLECT1 and ARM_IDLECT2 and return - @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 - strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - ldmfd sp!, {r0 - r12, pc} @ restore regs and return - -ENTRY(omap1610_idle_loop_suspend_sz) - .word . - omap1610_idle_loop_suspend -#endif /* CONFIG_ARCH_OMAP16XX */ - -/* - * Forces OMAP into deep sleep state - * - * omapXXXX_cpu_suspend() - * - * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed - * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1 - * in register r1. - * - * Note: This code get's copied to internal SRAM at boot. When the OMAP - * wakes up it continues execution at the point it went to sleep. - * - * Note: Because of errata work arounds we have processor specific functions - * here. They are mostly the same, but slightly different. - * - */ - -#if defined(CONFIG_ARCH_OMAP730) -ENTRY(omap730_cpu_suspend) - - @ save registers on stack - stmfd sp!, {r0 - r12, lr} - - @ Drain write cache - mov r4, #0 - mcr p15, 0, r0, c7, c10, 4 - nop - - @ load base address of Traffic Controller - mov r6, #TCMIF_ASM_BASE & 0xff000000 - orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000 - orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00 - - @ prepare to put SDRAM into self-refresh manually - ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] - orr r9, r7, #SELF_REFRESH_MODE & 0xff000000 - orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff - str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] - - @ prepare to put EMIFS to Sleep - ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff - str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - - @ load base address of ARM_IDLECT1 and ARM_IDLECT2 - mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 - - @ turn off clock domains - @ do not disable PERCK (0x04) - mov r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff - orr r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00 - strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - - @ request ARM idle - mov r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff - orr r3, r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff00 - strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - @ disable instruction cache - mrc p15, 0, r9, c1, c0, 0 - bic r2, r9, #0x1000 - mcr p15, 0, r2, c1, c0, 0 - nop - -/* - * Let's wait for the next wake up event to wake us up. r0 can't be - * used here because r0 holds ARM_IDLECT1 - */ - mov r2, #0 - mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt -/* - * omap730_cpu_suspend()'s resume point. - * - * It will just start executing here, so we'll restore stuff from the - * stack. - */ - @ re-enable Icache - mcr p15, 0, r9, c1, c0, 0 - - @ reset the ARM_IDLECT1 and ARM_IDLECT2. - strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - @ Restore EMIFF controls - str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] - str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - - @ restore regs and return - ldmfd sp!, {r0 - r12, pc} - -ENTRY(omap730_cpu_suspend_sz) - .word . - omap730_cpu_suspend -#endif /* CONFIG_ARCH_OMAP730 */ - -#ifdef CONFIG_ARCH_OMAP15XX -ENTRY(omap1510_cpu_suspend) - - @ save registers on stack - stmfd sp!, {r0 - r12, lr} - - @ load base address of Traffic Controller - mov r4, #TCMIF_ASM_BASE & 0xff000000 - orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000 - orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00 - - @ work around errata of OMAP1510 PDE bit for TC shut down - @ clear PDE bit - ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - bic r5, r5, #PDE_BIT & 0xff - str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - - @ set PWD_EN bit - and r5, r5, #PWD_EN_BIT & 0xff - str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - - @ prepare to put SDRAM into self-refresh manually - ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] - orr r5, r5, #SELF_REFRESH_MODE & 0xff000000 - orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff - str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] - - @ prepare to put EMIFS to Sleep - ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff - str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - - @ load base address of ARM_IDLECT1 and ARM_IDLECT2 - mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 - - @ turn off clock domains - mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff - orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00 - strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - - @ request ARM idle - mov r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff - orr r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00 - strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - mov r5, #IDLE_WAIT_CYCLES & 0xff - orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 -l_1510_2: - subs r5, r5, #1 - bne l_1510_2 -/* - * Let's wait for the next wake up event to wake us up. r0 can't be - * used here because r0 holds ARM_IDLECT1 - */ - mov r2, #0 - mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt -/* - * omap1510_cpu_suspend()'s resume point. - * - * It will just start executing here, so we'll restore stuff from the - * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. - */ - strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - @ restore regs and return - ldmfd sp!, {r0 - r12, pc} - -ENTRY(omap1510_cpu_suspend_sz) - .word . - omap1510_cpu_suspend -#endif /* CONFIG_ARCH_OMAP15XX */ - -#if defined(CONFIG_ARCH_OMAP16XX) -ENTRY(omap1610_cpu_suspend) - - @ save registers on stack - stmfd sp!, {r0 - r12, lr} - - @ Drain write cache - mov r4, #0 - mcr p15, 0, r0, c7, c10, 4 - nop - - @ load base address of Traffic Controller - mov r6, #TCMIF_ASM_BASE & 0xff000000 - orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000 - orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00 - - @ prepare to put SDRAM into self-refresh manually - ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] - orr r9, r7, #SELF_REFRESH_MODE & 0xff000000 - orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff - str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] - - @ prepare to put EMIFS to Sleep - ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff - str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - - @ load base address of ARM_IDLECT1 and ARM_IDLECT2 - mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 - - @ turn off clock domains - @ do not disable PERCK (0x04) - mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff - orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00 - strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - - @ request ARM idle - mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff - orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00 - strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - @ disable instruction cache - mrc p15, 0, r9, c1, c0, 0 - bic r2, r9, #0x1000 - mcr p15, 0, r2, c1, c0, 0 - nop - -/* - * Let's wait for the next wake up event to wake us up. r0 can't be - * used here because r0 holds ARM_IDLECT1 - */ - mov r2, #0 - mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt -/* - * omap1610_cpu_suspend()'s resume point. - * - * It will just start executing here, so we'll restore stuff from the - * stack. - */ - @ re-enable Icache - mcr p15, 0, r9, c1, c0, 0 - - @ reset the ARM_IDLECT1 and ARM_IDLECT2. - strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - @ Restore EMIFF controls - str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] - str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - - @ restore regs and return - ldmfd sp!, {r0 - r12, pc} - -ENTRY(omap1610_cpu_suspend_sz) - .word . - omap1610_cpu_suspend -#endif /* CONFIG_ARCH_OMAP16XX */ diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index ee82763b02b8..b7bf09b1b412 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -16,24 +16,94 @@ #include <linux/kernel.h> #include <linux/init.h> -#include <asm/mach/map.h> #include <asm/tlb.h> #include <asm/io.h> #include <asm/cacheflush.h> +#include <asm/mach/map.h> + #include <asm/arch/sram.h> +#include <asm/arch/board.h> #define OMAP1_SRAM_PA 0x20000000 #define OMAP1_SRAM_VA 0xd0000000 #define OMAP2_SRAM_PA 0x40200000 +#define OMAP2_SRAM_PUB_PA 0x4020f800 #define OMAP2_SRAM_VA 0xd0000000 +#define OMAP2_SRAM_PUB_VA 0xd0000800 +#if defined(CONFIG_ARCH_OMAP24XX) +#define SRAM_BOOTLOADER_SZ 0x00 +#else #define SRAM_BOOTLOADER_SZ 0x80 +#endif + +#define VA_REQINFOPERM0 IO_ADDRESS(0x68005048) +#define VA_READPERM0 IO_ADDRESS(0x68005050) +#define VA_WRITEPERM0 IO_ADDRESS(0x68005058) +#define VA_CONTROL_STAT IO_ADDRESS(0x480002F8) +#define GP_DEVICE 0x300 +#define TYPE_MASK 0x700 + +#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) static unsigned long omap_sram_base; static unsigned long omap_sram_size; static unsigned long omap_sram_ceil; +unsigned long omap_fb_sram_start; +unsigned long omap_fb_sram_size; + +/* Depending on the target RAMFS firewall setup, the public usable amount of + * SRAM varies. The default accessable size for all device types is 2k. A GP + * device allows ARM11 but not other initators for full size. This + * functionality seems ok until some nice security API happens. + */ +static int is_sram_locked(void) +{ + int type = 0; + + if (cpu_is_omap242x()) + type = __raw_readl(VA_CONTROL_STAT) & TYPE_MASK; + + if (type == GP_DEVICE) { + /* RAMFW: R/W access to all initators for all qualifier sets */ + if (cpu_is_omap242x()) { + __raw_writel(0xFF, VA_REQINFOPERM0); /* all q-vects */ + __raw_writel(0xCFDE, VA_READPERM0); /* all i-read */ + __raw_writel(0xCFDE, VA_WRITEPERM0); /* all i-write */ + } + return 0; + } else + return 1; /* assume locked with no PPA or security driver */ +} + +void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, + unsigned long *start, unsigned long *size) +{ + const struct omap_fbmem_config *fbmem_conf; + + fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); + if (fbmem_conf != NULL) { + *start = fbmem_conf->fb_sram_start; + *size = fbmem_conf->fb_sram_size; + } else { + *size = 0; + *start = 0; + } + + if (*size && ( + *start < start_avail || + *start + *size > start_avail + size_avail)) { + printk(KERN_ERR "invalid FB SRAM configuration\n"); + *start = start_avail; + *size = size_avail; + } + + if (*size) + pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size); +} + /* * The amount of SRAM depends on the core type. * Note that we cannot try to test for SRAM here because writes @@ -42,26 +112,45 @@ static unsigned long omap_sram_ceil; */ void __init omap_detect_sram(void) { - if (!cpu_is_omap24xx()) + unsigned long sram_start; + + if (cpu_is_omap24xx()) { + if (is_sram_locked()) { + omap_sram_base = OMAP2_SRAM_PUB_VA; + sram_start = OMAP2_SRAM_PUB_PA; + omap_sram_size = 0x800; /* 2K */ + } else { + omap_sram_base = OMAP2_SRAM_VA; + sram_start = OMAP2_SRAM_PA; + if (cpu_is_omap242x()) + omap_sram_size = 0xa0000; /* 640K */ + else if (cpu_is_omap243x()) + omap_sram_size = 0x10000; /* 64K */ + } + } else { omap_sram_base = OMAP1_SRAM_VA; - else - omap_sram_base = OMAP2_SRAM_VA; - - if (cpu_is_omap730()) - omap_sram_size = 0x32000; /* 200K */ - else if (cpu_is_omap15xx()) - omap_sram_size = 0x30000; /* 192K */ - else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710()) - omap_sram_size = 0x4000; /* 16K */ - else if (cpu_is_omap1611()) - omap_sram_size = 0x3e800; /* 250K */ - else if (cpu_is_omap2420()) - omap_sram_size = 0xa0014; /* 640K */ - else { - printk(KERN_ERR "Could not detect SRAM size\n"); - omap_sram_size = 0x4000; + sram_start = OMAP1_SRAM_PA; + + if (cpu_is_omap730()) + omap_sram_size = 0x32000; /* 200K */ + else if (cpu_is_omap15xx()) + omap_sram_size = 0x30000; /* 192K */ + else if (cpu_is_omap1610() || cpu_is_omap1621() || + cpu_is_omap1710()) + omap_sram_size = 0x4000; /* 16K */ + else if (cpu_is_omap1611()) + omap_sram_size = 0x3e800; /* 250K */ + else { + printk(KERN_ERR "Could not detect SRAM size\n"); + omap_sram_size = 0x4000; + } } - + get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ, + omap_sram_size - SRAM_BOOTLOADER_SZ, + &omap_fb_sram_start, &omap_fb_sram_size); + if (omap_fb_sram_size) + omap_sram_size -= sram_start + omap_sram_size - + omap_fb_sram_start; omap_sram_ceil = omap_sram_base + omap_sram_size; } @@ -80,12 +169,20 @@ static struct map_desc omap_sram_io_desc[] __initdata = { */ void __init omap_map_sram(void) { + unsigned long base; + if (omap_sram_size == 0) return; if (cpu_is_omap24xx()) { omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA; - omap_sram_io_desc[0].pfn = __phys_to_pfn(OMAP2_SRAM_PA); + + if (is_sram_locked()) + base = OMAP2_SRAM_PUB_PA; + else + base = OMAP2_SRAM_PA; + base = ROUND_DOWN(base, PAGE_SIZE); + omap_sram_io_desc[0].pfn = __phys_to_pfn(base); } omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE; @@ -93,7 +190,8 @@ void __init omap_map_sram(void) iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", - omap_sram_io_desc[0].pfn, omap_sram_io_desc[0].virtual, + __pfn_to_phys(omap_sram_io_desc[0].pfn), + omap_sram_io_desc[0].virtual, omap_sram_io_desc[0].length); /* @@ -118,8 +216,9 @@ void * omap_sram_push(void * start, unsigned long size) printk(KERN_ERR "Not enough space in SRAM\n"); return NULL; } + omap_sram_ceil -= size; - omap_sram_ceil &= ~0x3; + omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *)); memcpy((void *)omap_sram_ceil, start, size); return (void *)omap_sram_ceil; |