Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
arm
mach-at91
pm.c
Go to the documentation of this file.
1
/*
2
* arch/arm/mach-at91/pm.c
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
13
#include <
linux/gpio.h
>
14
#include <
linux/suspend.h
>
15
#include <linux/sched.h>
16
#include <
linux/proc_fs.h
>
17
#include <
linux/interrupt.h
>
18
#include <
linux/sysfs.h
>
19
#include <linux/module.h>
20
#include <
linux/platform_device.h
>
21
#include <
linux/io.h
>
22
23
#include <asm/irq.h>
24
#include <
linux/atomic.h
>
25
#include <
asm/mach/time.h
>
26
#include <
asm/mach/irq.h
>
27
28
#include <
mach/at91_aic.h
>
29
#include <
mach/at91_pmc.h
>
30
#include <mach/cpu.h>
31
32
#include "
generic.h
"
33
#include "
pm.h
"
34
35
/*
36
* Show the reason for the previous system reset.
37
*/
38
39
#include <
mach/at91_rstc.h
>
40
#include <
mach/at91_shdwc.h
>
41
42
static
void
__init
show_reset_status(
void
)
43
{
44
static
char
reset
[]
__initdata
=
"reset"
;
45
46
static
char
general[] __initdata =
"general"
;
47
static
char
wakeup[] __initdata =
"wakeup"
;
48
static
char
watchdog
[] __initdata =
"watchdog"
;
49
static
char
software
[] __initdata =
"software"
;
50
static
char
user
[] __initdata =
"user"
;
51
static
char
unknown
[] __initdata =
"unknown"
;
52
53
static
char
signal
[] __initdata =
"signal"
;
54
static
char
rtc
[] __initdata =
"rtc"
;
55
static
char
rtt[] __initdata =
"rtt"
;
56
static
char
restore[] __initdata =
"power-restored"
;
57
58
char
*
reason
, *
r2
=
reset
;
59
u32
reset_type
, wake_type;
60
61
if
(!
at91_shdwc_base
|| !
at91_rstc_base
)
62
return
;
63
64
reset_type =
at91_rstc_read
(
AT91_RSTC_SR
) &
AT91_RSTC_RSTTYP
;
65
wake_type =
at91_shdwc_read
(
AT91_SHDW_SR
);
66
67
switch
(reset_type) {
68
case
AT91_RSTC_RSTTYP_GENERAL
:
69
reason = general;
70
break
;
71
case
AT91_RSTC_RSTTYP_WAKEUP
:
72
/* board-specific code enabled the wakeup sources */
73
reason = wakeup;
74
75
/* "wakeup signal" */
76
if
(wake_type &
AT91_SHDW_WAKEUP0
)
77
r2 =
signal
;
78
else
{
79
r2 =
reason
;
80
if
(wake_type &
AT91_SHDW_RTTWK
)
/* rtt wakeup */
81
reason = rtt;
82
else
if
(wake_type &
AT91_SHDW_RTCWK
)
/* rtc wakeup */
83
reason =
rtc
;
84
else
if
(wake_type == 0)
/* power-restored wakeup */
85
reason = restore;
86
else
/* unknown wakeup */
87
reason =
unknown
;
88
}
89
break
;
90
case
AT91_RSTC_RSTTYP_WATCHDOG
:
91
reason =
watchdog
;
92
break
;
93
case
AT91_RSTC_RSTTYP_SOFTWARE
:
94
reason =
software
;
95
break
;
96
case
AT91_RSTC_RSTTYP_USER
:
97
reason =
user
;
98
break
;
99
default
:
100
reason =
unknown
;
101
break
;
102
}
103
pr_info
(
"AT91: Starting after %s %s\n"
, reason, r2);
104
}
105
106
static
int
at91_pm_valid_state(
suspend_state_t
state
)
107
{
108
switch
(state) {
109
case
PM_SUSPEND_ON
:
110
case
PM_SUSPEND_STANDBY
:
111
case
PM_SUSPEND_MEM
:
112
return
1;
113
114
default
:
115
return
0;
116
}
117
}
118
119
120
static
suspend_state_t
target_state;
121
122
/*
123
* Called after processes are frozen, but before we shutdown devices.
124
*/
125
static
int
at91_pm_begin(
suspend_state_t
state)
126
{
127
target_state =
state
;
128
return
0;
129
}
130
131
/*
132
* Verify that all the clocks are correct before entering
133
* slow-clock mode.
134
*/
135
static
int
at91_pm_verify_clocks(
void
)
136
{
137
unsigned
long
scsr;
138
int
i
;
139
140
scsr =
at91_pmc_read
(
AT91_PMC_SCSR
);
141
142
/* USB must not be using PLLB */
143
if
(
cpu_is_at91rm9200
()) {
144
if
((scsr & (
AT91RM9200_PMC_UHP
|
AT91RM9200_PMC_UDP
)) != 0) {
145
pr_err
(
"AT91: PM - Suspend-to-RAM with USB still active\n"
);
146
return
0;
147
}
148
}
else
if
(
cpu_is_at91sam9260
() ||
cpu_is_at91sam9261
() ||
cpu_is_at91sam9263
()
149
||
cpu_is_at91sam9g20
() ||
cpu_is_at91sam9g10
()) {
150
if
((scsr & (
AT91SAM926x_PMC_UHP
|
AT91SAM926x_PMC_UDP
)) != 0) {
151
pr_err
(
"AT91: PM - Suspend-to-RAM with USB still active\n"
);
152
return
0;
153
}
154
}
155
156
if
(!
IS_ENABLED
(CONFIG_AT91_PROGRAMMABLE_CLOCKS))
157
return
1;
158
159
/* PCK0..PCK3 must be disabled, or configured to use clk32k */
160
for
(i = 0; i < 4; i++) {
161
u32
css;
162
163
if
((scsr & (
AT91_PMC_PCK0
<< i)) == 0)
164
continue
;
165
166
css =
at91_pmc_read
(
AT91_PMC_PCKR
(i)) &
AT91_PMC_CSS
;
167
if
(css !=
AT91_PMC_CSS_SLOW
) {
168
pr_err
(
"AT91: PM - Suspend-to-RAM with PCK%d src %d\n"
, i, css);
169
return
0;
170
}
171
}
172
173
return
1;
174
}
175
176
/*
177
* Call this from platform driver suspend() to see how deeply to suspend.
178
* For example, some controllers (like OHCI) need one of the PLL clocks
179
* in order to act as a wakeup source, and those are not available when
180
* going into slow clock mode.
181
*
182
* REVISIT: generalize as clk_will_be_available(clk)? Other platforms have
183
* the very same problem (but not using at91 main_clk), and it'd be better
184
* to add one generic API rather than lots of platform-specific ones.
185
*/
186
int
at91_suspend_entering_slow_clock
(
void
)
187
{
188
return
(target_state ==
PM_SUSPEND_MEM
);
189
}
190
EXPORT_SYMBOL
(
at91_suspend_entering_slow_clock
);
191
192
193
static
void
(*slow_clock)(
void
__iomem
*pmc,
void
__iomem
*ramc0,
194
void
__iomem
*ramc1,
int
memctrl);
195
196
#ifdef CONFIG_AT91_SLOW_CLOCK
197
extern
void
at91_slow_clock(
void
__iomem
*pmc,
void
__iomem
*ramc0,
198
void
__iomem
*ramc1,
int
memctrl);
199
extern
u32
at91_slow_clock_sz;
200
#endif
201
202
static
int
at91_pm_enter(
suspend_state_t
state)
203
{
204
at91_gpio_suspend
();
205
at91_irq_suspend
();
206
207
pr_debug
(
"AT91: PM - wake mask %08x, pm state %d\n"
,
208
/* remember all the always-wake irqs */
209
(
at91_pmc_read
(
AT91_PMC_PCSR
)
210
| (1 <<
AT91_ID_FIQ
)
211
| (1 <<
AT91_ID_SYS
)
212
| (
at91_extern_irq
))
213
&
at91_aic_read
(
AT91_AIC_IMR
),
214
state);
215
216
switch
(state) {
217
/*
218
* Suspend-to-RAM is like STANDBY plus slow clock mode, so
219
* drivers must suspend more deeply: only the master clock
220
* controller may be using the main oscillator.
221
*/
222
case
PM_SUSPEND_MEM
:
223
/*
224
* Ensure that clocks are in a valid state.
225
*/
226
if
(!at91_pm_verify_clocks())
227
goto
error
;
228
229
/*
230
* Enter slow clock mode by switching over to clk32k and
231
* turning off the main oscillator; reverse on wakeup.
232
*/
233
if
(slow_clock) {
234
int
memctrl =
AT91_MEMCTRL_SDRAMC
;
235
236
if
(
cpu_is_at91rm9200
())
237
memctrl =
AT91_MEMCTRL_MC
;
238
else
if
(
cpu_is_at91sam9g45
())
239
memctrl =
AT91_MEMCTRL_DDRSDR
;
240
#ifdef CONFIG_AT91_SLOW_CLOCK
241
/* copy slow_clock handler to SRAM, and call it */
242
memcpy
(slow_clock, at91_slow_clock, at91_slow_clock_sz);
243
#endif
244
slow_clock(
at91_pmc_base
,
at91_ramc_base
[0],
245
at91_ramc_base
[1], memctrl);
246
break
;
247
}
else
{
248
pr_info
(
"AT91: PM - no slow clock mode enabled ...\n"
);
249
/* FALLTHROUGH leaving master clock alone */
250
}
251
252
/*
253
* STANDBY mode has *all* drivers suspended; ignores irqs not
254
* marked as 'wakeup' event sources; and reduces DRAM power.
255
* But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and
256
* nothing fancy done with main or cpu clocks.
257
*/
258
case
PM_SUSPEND_STANDBY
:
259
/*
260
* NOTE: the Wait-for-Interrupt instruction needs to be
261
* in icache so no SDRAM accesses are needed until the
262
* wakeup IRQ occurs and self-refresh is terminated.
263
* For ARM 926 based chips, this requirement is weaker
264
* as at91sam9 can access a RAM in self-refresh mode.
265
*/
266
if
(
cpu_is_at91rm9200
())
267
at91rm9200_standby();
268
else
if
(
cpu_is_at91sam9g45
())
269
at91sam9g45_standby();
270
else
271
at91sam9_standby();
272
break
;
273
274
case
PM_SUSPEND_ON
:
275
cpu_do_idle
();
276
break
;
277
278
default
:
279
pr_debug
(
"AT91: PM - bogus suspend state %d\n"
, state);
280
goto
error
;
281
}
282
283
pr_debug
(
"AT91: PM - wakeup %08x\n"
,
284
at91_aic_read
(
AT91_AIC_IPR
) &
at91_aic_read
(
AT91_AIC_IMR
));
285
286
error
:
287
target_state =
PM_SUSPEND_ON
;
288
at91_irq_resume
();
289
at91_gpio_resume
();
290
return
0;
291
}
292
293
/*
294
* Called right prior to thawing processes.
295
*/
296
static
void
at91_pm_end(
void
)
297
{
298
target_state =
PM_SUSPEND_ON
;
299
}
300
301
302
static
const
struct
platform_suspend_ops
at91_pm_ops = {
303
.valid = at91_pm_valid_state,
304
.begin = at91_pm_begin,
305
.enter = at91_pm_enter,
306
.end = at91_pm_end,
307
};
308
309
static
int
__init
at91_pm_init(
void
)
310
{
311
#ifdef CONFIG_AT91_SLOW_CLOCK
312
slow_clock = (
void
*) (
AT91_IO_VIRT_BASE
- at91_slow_clock_sz);
313
#endif
314
315
pr_info
(
"AT91: Power Management%s\n"
, (slow_clock ?
" (with slow clock mode)"
:
""
));
316
317
/* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */
318
if
(
cpu_is_at91rm9200
())
319
at91_ramc_write
(0,
AT91RM9200_SDRAMC_LPR
, 0);
320
321
suspend_set_ops
(&at91_pm_ops);
322
323
show_reset_status();
324
return
0;
325
}
326
arch_initcall
(at91_pm_init);
Generated on Thu Jan 10 2013 12:56:58 for Linux Kernel by
1.8.2