#
# Common support
-obj-y := common.o dma.o clock.o mux.o gpio.o mcbsp.o usb.o
+obj-y := common.o sram.o sram-fn.o clock.o dma.o mux.o gpio.o mcbsp.o usb.o
obj-m :=
obj-n :=
obj- :=
#include "../clock.h"
extern void omap_check_revision(void);
+extern void omap_detect_sram(void);
/*
* The machine specific code may provide the extra mapping besides the
static struct map_desc omap730_io_desc[] __initdata = {
{ OMAP730_DSP_BASE, OMAP730_DSP_START, OMAP730_DSP_SIZE, MT_DEVICE },
{ OMAP730_DSPREG_BASE, OMAP730_DSPREG_START, OMAP730_DSPREG_SIZE, MT_DEVICE },
- { OMAP730_SRAM_BASE, OMAP730_SRAM_START, OMAP730_SRAM_SIZE, MT_DEVICE }
};
#endif
static struct map_desc omap1510_io_desc[] __initdata = {
{ OMAP1510_DSP_BASE, OMAP1510_DSP_START, OMAP1510_DSP_SIZE, MT_DEVICE },
{ OMAP1510_DSPREG_BASE, OMAP1510_DSPREG_START, OMAP1510_DSPREG_SIZE, MT_DEVICE },
- { OMAP1510_SRAM_BASE, OMAP1510_SRAM_START, OMAP1510_SRAM_SIZE, MT_DEVICE }
};
#endif
static struct map_desc omap1610_io_desc[] __initdata = {
{ OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE },
{ OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
- { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP1610_SRAM_SIZE, MT_DEVICE }
};
static struct map_desc omap5912_io_desc[] __initdata = {
{ OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE },
{ OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
-/*
- * The OMAP5912 has 250kByte internal SRAM. Because the mapping is baseed on page
- * size (4kByte), it seems that the last 2kByte (=0x800) of the 250kByte are not mapped.
- * Add additional 2kByte (0x800) so that the last page is mapped and the last 2kByte
- * can be used.
- */
- { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP5912_SRAM_SIZE + 0x800, MT_DEVICE }
};
#endif
}
#endif
+ omap_sram_init();
+
/* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
* on a Posted Write in the TIPB Bridge".
*/
#include <asm/arch/dsp_common.h>
#include "clock.h"
+#include "sram.h"
static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
+static void (*omap_sram_idle)(void) = NULL;
+static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
+
/*
* Let's power down on idle, but only if we are really
* idle, because once we start down the path of
*/
void omap_pm_idle(void)
{
- int (*func_ptr)(void) = NULL;
unsigned int mask32 = 0;
/*
if ((mask32 & DSP_IDLE) == 0) {
__asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
- } else {
-
- if (cpu_is_omap1510()) {
- func_ptr = (void *)(OMAP1510_SRAM_IDLE_SUSPEND);
- } else if (cpu_is_omap1610() || cpu_is_omap1710()) {
- func_ptr = (void *)(OMAP1610_SRAM_IDLE_SUSPEND);
- } else if (cpu_is_omap5912()) {
- func_ptr = (void *)(OMAP5912_SRAM_IDLE_SUSPEND);
- }
-
- func_ptr();
- }
+ } else
+ omap_sram_idle();
}
/*
void omap_pm_suspend(void)
{
unsigned long arg0 = 0, arg1 = 0;
- int (*func_ptr)(unsigned short, unsigned short) = NULL;
printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev);
arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
- if (cpu_is_omap1510()) {
- func_ptr = (void *)(OMAP1510_SRAM_API_SUSPEND);
- } else if (cpu_is_omap1610() || cpu_is_omap1710()) {
- func_ptr = (void *)(OMAP1610_SRAM_API_SUSPEND);
- } else if (cpu_is_omap5912()) {
- func_ptr = (void *)(OMAP5912_SRAM_API_SUSPEND);
- }
-
/*
* Step 6c: ARM and Traffic controller shutdown
*
* Jump to assembly code. The processor will stay there
* until wake up.
*/
-
- func_ptr(arg0, arg1);
+ omap_sram_suspend(arg0, arg1);
/*
* If we are here, processor is woken up!
static int __init omap_pm_init(void)
{
printk("Power Management for TI OMAP.\n");
- pm_idle = omap_pm_idle;
/*
* We copy the assembler sleep/wakeup routines to SRAM.
* These routines need to be in SRAM as that's the only
* memory the MPU can see when it wakes up.
*/
-
-#ifdef CONFIG_ARCH_OMAP1510
if (cpu_is_omap1510()) {
- memcpy((void *)OMAP1510_SRAM_IDLE_SUSPEND,
- omap1510_idle_loop_suspend,
- omap1510_idle_loop_suspend_sz);
- memcpy((void *)OMAP1510_SRAM_API_SUSPEND, omap1510_cpu_suspend,
- omap1510_cpu_suspend_sz);
- } else
-#endif
- if (cpu_is_omap16xx()) {
- memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND,
- omap1610_idle_loop_suspend,
- omap1610_idle_loop_suspend_sz);
- memcpy((void *)OMAP1610_SRAM_API_SUSPEND, omap1610_cpu_suspend,
- omap1610_cpu_suspend_sz);
- } else if (cpu_is_omap5912()) {
- memcpy((void *)OMAP5912_SRAM_IDLE_SUSPEND,
- omap1610_idle_loop_suspend,
- omap1610_idle_loop_suspend_sz);
- memcpy((void *)OMAP5912_SRAM_API_SUSPEND, omap1610_cpu_suspend,
- omap1610_cpu_suspend_sz);
+ omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
+ omap1510_idle_loop_suspend_sz);
+ omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
+ omap1510_cpu_suspend_sz);
+ } else if (cpu_is_omap16xx()) {
+ omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
+ omap1610_idle_loop_suspend_sz);
+ omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
+ omap1610_cpu_suspend_sz);
+ }
+
+ if (omap_sram_idle == NULL || omap_sram_suspend == NULL) {
+ printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
+ return -ENODEV;
}
+ pm_idle = omap_pm_idle;
+
setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
#if 0
/* --- BEGIN BOARD-DEPENDENT CODE --- */
--- /dev/null
+/*
+ * linux/arch/arm/mach-omap/sram.S
+ *
+ * Functions that need to be run in internal SRAM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/arch/io.h>
+#include <asm/arch/hardware.h>
+
+ .text
+
+/*
+ * Reprograms ULPD and CKCTL.
+ */
+ENTRY(sram_reprogram_clock)
+ stmfd sp!, {r0 - r12, lr} @ save registers on stack
+
+ mov r2, #IO_ADDRESS(DPLL_CTL) & 0xff000000
+ orr r2, r2, #IO_ADDRESS(DPLL_CTL) & 0x00ff0000
+ orr r2, r2, #IO_ADDRESS(DPLL_CTL) & 0x0000ff00
+
+ mov r3, #IO_ADDRESS(ARM_CKCTL) & 0xff000000
+ orr r3, r3, #IO_ADDRESS(ARM_CKCTL) & 0x00ff0000
+ orr r3, r3, #IO_ADDRESS(ARM_CKCTL) & 0x0000ff00
+
+ tst r0, #1 << 4 @ want lock mode?
+ beq newck @ nope
+ bic r0, r0, #1 << 4 @ else clear lock bit
+ strh r0, [r2] @ set dpll into bypass mode
+ orr r0, r0, #1 << 4 @ set lock bit again
+
+newck:
+ strh r1, [r3] @ write new ckctl value
+ strh r0, [r2] @ write new dpll value
+
+ mov r4, #0x0700 @ let the clocks settle
+ orr r4, r4, #0x00ff
+delay: sub r4, r4, #1
+ cmp r4, #0
+ bne delay
+
+lock: ldrh r4, [r2], #0 @ read back dpll value
+ tst r0, #1 << 4 @ want lock mode?
+ beq out @ nope
+ tst r4, #1 << 0 @ dpll rate locked?
+ beq lock @ try again
+
+out:
+ ldmfd sp!, {r0 - r12, pc} @ restore regs and return
+ENTRY(sram_reprogram_clock_sz)
+ .word . - sram_reprogram_clock
--- /dev/null
+/*
+ * linux/arch/arm/mach-omap/sram.c
+ *
+ * OMAP SRAM detection and management
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mach/map.h>
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+
+#include "sram.h"
+
+#define OMAP1_SRAM_BASE 0xd0000000
+#define OMAP1_SRAM_START 0x20000000
+
+static unsigned long omap_sram_base;
+static unsigned long omap_sram_size;
+static unsigned long omap_sram_ceil;
+
+/*
+ * The amount of SRAM depends on the core type:
+ * 730 = 200K, 1510 = 512K, 5912 = 256K, 1610 = 16K, 1710 = 16K
+ * Note that we cannot try to test for SRAM here because writes
+ * to secure SRAM will hang the system. Also the SRAM is not
+ * yet mapped at this point.
+ */
+void __init omap_detect_sram(void)
+{
+ omap_sram_base = OMAP1_SRAM_BASE;
+
+ if (cpu_is_omap730())
+ omap_sram_size = 0xc8;
+ else if (cpu_is_omap1510())
+ omap_sram_size = 0x200;
+ else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710())
+ omap_sram_size = 0x4000;
+ else if (cpu_is_omap1611())
+ omap_sram_size = 0x3e800;
+ else {
+ printk(KERN_ERR "Could not detect SRAM size\n");
+ omap_sram_size = 0xc8;
+ }
+
+ printk(KERN_INFO "SRAM size: 0x%lx\n", omap_sram_size);
+ omap_sram_ceil = omap_sram_base + omap_sram_size;
+}
+
+static struct map_desc omap_sram_io_desc[] __initdata = {
+ { OMAP1_SRAM_BASE, OMAP1_SRAM_START, 0, MT_DEVICE }
+};
+
+/*
+ * In order to use last 2kB of SRAM on 1611b, we must round the size
+ * up to multiple of PAGE_SIZE. We cannot use ioremap for SRAM, as
+ * clock init needs SRAM early.
+ */
+void __init omap_map_sram(void)
+{
+ if (omap_sram_size == 0)
+ return;
+
+ omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE;
+ omap_sram_io_desc[0].length *= PAGE_SIZE;
+ iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
+ memset((void *)omap_sram_base, 0, omap_sram_size);
+}
+
+static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl) = NULL;
+
+void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
+{
+ return _omap_sram_reprogram_clock(dpllctl, ckctl);
+}
+
+void * omap_sram_push(void * start, unsigned long size)
+{
+ if (size > (omap_sram_ceil - omap_sram_base)) {
+ printk(KERN_ERR "Not enough space in SRAM\n");
+ return NULL;
+ }
+ omap_sram_ceil -= size;
+ omap_sram_ceil &= ~0x3;
+ memcpy((void *)omap_sram_ceil, start, size);
+
+ return (void *)omap_sram_ceil;
+}
+
+void __init omap_sram_init(void)
+{
+ omap_detect_sram();
+ omap_map_sram();
+ _omap_sram_reprogram_clock = omap_sram_push(sram_reprogram_clock,
+ sram_reprogram_clock_sz);
+}
--- /dev/null
+/*
+ * linux/arch/arm/mach-omap/sram.h
+ *
+ * Interface for functions that need to be run in internal SRAM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_OMAP_SRAM_H
+#define __ARCH_ARM_OMAP_SRAM_H
+
+extern void * omap_sram_push(void * start, unsigned long size);
+extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
+
+/* Do not use these */
+extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl);
+extern unsigned long sram_reprogram_clock_sz;
+
+#endif
/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-#define OMAP1510_SRAM_BASE 0xD0000000
-#define OMAP1510_SRAM_SIZE (SZ_128K + SZ_64K)
-#define OMAP1510_SRAM_START 0x20000000
-
#define OMAP1510_DSP_BASE 0xE0000000
#define OMAP1510_DSP_SIZE 0x28000
#define OMAP1510_DSP_START 0xE0000000
#define OMAP1510_DSPREG_SIZE SZ_128K
#define OMAP1510_DSPREG_START 0xE1000000
-/*
- * ----------------------------------------------------------------------------
- * Memory used by power management
- * ----------------------------------------------------------------------------
- */
-
-#define OMAP1510_SRAM_IDLE_SUSPEND (OMAP1510_SRAM_BASE + OMAP1510_SRAM_SIZE - 0x200)
-#define OMAP1510_SRAM_API_SUSPEND (OMAP1510_SRAM_IDLE_SUSPEND + 0x100)
-
#endif /* __ASM_ARCH_OMAP1510_H */
/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-#define OMAP16XX_SRAM_BASE 0xD0000000
-#define OMAP1610_SRAM_SIZE (SZ_16K)
-#define OMAP5912_SRAM_SIZE 0x3E800
-#define OMAP16XX_SRAM_START 0x20000000
-
#define OMAP16XX_DSP_BASE 0xE0000000
#define OMAP16XX_DSP_SIZE 0x28000
#define OMAP16XX_DSP_START 0xE0000000
#define OMAP16XX_DSPREG_SIZE SZ_128K
#define OMAP16XX_DSPREG_START 0xE1000000
-/*
- * ----------------------------------------------------------------------------
- * Memory used by power management
- * ----------------------------------------------------------------------------
- */
-
-#define OMAP1610_SRAM_IDLE_SUSPEND (OMAP16XX_SRAM_BASE + OMAP1610_SRAM_SIZE - 0x200)
-#define OMAP1610_SRAM_API_SUSPEND (OMAP1610_SRAM_IDLE_SUSPEND + 0x100)
-#define OMAP5912_SRAM_IDLE_SUSPEND (OMAP16XX_SRAM_BASE + OMAP5912_SRAM_SIZE - 0x200)
-#define OMAP5912_SRAM_API_SUSPEND (OMAP5912_SRAM_IDLE_SUSPEND + 0x100)
-
/*
* ---------------------------------------------------------------------------
* Interrupts
/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-#define OMAP730_SRAM_BASE 0xD0000000
-#define OMAP730_SRAM_SIZE (SZ_128K + SZ_64K + SZ_8K)
-#define OMAP730_SRAM_START 0x20000000
-
#define OMAP730_DSP_BASE 0xE0000000
#define OMAP730_DSP_SIZE 0x50000
#define OMAP730_DSP_START 0xE0000000
#define OMAP1610_IDLECT3 0xfffece24
#define OMAP1610_IDLE_LOOP_REQUEST 0x0400
-#ifndef OMAP1510_SRAM_IDLE_SUSPEND
-#define OMAP1510_SRAM_IDLE_SUSPEND 0
-#endif
-#ifndef OMAP1610_SRAM_IDLE_SUSPEND
-#define OMAP1610_SRAM_IDLE_SUSPEND 0
-#endif
-#ifndef OMAP5912_SRAM_IDLE_SUSPEND
-#define OMAP5912_SRAM_IDLE_SUSPEND 0
-#endif
-
-#ifndef OMAP1510_SRAM_API_SUSPEND
-#define OMAP1510_SRAM_API_SUSPEND 0
-#endif
-#ifndef OMAP1610_SRAM_API_SUSPEND
-#define OMAP1610_SRAM_API_SUSPEND 0
-#endif
-#ifndef OMAP5912_SRAM_API_SUSPEND
-#define OMAP5912_SRAM_API_SUSPEND 0
-#endif
-
#if !defined(CONFIG_ARCH_OMAP1510) && \
!defined(CONFIG_ARCH_OMAP16XX)
#error "Power management for this processor not implemented yet"
#ifndef __ASSEMBLER__
extern void omap_pm_idle(void);
extern void omap_pm_suspend(void);
-extern int omap1510_cpu_suspend(unsigned short, unsigned short);
-extern int omap1610_cpu_suspend(unsigned short, unsigned short);
-extern int omap1510_idle_loop_suspend(void);
-extern int omap1610_idle_loop_suspend(void);
+extern void omap1510_cpu_suspend(unsigned short, unsigned short);
+extern void omap1610_cpu_suspend(unsigned short, unsigned short);
+extern void omap1510_idle_loop_suspend(void);
+extern void omap1610_idle_loop_suspend(void);
+
extern unsigned int omap1510_cpu_suspend_sz;
extern unsigned int omap1510_idle_loop_suspend_sz;
extern unsigned int omap1610_cpu_suspend_sz;