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