Commit b6338bdc8305b27688a7feb8689e4ccfd42f0292

Authored by Jean Pihet
Committed by Russell King
1 parent 5756e9dd0d

ARM: 6649/1: omap: use fncpy to copy the PM code functions to SRAM

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>

Showing 11 changed files with 41 additions and 10 deletions Side-by-side Diff

arch/arm/mach-omap1/pm.h
... ... @@ -123,9 +123,9 @@
123 123 extern void omap1_pm_idle(void);
124 124 extern void omap1_pm_suspend(void);
125 125  
126   -extern void omap7xx_cpu_suspend(unsigned short, unsigned short);
127   -extern void omap1510_cpu_suspend(unsigned short, unsigned short);
128   -extern void omap1610_cpu_suspend(unsigned short, unsigned short);
  126 +extern void omap7xx_cpu_suspend(unsigned long, unsigned long);
  127 +extern void omap1510_cpu_suspend(unsigned long, unsigned long);
  128 +extern void omap1610_cpu_suspend(unsigned long, unsigned long);
129 129 extern void omap7xx_idle_loop_suspend(void);
130 130 extern void omap1510_idle_loop_suspend(void);
131 131 extern void omap1610_idle_loop_suspend(void);
arch/arm/mach-omap1/sleep.S
... ... @@ -58,6 +58,7 @@
58 58 */
59 59  
60 60 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
  61 + .align 3
61 62 ENTRY(omap7xx_cpu_suspend)
62 63  
63 64 @ save registers on stack
... ... @@ -137,6 +138,7 @@
137 138 #endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */
138 139  
139 140 #ifdef CONFIG_ARCH_OMAP15XX
  141 + .align 3
140 142 ENTRY(omap1510_cpu_suspend)
141 143  
142 144 @ save registers on stack
... ... @@ -211,6 +213,7 @@
211 213 #endif /* CONFIG_ARCH_OMAP15XX */
212 214  
213 215 #if defined(CONFIG_ARCH_OMAP16XX)
  216 + .align 3
214 217 ENTRY(omap1610_cpu_suspend)
215 218  
216 219 @ save registers on stack
arch/arm/mach-omap1/sram.S
... ... @@ -18,6 +18,7 @@
18 18 /*
19 19 * Reprograms ULPD and CKCTL.
20 20 */
  21 + .align 3
21 22 ENTRY(omap1_sram_reprogram_clock)
22 23 stmfd sp!, {r0 - r12, lr} @ save registers on stack
23 24  
arch/arm/mach-omap2/pm.h
... ... @@ -92,7 +92,7 @@
92 92 extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
93 93 void __iomem *sdrc_power);
94 94 extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
95   -extern void save_secure_ram_context(u32 *addr);
  95 +extern int save_secure_ram_context(u32 *addr);
96 96 extern void omap3_save_scratchpad_contents(void);
97 97  
98 98 extern unsigned int omap24xx_idle_loop_suspend_sz;
arch/arm/mach-omap2/sleep24xx.S
... ... @@ -47,6 +47,7 @@
47 47 * Note: This code get's copied to internal SRAM at boot. When the OMAP
48 48 * wakes up it continues execution at the point it went to sleep.
49 49 */
  50 + .align 3
50 51 ENTRY(omap24xx_idle_loop_suspend)
51 52 stmfd sp!, {r0, lr} @ save registers on stack
52 53 mov r0, #0 @ clear for mcr setup
... ... @@ -82,6 +83,7 @@
82 83 * The DLL load value is not kept in RETENTION or OFF. It needs to be restored
83 84 * at wake
84 85 */
  86 + .align 3
85 87 ENTRY(omap24xx_cpu_suspend)
86 88 stmfd sp!, {r0 - r12, lr} @ save registers on stack
87 89 mov r3, #0x0 @ clear for mcr call
arch/arm/mach-omap2/sleep34xx.S
... ... @@ -118,6 +118,7 @@
118 118  
119 119 .text
120 120 /* Function to call rom code to save secure ram context */
  121 + .align 3
121 122 ENTRY(save_secure_ram_context)
122 123 stmfd sp!, {r1-r12, lr} @ save registers on stack
123 124 adr r3, api_params @ r3 points to parameters
... ... @@ -169,6 +170,7 @@
169 170 * depending on the low power mode (non-OFF vs OFF modes),
170 171 * cf. 'Resume path for xxx mode' comments.
171 172 */
  173 + .align 3
