2 * PXA910 Power Management Routines
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
7 * (C) Copyright 2009 Marvell International Ltd.
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>
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>
28 int pxa910_set_wake(struct irq_data
*data
, unsigned int on
)
30 uint32_t awucrm
= 0, apcr
= 0;
33 /* setting wakeup sources */
36 case IRQ_PXA910_AP_GPIO
:
37 awucrm
= MPMU_AWUCRM_WAKEUP(2);
38 apcr
|= MPMU_APCR_SLPWP2
;
41 case IRQ_PXA910_KEYPAD
:
42 awucrm
= MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_KEYPRESS
;
43 apcr
|= MPMU_APCR_SLPWP3
;
45 case IRQ_PXA910_ROTARY
:
46 awucrm
= MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_NEWROTARY
;
47 apcr
|= MPMU_APCR_SLPWP3
;
49 case IRQ_PXA910_TRACKBALL
:
50 awucrm
= MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_TRACKBALL
;
51 apcr
|= MPMU_APCR_SLPWP3
;
54 case IRQ_PXA910_AP1_TIMER1
:
55 awucrm
= MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_1
;
56 apcr
|= MPMU_APCR_SLPWP4
;
58 case IRQ_PXA910_AP1_TIMER2
:
59 awucrm
= MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_2
;
60 apcr
|= MPMU_APCR_SLPWP4
;
62 case IRQ_PXA910_AP1_TIMER3
:
63 awucrm
= MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_3
;
64 apcr
|= MPMU_APCR_SLPWP4
;
66 case IRQ_PXA910_AP2_TIMER1
:
67 awucrm
= MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_1
;
68 apcr
|= MPMU_APCR_SLPWP4
;
70 case IRQ_PXA910_AP2_TIMER2
:
71 awucrm
= MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_2
;
72 apcr
|= MPMU_APCR_SLPWP4
;
74 case IRQ_PXA910_AP2_TIMER3
:
75 awucrm
= MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_3
;
76 apcr
|= MPMU_APCR_SLPWP4
;
78 case IRQ_PXA910_RTC_ALARM
:
79 awucrm
= MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_RTC_ALARM
;
80 apcr
|= MPMU_APCR_SLPWP4
;
85 awucrm
= MPMU_AWUCRM_WAKEUP(5);
86 apcr
|= MPMU_APCR_SLPWP5
;
90 awucrm
= MPMU_AWUCRM_WAKEUP(6)
93 apcr
|= MPMU_APCR_SLPWP6
;
96 case IRQ_PXA910_PMIC_INT
:
97 awucrm
= MPMU_AWUCRM_WAKEUP(7);
98 apcr
|= MPMU_APCR_SLPWP7
;
101 if (irq
>= IRQ_GPIO_START
&& irq
< IRQ_BOARD_START
) {
102 awucrm
= MPMU_AWUCRM_WAKEUP(2);
103 apcr
|= MPMU_APCR_SLPWP2
;
105 /* FIXME: This should return a proper error code ! */
106 printk(KERN_ERR
"Error: no defined wake up source irq: %d\n",
113 awucrm
|= __raw_readl(MPMU_AWUCRM
);
114 __raw_writel(awucrm
, MPMU_AWUCRM
);
117 apcr
= ~apcr
& __raw_readl(MPMU_APCR
);
118 __raw_writel(apcr
, MPMU_APCR
);
122 awucrm
= ~awucrm
& __raw_readl(MPMU_AWUCRM
);
123 __raw_writel(awucrm
, MPMU_AWUCRM
);
126 apcr
|= __raw_readl(MPMU_APCR
);
127 __raw_writel(apcr
, MPMU_APCR
);
133 void pxa910_pm_enter_lowpower_mode(int state
)
135 uint32_t idle_cfg
, apcr
;
137 idle_cfg
= __raw_readl(APMU_MOH_IDLE_CFG
);
138 apcr
= __raw_readl(MPMU_APCR
);
140 apcr
&= ~(MPMU_APCR_DDRCORSD
| MPMU_APCR_APBSD
| MPMU_APCR_AXISD
141 | MPMU_APCR_VCTCXOSD
| MPMU_APCR_STBYEN
);
142 idle_cfg
&= ~(APMU_MOH_IDLE_CFG_MOH_IDLE
143 | APMU_MOH_IDLE_CFG_MOH_PWRDWN
);
147 /* only shutdown APB in UDR */
148 apcr
|= MPMU_APCR_STBYEN
| MPMU_APCR_APBSD
;
150 case POWER_MODE_SYS_SLEEP
:
151 apcr
|= MPMU_APCR_SLPEN
; /* set the SLPEN bit */
152 apcr
|= MPMU_APCR_VCTCXOSD
; /* set VCTCXOSD */
154 case POWER_MODE_APPS_SLEEP
:
155 apcr
|= MPMU_APCR_DDRCORSD
; /* set DDRCORSD */
157 case POWER_MODE_APPS_IDLE
:
158 apcr
|= MPMU_APCR_AXISD
; /* set AXISDD bit */
160 case POWER_MODE_CORE_EXTIDLE
:
161 idle_cfg
|= APMU_MOH_IDLE_CFG_MOH_IDLE
;
162 idle_cfg
|= APMU_MOH_IDLE_CFG_MOH_PWRDWN
;
163 idle_cfg
|= APMU_MOH_IDLE_CFG_MOH_PWR_SW(3)
164 | APMU_MOH_IDLE_CFG_MOH_L2_PWR_SW(3);
166 case POWER_MODE_CORE_INTIDLE
:
170 /* program the memory controller hardware sleep type and auto wakeup */
171 idle_cfg
|= APMU_MOH_IDLE_CFG_MOH_DIS_MC_SW_REQ
;
172 idle_cfg
|= APMU_MOH_IDLE_CFG_MOH_MC_WAKE_EN
;
173 __raw_writel(0x0, APMU_MC_HW_SLP_TYPE
); /* auto refresh */
175 /* set DSPSD, DTCMSD, BBSD, MSASLPEN */
176 apcr
|= MPMU_APCR_DSPSD
| MPMU_APCR_DTCMSD
| MPMU_APCR_BBSD
177 | MPMU_APCR_MSASLPEN
;
179 /*always set SLEPEN bit mainly for MSA*/
180 apcr
|= MPMU_APCR_SLPEN
;
182 /* finally write the registers back */
183 __raw_writel(idle_cfg
, APMU_MOH_IDLE_CFG
);
184 __raw_writel(apcr
, MPMU_APCR
);
188 static int pxa910_pm_enter(suspend_state_t state
)
190 unsigned int idle_cfg
, reg
= 0;
192 /*pmic thread not completed,exit;otherwise system can't be waked up*/
193 reg
= __raw_readl(ICU_INT_CONF(IRQ_PXA910_PMIC_INT
));
194 if ((reg
& 0x3) == 0)
197 idle_cfg
= __raw_readl(APMU_MOH_IDLE_CFG
);
198 idle_cfg
|= APMU_MOH_IDLE_CFG_MOH_PWRDWN
199 | APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN
;
200 __raw_writel(idle_cfg
, APMU_MOH_IDLE_CFG
);
204 /* wait for l2 idle */
205 while (!(readl(CIU_REG(0x8)) & (1 << 16)))
212 /* wait for l2 idle */
213 while (!(readl(CIU_REG(0x8)) & (1 << 16)))
216 idle_cfg
= __raw_readl(APMU_MOH_IDLE_CFG
);
217 idle_cfg
&= ~(APMU_MOH_IDLE_CFG_MOH_PWRDWN
218 | APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN
);
219 __raw_writel(idle_cfg
, APMU_MOH_IDLE_CFG
);
225 * Called after processes are frozen, but before we shut down devices.
227 static int pxa910_pm_prepare(void)
229 pxa910_pm_enter_lowpower_mode(POWER_MODE_UDR
);
234 * Called after devices are re-setup, but before processes are thawed.
236 static void pxa910_pm_finish(void)
238 pxa910_pm_enter_lowpower_mode(POWER_MODE_CORE_INTIDLE
);
241 static int pxa910_pm_valid(suspend_state_t state
)
243 return ((state
== PM_SUSPEND_STANDBY
) || (state
== PM_SUSPEND_MEM
));
246 static const struct platform_suspend_ops pxa910_pm_ops
= {
247 .valid
= pxa910_pm_valid
,
248 .prepare
= pxa910_pm_prepare
,
249 .enter
= pxa910_pm_enter
,
250 .finish
= pxa910_pm_finish
,
253 static int __init
pxa910_pm_init(void)
257 if (!cpu_is_pxa910())
260 suspend_set_ops(&pxa910_pm_ops
);
262 /* Set the following bits for MMP3 playback with VCTXO on */
263 __raw_writel(__raw_readl(APMU_SQU_CLK_GATE_CTRL
) | (1 << 30),
264 APMU_SQU_CLK_GATE_CTRL
);
265 __raw_writel(__raw_readl(MPMU_FCCR
) | (1 << 28), MPMU_FCCR
);
267 awucrm
|= MPMU_AWUCRM_AP_ASYNC_INT
| MPMU_AWUCRM_AP_FULL_IDLE
;
268 __raw_writel(awucrm
, MPMU_AWUCRM
);
273 late_initcall(pxa910_pm_init
);