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