Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * PXA910 Power Management Routines
0004  *
0005  * (C) Copyright 2009 Marvell International Ltd.
0006  * All Rights Reserved
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/errno.h>
0011 #include <linux/err.h>
0012 #include <linux/time.h>
0013 #include <linux/delay.h>
0014 #include <linux/suspend.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/io.h>
0017 #include <linux/irq.h>
0018 #include <asm/mach-types.h>
0019 #include <asm/outercache.h>
0020 
0021 #include <linux/soc/mmp/cputype.h>
0022 #include "addr-map.h"
0023 #include "pm-pxa910.h"
0024 #include "regs-icu.h"
0025 #include "irqs.h"
0026 
0027 int pxa910_set_wake(struct irq_data *data, unsigned int on)
0028 {
0029     uint32_t awucrm = 0, apcr = 0;
0030     int irq = data->irq;
0031 
0032     /* setting wakeup sources */
0033     switch (irq) {
0034     /* wakeup line 2 */
0035     case IRQ_PXA910_AP_GPIO:
0036         awucrm = MPMU_AWUCRM_WAKEUP(2);
0037         apcr |= MPMU_APCR_SLPWP2;
0038         break;
0039     /* wakeup line 3 */
0040     case IRQ_PXA910_KEYPAD:
0041         awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_KEYPRESS;
0042         apcr |= MPMU_APCR_SLPWP3;
0043         break;
0044     case IRQ_PXA910_ROTARY:
0045         awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_NEWROTARY;
0046         apcr |= MPMU_APCR_SLPWP3;
0047         break;
0048     case IRQ_PXA910_TRACKBALL:
0049         awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_TRACKBALL;
0050         apcr |= MPMU_APCR_SLPWP3;
0051         break;
0052     /* wakeup line 4 */
0053     case IRQ_PXA910_AP1_TIMER1:
0054         awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_1;
0055         apcr |= MPMU_APCR_SLPWP4;
0056         break;
0057     case IRQ_PXA910_AP1_TIMER2:
0058         awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_2;
0059         apcr |= MPMU_APCR_SLPWP4;
0060         break;
0061     case IRQ_PXA910_AP1_TIMER3:
0062         awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_3;
0063         apcr |= MPMU_APCR_SLPWP4;
0064         break;
0065     case IRQ_PXA910_AP2_TIMER1:
0066         awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_1;
0067         apcr |= MPMU_APCR_SLPWP4;
0068         break;
0069     case IRQ_PXA910_AP2_TIMER2:
0070         awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_2;
0071         apcr |= MPMU_APCR_SLPWP4;
0072         break;
0073     case IRQ_PXA910_AP2_TIMER3:
0074         awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_3;
0075         apcr |= MPMU_APCR_SLPWP4;
0076         break;
0077     case IRQ_PXA910_RTC_ALARM:
0078         awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_RTC_ALARM;
0079         apcr |= MPMU_APCR_SLPWP4;
0080         break;
0081     /* wakeup line 5 */
0082     case IRQ_PXA910_USB1:
0083     case IRQ_PXA910_USB2:
0084         awucrm = MPMU_AWUCRM_WAKEUP(5);
0085         apcr |= MPMU_APCR_SLPWP5;
0086         break;
0087     /* wakeup line 6 */
0088     case IRQ_PXA910_MMC:
0089         awucrm = MPMU_AWUCRM_WAKEUP(6)
0090             | MPMU_AWUCRM_SDH1
0091             | MPMU_AWUCRM_SDH2;
0092         apcr |= MPMU_APCR_SLPWP6;
0093         break;
0094     /* wakeup line 7 */
0095     case IRQ_PXA910_PMIC_INT:
0096         awucrm = MPMU_AWUCRM_WAKEUP(7);
0097         apcr |= MPMU_APCR_SLPWP7;
0098         break;
0099     default:
0100         if (irq >= IRQ_GPIO_START && irq < IRQ_BOARD_START) {
0101             awucrm = MPMU_AWUCRM_WAKEUP(2);
0102             apcr |= MPMU_APCR_SLPWP2;
0103         } else {
0104             /* FIXME: This should return a proper error code ! */
0105             printk(KERN_ERR "Error: no defined wake up source irq: %d\n",
0106                 irq);
0107         }
0108     }
0109 
0110     if (on) {
0111         if (awucrm) {
0112             awucrm |= __raw_readl(MPMU_AWUCRM);
0113             __raw_writel(awucrm, MPMU_AWUCRM);
0114         }
0115         if (apcr) {
0116             apcr = ~apcr & __raw_readl(MPMU_APCR);
0117             __raw_writel(apcr, MPMU_APCR);
0118         }
0119     } else {
0120         if (awucrm) {
0121             awucrm = ~awucrm & __raw_readl(MPMU_AWUCRM);
0122             __raw_writel(awucrm, MPMU_AWUCRM);
0123         }
0124         if (apcr) {
0125             apcr |= __raw_readl(MPMU_APCR);
0126             __raw_writel(apcr, MPMU_APCR);
0127         }
0128     }
0129     return 0;
0130 }
0131 
0132 void pxa910_pm_enter_lowpower_mode(int state)
0133 {
0134     uint32_t idle_cfg, apcr;
0135 
0136     idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG);
0137     apcr = __raw_readl(MPMU_APCR);
0138 
0139     apcr &= ~(MPMU_APCR_DDRCORSD | MPMU_APCR_APBSD | MPMU_APCR_AXISD
0140         | MPMU_APCR_VCTCXOSD | MPMU_APCR_STBYEN);
0141     idle_cfg &= ~(APMU_MOH_IDLE_CFG_MOH_IDLE
0142         | APMU_MOH_IDLE_CFG_MOH_PWRDWN);
0143 
0144     switch (state) {
0145     case POWER_MODE_UDR:
0146         /* only shutdown APB in UDR */
0147         apcr |= MPMU_APCR_STBYEN | MPMU_APCR_APBSD;
0148         fallthrough;
0149     case POWER_MODE_SYS_SLEEP:
0150         apcr |= MPMU_APCR_SLPEN;        /* set the SLPEN bit */
0151         apcr |= MPMU_APCR_VCTCXOSD;     /* set VCTCXOSD */
0152         fallthrough;
0153     case POWER_MODE_APPS_SLEEP:
0154         apcr |= MPMU_APCR_DDRCORSD;     /* set DDRCORSD */
0155         fallthrough;
0156     case POWER_MODE_APPS_IDLE:
0157         apcr |= MPMU_APCR_AXISD;        /* set AXISDD bit */
0158         fallthrough;
0159     case POWER_MODE_CORE_EXTIDLE:
0160         idle_cfg |= APMU_MOH_IDLE_CFG_MOH_IDLE;
0161         idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN;
0162         idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWR_SW(3)
0163             | APMU_MOH_IDLE_CFG_MOH_L2_PWR_SW(3);
0164         fallthrough;
0165     case POWER_MODE_CORE_INTIDLE:
0166         break;
0167     }
0168 
0169     /* program the memory controller hardware sleep type and auto wakeup */
0170     idle_cfg |= APMU_MOH_IDLE_CFG_MOH_DIS_MC_SW_REQ;
0171     idle_cfg |= APMU_MOH_IDLE_CFG_MOH_MC_WAKE_EN;
0172     __raw_writel(0x0, APMU_MC_HW_SLP_TYPE);     /* auto refresh */
0173 
0174     /* set DSPSD, DTCMSD, BBSD, MSASLPEN */
0175     apcr |= MPMU_APCR_DSPSD | MPMU_APCR_DTCMSD | MPMU_APCR_BBSD
0176         | MPMU_APCR_MSASLPEN;
0177 
0178     /*always set SLEPEN bit mainly for MSA*/
0179     apcr |= MPMU_APCR_SLPEN;
0180 
0181     /* finally write the registers back */
0182     __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG);
0183     __raw_writel(apcr, MPMU_APCR);
0184 
0185 }
0186 
0187 static int pxa910_pm_enter(suspend_state_t state)
0188 {
0189     unsigned int idle_cfg, reg = 0;
0190 
0191     /*pmic thread not completed,exit;otherwise system can't be waked up*/
0192     reg = __raw_readl(ICU_INT_CONF(IRQ_PXA910_PMIC_INT));
0193     if ((reg & 0x3) == 0)
0194         return -EAGAIN;
0195 
0196     idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG);
0197     idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN
0198         | APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN;
0199     __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG);
0200 
0201     /* disable L2 */
0202     outer_disable();
0203     /* wait for l2 idle */
0204     while (!(readl(CIU_REG(0x8)) & (1 << 16)))
0205         udelay(1);
0206 
0207     cpu_do_idle();
0208 
0209     /* enable L2 */
0210     outer_resume();
0211     /* wait for l2 idle */
0212     while (!(readl(CIU_REG(0x8)) & (1 << 16)))
0213         udelay(1);
0214 
0215     idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG);
0216     idle_cfg &= ~(APMU_MOH_IDLE_CFG_MOH_PWRDWN
0217         | APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN);
0218     __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG);
0219 
0220     return 0;
0221 }
0222 
0223 /*
0224  * Called after processes are frozen, but before we shut down devices.
0225  */
0226 static int pxa910_pm_prepare(void)
0227 {
0228     pxa910_pm_enter_lowpower_mode(POWER_MODE_UDR);
0229     return 0;
0230 }
0231 
0232 /*
0233  * Called after devices are re-setup, but before processes are thawed.
0234  */
0235 static void pxa910_pm_finish(void)
0236 {
0237     pxa910_pm_enter_lowpower_mode(POWER_MODE_CORE_INTIDLE);
0238 }
0239 
0240 static int pxa910_pm_valid(suspend_state_t state)
0241 {
0242     return ((state == PM_SUSPEND_STANDBY) || (state == PM_SUSPEND_MEM));
0243 }
0244 
0245 static const struct platform_suspend_ops pxa910_pm_ops = {
0246     .valid      = pxa910_pm_valid,
0247     .prepare    = pxa910_pm_prepare,
0248     .enter      = pxa910_pm_enter,
0249     .finish     = pxa910_pm_finish,
0250 };
0251 
0252 static int __init pxa910_pm_init(void)
0253 {
0254     uint32_t awucrm = 0;
0255 
0256     if (!cpu_is_pxa910())
0257         return -EIO;
0258 
0259     suspend_set_ops(&pxa910_pm_ops);
0260 
0261     /* Set the following bits for MMP3 playback with VCTXO on */
0262     __raw_writel(__raw_readl(APMU_SQU_CLK_GATE_CTRL) | (1 << 30),
0263         APMU_SQU_CLK_GATE_CTRL);
0264     __raw_writel(__raw_readl(MPMU_FCCR) | (1 << 28), MPMU_FCCR);
0265 
0266     awucrm |= MPMU_AWUCRM_AP_ASYNC_INT | MPMU_AWUCRM_AP_FULL_IDLE;
0267     __raw_writel(awucrm, MPMU_AWUCRM);
0268 
0269     return 0;
0270 }
0271 
0272 late_initcall(pxa910_pm_init);