ARM: at91/pm: rename function name: at91_slow_clock() --> at91_pm_suspend_sram_fn()
[deliverable/linux.git] / arch / arm / mach-at91 / pm.c
CommitLineData
907d6deb 1/*
9d041268 2 * arch/arm/mach-at91/pm.c
907d6deb
AV
3 * AT91 Power Management
4 *
5 * Copyright (C) 2005 David Brownell
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
2f8163ba 13#include <linux/gpio.h>
95d9ffbe 14#include <linux/suspend.h>
907d6deb
AV
15#include <linux/sched.h>
16#include <linux/proc_fs.h>
d2e46790 17#include <linux/genalloc.h>
907d6deb
AV
18#include <linux/interrupt.h>
19#include <linux/sysfs.h>
20#include <linux/module.h>
f5598d34 21#include <linux/of.h>
d2e46790 22#include <linux/of_platform.h>
827de1f1 23#include <linux/of_address.h>
907d6deb 24#include <linux/platform_device.h>
fced80c7 25#include <linux/io.h>
2edb90ae 26#include <linux/clk/at91_pmc.h>
907d6deb 27
907d6deb 28#include <asm/irq.h>
60063497 29#include <linux/atomic.h>
907d6deb
AV
30#include <asm/mach/time.h>
31#include <asm/mach/irq.h>
d94e688c 32#include <asm/fncpy.h>
907d6deb 33
a09e64fb 34#include <mach/cpu.h>
ac11a1d4 35#include <mach/hardware.h>
907d6deb
AV
36
37#include "generic.h"
1ea60cf7 38#include "pm.h"
907d6deb 39
f5598d34
AB
40static struct {
41 unsigned long uhp_udp_mask;
42 int memctrl;
43} at91_pm_data;
44
5ad945ea 45static void (*at91_pm_standby)(void);
827de1f1 46void __iomem *at91_ramc_base[2];
5ad945ea 47
907d6deb
AV
48static int at91_pm_valid_state(suspend_state_t state)
49{
50 switch (state) {
51 case PM_SUSPEND_ON:
52 case PM_SUSPEND_STANDBY:
53 case PM_SUSPEND_MEM:
54 return 1;
55
56 default:
57 return 0;
58 }
59}
60
61
62static suspend_state_t target_state;
63
64/*
65 * Called after processes are frozen, but before we shutdown devices.
66 */
c697eece 67static int at91_pm_begin(suspend_state_t state)
907d6deb
AV
68{
69 target_state = state;
70 return 0;
71}
72
73/*
74 * Verify that all the clocks are correct before entering
75 * slow-clock mode.
76 */
77static int at91_pm_verify_clocks(void)
78{
79 unsigned long scsr;
80 int i;
81
b5514952 82 scsr = at91_pmc_read(AT91_PMC_SCSR);
907d6deb
AV
83
84 /* USB must not be using PLLB */
f5598d34
AB
85 if ((scsr & at91_pm_data.uhp_udp_mask) != 0) {
86 pr_err("AT91: PM - Suspend-to-RAM with USB still active\n");
87 return 0;
907d6deb
AV
88 }
89
907d6deb
AV
90 /* PCK0..PCK3 must be disabled, or configured to use clk32k */
91 for (i = 0; i < 4; i++) {
92 u32 css;
93
94 if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
95 continue;
96
b5514952 97 css = at91_pmc_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
907d6deb 98 if (css != AT91_PMC_CSS_SLOW) {
7f96b1ca 99 pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
907d6deb
AV
100 return 0;
101 }
102 }
907d6deb
AV
103
104 return 1;
105}
106
107/*
108 * Call this from platform driver suspend() to see how deeply to suspend.
109 * For example, some controllers (like OHCI) need one of the PLL clocks
110 * in order to act as a wakeup source, and those are not available when
111 * going into slow clock mode.
112 *
113 * REVISIT: generalize as clk_will_be_available(clk)? Other platforms have
114 * the very same problem (but not using at91 main_clk), and it'd be better
115 * to add one generic API rather than lots of platform-specific ones.
116 */
117int at91_suspend_entering_slow_clock(void)
118{
119 return (target_state == PM_SUSPEND_MEM);
120}
121EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
122
5726a8b9 123static void (*at91_suspend_sram_fn)(void __iomem *pmc, void __iomem *ramc0,
fb7e197b 124 void __iomem *ramc1, int memctrl);
907d6deb 125
5726a8b9 126extern void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *ramc0,
fb7e197b 127 void __iomem *ramc1, int memctrl);
5726a8b9 128extern u32 at91_pm_suspend_in_sram_sz;
f5d0f457 129
23be4be5
WY
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
5726a8b9
WY
137 at91_suspend_sram_fn(at91_pmc_base, at91_ramc_base[0],
138 at91_ramc_base[1], pm_data);
23be4be5
WY
139}
140
907d6deb
AV
141static int at91_pm_enter(suspend_state_t state)
142{
85c4b31e 143 at91_pinctrl_gpio_suspend();
907d6deb 144
907d6deb 145 switch (state) {
23be4be5
WY
146 /*
147 * Suspend-to-RAM is like STANDBY plus slow clock mode, so
148 * drivers must suspend more deeply, the master clock switches
149 * to the clk32k and turns off the main oscillator
150 */
151 case PM_SUSPEND_MEM:
907d6deb 152 /*
23be4be5 153 * Ensure that clocks are in a valid state.
907d6deb 154 */
23be4be5
WY
155 if (!at91_pm_verify_clocks())
156 goto error;
907d6deb 157
23be4be5 158 at91_pm_suspend(state);
907d6deb 159
23be4be5 160 break;
907d6deb 161
23be4be5
WY
162 /*
163 * STANDBY mode has *all* drivers suspended; ignores irqs not
164 * marked as 'wakeup' event sources; and reduces DRAM power.
165 * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and
166 * nothing fancy done with main or cpu clocks.
167 */
168 case PM_SUSPEND_STANDBY:
169 at91_pm_suspend(state);
170 break;
171
172 case PM_SUSPEND_ON:
173 cpu_do_idle();
174 break;
175
176 default:
177 pr_debug("AT91: PM - bogus suspend state %d\n", state);
178 goto error;
907d6deb
AV
179 }
180
907d6deb
AV
181error:
182 target_state = PM_SUSPEND_ON;
07192604 183
85c4b31e 184 at91_pinctrl_gpio_resume();
907d6deb
AV
185 return 0;
186}
187
c697eece
RW
188/*
189 * Called right prior to thawing processes.
190 */
191static void at91_pm_end(void)
192{
193 target_state = PM_SUSPEND_ON;
194}
195
907d6deb 196
2f55ac07 197static const struct platform_suspend_ops at91_pm_ops = {
c697eece
RW
198 .valid = at91_pm_valid_state,
199 .begin = at91_pm_begin,
200 .enter = at91_pm_enter,
201 .end = at91_pm_end,
907d6deb
AV
202};
203
5ad945ea
DL
204static struct platform_device at91_cpuidle_device = {
205 .name = "cpuidle-at91",
206};
207
047794e1 208static void at91_pm_set_standby(void (*at91_standby)(void))
5ad945ea
DL
209{
210 if (at91_standby) {
211 at91_cpuidle_device.dev.platform_data = at91_standby;
212 at91_pm_standby = at91_standby;
213 }
214}
215
444d2d33 216static const struct of_device_id ramc_ids[] __initconst = {
827de1f1
AB
217 { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
218 { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
219 { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby },
220 { .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby },
221 { /*sentinel*/ }
222};
223
444d2d33 224static __init void at91_dt_ramc(void)
827de1f1
AB
225{
226 struct device_node *np;
227 const struct of_device_id *of_id;
228 int idx = 0;
229 const void *standby = NULL;
230
231 for_each_matching_node_and_match(np, ramc_ids, &of_id) {
232 at91_ramc_base[idx] = of_iomap(np, 0);
233 if (!at91_ramc_base[idx])
234 panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx);
235
236 if (!standby)
237 standby = of_id->data;
238
239 idx++;
240 }
241
242 if (!idx)
243 panic(pr_fmt("unable to find compatible ram controller node in dtb\n"));
244
245 if (!standby) {
246 pr_warn("ramc no standby function available\n");
247 return;
248 }
249
250 at91_pm_set_standby(standby);
251}
252
d2e46790
AB
253static void __init at91_pm_sram_init(void)
254{
255 struct gen_pool *sram_pool;
256 phys_addr_t sram_pbase;
257 unsigned long sram_base;
258 struct device_node *node;
4a031f7d 259 struct platform_device *pdev = NULL;
d2e46790 260
4a031f7d
AB
261 for_each_compatible_node(node, NULL, "mmio-sram") {
262 pdev = of_find_device_by_node(node);
263 if (pdev) {
264 of_node_put(node);
265 break;
266 }
d2e46790
AB
267 }
268
d2e46790
AB
269 if (!pdev) {
270 pr_warn("%s: failed to find sram device!\n", __func__);
4a031f7d 271 return;
d2e46790
AB
272 }
273
274 sram_pool = dev_get_gen_pool(&pdev->dev);
275 if (!sram_pool) {
276 pr_warn("%s: sram pool unavailable!\n", __func__);
4a031f7d 277 return;
d2e46790
AB
278 }
279
5726a8b9 280 sram_base = gen_pool_alloc(sram_pool, at91_pm_suspend_in_sram_sz);
d2e46790 281 if (!sram_base) {
5726a8b9 282 pr_warn("%s: unable to alloc sram!\n", __func__);
4a031f7d 283 return;
d2e46790
AB
284 }
285
286 sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base);
5726a8b9
WY
287 at91_suspend_sram_fn = __arm_ioremap_exec(sram_pbase,
288 at91_pm_suspend_in_sram_sz, false);
289 if (!at91_suspend_sram_fn) {
d94e688c
WY
290 pr_warn("SRAM: Could not map\n");
291 return;
292 }
293
5726a8b9
WY
294 /* Copy the pm suspend handler to SRAM */
295 at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
296 &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
d2e46790 297}
d2e46790 298
4db0ba22 299static void __init at91_pm_init(void)
907d6deb 300{
d2e46790 301 at91_pm_sram_init();
f5d0f457 302
5ad945ea
DL
303 if (at91_cpuidle_device.dev.platform_data)
304 platform_device_register(&at91_cpuidle_device);
907d6deb 305
5726a8b9 306 if (at91_suspend_sram_fn)
d94e688c
WY
307 suspend_set_ops(&at91_pm_ops);
308 else
309 pr_info("AT91: PM not supported, due to no SRAM allocated\n");
4db0ba22 310}
907d6deb 311
ad3fc3e3 312void __init at91rm9200_pm_init(void)
4db0ba22 313{
827de1f1
AB
314 at91_dt_ramc();
315
4db0ba22
AB
316 /*
317 * AT91RM9200 SDRAM low-power mode cannot be used with self-refresh.
318 */
319 at91_ramc_write(0, AT91RM9200_SDRAMC_LPR, 0);
320
321 at91_pm_data.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP;
322 at91_pm_data.memctrl = AT91_MEMCTRL_MC;
323
324 at91_pm_init();
325}
326
ad3fc3e3 327void __init at91sam9260_pm_init(void)
4db0ba22 328{
827de1f1 329 at91_dt_ramc();
4db0ba22
AB
330 at91_pm_data.memctrl = AT91_MEMCTRL_SDRAMC;
331 at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
332 return at91_pm_init();
333}
334
ad3fc3e3 335void __init at91sam9g45_pm_init(void)
4db0ba22 336{
827de1f1 337 at91_dt_ramc();
4db0ba22
AB
338 at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP;
339 at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
340 return at91_pm_init();
907d6deb 341}
bf02280e 342
ad3fc3e3 343void __init at91sam9x5_pm_init(void)
bf02280e 344{
827de1f1 345 at91_dt_ramc();
bf02280e
NF
346 at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
347 at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
348 return at91_pm_init();
349}
This page took 0.779046 seconds and 5 git commands to generate.