ARM: 6649/1: omap: use fncpy to copy the PM code functions to SRAM
authorJean Pihet <j-pihet@ti.com>
Wed, 2 Feb 2011 15:38:06 +0000 (16:38 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 4 Feb 2011 14:26:08 +0000 (14:26 +0000)
The new fncpy API is better suited* for copying some
code to SRAM at runtime. This patch changes the ad-hoc
code to the more generic fncpy API.

*: 1. fncpy ensures that the thumb mode bit is propagated,
   2. fncpy provides the security of type safety between the
     original function and the sram function pointer.

Tested OK on OMAP3 in low power modes (RET/OFF)
using omap2plus_defconfig with !CONFIG_THUMB2_KERNEL.
Compile tested on OMAP1/2 using omap1_defconfig.

Boot tested on OMAP1 & OMAP2
Tested OK with suspend/resume on OMAP2420/n810

Boots fine on osk5912 and n800

Signed-off-by: Jean Pihet <j-pihet@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Dave Martin <dave.martin@linaro.org>
Tested-by: Kevin Hilman <khilman@ti.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mach-omap1/pm.h
arch/arm/mach-omap1/sleep.S
arch/arm/mach-omap1/sram.S
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/sleep24xx.S
arch/arm/mach-omap2/sleep34xx.S
arch/arm/mach-omap2/sram242x.S
arch/arm/mach-omap2/sram243x.S
arch/arm/mach-omap2/sram34xx.S
arch/arm/plat-omap/include/plat/sram.h
arch/arm/plat-omap/sram.c

index 56a647986ae95c53b7288f7a1bbe2623c3c7bdb1..cd926dcb5e7fbd93f823639f5c2869073ea92bea 100644 (file)
@@ -123,9 +123,9 @@ extern void allow_idle_sleep(void);
 extern void omap1_pm_idle(void);
 extern void omap1_pm_suspend(void);
 
-extern void omap7xx_cpu_suspend(unsigned short, unsigned short);
-extern void omap1510_cpu_suspend(unsigned short, unsigned short);
-extern void omap1610_cpu_suspend(unsigned short, unsigned short);
+extern void omap7xx_cpu_suspend(unsigned long, unsigned long);
+extern void omap1510_cpu_suspend(unsigned long, unsigned long);
+extern void omap1610_cpu_suspend(unsigned long, unsigned long);
 extern void omap7xx_idle_loop_suspend(void);
 extern void omap1510_idle_loop_suspend(void);
 extern void omap1610_idle_loop_suspend(void);
index ef771ce8b030bf03b6b077c3b0f56dca24cc5a36..c875bdc902c556d1414fbfe8e33c8d932e203d1a 100644 (file)
@@ -58,6 +58,7 @@
  */
 
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+       .align  3
 ENTRY(omap7xx_cpu_suspend)
 
        @ save registers on stack
@@ -137,6 +138,7 @@ ENTRY(omap7xx_cpu_suspend_sz)
 #endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */
 
 #ifdef CONFIG_ARCH_OMAP15XX
+       .align  3
 ENTRY(omap1510_cpu_suspend)
 
        @ save registers on stack
@@ -211,6 +213,7 @@ ENTRY(omap1510_cpu_suspend_sz)
 #endif /* CONFIG_ARCH_OMAP15XX */
 
 #if defined(CONFIG_ARCH_OMAP16XX)
+       .align  3
 ENTRY(omap1610_cpu_suspend)
 
        @ save registers on stack
index 7724e520d07c5c648b982418177d18a8a54e3c65..692587d07ea5c8e2b2795872bc4f4c30166cb6b7 100644 (file)
@@ -18,6 +18,7 @@
 /*
  * Reprograms ULPD and CKCTL.
  */
+       .align  3
 ENTRY(omap1_sram_reprogram_clock)
        stmfd   sp!, {r0 - r12, lr}             @ save registers on stack
 
index 1c1b0ab5b97877695b00a71506d97850a679a410..39580e6060e884469b33d9743c92d987511ddd31 100644 (file)
@@ -92,7 +92,7 @@ extern void omap24xx_idle_loop_suspend(void);
 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 void save_secure_ram_context(u32 *addr);
+extern int save_secure_ram_context(u32 *addr);
 extern void omap3_save_scratchpad_contents(void);
 
 extern unsigned int omap24xx_idle_loop_suspend_sz;
index c7780cc8d919f3ef685abafca350b16f80e75d10..b5071a47ec395d2619f432eef9226b44a17a8bf7 100644 (file)
@@ -47,6 +47,7 @@
  * 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.
  */
+       .align  3
 ENTRY(omap24xx_idle_loop_suspend)
        stmfd   sp!, {r0, lr}           @ save registers on stack
        mov     r0, #0                  @ clear for mcr setup
@@ -82,6 +83,7 @@ ENTRY(omap24xx_idle_loop_suspend_sz)
  * The DLL load value is not kept in RETENTION or OFF. It needs to be restored
  * at wake
  */
+       .align  3
 ENTRY(omap24xx_cpu_suspend)
        stmfd   sp!, {r0 - r12, lr}     @ save registers on stack
        mov     r3, #0x0                @ clear for mcr call
index 98d8232808b8bf8becddc6a7d047d581c59fadf8..951a0be66cf7928062ee76ef58c53fc86419c239 100644 (file)
@@ -118,6 +118,7 @@ ENTRY(enable_omap3630_toggle_l2_on_restore)
 
        .text
 /* 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
        adr     r3, api_params          @ r3 points to parameters
@@ -169,6 +170,7 @@ ENTRY(save_secure_ram_context_sz)
  *   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
 
index 055310cc77decbbd2c454ec08d40dbc0323e643c..ff9b9dbcb30efa9e2a10707b7247646261b40524 100644 (file)
@@ -39,6 +39,7 @@
 
        .text
 
+       .align  3
 ENTRY(omap242x_sram_ddr_init)
        stmfd   sp!, {r0 - r12, lr}     @ save registers on stack
 
@@ -143,6 +144,7 @@ ENTRY(omap242x_sram_ddr_init_sz)
  * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
  * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
  */
+       .align  3
 ENTRY(omap242x_sram_reprogram_sdrc)
        stmfd   sp!, {r0 - r10, lr}     @ save registers on stack
        mov     r3, #0x0                @ clear for mrc call
@@ -238,6 +240,7 @@ ENTRY(omap242x_sram_reprogram_sdrc_sz)
 /*
  * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
  */
+       .align  3
 ENTRY(omap242x_sram_set_prcm)
        stmfd   sp!, {r0-r12, lr}       @ regs to stack
        adr     r4, pbegin              @ addr of preload start
index f9007580aea344c2f264ae55fde119b187f68b0f..76730209fa0e4ed29820d9608eea2bdab643c04c 100644 (file)
@@ -39,6 +39,7 @@
 
        .text
 
+       .align  3
 ENTRY(omap243x_sram_ddr_init)
        stmfd   sp!, {r0 - r12, lr}     @ save registers on stack
 
@@ -143,6 +144,7 @@ ENTRY(omap243x_sram_ddr_init_sz)
  * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
  * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
  */
+       .align  3
 ENTRY(omap243x_sram_reprogram_sdrc)
        stmfd   sp!, {r0 - r10, lr}     @ save registers on stack
        mov     r3, #0x0                @ clear for mrc call
@@ -238,6 +240,7 @@ ENTRY(omap243x_sram_reprogram_sdrc_sz)
 /*
  * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
  */
+       .align  3
 ENTRY(omap243x_sram_set_prcm)
        stmfd   sp!, {r0-r12, lr}       @ regs to stack
        adr     r4, pbegin              @ addr of preload start
index 7f893a29d5005052d60c0493c5a37960b71b0ce2..25011ca2145d6abba4d98e4cc441f061c2f9d91c 100644 (file)
  * since it will cause the ARM MMU to attempt to walk the page tables.
  * These crashes may be intermittent.
  */
+       .align  3
 ENTRY(omap3_sram_configure_core_dpll)
        stmfd   sp!, {r1-r12, lr}       @ store regs to stack
 
index 9967d5e855c76c810e3190fd93f81742993230d3..f500fc34d06595254fb8688cb7c633a7807c113d 100644 (file)
 #define __ARCH_ARM_OMAP_SRAM_H
 
 #ifndef __ASSEMBLY__
-extern void * omap_sram_push(void * start, unsigned long size);
+#include <asm/fncpy.h>
+
+extern void *omap_sram_push_address(unsigned long size);
+
+/* Macro to push a function to the internal SRAM, using the fncpy API */
+#define omap_sram_push(funcp, size) ({                         \
+       typeof(&(funcp)) _res = NULL;                           \
+       void *_sram_address = omap_sram_push_address(size);     \
+       if (_sram_address)                                      \
+               _res = fncpy(_sram_address, &(funcp), size);    \
+       _res;                                                   \
+})
+
 extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
 
 extern void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
index e26e50487d6010fc3ecace2585edb03429b3e990..68fcc7dc56e7a4b4acf849f392e3320211822ba9 100644 (file)
@@ -242,7 +242,14 @@ static void __init omap_map_sram(void)
               omap_sram_size - SRAM_BOOTLOADER_SZ);
 }
 
-void * omap_sram_push(void * start, unsigned long size)
+/*
+ * Memory allocator for SRAM: calculates the new ceiling address
+ * for pushing a function using the fncpy API.
+ *
+ * Note that fncpy requires the returned address to be aligned
+ * to an 8-byte boundary.
+ */
+void *omap_sram_push_address(unsigned long size)
 {
        if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
                printk(KERN_ERR "Not enough space in SRAM\n");
@@ -250,10 +257,7 @@ void * omap_sram_push(void * start, unsigned long size)
        }
 
        omap_sram_ceil -= size;
-       omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *));
-       memcpy((void *)omap_sram_ceil, start, size);
-       flush_icache_range((unsigned long)omap_sram_ceil,
-               (unsigned long)(omap_sram_ceil + size));
+       omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, FNCPY_ALIGN);
 
        return (void *)omap_sram_ceil;
 }