172 174 ENTRY(omap34xx_cpu_suspend)
173 175 stmfd sp!, {r0-r12, lr} @ save registers on stack
174 176  
arch/arm/mach-omap2/sram242x.S
... ... @@ -39,6 +39,7 @@
39 39  
40 40 .text
41 41  
  42 + .align 3
42 43 ENTRY(omap242x_sram_ddr_init)
43 44 stmfd sp!, {r0 - r12, lr} @ save registers on stack
44 45  
... ... @@ -143,6 +144,7 @@
143 144 * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
144 145 * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
145 146 */
  147 + .align 3
146 148 ENTRY(omap242x_sram_reprogram_sdrc)
147 149 stmfd sp!, {r0 - r10, lr} @ save registers on stack
148 150 mov r3, #0x0 @ clear for mrc call
... ... @@ -238,6 +240,7 @@
238 240 /*
239 241 * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
240 242 */
  243 + .align 3
241 244 ENTRY(omap242x_sram_set_prcm)
242 245 stmfd sp!, {r0-r12, lr} @ regs to stack
243 246 adr r4, pbegin @ addr of preload start
arch/arm/mach-omap2/sram243x.S
... ... @@ -39,6 +39,7 @@
39 39  
40 40 .text
41 41  
  42 + .align 3
42 43 ENTRY(omap243x_sram_ddr_init)
43 44 stmfd sp!, {r0 - r12, lr} @ save registers on stack
44 45  
... ... @@ -143,6 +144,7 @@
143 144 * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
144 145 * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
145 146 */
  147 + .align 3
146 148 ENTRY(omap243x_sram_reprogram_sdrc)
147 149 stmfd sp!, {r0 - r10, lr} @ save registers on stack
148 150 mov r3, #0x0 @ clear for mrc call
... ... @@ -238,6 +240,7 @@
238 240 /*
239 241 * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
240 242 */
  243 + .align 3
241 244 ENTRY(omap243x_sram_set_prcm)
242 245 stmfd sp!, {r0-r12, lr} @ regs to stack
243 246 adr r4, pbegin @ addr of preload start
arch/arm/mach-omap2/sram34xx.S
... ... @@ -111,6 +111,7 @@
111 111 * since it will cause the ARM MMU to attempt to walk the page tables.
112 112 * These crashes may be intermittent.
113 113 */
  114 + .align 3
114 115 ENTRY(omap3_sram_configure_core_dpll)
115 116 stmfd sp!, {r1-r12, lr} @ store regs to stack
116 117  
arch/arm/plat-omap/include/plat/sram.h
... ... @@ -12,7 +12,19 @@
12 12 #define __ARCH_ARM_OMAP_SRAM_H
13 13  
14 14 #ifndef __ASSEMBLY__
15   -extern void * omap_sram_push(void * start, unsigned long size);
  15 +#include <asm/fncpy.h>
  16 +
  17 +extern void *omap_sram_push_address(unsigned long size);
  18 +
  19 +/* Macro to push a function to the internal SRAM, using the fncpy API */
  20 +#define omap_sram_push(funcp, size) ({ \
  21 + typeof(&(funcp)) _res = NULL; \
  22 + void *_sram_address = omap_sram_push_address(size); \
  23 + if (_sram_address) \
  24 + _res = fncpy(_sram_address, &(funcp), size); \
  25 + _res; \
  26 +})
  27 +
16 28 extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
17 29  
18 30 extern void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
arch/arm/plat-omap/sram.c
... ... @@ -242,7 +242,14 @@
242 242 omap_sram_size - SRAM_BOOTLOADER_SZ);
243 243 }
244 244  
245   -void * omap_sram_push(void * start, unsigned long size)
  245 +/*
  246 + * Memory allocator for SRAM: calculates the new ceiling address
  247 + * for pushing a function using the fncpy API.
  248 + *
  249 + * Note that fncpy requires the returned address to be aligned
  250 + * to an 8-byte boundary.
  251 + */
  252 +void *omap_sram_push_address(unsigned long size)
246 253 {
247 254 if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
248 255 printk(KERN_ERR "Not enough space in SRAM\n");
... ... @@ -250,10 +257,7 @@
250 257 }
251 258  
252 259 omap_sram_ceil -= size;
253   - omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *));
254   - memcpy((void *)omap_sram_ceil, start, size);
255   - flush_icache_range((unsigned long)omap_sram_ceil,
256   - (unsigned long)(omap_sram_ceil + size));
  260 + omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, FNCPY_ALIGN);
257 261  
258 262 return (void *)omap_sram_ceil;
259 263 }