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 28int pxa910_set_wake(struct irq_data *data, unsigned int on) 29{ 30 uint32_t awucrm = 0, apcr = 0; 31 int irq = data->irq; 32 33 /* setting wakeup sources */ 34 switch (irq) { 35 /* wakeup line 2 */ 36 case IRQ_PXA910_AP_GPIO: 37 awucrm = MPMU_AWUCRM_WAKEUP(2); 38 apcr |= MPMU_APCR_SLPWP2; 39 break; 40 /* wakeup line 3 */ 41 case IRQ_PXA910_KEYPAD: 42 awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_KEYPRESS; 43 apcr |= MPMU_APCR_SLPWP3; 44 break; 45 case IRQ_PXA910_ROTARY: 46 awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_NEWROTARY; 47 apcr |= MPMU_APCR_SLPWP3; 48 break; 49 case IRQ_PXA910_TRACKBALL: 50 awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_TRACKBALL; 51 apcr |= MPMU_APCR_SLPWP3; 52 break; 53 /* wakeup line 4 */ 54 case IRQ_PXA910_AP1_TIMER1: 55 awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_1; 56 apcr |= MPMU_APCR_SLPWP4; 57 break; 58 case IRQ_PXA910_AP1_TIMER2: 59 awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_2; 60 apcr |= MPMU_APCR_SLPWP4; 61 break; 62 case IRQ_PXA910_AP1_TIMER3: 63 awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_3; 64 apcr |= MPMU_APCR_SLPWP4; 65 break; 66 case IRQ_PXA910_AP2_TIMER1: 67 awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_1; 68 apcr |= MPMU_APCR_SLPWP4; 69 break; 70 case IRQ_PXA910_AP2_TIMER2: 71 awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_2; 72 apcr |= MPMU_APCR_SLPWP4; 73 break; 74 case IRQ_PXA910_AP2_TIMER3: 75 awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_3; 76 apcr |= MPMU_APCR_SLPWP4; 77 break; 78 case IRQ_PXA910_RTC_ALARM: 79 awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_RTC_ALARM; 80 apcr |= MPMU_APCR_SLPWP4; 81 break; 82 /* wakeup line 5 */ 83 case IRQ_PXA910_USB1: 84 case IRQ_PXA910_USB2: 85 awucrm = MPMU_AWUCRM_WAKEUP(5); 86 apcr |= MPMU_APCR_SLPWP5; 87 break; 88 /* wakeup line 6 */ 89 case IRQ_PXA910_MMC: 90 awucrm = MPMU_AWUCRM_WAKEUP(6) 91 | MPMU_AWUCRM_SDH1 92 | MPMU_AWUCRM_SDH2; 93 apcr |= MPMU_APCR_SLPWP6; 94 break; 95 /* wakeup line 7 */ 96 case IRQ_PXA910_PMIC_INT: 97 awucrm = MPMU_AWUCRM_WAKEUP(7); 98 apcr |= MPMU_APCR_SLPWP7; 99 break; 100 default: 101 if (irq >= IRQ_GPIO_START && irq < IRQ_BOARD_START) { 102 awucrm = MPMU_AWUCRM_WAKEUP(2); 103 apcr |= MPMU_APCR_SLPWP2; 104 } else { 105 /* FIXME: This should return a proper error code ! */ 106 printk(KERN_ERR "Error: no defined wake up source irq: %d\n", 107 irq); 108 } 109 } 110 111 if (on) { 112 if (awucrm) { 113 awucrm |= __raw_readl(MPMU_AWUCRM); 114 __raw_writel(awucrm, MPMU_AWUCRM); 115 } 116 if (apcr) { 117 apcr = ~apcr & __raw_readl(MPMU_APCR); 118 __raw_writel(apcr, MPMU_APCR); 119 } 120 } else { 121 if (awucrm) { 122 awucrm = ~awucrm & __raw_readl(MPMU_AWUCRM); 123 __raw_writel(awucrm, MPMU_AWUCRM); 124 } 125 if (apcr) { 126 apcr |= __raw_readl(MPMU_APCR); 127 __raw_writel(apcr, MPMU_APCR); 128 } 129 } 130 return 0; 131} 132 133void pxa910_pm_enter_lowpower_mode(int state) 134{ 135 uint32_t idle_cfg, apcr; 136 137 idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG); 138 apcr = __raw_readl(MPMU_APCR); 139 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); 144 145 switch (state) { 146 case POWER_MODE_UDR: 147 /* only shutdown APB in UDR */ 148 apcr |= MPMU_APCR_STBYEN | MPMU_APCR_APBSD; 149 /* fall through */ 150 case POWER_MODE_SYS_SLEEP: 151 apcr |= MPMU_APCR_SLPEN; /* set the SLPEN bit */ 152 apcr |= MPMU_APCR_VCTCXOSD; /* set VCTCXOSD */ 153 /* fall through */ 154 case POWER_MODE_APPS_SLEEP: 155 apcr |= MPMU_APCR_DDRCORSD; /* set DDRCORSD */ 156 /* fall through */ 157 case POWER_MODE_APPS_IDLE: 158 apcr |= MPMU_APCR_AXISD; /* set AXISDD bit */ 159 /* fall through */ 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); 165 /* fall through */ 166 case POWER_MODE_CORE_INTIDLE: 167 break; 168 } 169 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 */ 174 175 /* set DSPSD, DTCMSD, BBSD, MSASLPEN */ 176 apcr |= MPMU_APCR_DSPSD | MPMU_APCR_DTCMSD | MPMU_APCR_BBSD 177 | MPMU_APCR_MSASLPEN; 178 179 /*always set SLEPEN bit mainly for MSA*/ 180 apcr |= MPMU_APCR_SLPEN; 181 182 /* finally write the registers back */ 183 __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG); 184 __raw_writel(apcr, MPMU_APCR); 185 186} 187 188static int pxa910_pm_enter(suspend_state_t state) 189{ 190 unsigned int idle_cfg, reg = 0; 191 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) 195 return -EAGAIN; 196 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); 201 202 /* disable L2 */ 203 outer_disable(); 204 /* wait for l2 idle */ 205 while (!(readl(CIU_REG(0x8)) & (1 << 16))) 206 udelay(1); 207 208 cpu_do_idle(); 209 210 /* enable L2 */ 211 outer_resume(); 212 /* wait for l2 idle */ 213 while (!(readl(CIU_REG(0x8)) & (1 << 16))) 214 udelay(1); 215 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); 220 221 return 0; 222} 223 224/* 225 * Called after processes are frozen, but before we shut down devices. 226 */ 227static int pxa910_pm_prepare(void) 228{ 229 pxa910_pm_enter_lowpower_mode(POWER_MODE_UDR); 230 return 0; 231} 232 233/* 234 * Called after devices are re-setup, but before processes are thawed. 235 */ 236static void pxa910_pm_finish(void) 237{ 238 pxa910_pm_enter_lowpower_mode(POWER_MODE_CORE_INTIDLE); 239} 240 241static int pxa910_pm_valid(suspend_state_t state) 242{ 243 return ((state == PM_SUSPEND_STANDBY) || (state == PM_SUSPEND_MEM)); 244} 245 246static 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, 251}; 252 253static int __init pxa910_pm_init(void) 254{ 255 uint32_t awucrm = 0; 256 257 if (!cpu_is_pxa910()) 258 return -EIO; 259 260 suspend_set_ops(&pxa910_pm_ops); 261 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); 266 267 awucrm |= MPMU_AWUCRM_AP_ASYNC_INT | MPMU_AWUCRM_AP_FULL_IDLE; 268 __raw_writel(awucrm, MPMU_AWUCRM); 269 270 return 0; 271} 272 273late_initcall(pxa910_pm_init); 274