aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-at91/pm.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-22 12:04:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-22 12:04:39 -0400
commitd0440c59f52d31aa7f74ba8e35cc22ee96acea84 (patch)
tree199470b64cdc30e9f0f7ecd5286ff7cc2e0a969d /arch/arm/mach-at91/pm.c
parent38eb1dbb0d7d190bdfe2ea824e94dab19e32737f (diff)
parentc4c14f393fe4991a423c21516511ff1011140143 (diff)
Merge tag 'armsoc-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC cleanups from Olof Johansson: "We've got a fairly large cleanup branch this time. The bulk of this is removal of non-DT platforms of several flavors: - Atmel at91 platforms go full-DT, with removal of remaining board-file based support - OMAP removes legacy board files for three more platforms - removal of non-DT mach-msm, newer Qualcomm platforms now live in mach-qcom - Freescale i.MX25 also removes non-DT platform support" Most of the rest of the changes here are fallout from the above, i.e. for example removal of drivers that now lack platforms, etc. * tag 'armsoc-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (58 commits) mmc: Remove msm_sdcc driver gpio: Remove gpio-msm-v1 driver ARM: Remove mach-msm and associated ARM architecture code ARM: shmobile: cpuidle: Remove the pointless default driver ARM: davinci: dm646x: Add interrupt resource for McASPs ARM: davinci: irqs: Correct McASP1 TX interrupt definition for DM646x ARM: davinci: dm646x: Clean up the McASP DMA resources ARM: davinci: devices-da8xx: Add support for McASP2 on da830 ARM: davinci: devices-da8xx: Clean up and correct the McASP device creation ARM: davinci: devices-da8xx: Add interrupt resource to McASP structs ARM: davinci: devices-da8xx: Add resource name for the McASP DMA request ARM: OMAP2+: Remove legacy support for omap3 TouchBook ARM: OMAP3: Remove legacy support for devkit8000 ARM: OMAP3: Remove legacy support for EMA-Tech Stalker board ARM: shmobile: Consolidate the pm code for R-Car Gen2 ARM: shmobile: r8a7791: Correct SYSCIER value ARM: shmobile: r8a7790: Correct SYSCIER value ARM: at91: remove old setup ARM: at91: sama5d4: remove useless map_io ARM: at91: sama5 use SoC detection infrastructure ...
Diffstat (limited to 'arch/arm/mach-at91/pm.c')
-rw-r--r--arch/arm/mach-at91/pm.c139
1 files changed, 67 insertions, 72 deletions
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index aa4116e9452f..ac947cdd506c 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -29,6 +29,8 @@
29#include <linux/atomic.h> 29#include <linux/atomic.h>
30#include <asm/mach/time.h> 30#include <asm/mach/time.h>
31#include <asm/mach/irq.h> 31#include <asm/mach/irq.h>
32#include <asm/fncpy.h>
33#include <asm/cacheflush.h>
32 34
33#include <mach/cpu.h> 35#include <mach/cpu.h>
34#include <mach/hardware.h> 36#include <mach/hardware.h>
@@ -41,7 +43,6 @@ static struct {
41 int memctrl; 43 int memctrl;
42} at91_pm_data; 44} at91_pm_data;
43 45
44static void (*at91_pm_standby)(void);
45void __iomem *at91_ramc_base[2]; 46void __iomem *at91_ramc_base[2];
46 47
47static int at91_pm_valid_state(suspend_state_t state) 48static int at91_pm_valid_state(suspend_state_t state)
@@ -119,76 +120,67 @@ int at91_suspend_entering_slow_clock(void)
119} 120}
120EXPORT_SYMBOL(at91_suspend_entering_slow_clock); 121EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
121 122
122 123static void (*at91_suspend_sram_fn)(void __iomem *pmc, void __iomem *ramc0,
123static void (*slow_clock)(void __iomem *pmc, void __iomem *ramc0,
124 void __iomem *ramc1, int memctrl); 124 void __iomem *ramc1, int memctrl);
125 125
126#ifdef CONFIG_AT91_SLOW_CLOCK 126extern void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *ramc0,
127extern void at91_slow_clock(void __iomem *pmc, void __iomem *ramc0,
128 void __iomem *ramc1, int memctrl); 127 void __iomem *ramc1, int memctrl);
129extern u32 at91_slow_clock_sz; 128extern u32 at91_pm_suspend_in_sram_sz;
130#endif 129
130static void at91_pm_suspend(suspend_state_t state)
131{
132 unsigned int pm_data = at91_pm_data.memctrl;
133
134 pm_data |= (state == PM_SUSPEND_MEM) ?
135 AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0;
136
137 flush_cache_all();
138 outer_disable();
139
140 at91_suspend_sram_fn(at91_pmc_base, at91_ramc_base[0],
141 at91_ramc_base[1], pm_data);
142
143 outer_resume();
144}
131 145
132static int at91_pm_enter(suspend_state_t state) 146static int at91_pm_enter(suspend_state_t state)
133{ 147{
134 at91_pinctrl_gpio_suspend(); 148 at91_pinctrl_gpio_suspend();
135 149
136 switch (state) { 150 switch (state) {
151 /*
152 * Suspend-to-RAM is like STANDBY plus slow clock mode, so
153 * drivers must suspend more deeply, the master clock switches
154 * to the clk32k and turns off the main oscillator
155 */
156 case PM_SUSPEND_MEM:
137 /* 157 /*
138 * Suspend-to-RAM is like STANDBY plus slow clock mode, so 158 * Ensure that clocks are in a valid state.
139 * drivers must suspend more deeply: only the master clock
140 * controller may be using the main oscillator.
141 */ 159 */
142 case PM_SUSPEND_MEM: 160 if (!at91_pm_verify_clocks())
143 /* 161 goto error;
144 * Ensure that clocks are in a valid state.
145 */
146 if (!at91_pm_verify_clocks())
147 goto error;
148
149 /*
150 * Enter slow clock mode by switching over to clk32k and
151 * turning off the main oscillator; reverse on wakeup.
152 */
153 if (slow_clock) {
154#ifdef CONFIG_AT91_SLOW_CLOCK
155 /* copy slow_clock handler to SRAM, and call it */
156 memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz);
157#endif
158 slow_clock(at91_pmc_base, at91_ramc_base[0],
159 at91_ramc_base[1],
160 at91_pm_data.memctrl);
161 break;
162 } else {
163 pr_info("AT91: PM - no slow clock mode enabled ...\n");
164 /* FALLTHROUGH leaving master clock alone */
165 }
166 162
167 /* 163 at91_pm_suspend(state);
168 * STANDBY mode has *all* drivers suspended; ignores irqs not
169 * marked as 'wakeup' event sources; and reduces DRAM power.
170 * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and
171 * nothing fancy done with main or cpu clocks.
172 */
173 case PM_SUSPEND_STANDBY:
174 /*
175 * NOTE: the Wait-for-Interrupt instruction needs to be
176 * in icache so no SDRAM accesses are needed until the
177 * wakeup IRQ occurs and self-refresh is terminated.
178 * For ARM 926 based chips, this requirement is weaker
179 * as at91sam9 can access a RAM in self-refresh mode.
180 */
181 if (at91_pm_standby)
182 at91_pm_standby();
183 break;
184 164
185 case PM_SUSPEND_ON: 165 break;
186 cpu_do_idle();
187 break;
188 166
189 default: 167 /*
190 pr_debug("AT91: PM - bogus suspend state %d\n", state); 168 * STANDBY mode has *all* drivers suspended; ignores irqs not
191 goto error; 169 * marked as 'wakeup' event sources; and reduces DRAM power.
170 * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and
171 * nothing fancy done with main or cpu clocks.
172 */
173 case PM_SUSPEND_STANDBY:
174 at91_pm_suspend(state);
175 break;
176
177 case PM_SUSPEND_ON:
178 cpu_do_idle();
179 break;
180
181 default:
182 pr_debug("AT91: PM - bogus suspend state %d\n", state);
183 goto error;
192 } 184 }
193 185
194error: 186error:
@@ -218,12 +210,10 @@ static struct platform_device at91_cpuidle_device = {
218 .name = "cpuidle-at91", 210 .name = "cpuidle-at91",
219}; 211};
220 212
221void at91_pm_set_standby(void (*at91_standby)(void)) 213static void at91_pm_set_standby(void (*at91_standby)(void))
222{ 214{
223 if (at91_standby) { 215 if (at91_standby)
224 at91_cpuidle_device.dev.platform_data = at91_standby; 216 at91_cpuidle_device.dev.platform_data = at91_standby;
225 at91_pm_standby = at91_standby;
226 }
227} 217}
228 218
229static const struct of_device_id ramc_ids[] __initconst = { 219static const struct of_device_id ramc_ids[] __initconst = {
@@ -263,7 +253,6 @@ static __init void at91_dt_ramc(void)
263 at91_pm_set_standby(standby); 253 at91_pm_set_standby(standby);
264} 254}
265 255
266#ifdef CONFIG_AT91_SLOW_CLOCK
267static void __init at91_pm_sram_init(void) 256static void __init at91_pm_sram_init(void)
268{ 257{
269 struct gen_pool *sram_pool; 258 struct gen_pool *sram_pool;
@@ -291,30 +280,36 @@ static void __init at91_pm_sram_init(void)
291 return; 280 return;
292 } 281 }
293 282
294 sram_base = gen_pool_alloc(sram_pool, at91_slow_clock_sz); 283 sram_base = gen_pool_alloc(sram_pool, at91_pm_suspend_in_sram_sz);
295 if (!sram_base) { 284 if (!sram_base) {
296 pr_warn("%s: unable to alloc ocram!\n", __func__); 285 pr_warn("%s: unable to alloc sram!\n", __func__);
297 return; 286 return;
298 } 287 }
299 288
300 sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base); 289 sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base);
301 slow_clock = __arm_ioremap_exec(sram_pbase, at91_slow_clock_sz, false); 290 at91_suspend_sram_fn = __arm_ioremap_exec(sram_pbase,
302} 291 at91_pm_suspend_in_sram_sz, false);
303#endif 292 if (!at91_suspend_sram_fn) {
293 pr_warn("SRAM: Could not map\n");
294 return;
295 }
304 296
297 /* Copy the pm suspend handler to SRAM */
298 at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
299 &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
300}
305 301
306static void __init at91_pm_init(void) 302static void __init at91_pm_init(void)
307{ 303{
308#ifdef CONFIG_AT91_SLOW_CLOCK
309 at91_pm_sram_init(); 304 at91_pm_sram_init();
310#endif
311
312 pr_info("AT91: Power Management%s\n", (slow_clock ? " (with slow clock mode)" : ""));
313 305
314 if (at91_cpuidle_device.dev.platform_data) 306 if (at91_cpuidle_device.dev.platform_data)
315 platform_device_register(&at91_cpuidle_device); 307 platform_device_register(&at91_cpuidle_device);
316 308
317 suspend_set_ops(&at91_pm_ops); 309 if (at91_suspend_sram_fn)
310 suspend_set_ops(&at91_pm_ops);
311 else
312 pr_info("AT91: PM not supported, due to no SRAM allocated\n");
318} 313}
319 314
320void __init at91rm9200_pm_init(void) 315void __init at91rm9200_pm_init(void)