summaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-24 21:20:54 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-24 21:20:54 +0400
commitb6844e8f64920cdee620157252169ba63afb0c89 (patch)
tree339a447f4d1b6b2a447d10d24de227ddfbd4cc65 /arch/arm/mach-omap2
parent2f175074e6811974ee77ddeb026f4d21aa3eca4d (diff)
parent3ad55155b222f2a901405dea20ff7c68828ecd92 (diff)
downloadlinux-b6844e8f64920cdee620157252169ba63afb0c89.tar.xz
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (237 commits) ARM: 7004/1: fix traps.h compile warnings ARM: 6998/2: kernel: use proper memory barriers for bitops ARM: 6997/1: ep93xx: increase NR_BANKS to 16 for support of 128MB RAM ARM: Fix build errors caused by adding generic macros ARM: CPU hotplug: ensure we migrate all IRQs off a downed CPU ARM: CPU hotplug: pass in proper affinity mask on IRQ migration ARM: GIC: avoid routing interrupts to offline CPUs ARM: CPU hotplug: fix abuse of irqdesc->node ARM: 6981/2: mmci: adjust calculation of f_min ARM: 7000/1: LPAE: Use long long printk format for displaying the pud ARM: 6999/1: head, zImage: Always Enter the kernel in ARM state ARM: btc: avoid invalidating the branch target cache on kernel TLB maintanence ARM: ARM_DMA_ZONE_SIZE is no more ARM: mach-shark: move ARM_DMA_ZONE_SIZE to mdesc->dma_zone_size ARM: mach-sa1100: move ARM_DMA_ZONE_SIZE to mdesc->dma_zone_size ARM: mach-realview: move from ARM_DMA_ZONE_SIZE to mdesc->dma_zone_size ARM: mach-pxa: move from ARM_DMA_ZONE_SIZE to mdesc->dma_zone_size ARM: mach-ixp4xx: move from ARM_DMA_ZONE_SIZE to mdesc->dma_zone_size ARM: mach-h720x: move from ARM_DMA_ZONE_SIZE to mdesc->dma_zone_size ARM: mach-davinci: move from ARM_DMA_ZONE_SIZE to mdesc->dma_zone_size ...
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/control.c7
-rw-r--r--arch/arm/mach-omap2/control.h6
-rw-r--r--arch/arm/mach-omap2/include/mach/entry-macro.S3
-rw-r--r--arch/arm/mach-omap2/omap-smp.c8
-rw-r--r--arch/arm/mach-omap2/pm.h22
-rw-r--r--arch/arm/mach-omap2/pm34xx.c80
-rw-r--r--arch/arm/mach-omap2/sleep34xx.S518
7 files changed, 249 insertions, 395 deletions
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index da53ba3917ca..aab884fecc55 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -286,14 +286,15 @@ void omap3_save_scratchpad_contents(void)
scratchpad_contents.boot_config_ptr = 0x0;
if (cpu_is_omap3630())
scratchpad_contents.public_restore_ptr =
- virt_to_phys(get_omap3630_restore_pointer());
+ virt_to_phys(omap3_restore_3630);
else if (omap_rev() != OMAP3430_REV_ES3_0 &&
omap_rev() != OMAP3430_REV_ES3_1)
scratchpad_contents.public_restore_ptr =
- virt_to_phys(get_restore_pointer());
+ virt_to_phys(omap3_restore);
else
scratchpad_contents.public_restore_ptr =
- virt_to_phys(get_es3_restore_pointer());
+ virt_to_phys(omap3_restore_es3);
+
if (omap_type() == OMAP2_DEVICE_TYPE_GP)
scratchpad_contents.secure_ram_restore_ptr = 0x0;
else
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index a016c8b59e00..d4ef75d5a382 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -386,9 +386,9 @@ extern void omap4_ctrl_pad_writel(u32 val, u16 offset);
extern void omap3_save_scratchpad_contents(void);
extern void omap3_clear_scratchpad_contents(void);
-extern u32 *get_restore_pointer(void);
-extern u32 *get_es3_restore_pointer(void);
-extern u32 *get_omap3630_restore_pointer(void);
+extern void omap3_restore(void);
+extern void omap3_restore_es3(void);
+extern void omap3_restore_3630(void);
extern u32 omap3_arm_context[128];
extern void omap3_control_save_context(void);
extern void omap3_control_restore_context(void);
diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S
index a48690b90990..ceb8b7e593d7 100644
--- a/arch/arm/mach-omap2/include/mach/entry-macro.S
+++ b/arch/arm/mach-omap2/include/mach/entry-macro.S
@@ -165,6 +165,3 @@
#endif
#endif /* MULTI_OMAP2 */
-
- .macro irq_prio_table
- .endm
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index ecfe93c4b585..ce65e9329c7b 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -125,14 +125,6 @@ void __init smp_init_cpus(void)
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
- int i;
-
- /*
- * Initialise the present map, which describes the set of CPUs
- * actually populated at the present time.
- */
- for (i = 0; i < max_cpus; i++)
- set_cpu_present(i, true);
/*
* Initialise the SCU and wake up the secondary core using
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 45bcfce77352..04ee56646126 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -88,18 +88,28 @@ extern int pm_dbg_regset_init(int reg_set);
#define pm_dbg_regset_init(reg_set) do {} while (0);
#endif /* CONFIG_PM_DEBUG */
+/* 24xx */
extern void omap24xx_idle_loop_suspend(void);
+extern unsigned int omap24xx_idle_loop_suspend_sz;
extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
void __iomem *sdrc_power);
-extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
-extern int save_secure_ram_context(u32 *addr);
-extern void omap3_save_scratchpad_contents(void);
+extern unsigned int omap24xx_cpu_suspend_sz;
-extern unsigned int omap24xx_idle_loop_suspend_sz;
+/* 3xxx */
+extern void omap34xx_cpu_suspend(int save_state);
+
+/* omap3_do_wfi function pointer and size, for copy to SRAM */
+extern void omap3_do_wfi(void);
+extern unsigned int omap3_do_wfi_sz;
+/* ... and its pointer from SRAM after copy */
+extern void (*omap3_do_wfi_sram)(void);
+
+/* save_secure_ram_context function pointer and size, for copy to SRAM */
+extern int save_secure_ram_context(u32 *addr);
extern unsigned int save_secure_ram_context_sz;
-extern unsigned int omap24xx_cpu_suspend_sz;
-extern unsigned int omap34xx_cpu_suspend_sz;
+
+extern void omap3_save_scratchpad_contents(void);
#define PM_RTA_ERRATUM_i608 (1 << 0)
#define PM_SDRC_WAKEUP_ERRATUM_i583 (1 << 1)
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c155c9d1c82c..b77d82665abb 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -31,6 +31,8 @@
#include <linux/console.h>
#include <trace/events/power.h>
+#include <asm/suspend.h>
+
#include <plat/sram.h>
#include "clockdomain.h"
#include "powerdomain.h"
@@ -40,8 +42,6 @@
#include <plat/gpmc.h>
#include <plat/dma.h>
-#include <asm/tlbflush.h>
-
#include "cm2xxx_3xxx.h"
#include "cm-regbits-34xx.h"
#include "prm-regbits-34xx.h"
@@ -64,11 +64,6 @@ static inline bool is_suspending(void)
}
#endif
-/* Scratchpad offsets */
-#define OMAP343X_TABLE_ADDRESS_OFFSET 0xc4
-#define OMAP343X_TABLE_VALUE_OFFSET 0xc0
-#define OMAP343X_CONTROL_REG_VALUE_OFFSET 0xc8
-
/* pm34xx errata defined in pm.h */
u16 pm34xx_errata;
@@ -83,9 +78,8 @@ struct power_state {
static LIST_HEAD(pwrst_list);
-static void (*_omap_sram_idle)(u32 *addr, int save_state);
-
static int (*_omap_save_secure_sram)(u32 *addr);
+void (*omap3_do_wfi_sram)(void);
static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
static struct powerdomain *core_pwrdm, *per_pwrdm;
@@ -312,28 +306,25 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
return IRQ_HANDLED;
}
-/* Function to restore the table entry that was modified for enabling MMU */
-static void restore_table_entry(void)
+static void omap34xx_save_context(u32 *save)
{
- void __iomem *scratchpad_address;
- u32 previous_value, control_reg_value;
- u32 *address;
+ u32 val;
- scratchpad_address = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD);
+ /* Read Auxiliary Control Register */
+ asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (val));
+ *save++ = 1;
+ *save++ = val;
- /* Get address of entry that was modified */
- address = (u32 *)__raw_readl(scratchpad_address +
- OMAP343X_TABLE_ADDRESS_OFFSET);
- /* Get the previous value which needs to be restored */
- previous_value = __raw_readl(scratchpad_address +
- OMAP343X_TABLE_VALUE_OFFSET);
- address = __va(address);
- *address = previous_value;
- flush_tlb_all();
- control_reg_value = __raw_readl(scratchpad_address
- + OMAP343X_CONTROL_REG_VALUE_OFFSET);
- /* This will enable caches and prediction */
- set_cr(control_reg_value);
+ /* Read L2 AUX ctrl register */
+ asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
+ *save++ = 1;
+ *save++ = val;
+}
+
+static int omap34xx_do_sram_idle(unsigned long save_state)
+{
+ omap34xx_cpu_suspend(save_state);
+ return 0;
}
void omap_sram_idle(void)
@@ -352,9 +343,6 @@ void omap_sram_idle(void)
int core_prev_state, per_prev_state;
u32 sdrc_pwr = 0;
- if (!_omap_sram_idle)
- return;
-
pwrdm_clear_all_prev_pwrst(mpu_pwrdm);
pwrdm_clear_all_prev_pwrst(neon_pwrdm);
pwrdm_clear_all_prev_pwrst(core_pwrdm);
@@ -432,12 +420,16 @@ void omap_sram_idle(void)
sdrc_pwr = sdrc_read_reg(SDRC_POWER);
/*
- * omap3_arm_context is the location where ARM registers
- * get saved. The restore path then reads from this
- * location and restores them back.
+ * omap3_arm_context is the location where some ARM context
+ * get saved. The rest is placed on the stack, and restored
+ * from there before resuming.
*/
- _omap_sram_idle(omap3_arm_context, save_state);
- cpu_init();
+ if (save_state)
+ omap34xx_save_context(omap3_arm_context);
+ if (save_state == 1 || save_state == 3)
+ cpu_suspend(save_state, omap34xx_do_sram_idle);
+ else
+ omap34xx_do_sram_idle(save_state);
/* Restore normal SDRC POWER settings */
if (omap_rev() >= OMAP3430_REV_ES3_0 &&
@@ -445,10 +437,6 @@ void omap_sram_idle(void)
core_next_state == PWRDM_POWER_OFF)
sdrc_write_reg(sdrc_pwr, SDRC_POWER);
- /* Restore table entry modified during MMU restoration */
- if (pwrdm_read_prev_pwrst(mpu_pwrdm) == PWRDM_POWER_OFF)
- restore_table_entry();
-
/* CORE */
if (core_next_state < PWRDM_POWER_ON) {
core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);
@@ -852,10 +840,17 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
return 0;
}
+/*
+ * Push functions to SRAM
+ *
+ * The minimum set of functions is pushed to SRAM for execution:
+ * - omap3_do_wfi for erratum i581 WA,
+ * - save_secure_ram_context for security extensions.
+ */
void omap_push_sram_idle(void)
{
- _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
- omap34xx_cpu_suspend_sz);
+ omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
+
if (omap_type() != OMAP2_DEVICE_TYPE_GP)
_omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
save_secure_ram_context_sz);
@@ -920,7 +915,6 @@ static int __init omap3_pm_init(void)
per_clkdm = clkdm_lookup("per_clkdm");
core_clkdm = clkdm_lookup("core_clkdm");
- omap_push_sram_idle();
#ifdef CONFIG_SUSPEND
suspend_set_ops(&omap_pm_ops);
#endif /* CONFIG_SUSPEND */
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 63f10669571a..f2ea1bd1c691 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -74,46 +74,6 @@
* API functions
*/
-/*
- * The "get_*restore_pointer" functions are used to provide a
- * physical restore address where the ROM code jumps while waking
- * up from MPU OFF/OSWR state.
- * The restore pointer is stored into the scratchpad.
- */
-
- .text
-/* Function call to get the restore pointer for resume from OFF */
-ENTRY(get_restore_pointer)
- stmfd sp!, {lr} @ save registers on stack
- adr r0, restore
- ldmfd sp!, {pc} @ restore regs and return
-ENDPROC(get_restore_pointer)
- .align
-ENTRY(get_restore_pointer_sz)
- .word . - get_restore_pointer
-
- .text
-/* Function call to get the restore pointer for 3630 resume from OFF */
-ENTRY(get_omap3630_restore_pointer)
- stmfd sp!, {lr} @ save registers on stack
- adr r0, restore_3630
- ldmfd sp!, {pc} @ restore regs and return
-ENDPROC(get_omap3630_restore_pointer)
- .align
-ENTRY(get_omap3630_restore_pointer_sz)
- .word . - get_omap3630_restore_pointer
-
- .text
-/* Function call to get the restore pointer for ES3 to resume from OFF */
-ENTRY(get_es3_restore_pointer)
- stmfd sp!, {lr} @ save registers on stack
- adr r0, restore_es3
- ldmfd sp!, {pc} @ restore regs and return
-ENDPROC(get_es3_restore_pointer)
- .align
-ENTRY(get_es3_restore_pointer_sz)
- .word . - get_es3_restore_pointer
-
.text
/*
* L2 cache needs to be toggled for stable OFF mode functionality on 3630.
@@ -133,7 +93,7 @@ ENDPROC(enable_omap3630_toggle_l2_on_restore)
/* Function to call rom code to save secure ram context */
.align 3
ENTRY(save_secure_ram_context)
- stmfd sp!, {r1-r12, lr} @ save registers on stack
+ stmfd sp!, {r4 - r11, lr} @ save registers on stack
adr r3, api_params @ r3 points to parameters
str r0, [r3,#0x4] @ r0 has sdram address
ldr r12, high_mask
@@ -152,7 +112,7 @@ ENTRY(save_secure_ram_context)
nop
nop
nop
- ldmfd sp!, {r1-r12, pc}
+ ldmfd sp!, {r4 - r11, pc}
.align
sram_phy_addr_mask:
.word SRAM_BASE_P
@@ -179,69 +139,38 @@ ENTRY(save_secure_ram_context_sz)
*
*
* Notes:
- * - this code gets copied to internal SRAM at boot and after wake-up
- * from OFF mode. The execution pointer in SRAM is _omap_sram_idle.
+ * - only the minimum set of functions gets copied to internal SRAM at boot
+ * and after wake-up from OFF mode, cf. omap_push_sram_idle. The function
+ * pointers in SDRAM or SRAM are called depending on the desired low power
+ * target state.
* - when the OMAP wakes up it continues at different execution points
* depending on the low power mode (non-OFF vs OFF modes),
* cf. 'Resume path for xxx mode' comments.
*/
.align 3
ENTRY(omap34xx_cpu_suspend)
- stmfd sp!, {r0-r12, lr} @ save registers on stack
+ stmfd sp!, {r4 - r11, lr} @ save registers on stack
/*
- * r0 contains CPU context save/restore pointer in sdram
- * r1 contains information about saving context:
+ * r0 contains information about saving context:
* 0 - No context lost
* 1 - Only L1 and logic lost
* 2 - Only L2 lost (Even L1 is retained we clean it along with L2)
* 3 - Both L1 and L2 lost and logic lost
*/
- /* Directly jump to WFI is the context save is not required */
- cmp r1, #0x0
- beq omap3_do_wfi
+ /*
+ * For OFF mode: save context and jump to WFI in SDRAM (omap3_do_wfi)
+ * For non-OFF modes: jump to the WFI code in SRAM (omap3_do_wfi_sram)
+ */
+ ldr r4, omap3_do_wfi_sram_addr
+ ldr r5, [r4]
+ cmp r0, #0x0 @ If no context save required,
+ bxeq r5 @ jump to the WFI code in SRAM
+
/* Otherwise fall through to the save context code */
save_context_wfi:
- mov r8, r0 @ Store SDRAM address in r8
- mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register
- mov r4, #0x1 @ Number of parameters for restore call
- stmia r8!, {r4-r5} @ Push parameters for restore call
- mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register
- stmia r8!, {r4-r5} @ Push parameters for restore call
-
- /* Check what that target sleep state is from r1 */
- cmp r1, #0x2 @ Only L2 lost, no need to save context
- beq clean_caches
-
-l1_logic_lost:
- mov r4, sp @ Store sp
- mrs r5, spsr @ Store spsr
- mov r6, lr @ Store lr
- stmia r8!, {r4-r6}
-
- mrc p15, 0, r4, c1, c0, 2 @ Coprocessor access control register
- mrc p15, 0, r5, c2, c0, 0 @ TTBR0
- mrc p15, 0, r6, c2, c0, 1 @ TTBR1
- mrc p15, 0, r7, c2, c0, 2 @ TTBCR
- stmia r8!, {r4-r7}
-
- mrc p15, 0, r4, c3, c0, 0 @ Domain access Control Register
- mrc p15, 0, r5, c10, c2, 0 @ PRRR
- mrc p15, 0, r6, c10, c2, 1 @ NMRR
- stmia r8!,{r4-r6}
-
- mrc p15, 0, r4, c13, c0, 1 @ Context ID
- mrc p15, 0, r5, c13, c0, 2 @ User r/w thread and process ID
- mrc p15, 0, r6, c12, c0, 0 @ Secure or NS vector base address
- mrs r7, cpsr @ Store current cpsr
- stmia r8!, {r4-r7}
-
- mrc p15, 0, r4, c1, c0, 0 @ save control register
- stmia r8!, {r4}
-
-clean_caches:
/*
* jump out to kernel flush routine
* - reuse that code is better
@@ -284,7 +213,32 @@ clean_caches:
THUMB( nop )
.arm
-omap3_do_wfi:
+ b omap3_do_wfi
+
+/*
+ * Local variables
+ */
+omap3_do_wfi_sram_addr:
+ .word omap3_do_wfi_sram
+kernel_flush:
+ .word v7_flush_dcache_all
+
+/* ===================================
+ * == WFI instruction => Enter idle ==
+ * ===================================
+ */
+
+/*
+ * Do WFI instruction
+ * Includes the resume path for non-OFF modes
+ *
+ * This code gets copied to internal SRAM and is accessible
+ * from both SDRAM and SRAM:
+ * - executed from SRAM for non-off modes (omap3_do_wfi_sram),
+ * - executed from SDRAM for OFF mode (omap3_do_wfi).
+ */
+ .align 3
+ENTRY(omap3_do_wfi)
ldr r4, sdrc_power @ read the SDRC_POWER register
ldr r5, [r4] @ read the contents of SDRC_POWER
orr r5, r5, #0x40 @ enable self refresh on idle req
@@ -316,8 +270,86 @@ omap3_do_wfi:
nop
nop
nop
- bl wait_sdrc_ok
+/*
+ * This function implements the erratum ID i581 WA:
+ * SDRC state restore before accessing the SDRAM
+ *
+ * Only used at return from non-OFF mode. For OFF
+ * mode the ROM code configures the SDRC and
+ * the DPLL before calling the restore code directly
+ * from DDR.
+ */
+
+/* Make sure SDRC accesses are ok */
+wait_sdrc_ok:
+
+/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
+ ldr r4, cm_idlest_ckgen
+wait_dpll3_lock:
+ ldr r5, [r4]
+ tst r5, #1
+ beq wait_dpll3_lock
+
+ ldr r4, cm_idlest1_core
+wait_sdrc_ready:
+ ldr r5, [r4]
+ tst r5, #0x2
+ bne wait_sdrc_ready
+ /* allow DLL powerdown upon hw idle req */
+ ldr r4, sdrc_power
+ ldr r5, [r4]
+ bic r5, r5, #0x40
+ str r5, [r4]
+
+/*
+ * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
+ * base instead.
+ * Be careful not to clobber r7 when maintaing this code.
+ */
+
+is_dll_in_lock_mode:
+ /* Is dll in lock mode? */
+ ldr r4, sdrc_dlla_ctrl
+ ldr r5, [r4]
+ tst r5, #0x4
+ bne exit_nonoff_modes @ Return if locked
+ /* wait till dll locks */
+ adr r7, kick_counter
+wait_dll_lock_timed:
+ ldr r4, wait_dll_lock_counter
+ add r4, r4, #1
+ str r4, [r7, #wait_dll_lock_counter - kick_counter]
+ ldr r4, sdrc_dlla_status
+ /* Wait 20uS for lock */
+ mov r6, #8
+wait_dll_lock:
+ subs r6, r6, #0x1
+ beq kick_dll
+ ldr r5, [r4]
+ and r5, r5, #0x4
+ cmp r5, #0x4
+ bne wait_dll_lock
+ b exit_nonoff_modes @ Return when locked
+
+ /* disable/reenable DLL if not locked */
+kick_dll:
+ ldr r4, sdrc_dlla_ctrl
+ ldr r5, [r4]
+ mov r6, r5
+ bic r6, #(1<<3) @ disable dll
+ str r6, [r4]
+ dsb
+ orr r6, r6, #(1<<3) @ enable dll
+ str r6, [r4]
+ dsb
+ ldr r4, kick_counter
+ add r4, r4, #1
+ str r4, [r7] @ kick_counter
+ b wait_dll_lock_timed
+
+exit_nonoff_modes:
+ /* Re-enable C-bit if needed */
mrc p15, 0, r0, c1, c0, 0
tst r0, #(1 << 2) @ Check C bit enabled?
orreq r0, r0, #(1 << 2) @ Enable the C bit if cleared
@@ -329,7 +361,32 @@ omap3_do_wfi:
* == Exit point from non-OFF modes ==
* ===================================
*/
- ldmfd sp!, {r0-r12, pc} @ restore regs and return
+ ldmfd sp!, {r4 - r11, pc} @ restore regs and return
+
+/*
+ * Local variables
+ */
+sdrc_power:
+ .word SDRC_POWER_V
+cm_idlest1_core:
+ .word CM_IDLEST1_CORE_V
+cm_idlest_ckgen:
+ .word CM_IDLEST_CKGEN_V
+sdrc_dlla_status:
+ .word SDRC_DLLA_STATUS_V
+sdrc_dlla_ctrl:
+ .word SDRC_DLLA_CTRL_V
+ /*
+ * When exporting to userspace while the counters are in SRAM,
+ * these 2 words need to be at the end to facilitate retrival!
+ */
+kick_counter:
+ .word 0
+wait_dll_lock_counter:
+ .word 0
+
+ENTRY(omap3_do_wfi_sz)
+ .word . - omap3_do_wfi
/*
@@ -346,13 +403,17 @@ omap3_do_wfi:
* restore_es3: applies to 34xx >= ES3.0
* restore_3630: applies to 36xx
* restore: common code for 3xxx
+ *
+ * Note: when back from CORE and MPU OFF mode we are running
+ * from SDRAM, without MMU, without the caches and prediction.
+ * Also the SRAM content has been cleared.
*/
-restore_es3:
+ENTRY(omap3_restore_es3)
ldr r5, pm_prepwstst_core_p
ldr r4, [r5]
and r4, r4, #0x3
cmp r4, #0x0 @ Check if previous power state of CORE is OFF
- bne restore
+ bne omap3_restore @ Fall through to OMAP3 common code
adr r0, es3_sdrc_fix
ldr r1, sram_base
ldr r2, es3_sdrc_fix_sz
@@ -364,35 +425,32 @@ copy_to_sram:
bne copy_to_sram
ldr r1, sram_base
blx r1
- b restore
+ b omap3_restore @ Fall through to OMAP3 common code
+ENDPROC(omap3_restore_es3)
-restore_3630:
+ENTRY(omap3_restore_3630)
ldr r1, pm_prepwstst_core_p
ldr r2, [r1]
and r2, r2, #0x3
cmp r2, #0x0 @ Check if previous power state of CORE is OFF
- bne restore
+ bne omap3_restore @ Fall through to OMAP3 common code
/* Disable RTA before giving control */
ldr r1, control_mem_rta
mov r2, #OMAP36XX_RTA_DISABLE
str r2, [r1]
+ENDPROC(omap3_restore_3630)
/* Fall through to common code for the remaining logic */
-restore:
+ENTRY(omap3_restore)
/*
- * Check what was the reason for mpu reset and store the reason in r9:
- * 0 - No context lost
- * 1 - Only L1 and logic lost
- * 2 - Only L2 lost - In this case, we wont be here
- * 3 - Both L1 and L2 lost
+ * Read the pwstctrl register to check the reason for mpu reset.
+ * This tells us what was lost.
*/
ldr r1, pm_pwstctrl_mpu
ldr r2, [r1]
and r2, r2, #0x3
cmp r2, #0x0 @ Check if target power state was OFF or RET
- moveq r9, #0x3 @ MPU OFF => L1 and L2 lost
- movne r9, #0x1 @ Only L1 and L2 lost => avoid L2 invalidation
bne logic_l1_restore
ldr r0, l2dis_3630
@@ -471,115 +529,39 @@ logic_l1_restore:
orr r1, r1, #2 @ re-enable L2 cache
mcr p15, 0, r1, c1, c0, 1
skipl2reen:
- mov r1, #0
- /*
- * Invalidate all instruction caches to PoU
- * and flush branch target cache
- */
- mcr p15, 0, r1, c7, c5, 0
- ldr r4, scratchpad_base
- ldr r3, [r4,#0xBC]
- adds r3, r3, #16
-
- ldmia r3!, {r4-r6}
- mov sp, r4 @ Restore sp
- msr spsr_cxsf, r5 @ Restore spsr
- mov lr, r6 @ Restore lr
-
- ldmia r3!, {r4-r7}
- mcr p15, 0, r4, c1, c0, 2 @ Coprocessor access Control Register
- mcr p15, 0, r5, c2, c0, 0 @ TTBR0
- mcr p15, 0, r6, c2, c0, 1 @ TTBR1
- mcr p15, 0, r7, c2, c0, 2 @ TTBCR
-
- ldmia r3!,{r4-r6}
- mcr p15, 0, r4, c3, c0, 0 @ Domain access Control Register
- mcr p15, 0, r5, c10, c2, 0 @ PRRR
- mcr p15, 0, r6, c10, c2, 1 @ NMRR
-
-
- ldmia r3!,{r4-r7}
- mcr p15, 0, r4, c13, c0, 1 @ Context ID
- mcr p15, 0, r5, c13, c0, 2 @ User r/w thread and process ID
- mrc p15, 0, r6, c12, c0, 0 @ Secure or NS vector base address
- msr cpsr, r7 @ store cpsr
-
- /* Enabling MMU here */
- mrc p15, 0, r7, c2, c0, 2 @ Read TTBRControl
- /* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1 */
- and r7, #0x7
- cmp r7, #0x0
- beq usettbr0
-ttbr_error:
- /*
- * More work needs to be done to support N[0:2] value other than 0
- * So looping here so that the error can be detected
- */
- b ttbr_error
-usettbr0:
- mrc p15, 0, r2, c2, c0, 0
- ldr r5, ttbrbit_mask
- and r2, r5
- mov r4, pc
- ldr r5, table_index_mask
- and r4, r5 @ r4 = 31 to 20 bits of pc
- /* Extract the value to be written to table entry */
- ldr r1, table_entry
- /* r1 has the value to be written to table entry*/
- add r1, r1, r4
- /* Getting the address of table entry to modify */
- lsr r4, #18
- /* r2 has the location which needs to be modified */
- add r2, r4
- /* Storing previous entry of location being modified */
- ldr r5, scratchpad_base
- ldr r4, [r2]
- str r4, [r5, #0xC0]
- /* Modify the table entry */
- str r1, [r2]
- /*
- * Storing address of entry being modified
- * - will be restored after enabling MMU
- */
- ldr r5, scratchpad_base
- str r2, [r5, #0xC4]
-
- mov r0, #0
- mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer
- mcr p15, 0, r0, c7, c5, 6 @ Invalidate branch predictor array
- mcr p15, 0, r0, c8, c5, 0 @ Invalidate instruction TLB
- mcr p15, 0, r0, c8, c6, 0 @ Invalidate data TLB
- /*
- * Restore control register. This enables the MMU.
- * The caches and prediction are not enabled here, they
- * will be enabled after restoring the MMU table entry.
- */
- ldmia r3!, {r4}
- /* Store previous value of control register in scratchpad */
- str r4, [r5, #0xC8]
- ldr r2, cache_pred_disable_mask
- and r4, r2
- mcr p15, 0, r4, c1, c0, 0
- dsb
- isb
- ldr r0, =restoremmu_on
- bx r0
+ /* Now branch to the common CPU resume function */
+ b cpu_resume
+ENDPROC(omap3_restore)
+
+ .ltorg
/*
- * ==============================
- * == Exit point from OFF mode ==
- * ==============================
+ * Local variables
*/
-restoremmu_on:
- ldmfd sp!, {r0-r12, pc} @ restore regs and return
-
+pm_prepwstst_core_p:
+ .word PM_PREPWSTST_CORE_P
+pm_pwstctrl_mpu:
+ .word PM_PWSTCTRL_MPU_P
+scratchpad_base:
+ .word SCRATCHPAD_BASE_P
+sram_base:
+ .word SRAM_BASE_P + 0x8000
+control_stat:
+ .word CONTROL_STAT
+control_mem_rta:
+ .word CONTROL_MEM_RTA_CTRL
+l2dis_3630:
+ .word 0
/*
* Internal functions
*/
-/* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */
+/*
+ * This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0
+ * Copied to and run from SRAM in order to reconfigure the SDRC parameters.
+ */
.text
.align 3
ENTRY(es3_sdrc_fix)
@@ -609,6 +591,9 @@ ENTRY(es3_sdrc_fix)
str r5, [r4] @ kick off refreshes
bx lr
+/*
+ * Local variables
+ */
.align
sdrc_syscfg:
.word SDRC_SYSCONFIG_P
@@ -627,128 +612,3 @@ sdrc_manual_1:
ENDPROC(es3_sdrc_fix)
ENTRY(es3_sdrc_fix_sz)
.word . - es3_sdrc_fix
-
-/*
- * This function implements the erratum ID i581 WA:
- * SDRC state restore before accessing the SDRAM
- *
- * Only used at return from non-OFF mode. For OFF
- * mode the ROM code configures the SDRC and
- * the DPLL before calling the restore code directly
- * from DDR.
- */
-
-/* Make sure SDRC accesses are ok */
-wait_sdrc_ok:
-
-/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
- ldr r4, cm_idlest_ckgen
-wait_dpll3_lock:
- ldr r5, [r4]
- tst r5, #1
- beq wait_dpll3_lock
-
- ldr r4, cm_idlest1_core
-wait_sdrc_ready:
- ldr r5, [r4]
- tst r5, #0x2
- bne wait_sdrc_ready
- /* allow DLL powerdown upon hw idle req */
- ldr r4, sdrc_power
- ldr r5, [r4]
- bic r5, r5, #0x40
- str r5, [r4]
-
-/*
- * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
- * base instead.
- * Be careful not to clobber r7 when maintaing this code.
- */
-
-is_dll_in_lock_mode:
- /* Is dll in lock mode? */
- ldr r4, sdrc_dlla_ctrl
- ldr r5, [r4]
- tst r5, #0x4
- bxne lr @ Return if locked
- /* wait till dll locks */
- adr r7, kick_counter
-wait_dll_lock_timed:
- ldr r4, wait_dll_lock_counter
- add r4, r4, #1
- str r4, [r7, #wait_dll_lock_counter - kick_counter]
- ldr r4, sdrc_dlla_status
- /* Wait 20uS for lock */
- mov r6, #8
-wait_dll_lock:
- subs r6, r6, #0x1
- beq kick_dll
- ldr r5, [r4]
- and r5, r5, #0x4
- cmp r5, #0x4
- bne wait_dll_lock
- bx lr @ Return when locked
-
- /* disable/reenable DLL if not locked */
-kick_dll:
- ldr r4, sdrc_dlla_ctrl
- ldr r5, [r4]
- mov r6, r5
- bic r6, #(1<<3) @ disable dll
- str r6, [r4]
- dsb
- orr r6, r6, #(1<<3) @ enable dll
- str r6, [r4]
- dsb
- ldr r4, kick_counter
- add r4, r4, #1
- str r4, [r7] @ kick_counter
- b wait_dll_lock_timed
-
- .align
-cm_idlest1_core:
- .word CM_IDLEST1_CORE_V
-cm_idlest_ckgen:
- .word CM_IDLEST_CKGEN_V
-sdrc_dlla_status:
- .word SDRC_DLLA_STATUS_V
-sdrc_dlla_ctrl:
- .word SDRC_DLLA_CTRL_V
-pm_prepwstst_core_p:
- .word PM_PREPWSTST_CORE_P
-pm_pwstctrl_mpu:
- .word PM_PWSTCTRL_MPU_P
-scratchpad_base:
- .word SCRATCHPAD_BASE_P
-sram_base:
- .word SRAM_BASE_P + 0x8000
-sdrc_power:
- .word SDRC_POWER_V
-ttbrbit_mask:
- .word 0xFFFFC000
-table_index_mask:
- .word 0xFFF00000
-table_entry:
- .word 0x00000C02
-cache_pred_disable_mask:
- .word 0xFFFFE7FB
-control_stat:
- .word CONTROL_STAT
-control_mem_rta:
- .word CONTROL_MEM_RTA_CTRL
-kernel_flush:
- .word v7_flush_dcache_all
-l2dis_3630:
- .word 0
- /*
- * When exporting to userspace while the counters are in SRAM,
- * these 2 words need to be at the end to facilitate retrival!
- */
-kick_counter:
- .word 0
-wait_dll_lock_counter:
- .word 0
-ENDPROC(omap34xx_cpu_suspend)
-
-ENTRY(omap34xx_cpu_suspend_sz)
- .word . - omap34xx_cpu_suspend