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