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-mmp
pm-pxa910.c
Go to the documentation of this file.
1
/*
2
* PXA910 Power Management Routines
3
*
4
* This software program is licensed subject to the GNU General Public License
5
* (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html
6
*
7
* (C) Copyright 2009 Marvell International Ltd.
8
* All Rights Reserved
9
*/
10
11
#include <linux/kernel.h>
12
#include <linux/errno.h>
13
#include <
linux/err.h
>
14
#include <linux/time.h>
15
#include <
linux/delay.h
>
16
#include <
linux/suspend.h
>
17
#include <
linux/interrupt.h
>
18
#include <
linux/io.h
>
19
#include <
linux/irq.h
>
20
#include <
asm/mach-types.h
>
21
#include <mach/hardware.h>
22
#include <mach/cputype.h>
23
#include <mach/addr-map.h>
24
#include <
mach/pm-pxa910.h
>
25
#include <
mach/regs-icu.h
>
26
#include <mach/irqs.h>
27
28
int
pxa910_set_wake
(
struct
irq_data
*
data
,
unsigned
int
on)
29
{
30
int
irq
= data->
irq
;
31
struct
irq_desc
*
desc
=
irq_to_desc
(data->
irq
);
32
uint32_t
awucrm = 0, apcr = 0;
33
34
if
(
unlikely
(irq >=
nr_irqs
)) {
35
pr_err
(
"IRQ nubmers are out of boundary!\n"
);
36
return
-
EINVAL
;
37
}
38
39
if
(on) {
40
if
(desc->
action
)
41
desc->
action
->flags |=
IRQF_NO_SUSPEND
;
42
}
else
{
43
if
(desc->
action
)
44
desc->
action
->flags &= ~
IRQF_NO_SUSPEND
;
45
}
46
47
/* setting wakeup sources */
48
switch
(irq) {
49
/* wakeup line 2 */
50
case
IRQ_PXA910_AP_GPIO
:
51
awucrm =
MPMU_AWUCRM_WAKEUP
(2);
52
apcr |=
MPMU_APCR_SLPWP2
;
53
break
;
54
/* wakeup line 3 */
55
case
IRQ_PXA910_KEYPAD
:
56
awucrm =
MPMU_AWUCRM_WAKEUP
(3) |
MPMU_AWUCRM_KEYPRESS
;
57
apcr |=
MPMU_APCR_SLPWP3
;
58
break
;
59
case
IRQ_PXA910_ROTARY
:
60
awucrm =
MPMU_AWUCRM_WAKEUP
(3) |
MPMU_AWUCRM_NEWROTARY
;
61
apcr |=
MPMU_APCR_SLPWP3
;
62
break
;
63
case
IRQ_PXA910_TRACKBALL
:
64
awucrm =
MPMU_AWUCRM_WAKEUP
(3) |
MPMU_AWUCRM_TRACKBALL
;
65
apcr |=
MPMU_APCR_SLPWP3
;
66
break
;
67
/* wakeup line 4 */
68
case
IRQ_PXA910_AP1_TIMER1
:
69
awucrm =
MPMU_AWUCRM_WAKEUP
(4) |
MPMU_AWUCRM_AP1_TIMER_1
;
70
apcr |=
MPMU_APCR_SLPWP4
;
71
break
;
72
case
IRQ_PXA910_AP1_TIMER2
:
73
awucrm =
MPMU_AWUCRM_WAKEUP
(4) |
MPMU_AWUCRM_AP1_TIMER_2
;
74
apcr |=
MPMU_APCR_SLPWP4
;
75
break
;
76
case
IRQ_PXA910_AP1_TIMER3
:
77
awucrm =
MPMU_AWUCRM_WAKEUP
(4) |
MPMU_AWUCRM_AP1_TIMER_3
;
78
apcr |=
MPMU_APCR_SLPWP4
;
79
break
;
80
case
IRQ_PXA910_AP2_TIMER1
:
81
awucrm =
MPMU_AWUCRM_WAKEUP
(4) |
MPMU_AWUCRM_AP2_TIMER_1
;
82
apcr |=
MPMU_APCR_SLPWP4
;
83
break
;
84
case
IRQ_PXA910_AP2_TIMER2
:
85
awucrm =
MPMU_AWUCRM_WAKEUP
(4) |
MPMU_AWUCRM_AP2_TIMER_2
;
86
apcr |=
MPMU_APCR_SLPWP4
;
87
break
;
88
case
IRQ_PXA910_AP2_TIMER3
:
89
awucrm =
MPMU_AWUCRM_WAKEUP
(4) |
MPMU_AWUCRM_AP2_TIMER_3
;
90
apcr |=
MPMU_APCR_SLPWP4
;
91
break
;
92
case
IRQ_PXA910_RTC_ALARM
:
93
awucrm =
MPMU_AWUCRM_WAKEUP
(4) |
MPMU_AWUCRM_RTC_ALARM
;
94
apcr |=
MPMU_APCR_SLPWP4
;
95
break
;
96
/* wakeup line 5 */
97
case
IRQ_PXA910_USB1
:
98
case
IRQ_PXA910_USB2
:
99
awucrm =
MPMU_AWUCRM_WAKEUP
(5);
100
apcr |=
MPMU_APCR_SLPWP5
;
101
break
;
102
/* wakeup line 6 */
103
case
IRQ_PXA910_MMC
:
104
awucrm =
MPMU_AWUCRM_WAKEUP
(6)
105
|
MPMU_AWUCRM_SDH1
106
|
MPMU_AWUCRM_SDH2
;
107
apcr |=
MPMU_APCR_SLPWP6
;
108
break
;
109
/* wakeup line 7 */
110
case
IRQ_PXA910_PMIC_INT
:
111
awucrm =
MPMU_AWUCRM_WAKEUP
(7);
112
apcr |=
MPMU_APCR_SLPWP7
;
113
break
;
114
default
:
115
if
(irq >=
IRQ_GPIO_START
&& irq <
IRQ_BOARD_START
) {
116
awucrm =
MPMU_AWUCRM_WAKEUP
(2);
117
apcr |=
MPMU_APCR_SLPWP2
;
118
}
else
119
printk
(
KERN_ERR
"Error: no defined wake up source irq: %d\n"
,
120
irq);
121
}
122
123
if
(on) {
124
if
(awucrm) {
125
awucrm |=
__raw_readl
(
MPMU_AWUCRM
);
126
__raw_writel
(awucrm,
MPMU_AWUCRM
);
127
}
128
if
(apcr) {
129
apcr = ~apcr &
__raw_readl
(
MPMU_APCR
);
130
__raw_writel
(apcr,
MPMU_APCR
);
131
}
132
}
else
{
133
if
(awucrm) {
134
awucrm = ~awucrm &
__raw_readl
(
MPMU_AWUCRM
);
135
__raw_writel
(awucrm,
MPMU_AWUCRM
);
136
}
137
if
(apcr) {
138
apcr |=
__raw_readl
(
MPMU_APCR
);
139
__raw_writel
(apcr,
MPMU_APCR
);
140
}
141
}
142
return
0;
143
}
144
145
void
pxa910_pm_enter_lowpower_mode
(
int
state
)
146
{
147
uint32_t
idle_cfg, apcr;
148
149
idle_cfg =
__raw_readl
(
APMU_MOH_IDLE_CFG
);
150
apcr =
__raw_readl
(
MPMU_APCR
);
151
152
apcr &= ~(
MPMU_APCR_DDRCORSD
|
MPMU_APCR_APBSD
|
MPMU_APCR_AXISD
153
|
MPMU_APCR_VCTCXOSD
|
MPMU_APCR_STBYEN
);
154
idle_cfg &= ~(
APMU_MOH_IDLE_CFG_MOH_IDLE
155
|
APMU_MOH_IDLE_CFG_MOH_PWRDWN
);
156
157
switch
(state) {
158
case
POWER_MODE_UDR
:
159
/* only shutdown APB in UDR */
160
apcr |=
MPMU_APCR_STBYEN
|
MPMU_APCR_APBSD
;
161
/* fall through */
162
case
POWER_MODE_SYS_SLEEP
:
163
apcr |=
MPMU_APCR_SLPEN
;
/* set the SLPEN bit */
164
apcr |=
MPMU_APCR_VCTCXOSD
;
/* set VCTCXOSD */
165
/* fall through */
166
case
POWER_MODE_APPS_SLEEP
:
167
apcr |=
MPMU_APCR_DDRCORSD
;
/* set DDRCORSD */
168
/* fall through */
169
case
POWER_MODE_APPS_IDLE
:
170
apcr |=
MPMU_APCR_AXISD
;
/* set AXISDD bit */
171
/* fall through */
172
case
POWER_MODE_CORE_EXTIDLE
:
173
idle_cfg |=
APMU_MOH_IDLE_CFG_MOH_IDLE
;
174
idle_cfg |=
APMU_MOH_IDLE_CFG_MOH_PWRDWN
;
175
idle_cfg |=
APMU_MOH_IDLE_CFG_MOH_PWR_SW
(3)
176
|
APMU_MOH_IDLE_CFG_MOH_L2_PWR_SW
(3);
177
/* fall through */
178
case
POWER_MODE_CORE_INTIDLE
:
179
break
;
180
}
181
182
/* program the memory controller hardware sleep type and auto wakeup */
183
idle_cfg |=
APMU_MOH_IDLE_CFG_MOH_DIS_MC_SW_REQ
;
184
idle_cfg |=
APMU_MOH_IDLE_CFG_MOH_MC_WAKE_EN
;
185
__raw_writel
(0x0,
APMU_MC_HW_SLP_TYPE
);
/* auto refresh */
186
187
/* set DSPSD, DTCMSD, BBSD, MSASLPEN */
188
apcr |=
MPMU_APCR_DSPSD
|
MPMU_APCR_DTCMSD
|
MPMU_APCR_BBSD
189
|
MPMU_APCR_MSASLPEN
;
190
191
/*always set SLEPEN bit mainly for MSA*/
192
apcr |=
MPMU_APCR_SLPEN
;
193
194
/* finally write the registers back */
195
__raw_writel
(idle_cfg,
APMU_MOH_IDLE_CFG
);
196
__raw_writel
(apcr,
MPMU_APCR
);
197
198
}
199
200
static
int
pxa910_pm_enter(
suspend_state_t
state
)
201
{
202
unsigned
int
idle_cfg,
reg
= 0;
203
204
/*pmic thread not completed,exit;otherwise system can't be waked up*/
205
reg =
__raw_readl
(
ICU_INT_CONF
(
IRQ_PXA910_PMIC_INT
));
206
if
((reg & 0x3) == 0)
207
return
-
EAGAIN
;
208
209
idle_cfg =
__raw_readl
(
APMU_MOH_IDLE_CFG
);
210
idle_cfg |=
APMU_MOH_IDLE_CFG_MOH_PWRDWN
211
|
APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN
;
212
__raw_writel
(idle_cfg,
APMU_MOH_IDLE_CFG
);
213
214
/* disable L2 */
215
outer_disable();
216
/* wait for l2 idle */
217
while
(!(
readl
(
CIU_REG
(0x8)) & (1 << 16)))
218
udelay
(1);
219
220
cpu_do_idle
();
221
222
/* enable L2 */
223
outer_resume();
224
/* wait for l2 idle */
225
while
(!(
readl
(
CIU_REG
(0x8)) & (1 << 16)))
226
udelay
(1);
227
228
idle_cfg =
__raw_readl
(
APMU_MOH_IDLE_CFG
);
229
idle_cfg &= ~(
APMU_MOH_IDLE_CFG_MOH_PWRDWN
230
|
APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN
);
231
__raw_writel
(idle_cfg,
APMU_MOH_IDLE_CFG
);
232
233
return
0;
234
}
235
236
/*
237
* Called after processes are frozen, but before we shut down devices.
238
*/
239
static
int
pxa910_pm_prepare(
void
)
240
{
241
pxa910_pm_enter_lowpower_mode
(
POWER_MODE_UDR
);
242
return
0;
243
}
244
245
/*
246
* Called after devices are re-setup, but before processes are thawed.
247
*/
248
static
void
pxa910_pm_finish(
void
)
249
{
250
pxa910_pm_enter_lowpower_mode
(
POWER_MODE_CORE_INTIDLE
);
251
}
252
253
static
int
pxa910_pm_valid(
suspend_state_t
state)
254
{
255
return
((state ==
PM_SUSPEND_STANDBY
) || (state ==
PM_SUSPEND_MEM
));
256
}
257
258
static
const
struct
platform_suspend_ops
pxa910_pm_ops = {
259
.valid = pxa910_pm_valid,
260
.prepare = pxa910_pm_prepare,
261
.enter = pxa910_pm_enter,
262
.finish = pxa910_pm_finish,
263
};
264
265
static
int
__init
pxa910_pm_init(
void
)
266
{
267
uint32_t
awucrm = 0;
268
269
if
(!
cpu_is_pxa910
())
270
return
-
EIO
;
271
272
suspend_set_ops
(&pxa910_pm_ops);
273
274
/* Set the following bits for MMP3 playback with VCTXO on */
275
__raw_writel
(
__raw_readl
(
APMU_SQU_CLK_GATE_CTRL
) | (1 << 30),
276
APMU_SQU_CLK_GATE_CTRL
);
277
__raw_writel
(
__raw_readl
(
MPMU_FCCR
) | (1 << 28),
MPMU_FCCR
);
278
279
awucrm |=
MPMU_AWUCRM_AP_ASYNC_INT
|
MPMU_AWUCRM_AP_FULL_IDLE
;
280
__raw_writel
(awucrm,
MPMU_AWUCRM
);
281
282
return
0;
283
}
284
285
late_initcall
(pxa910_pm_init);
Generated on Thu Jan 10 2013 12:59:48 for Linux Kernel by
1.8.2