diff options
| -rw-r--r-- | arch/arm/Kconfig | 2 | ||||
| -rw-r--r-- | arch/arm/mach-mmp/Makefile | 5 | ||||
| -rw-r--r-- | arch/arm/mach-mmp/include/mach/addr-map.h | 12 | ||||
| -rw-r--r-- | arch/arm/mach-mmp/include/mach/pm-mmp2.h | 61 | ||||
| -rw-r--r-- | arch/arm/mach-mmp/include/mach/pm-pxa910.h | 77 | ||||
| -rw-r--r-- | arch/arm/mach-mmp/include/mach/regs-apbc.h | 3 | ||||
| -rw-r--r-- | arch/arm/mach-mmp/include/mach/regs-apmu.h | 3 | ||||
| -rw-r--r-- | arch/arm/mach-mmp/irq.c | 13 | ||||
| -rw-r--r-- | arch/arm/mach-mmp/pm-mmp2.c | 264 | ||||
| -rw-r--r-- | arch/arm/mach-mmp/pm-pxa910.c | 285 | ||||
| -rw-r--r-- | arch/arm/mach-mmp/ttc_dkb.c | 11 | ||||
| -rw-r--r-- | arch/arm/mm/cache-tauros2.c | 24 | ||||
| -rw-r--r-- | arch/arm/mm/proc-mohawk.S | 35 |
13 files changed, 788 insertions, 7 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4cf9d4280972..aaa22f89fd23 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -2275,7 +2275,7 @@ source "kernel/power/Kconfig" | |||
| 2275 | config ARCH_SUSPEND_POSSIBLE | 2275 | config ARCH_SUSPEND_POSSIBLE |
| 2276 | depends on !ARCH_S5PC100 | 2276 | depends on !ARCH_S5PC100 |
| 2277 | depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \ | 2277 | depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \ |
| 2278 | CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE | 2278 | CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE || CPU_MOHAWK |
| 2279 | def_bool y | 2279 | def_bool y |
| 2280 | 2280 | ||
| 2281 | config ARM_CPU_SUSPEND | 2281 | config ARM_CPU_SUSPEND |
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile index b920b9bfbdb6..b786f7e6cd1f 100644 --- a/arch/arm/mach-mmp/Makefile +++ b/arch/arm/mach-mmp/Makefile | |||
| @@ -9,6 +9,11 @@ obj-$(CONFIG_CPU_PXA168) += pxa168.o | |||
| 9 | obj-$(CONFIG_CPU_PXA910) += pxa910.o | 9 | obj-$(CONFIG_CPU_PXA910) += pxa910.o |
| 10 | obj-$(CONFIG_CPU_MMP2) += mmp2.o sram.o | 10 | obj-$(CONFIG_CPU_MMP2) += mmp2.o sram.o |
| 11 | 11 | ||
| 12 | ifeq ($(CONFIG_PM),y) | ||
| 13 | obj-$(CONFIG_CPU_PXA910) += pm-pxa910.o | ||
| 14 | obj-$(CONFIG_CPU_MMP2) += pm-mmp2.o | ||
| 15 | endif | ||
| 16 | |||
| 12 | # board support | 17 | # board support |
| 13 | obj-$(CONFIG_MACH_ASPENITE) += aspenite.o | 18 | obj-$(CONFIG_MACH_ASPENITE) += aspenite.o |
| 14 | obj-$(CONFIG_MACH_ZYLONITE2) += aspenite.o | 19 | obj-$(CONFIG_MACH_ZYLONITE2) += aspenite.o |
diff --git a/arch/arm/mach-mmp/include/mach/addr-map.h b/arch/arm/mach-mmp/include/mach/addr-map.h index b1ece08174e8..f88a44c0ef91 100644 --- a/arch/arm/mach-mmp/include/mach/addr-map.h +++ b/arch/arm/mach-mmp/include/mach/addr-map.h | |||
| @@ -31,4 +31,16 @@ | |||
| 31 | #define SMC_CS1_PHYS_BASE 0x90000000 | 31 | #define SMC_CS1_PHYS_BASE 0x90000000 |
| 32 | #define SMC_CS1_PHYS_SIZE 0x10000000 | 32 | #define SMC_CS1_PHYS_SIZE 0x10000000 |
| 33 | 33 | ||
| 34 | #define APMU_VIRT_BASE (AXI_VIRT_BASE + 0x82800) | ||
| 35 | #define APMU_REG(x) (APMU_VIRT_BASE + (x)) | ||
| 36 | |||
| 37 | #define APBC_VIRT_BASE (APB_VIRT_BASE + 0x015000) | ||
| 38 | #define APBC_REG(x) (APBC_VIRT_BASE + (x)) | ||
| 39 | |||
| 40 | #define MPMU_VIRT_BASE (APB_VIRT_BASE + 0x50000) | ||
| 41 | #define MPMU_REG(x) (MPMU_VIRT_BASE + (x)) | ||
| 42 | |||
| 43 | #define CIU_VIRT_BASE (AXI_VIRT_BASE + 0x82c00) | ||
| 44 | #define CIU_REG(x) (CIU_VIRT_BASE + (x)) | ||
| 45 | |||
| 34 | #endif /* __ASM_MACH_ADDR_MAP_H */ | 46 | #endif /* __ASM_MACH_ADDR_MAP_H */ |
diff --git a/arch/arm/mach-mmp/include/mach/pm-mmp2.h b/arch/arm/mach-mmp/include/mach/pm-mmp2.h new file mode 100644 index 000000000000..98bd66ce8006 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/pm-mmp2.h | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | /* | ||
| 2 | * MMP2 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 2010 Marvell International Ltd. | ||
| 8 | * All Rights Reserved | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef __MMP2_PM_H__ | ||
| 12 | #define __MMP2_PM_H__ | ||
| 13 | |||
| 14 | #include <mach/addr-map.h> | ||
| 15 | |||
| 16 | #define APMU_PJ_IDLE_CFG APMU_REG(0x018) | ||
| 17 | #define APMU_PJ_IDLE_CFG_PJ_IDLE (1 << 1) | ||
| 18 | #define APMU_PJ_IDLE_CFG_PJ_PWRDWN (1 << 5) | ||
| 19 | #define APMU_PJ_IDLE_CFG_PWR_SW(x) ((x) << 16) | ||
| 20 | #define APMU_PJ_IDLE_CFG_L2_PWR_SW (1 << 19) | ||
| 21 | #define APMU_PJ_IDLE_CFG_ISO_MODE_CNTRL_MASK (3 << 28) | ||
| 22 | |||
| 23 | #define APMU_SRAM_PWR_DWN APMU_REG(0x08c) | ||
| 24 | |||
| 25 | #define MPMU_SCCR MPMU_REG(0x038) | ||
| 26 | #define MPMU_PCR_PJ MPMU_REG(0x1000) | ||
| 27 | #define MPMU_PCR_PJ_AXISD (1 << 31) | ||
| 28 | #define MPMU_PCR_PJ_SLPEN (1 << 29) | ||
| 29 | #define MPMU_PCR_PJ_SPSD (1 << 28) | ||
| 30 | #define MPMU_PCR_PJ_DDRCORSD (1 << 27) | ||
| 31 | #define MPMU_PCR_PJ_APBSD (1 << 26) | ||
| 32 | #define MPMU_PCR_PJ_INTCLR (1 << 24) | ||
| 33 | #define MPMU_PCR_PJ_SLPWP0 (1 << 23) | ||
| 34 | #define MPMU_PCR_PJ_SLPWP1 (1 << 22) | ||
| 35 | #define MPMU_PCR_PJ_SLPWP2 (1 << 21) | ||
| 36 | #define MPMU_PCR_PJ_SLPWP3 (1 << 20) | ||
| 37 | #define MPMU_PCR_PJ_VCTCXOSD (1 << 19) | ||
| 38 | #define MPMU_PCR_PJ_SLPWP4 (1 << 18) | ||
| 39 | #define MPMU_PCR_PJ_SLPWP5 (1 << 17) | ||
| 40 | #define MPMU_PCR_PJ_SLPWP6 (1 << 16) | ||
| 41 | #define MPMU_PCR_PJ_SLPWP7 (1 << 15) | ||
| 42 | |||
| 43 | #define MPMU_PLL2_CTRL1 MPMU_REG(0x0414) | ||
| 44 | #define MPMU_CGR_PJ MPMU_REG(0x1024) | ||
| 45 | #define MPMU_WUCRM_PJ MPMU_REG(0x104c) | ||
| 46 | #define MPMU_WUCRM_PJ_WAKEUP(x) (1 << (x)) | ||
| 47 | #define MPMU_WUCRM_PJ_RTC_ALARM (1 << 17) | ||
| 48 | |||
| 49 | enum { | ||
| 50 | POWER_MODE_ACTIVE = 0, | ||
| 51 | POWER_MODE_CORE_INTIDLE, | ||
| 52 | POWER_MODE_CORE_EXTIDLE, | ||
| 53 | POWER_MODE_APPS_IDLE, | ||
| 54 | POWER_MODE_APPS_SLEEP, | ||
| 55 | POWER_MODE_CHIP_SLEEP, | ||
| 56 | POWER_MODE_SYS_SLEEP, | ||
| 57 | }; | ||
| 58 | |||
| 59 | extern void mmp2_pm_enter_lowpower_mode(int state); | ||
| 60 | extern int mmp2_set_wake(struct irq_data *d, unsigned int on); | ||
| 61 | #endif | ||
diff --git a/arch/arm/mach-mmp/include/mach/pm-pxa910.h b/arch/arm/mach-mmp/include/mach/pm-pxa910.h new file mode 100644 index 000000000000..8cac8ab5253d --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/pm-pxa910.h | |||
| @@ -0,0 +1,77 @@ | |||
| 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 | #ifndef __PXA910_PM_H__ | ||
| 12 | #define __PXA910_PM_H__ | ||
| 13 | |||
| 14 | #define APMU_MOH_IDLE_CFG APMU_REG(0x0018) | ||
| 15 | #define APMU_MOH_IDLE_CFG_MOH_IDLE (1 << 1) | ||
| 16 | #define APMU_MOH_IDLE_CFG_MOH_PWRDWN (1 << 5) | ||
| 17 | #define APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN (1 << 6) | ||
| 18 | #define APMU_MOH_IDLE_CFG_MOH_PWR_SW(x) (((x) & 0x3) << 16) | ||
| 19 | #define APMU_MOH_IDLE_CFG_MOH_L2_PWR_SW(x) (((x) & 0x3) << 18) | ||
| 20 | #define APMU_MOH_IDLE_CFG_MOH_DIS_MC_SW_REQ (1 << 21) | ||
| 21 | #define APMU_MOH_IDLE_CFG_MOH_MC_WAKE_EN (1 << 20) | ||
| 22 | |||
| 23 | #define APMU_SQU_CLK_GATE_CTRL APMU_REG(0x001c) | ||
| 24 | #define APMU_MC_HW_SLP_TYPE APMU_REG(0x00b0) | ||
| 25 | |||
| 26 | #define MPMU_FCCR MPMU_REG(0x0008) | ||
| 27 | #define MPMU_APCR MPMU_REG(0x1000) | ||
| 28 | #define MPMU_APCR_AXISD (1 << 31) | ||
| 29 | #define MPMU_APCR_DSPSD (1 << 30) | ||
| 30 | #define MPMU_APCR_SLPEN (1 << 29) | ||
| 31 | #define MPMU_APCR_DTCMSD (1 << 28) | ||
| 32 | #define MPMU_APCR_DDRCORSD (1 << 27) | ||
| 33 | #define MPMU_APCR_APBSD (1 << 26) | ||
| 34 | #define MPMU_APCR_BBSD (1 << 25) | ||
| 35 | #define MPMU_APCR_SLPWP0 (1 << 23) | ||
| 36 | #define MPMU_APCR_SLPWP1 (1 << 22) | ||
| 37 | #define MPMU_APCR_SLPWP2 (1 << 21) | ||
| 38 | #define MPMU_APCR_SLPWP3 (1 << 20) | ||
| 39 | #define MPMU_APCR_VCTCXOSD (1 << 19) | ||
| 40 | #define MPMU_APCR_SLPWP4 (1 << 18) | ||
| 41 | #define MPMU_APCR_SLPWP5 (1 << 17) | ||
| 42 | #define MPMU_APCR_SLPWP6 (1 << 16) | ||
| 43 | #define MPMU_APCR_SLPWP7 (1 << 15) | ||
| 44 | #define MPMU_APCR_MSASLPEN (1 << 14) | ||
| 45 | #define MPMU_APCR_STBYEN (1 << 13) | ||
| 46 | |||
| 47 | #define MPMU_AWUCRM MPMU_REG(0x104c) | ||
| 48 | #define MPMU_AWUCRM_AP_ASYNC_INT (1 << 25) | ||
| 49 | #define MPMU_AWUCRM_AP_FULL_IDLE (1 << 24) | ||
| 50 | #define MPMU_AWUCRM_SDH1 (1 << 23) | ||
| 51 | #define MPMU_AWUCRM_SDH2 (1 << 22) | ||
| 52 | #define MPMU_AWUCRM_KEYPRESS (1 << 21) | ||
| 53 | #define MPMU_AWUCRM_TRACKBALL (1 << 20) | ||
| 54 | #define MPMU_AWUCRM_NEWROTARY (1 << 19) | ||
| 55 | #define MPMU_AWUCRM_RTC_ALARM (1 << 17) | ||
| 56 | #define MPMU_AWUCRM_AP2_TIMER_3 (1 << 13) | ||
| 57 | #define MPMU_AWUCRM_AP2_TIMER_2 (1 << 12) | ||
| 58 | #define MPMU_AWUCRM_AP2_TIMER_1 (1 << 11) | ||
| 59 | #define MPMU_AWUCRM_AP1_TIMER_3 (1 << 10) | ||
| 60 | #define MPMU_AWUCRM_AP1_TIMER_2 (1 << 9) | ||
| 61 | #define MPMU_AWUCRM_AP1_TIMER_1 (1 << 8) | ||
| 62 | #define MPMU_AWUCRM_WAKEUP(x) (1 << ((x) & 0x7)) | ||
| 63 | |||
| 64 | enum { | ||
| 65 | POWER_MODE_ACTIVE = 0, | ||
| 66 | POWER_MODE_CORE_INTIDLE, | ||
| 67 | POWER_MODE_CORE_EXTIDLE, | ||
| 68 | POWER_MODE_APPS_IDLE, | ||
| 69 | POWER_MODE_APPS_SLEEP, | ||
| 70 | POWER_MODE_SYS_SLEEP, | ||
| 71 | POWER_MODE_HIBERNATE, | ||
| 72 | POWER_MODE_UDR, | ||
| 73 | }; | ||
| 74 | |||
| 75 | extern int pxa910_set_wake(struct irq_data *data, unsigned int on); | ||
| 76 | |||
| 77 | #endif | ||
diff --git a/arch/arm/mach-mmp/include/mach/regs-apbc.h b/arch/arm/mach-mmp/include/mach/regs-apbc.h index 8a37fb003655..68b0c93ec6a1 100644 --- a/arch/arm/mach-mmp/include/mach/regs-apbc.h +++ b/arch/arm/mach-mmp/include/mach/regs-apbc.h | |||
| @@ -13,9 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | #include <mach/addr-map.h> | 14 | #include <mach/addr-map.h> |
| 15 | 15 | ||
| 16 | #define APBC_VIRT_BASE (APB_VIRT_BASE + 0x015000) | ||
| 17 | #define APBC_REG(x) (APBC_VIRT_BASE + (x)) | ||
| 18 | |||
| 19 | /* | 16 | /* |
| 20 | * APB clock register offsets for PXA168 | 17 | * APB clock register offsets for PXA168 |
| 21 | */ | 18 | */ |
diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h index 8447ac63e28f..7af8deb63e83 100644 --- a/arch/arm/mach-mmp/include/mach/regs-apmu.h +++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h | |||
| @@ -13,9 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | #include <mach/addr-map.h> | 14 | #include <mach/addr-map.h> |
| 15 | 15 | ||
| 16 | #define APMU_VIRT_BASE (AXI_VIRT_BASE + 0x82800) | ||
| 17 | #define APMU_REG(x) (APMU_VIRT_BASE + (x)) | ||
| 18 | |||
| 19 | /* Clock Reset Control */ | 16 | /* Clock Reset Control */ |
| 20 | #define APMU_IRE APMU_REG(0x048) | 17 | #define APMU_IRE APMU_REG(0x048) |
| 21 | #define APMU_LCD APMU_REG(0x04c) | 18 | #define APMU_LCD APMU_REG(0x04c) |
diff --git a/arch/arm/mach-mmp/irq.c b/arch/arm/mach-mmp/irq.c index 3705470c9f1e..fcfe0e3bd701 100644 --- a/arch/arm/mach-mmp/irq.c +++ b/arch/arm/mach-mmp/irq.c | |||
| @@ -23,6 +23,13 @@ | |||
| 23 | 23 | ||
| 24 | #include <mach/irqs.h> | 24 | #include <mach/irqs.h> |
| 25 | 25 | ||
| 26 | #ifdef CONFIG_CPU_MMP2 | ||
| 27 | #include <mach/pm-mmp2.h> | ||
| 28 | #endif | ||
| 29 | #ifdef CONFIG_CPU_PXA910 | ||
| 30 | #include <mach/pm-pxa910.h> | ||
| 31 | #endif | ||
| 32 | |||
| 26 | #include "common.h" | 33 | #include "common.h" |
| 27 | 34 | ||
| 28 | #define MAX_ICU_NR 16 | 35 | #define MAX_ICU_NR 16 |
| @@ -209,6 +216,9 @@ void __init icu_init_irq(void) | |||
| 209 | set_irq_flags(irq, IRQF_VALID); | 216 | set_irq_flags(irq, IRQF_VALID); |
| 210 | } | 217 | } |
| 211 | irq_set_default_host(icu_data[0].domain); | 218 | irq_set_default_host(icu_data[0].domain); |
| 219 | #ifdef CONFIG_CPU_PXA910 | ||
| 220 | icu_irq_chip.irq_set_wake = pxa910_set_wake; | ||
| 221 | #endif | ||
| 212 | } | 222 | } |
| 213 | 223 | ||
| 214 | /* MMP2 (ARMv7) */ | 224 | /* MMP2 (ARMv7) */ |
| @@ -305,6 +315,9 @@ void __init mmp2_init_icu(void) | |||
| 305 | set_irq_flags(irq, IRQF_VALID); | 315 | set_irq_flags(irq, IRQF_VALID); |
| 306 | } | 316 | } |
| 307 | irq_set_default_host(icu_data[0].domain); | 317 | irq_set_default_host(icu_data[0].domain); |
| 318 | #ifdef CONFIG_CPU_MMP2 | ||
| 319 | icu_irq_chip.irq_set_wake = mmp2_set_wake; | ||
| 320 | #endif | ||
| 308 | } | 321 | } |
| 309 | 322 | ||
| 310 | #ifdef CONFIG_OF | 323 | #ifdef CONFIG_OF |
diff --git a/arch/arm/mach-mmp/pm-mmp2.c b/arch/arm/mach-mmp/pm-mmp2.c new file mode 100644 index 000000000000..461a191a32d2 --- /dev/null +++ b/arch/arm/mach-mmp/pm-mmp2.c | |||
| @@ -0,0 +1,264 @@ | |||
| 1 | /* | ||
| 2 | * MMP2 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 2012 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/irq.h> | ||
| 18 | #include <linux/io.h> | ||
| 19 | #include <linux/interrupt.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-mmp2.h> | ||
| 25 | #include <mach/regs-icu.h> | ||
| 26 | #include <mach/irqs.h> | ||
| 27 | |||
| 28 | int mmp2_set_wake(struct irq_data *d, unsigned int on) | ||
| 29 | { | ||
| 30 | int irq = d->irq; | ||
| 31 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 32 | unsigned long data = 0; | ||
| 33 | |||
| 34 | if (unlikely(irq >= nr_irqs)) { | ||
| 35 | pr_err("IRQ nubmers are out of boundary!\n"); | ||
| 36 | return -EINVAL; | ||
| 37 | } | ||
| 38 | |||
| 39 | if (on) { | ||
| 40 | if (desc->action) | ||
| 41 | desc->action->flags |= IRQF_NO_SUSPEND; | ||
| 42 | } else { | ||
| 43 | if (desc->action) | ||
| 44 | desc->action->flags &= ~IRQF_NO_SUSPEND; | ||
| 45 | } | ||
| 46 | |||
| 47 | /* enable wakeup sources */ | ||
| 48 | switch (irq) { | ||
| 49 | case IRQ_MMP2_RTC: | ||
| 50 | case IRQ_MMP2_RTC_ALARM: | ||
| 51 | data = MPMU_WUCRM_PJ_WAKEUP(4) | MPMU_WUCRM_PJ_RTC_ALARM; | ||
| 52 | break; | ||
| 53 | case IRQ_MMP2_PMIC: | ||
| 54 | data = MPMU_WUCRM_PJ_WAKEUP(7); | ||
| 55 | break; | ||
| 56 | case IRQ_MMP2_MMC2: | ||
| 57 | /* mmc use WAKEUP2, same as GPIO wakeup source */ | ||
| 58 | data = MPMU_WUCRM_PJ_WAKEUP(2); | ||
| 59 | break; | ||
| 60 | } | ||
| 61 | if (on) { | ||
| 62 | if (data) { | ||
| 63 | data |= __raw_readl(MPMU_WUCRM_PJ); | ||
| 64 | __raw_writel(data, MPMU_WUCRM_PJ); | ||
| 65 | } | ||
| 66 | } else { | ||
| 67 | if (data) { | ||
| 68 | data = ~data & __raw_readl(MPMU_WUCRM_PJ); | ||
| 69 | __raw_writel(data, MPMU_WUCRM_PJ); | ||
| 70 | } | ||
| 71 | } | ||
| 72 | return 0; | ||
| 73 | } | ||
| 74 | |||
| 75 | static void pm_scu_clk_disable(void) | ||
| 76 | { | ||
| 77 | unsigned int val; | ||
| 78 | |||
| 79 | /* close AXI fabric clock gate */ | ||
| 80 | __raw_writel(0x0, CIU_REG(0x64)); | ||
| 81 | __raw_writel(0x0, CIU_REG(0x68)); | ||
| 82 | |||
| 83 | /* close MCB master clock gate */ | ||
| 84 | val = __raw_readl(CIU_REG(0x1c)); | ||
| 85 | val |= 0xf0; | ||
| 86 | __raw_writel(val, CIU_REG(0x1c)); | ||
| 87 | |||
| 88 | return ; | ||
| 89 | } | ||
| 90 | |||
| 91 | static void pm_scu_clk_enable(void) | ||
| 92 | { | ||
| 93 | unsigned int val; | ||
| 94 | |||
| 95 | /* open AXI fabric clock gate */ | ||
| 96 | __raw_writel(0x03003003, CIU_REG(0x64)); | ||
| 97 | __raw_writel(0x00303030, CIU_REG(0x68)); | ||
| 98 | |||
| 99 | /* open MCB master clock gate */ | ||
| 100 | val = __raw_readl(CIU_REG(0x1c)); | ||
| 101 | val &= ~(0xf0); | ||
| 102 | __raw_writel(val, CIU_REG(0x1c)); | ||
| 103 | |||
| 104 | return ; | ||
| 105 | } | ||
| 106 | |||
| 107 | static void pm_mpmu_clk_disable(void) | ||
| 108 | { | ||
| 109 | /* | ||
| 110 | * disable clocks in MPMU_CGR_PJ register | ||
| 111 | * except clock for APMU_PLL1, APMU_PLL1_2 and AP_26M | ||
| 112 | */ | ||
| 113 | __raw_writel(0x0000a010, MPMU_CGR_PJ); | ||
| 114 | } | ||
| 115 | |||
| 116 | static void pm_mpmu_clk_enable(void) | ||
| 117 | { | ||
| 118 | unsigned int val; | ||
| 119 | |||
| 120 | __raw_writel(0xdffefffe, MPMU_CGR_PJ); | ||
| 121 | val = __raw_readl(MPMU_PLL2_CTRL1); | ||
| 122 | val |= (1 << 29); | ||
| 123 | __raw_writel(val, MPMU_PLL2_CTRL1); | ||
| 124 | |||
| 125 | return ; | ||
| 126 | } | ||
| 127 | |||
| 128 | void mmp2_pm_enter_lowpower_mode(int state) | ||
| 129 | { | ||
| 130 | uint32_t idle_cfg, apcr; | ||
| 131 | |||
| 132 | idle_cfg = __raw_readl(APMU_PJ_IDLE_CFG); | ||
| 133 | apcr = __raw_readl(MPMU_PCR_PJ); | ||
| 134 | apcr &= ~(MPMU_PCR_PJ_SLPEN | MPMU_PCR_PJ_DDRCORSD | MPMU_PCR_PJ_APBSD | ||
| 135 | | MPMU_PCR_PJ_AXISD | MPMU_PCR_PJ_VCTCXOSD | (1 << 13)); | ||
| 136 | idle_cfg &= ~APMU_PJ_IDLE_CFG_PJ_IDLE; | ||
| 137 | |||
| 138 | switch (state) { | ||
| 139 | case POWER_MODE_SYS_SLEEP: | ||
| 140 | apcr |= MPMU_PCR_PJ_SLPEN; /* set the SLPEN bit */ | ||
| 141 | apcr |= MPMU_PCR_PJ_VCTCXOSD; /* set VCTCXOSD */ | ||
| 142 | /* fall through */ | ||
| 143 | case POWER_MODE_CHIP_SLEEP: | ||
| 144 | apcr |= MPMU_PCR_PJ_SLPEN; | ||
| 145 | /* fall through */ | ||
| 146 | case POWER_MODE_APPS_SLEEP: | ||
| 147 | apcr |= MPMU_PCR_PJ_APBSD; /* set APBSD */ | ||
| 148 | /* fall through */ | ||
| 149 | case POWER_MODE_APPS_IDLE: | ||
| 150 | apcr |= MPMU_PCR_PJ_AXISD; /* set AXISDD bit */ | ||
| 151 | apcr |= MPMU_PCR_PJ_DDRCORSD; /* set DDRCORSD bit */ | ||
| 152 | idle_cfg |= APMU_PJ_IDLE_CFG_PJ_PWRDWN; /* PJ power down */ | ||
| 153 | apcr |= MPMU_PCR_PJ_SPSD; | ||
| 154 | /* fall through */ | ||
| 155 | case POWER_MODE_CORE_EXTIDLE: | ||
| 156 | idle_cfg |= APMU_PJ_IDLE_CFG_PJ_IDLE; /* set the IDLE bit */ | ||
| 157 | idle_cfg &= ~APMU_PJ_IDLE_CFG_ISO_MODE_CNTRL_MASK; | ||
| 158 | idle_cfg |= APMU_PJ_IDLE_CFG_PWR_SW(3) | ||
| 159 | | APMU_PJ_IDLE_CFG_L2_PWR_SW; | ||
| 160 | break; | ||
| 161 | case POWER_MODE_CORE_INTIDLE: | ||
| 162 | apcr &= ~MPMU_PCR_PJ_SPSD; | ||
| 163 | break; | ||
| 164 | } | ||
| 165 | |||
| 166 | /* set reserve bits */ | ||
| 167 | apcr |= (1 << 30) | (1 << 25); | ||
| 168 | |||
| 169 | /* finally write the registers back */ | ||
| 170 | __raw_writel(idle_cfg, APMU_PJ_IDLE_CFG); | ||
| 171 | __raw_writel(apcr, MPMU_PCR_PJ); /* 0xfe086000 */ | ||
| 172 | } | ||
| 173 | |||
| 174 | static int mmp2_pm_enter(suspend_state_t state) | ||
| 175 | { | ||
| 176 | int temp; | ||
| 177 | |||
| 178 | temp = __raw_readl(MMP2_ICU_INT4_MASK); | ||
| 179 | if (temp & (1 << 1)) { | ||
| 180 | printk(KERN_ERR "%s: PMIC interrupt is handling\n", __func__); | ||
| 181 | return -EAGAIN; | ||
| 182 | } | ||
| 183 | |||
| 184 | temp = __raw_readl(APMU_SRAM_PWR_DWN); | ||
| 185 | temp |= ((1 << 19) | (1 << 18)); | ||
| 186 | __raw_writel(temp, APMU_SRAM_PWR_DWN); | ||
| 187 | pm_mpmu_clk_disable(); | ||
| 188 | pm_scu_clk_disable(); | ||
| 189 | |||
| 190 | printk(KERN_INFO "%s: before suspend\n", __func__); | ||
| 191 | cpu_do_idle(); | ||
| 192 | printk(KERN_INFO "%s: after suspend\n", __func__); | ||
| 193 | |||
| 194 | pm_mpmu_clk_enable(); /* enable clocks in MPMU */ | ||
| 195 | pm_scu_clk_enable(); /* enable clocks in SCU */ | ||
| 196 | |||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | /* | ||
| 201 | * Called after processes are frozen, but before we shut down devices. | ||
| 202 | */ | ||
| 203 | static int mmp2_pm_prepare(void) | ||
| 204 | { | ||
| 205 | mmp2_pm_enter_lowpower_mode(POWER_MODE_SYS_SLEEP); | ||
| 206 | |||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | /* | ||
| 211 | * Called after devices are re-setup, but before processes are thawed. | ||
| 212 | */ | ||
| 213 | static void mmp2_pm_finish(void) | ||
| 214 | { | ||
| 215 | mmp2_pm_enter_lowpower_mode(POWER_MODE_CORE_INTIDLE); | ||
| 216 | } | ||
| 217 | |||
| 218 | static int mmp2_pm_valid(suspend_state_t state) | ||
| 219 | { | ||
| 220 | return ((state == PM_SUSPEND_STANDBY) || (state == PM_SUSPEND_MEM)); | ||
| 221 | } | ||
| 222 | |||
| 223 | /* | ||
| 224 | * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. | ||
| 225 | */ | ||
| 226 | static const struct platform_suspend_ops mmp2_pm_ops = { | ||
| 227 | .valid = mmp2_pm_valid, | ||
| 228 | .prepare = mmp2_pm_prepare, | ||
| 229 | .enter = mmp2_pm_enter, | ||
| 230 | .finish = mmp2_pm_finish, | ||
| 231 | }; | ||
| 232 | |||
| 233 | static int __init mmp2_pm_init(void) | ||
| 234 | { | ||
| 235 | uint32_t apcr; | ||
| 236 | |||
| 237 | if (!cpu_is_mmp2()) | ||
| 238 | return -EIO; | ||
| 239 | |||
| 240 | suspend_set_ops(&mmp2_pm_ops); | ||
| 241 | |||
| 242 | /* | ||
| 243 | * Set bit 0, Slow clock Select 32K clock input instead of VCXO | ||
| 244 | * VCXO is chosen by default, which would be disabled in suspend | ||
| 245 | */ | ||
| 246 | __raw_writel(0x5, MPMU_SCCR); | ||
| 247 | |||
| 248 | /* | ||
| 249 | * Clear bit 23 of CIU_CPU_CONF | ||
| 250 | * direct PJ4 to DDR access through Memory Controller slow queue | ||
| 251 | * fast queue has issue and cause lcd will flick | ||
| 252 | */ | ||
| 253 | __raw_writel(__raw_readl(CIU_REG(0x8)) & ~(0x1 << 23), CIU_REG(0x8)); | ||
| 254 | |||
| 255 | /* Clear default low power control bit */ | ||
| 256 | apcr = __raw_readl(MPMU_PCR_PJ); | ||
| 257 | apcr &= ~(MPMU_PCR_PJ_SLPEN | MPMU_PCR_PJ_DDRCORSD | ||
| 258 | | MPMU_PCR_PJ_APBSD | MPMU_PCR_PJ_AXISD | 1 << 13); | ||
| 259 | __raw_writel(apcr, MPMU_PCR_PJ); | ||
| 260 | |||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | late_initcall(mmp2_pm_init); | ||
diff --git a/arch/arm/mach-mmp/pm-pxa910.c b/arch/arm/mach-mmp/pm-pxa910.c new file mode 100644 index 000000000000..48981ca801a5 --- /dev/null +++ b/arch/arm/mach-mmp/pm-pxa910.c | |||
| @@ -0,0 +1,285 @@ | |||
| 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 | |||
| 28 | int pxa910_set_wake(struct irq_data *data, unsigned int on) | ||
| 29 | { | ||
| 30 | int irq = data->irq; | ||
| 31 | struct irq_desc *desc = irq_to_desc(data->irq); | ||
| 32 | uint32_t awucrm = 0, apcr = 0; | ||
| 33 | |||
| 34 | if (unlikely(irq >= nr_irqs)) { | ||
| 35 | pr_err("IRQ nubmers are out of boundary!\n"); | ||
| 36 | return -EINVAL; | ||
| 37 | } | ||
| 38 | |||
| 39 | if (on) { | ||
| 40 | if (desc->action) | ||
| 41 | desc->action->flags |= IRQF_NO_SUSPEND; | ||
| 42 | } else { | ||
| 43 | if (desc->action) | ||
| 44 | desc->action->flags &= ~IRQF_NO_SUSPEND; | ||
| 45 | } | ||
| 46 | |||
| 47 | /* setting wakeup sources */ | ||
| 48 | switch (irq) { | ||
| 49 | /* wakeup line 2 */ | ||
| 50 | case IRQ_PXA910_AP_GPIO: | ||
| 51 | awucrm = MPMU_AWUCRM_WAKEUP(2); | ||
| 52 | apcr |= MPMU_APCR_SLPWP2; | ||
| 53 | break; | ||
| 54 | /* wakeup line 3 */ | ||
| 55 | case IRQ_PXA910_KEYPAD: | ||
| 56 | awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_KEYPRESS; | ||
| 57 | apcr |= MPMU_APCR_SLPWP3; | ||
| 58 | break; | ||
| 59 | case IRQ_PXA910_ROTARY: | ||
| 60 | awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_NEWROTARY; | ||
| 61 | apcr |= MPMU_APCR_SLPWP3; | ||
| 62 | break; | ||
| 63 | case IRQ_PXA910_TRACKBALL: | ||
| 64 | awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_TRACKBALL; | ||
| 65 | apcr |= MPMU_APCR_SLPWP3; | ||
| 66 | break; | ||
| 67 | /* wakeup line 4 */ | ||
| 68 | case IRQ_PXA910_AP1_TIMER1: | ||
| 69 | awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_1; | ||
| 70 | apcr |= MPMU_APCR_SLPWP4; | ||
| 71 | break; | ||
| 72 | case IRQ_PXA910_AP1_TIMER2: | ||
| 73 | awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_2; | ||
| 74 | apcr |= MPMU_APCR_SLPWP4; | ||
| 75 | break; | ||
| 76 | case IRQ_PXA910_AP1_TIMER3: | ||
| 77 | awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_3; | ||
| 78 | apcr |= MPMU_APCR_SLPWP4; | ||
| 79 | break; | ||
| 80 | case IRQ_PXA910_AP2_TIMER1: | ||
| 81 | awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_1; | ||
| 82 | apcr |= MPMU_APCR_SLPWP4; | ||
| 83 | break; | ||
| 84 | case IRQ_PXA910_AP2_TIMER2: | ||
| 85 | awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_2; | ||
| 86 | apcr |= MPMU_APCR_SLPWP4; | ||
| 87 | break; | ||
| 88 | case IRQ_PXA910_AP2_TIMER3: | ||
| 89 | awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_3; | ||
| 90 | apcr |= MPMU_APCR_SLPWP4; | ||
| 91 | break; | ||
| 92 | case IRQ_PXA910_RTC_ALARM: | ||
| 93 | awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_RTC_ALARM; | ||
| 94 | apcr |= MPMU_APCR_SLPWP4; | ||
| 95 | break; | ||
| 96 | /* wakeup line 5 */ | ||
| 97 | case IRQ_PXA910_USB1: | ||
| 98 | case IRQ_PXA910_USB2: | ||
| 99 | awucrm = MPMU_AWUCRM_WAKEUP(5); | ||
| 100 | apcr |= MPMU_APCR_SLPWP5; | ||
| 101 | break; | ||
| 102 | /* wakeup line 6 */ | ||
| 103 | case IRQ_PXA910_MMC: | ||
| 104 | awucrm = MPMU_AWUCRM_WAKEUP(6) | ||
| 105 | | MPMU_AWUCRM_SDH1 | ||
| 106 | | MPMU_AWUCRM_SDH2; | ||
| 107 | apcr |= MPMU_APCR_SLPWP6; | ||
| 108 | break; | ||
| 109 | /* wakeup line 7 */ | ||
| 110 | case IRQ_PXA910_PMIC_INT: | ||
| 111 | awucrm = MPMU_AWUCRM_WAKEUP(7); | ||
| 112 | apcr |= MPMU_APCR_SLPWP7; | ||
| 113 | break; | ||
| 114 | default: | ||
| 115 | if (irq >= IRQ_GPIO_START && irq < IRQ_BOARD_START) { | ||
| 116 | awucrm = MPMU_AWUCRM_WAKEUP(2); | ||
| 117 | apcr |= MPMU_APCR_SLPWP2; | ||
| 118 | } else | ||
| 119 | printk(KERN_ERR "Error: no defined wake up source irq: %d\n", | ||
| 120 | irq); | ||
| 121 | } | ||
| 122 | |||
| 123 | if (on) { | ||
| 124 | if (awucrm) { | ||
| 125 | awucrm |= __raw_readl(MPMU_AWUCRM); | ||
| 126 | __raw_writel(awucrm, MPMU_AWUCRM); | ||
| 127 | } | ||
| 128 | if (apcr) { | ||
| 129 | apcr = ~apcr & __raw_readl(MPMU_APCR); | ||
| 130 | __raw_writel(apcr, MPMU_APCR); | ||
| 131 | } | ||
| 132 | } else { | ||
| 133 | if (awucrm) { | ||
| 134 | awucrm = ~awucrm & __raw_readl(MPMU_AWUCRM); | ||
| 135 | __raw_writel(awucrm, MPMU_AWUCRM); | ||
| 136 | } | ||
| 137 | if (apcr) { | ||
| 138 | apcr |= __raw_readl(MPMU_APCR); | ||
| 139 | __raw_writel(apcr, MPMU_APCR); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | void pxa910_pm_enter_lowpower_mode(int state) | ||
| 146 | { | ||
| 147 | uint32_t idle_cfg, apcr; | ||
| 148 | |||
| 149 | idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG); | ||
| 150 | apcr = __raw_readl(MPMU_APCR); | ||
| 151 | |||
| 152 | apcr &= ~(MPMU_APCR_DDRCORSD | MPMU_APCR_APBSD | MPMU_APCR_AXISD | ||
| 153 | | MPMU_APCR_VCTCXOSD | MPMU_APCR_STBYEN); | ||
| 154 | idle_cfg &= ~(APMU_MOH_IDLE_CFG_MOH_IDLE | ||
| 155 | | APMU_MOH_IDLE_CFG_MOH_PWRDWN); | ||
| 156 | |||
| 157 | switch (state) { | ||
| 158 | case POWER_MODE_UDR: | ||
| 159 | /* only shutdown APB in UDR */ | ||
| 160 | apcr |= MPMU_APCR_STBYEN | MPMU_APCR_APBSD; | ||
| 161 | /* fall through */ | ||
| 162 | case POWER_MODE_SYS_SLEEP: | ||
| 163 | apcr |= MPMU_APCR_SLPEN; /* set the SLPEN bit */ | ||
| 164 | apcr |= MPMU_APCR_VCTCXOSD; /* set VCTCXOSD */ | ||
| 165 | /* fall through */ | ||
| 166 | case POWER_MODE_APPS_SLEEP: | ||
| 167 | apcr |= MPMU_APCR_DDRCORSD; /* set DDRCORSD */ | ||
| 168 | /* fall through */ | ||
| 169 | case POWER_MODE_APPS_IDLE: | ||
| 170 | apcr |= MPMU_APCR_AXISD; /* set AXISDD bit */ | ||
| 171 | /* fall through */ | ||
| 172 | case POWER_MODE_CORE_EXTIDLE: | ||
| 173 | idle_cfg |= APMU_MOH_IDLE_CFG_MOH_IDLE; | ||
| 174 | idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN; | ||
| 175 | idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWR_SW(3) | ||
| 176 | | APMU_MOH_IDLE_CFG_MOH_L2_PWR_SW(3); | ||
| 177 | /* fall through */ | ||
| 178 | case POWER_MODE_CORE_INTIDLE: | ||
| 179 | break; | ||
| 180 | } | ||
| 181 | |||
| 182 | /* program the memory controller hardware sleep type and auto wakeup */ | ||
| 183 | idle_cfg |= APMU_MOH_IDLE_CFG_MOH_DIS_MC_SW_REQ; | ||
| 184 | idle_cfg |= APMU_MOH_IDLE_CFG_MOH_MC_WAKE_EN; | ||
| 185 | __raw_writel(0x0, APMU_MC_HW_SLP_TYPE); /* auto refresh */ | ||
| 186 | |||
| 187 | /* set DSPSD, DTCMSD, BBSD, MSASLPEN */ | ||
| 188 | apcr |= MPMU_APCR_DSPSD | MPMU_APCR_DTCMSD | MPMU_APCR_BBSD | ||
| 189 | | MPMU_APCR_MSASLPEN; | ||
| 190 | |||
| 191 | /*always set SLEPEN bit mainly for MSA*/ | ||
| 192 | apcr |= MPMU_APCR_SLPEN; | ||
| 193 | |||
| 194 | /* finally write the registers back */ | ||
| 195 | __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG); | ||
| 196 | __raw_writel(apcr, MPMU_APCR); | ||
| 197 | |||
| 198 | } | ||
| 199 | |||
| 200 | static int pxa910_pm_enter(suspend_state_t state) | ||
| 201 | { | ||
| 202 | unsigned int idle_cfg, reg = 0; | ||
| 203 | |||
| 204 | /*pmic thread not completed,exit;otherwise system can't be waked up*/ | ||
| 205 | reg = __raw_readl(ICU_INT_CONF(IRQ_PXA910_PMIC_INT)); | ||
| 206 | if ((reg & 0x3) == 0) | ||
| 207 | return -EAGAIN; | ||
| 208 | |||
| 209 | idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG); | ||
| 210 | idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN | ||
| 211 | | APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN; | ||
| 212 | __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG); | ||
| 213 | |||
| 214 | /* disable L2 */ | ||
| 215 | outer_disable(); | ||
| 216 | /* wait for l2 idle */ | ||
| 217 | while (!(readl(CIU_REG(0x8)) & (1 << 16))) | ||
| 218 | udelay(1); | ||
| 219 | |||
| 220 | cpu_do_idle(); | ||
| 221 | |||
| 222 | /* enable L2 */ | ||
| 223 | outer_resume(); | ||
| 224 | /* wait for l2 idle */ | ||
| 225 | while (!(readl(CIU_REG(0x8)) & (1 << 16))) | ||
| 226 | udelay(1); | ||
| 227 | |||
| 228 | idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG); | ||
| 229 | idle_cfg &= ~(APMU_MOH_IDLE_CFG_MOH_PWRDWN | ||
| 230 | | APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN); | ||
| 231 | __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG); | ||
| 232 | |||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | /* | ||
| 237 | * Called after processes are frozen, but before we shut down devices. | ||
| 238 | */ | ||
| 239 | static int pxa910_pm_prepare(void) | ||
| 240 | { | ||
| 241 | pxa910_pm_enter_lowpower_mode(POWER_MODE_UDR); | ||
| 242 | return 0; | ||
| 243 | } | ||
| 244 | |||
| 245 | /* | ||
| 246 | * Called after devices are re-setup, but before processes are thawed. | ||
| 247 | */ | ||
| 248 | static void pxa910_pm_finish(void) | ||
| 249 | { | ||
| 250 | pxa910_pm_enter_lowpower_mode(POWER_MODE_CORE_INTIDLE); | ||
| 251 | } | ||
| 252 | |||
| 253 | static int pxa910_pm_valid(suspend_state_t state) | ||
| 254 | { | ||
| 255 | return ((state == PM_SUSPEND_STANDBY) || (state == PM_SUSPEND_MEM)); | ||
| 256 | } | ||
| 257 | |||
| 258 | static const struct platform_suspend_ops pxa910_pm_ops = { | ||
| 259 | .valid = pxa910_pm_valid, | ||
| 260 | .prepare = pxa910_pm_prepare, | ||
| 261 | .enter = pxa910_pm_enter, | ||
| 262 | .finish = pxa910_pm_finish, | ||
| 263 | }; | ||
| 264 | |||
| 265 | static int __init pxa910_pm_init(void) | ||
| 266 | { | ||
| 267 | uint32_t awucrm = 0; | ||
| 268 | |||
| 269 | if (!cpu_is_pxa910()) | ||
| 270 | return -EIO; | ||
| 271 | |||
| 272 | suspend_set_ops(&pxa910_pm_ops); | ||
| 273 | |||
| 274 | /* Set the following bits for MMP3 playback with VCTXO on */ | ||
| 275 | __raw_writel(__raw_readl(APMU_SQU_CLK_GATE_CTRL) | (1 << 30), | ||
| 276 | APMU_SQU_CLK_GATE_CTRL); | ||
| 277 | __raw_writel(__raw_readl(MPMU_FCCR) | (1 << 28), MPMU_FCCR); | ||
| 278 | |||
| 279 | awucrm |= MPMU_AWUCRM_AP_ASYNC_INT | MPMU_AWUCRM_AP_FULL_IDLE; | ||
| 280 | __raw_writel(awucrm, MPMU_AWUCRM); | ||
| 281 | |||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | |||
| 285 | late_initcall(pxa910_pm_init); | ||
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c index 3fc9ed21f97d..e8cf5ea15263 100644 --- a/arch/arm/mach-mmp/ttc_dkb.c +++ b/arch/arm/mach-mmp/ttc_dkb.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
| 18 | #include <linux/i2c/pca953x.h> | 18 | #include <linux/i2c/pca953x.h> |
| 19 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
| 20 | #include <linux/mfd/88pm860x.h> | ||
| 20 | 21 | ||
| 21 | #include <asm/mach-types.h> | 22 | #include <asm/mach-types.h> |
| 22 | #include <asm/mach/arch.h> | 23 | #include <asm/mach/arch.h> |
| @@ -135,8 +136,18 @@ static struct pca953x_platform_data max7312_data[] = { | |||
| 135 | }, | 136 | }, |
| 136 | }; | 137 | }; |
| 137 | 138 | ||
| 139 | static struct pm860x_platform_data ttc_dkb_pm8607_info = { | ||
| 140 | .irq_base = IRQ_BOARD_START, | ||
| 141 | }; | ||
| 142 | |||
| 138 | static struct i2c_board_info ttc_dkb_i2c_info[] = { | 143 | static struct i2c_board_info ttc_dkb_i2c_info[] = { |
| 139 | { | 144 | { |
| 145 | .type = "88PM860x", | ||
| 146 | .addr = 0x34, | ||
| 147 | .platform_data = &ttc_dkb_pm8607_info, | ||
| 148 | .irq = IRQ_PXA910_PMIC_INT, | ||
| 149 | }, | ||
| 150 | { | ||
| 140 | .type = "max7312", | 151 | .type = "max7312", |
| 141 | .addr = 0x23, | 152 | .addr = 0x23, |
| 142 | .irq = MMP_GPIO_TO_IRQ(80), | 153 | .irq = MMP_GPIO_TO_IRQ(80), |
diff --git a/arch/arm/mm/cache-tauros2.c b/arch/arm/mm/cache-tauros2.c index 1fbca05fe906..23a7643e9a87 100644 --- a/arch/arm/mm/cache-tauros2.c +++ b/arch/arm/mm/cache-tauros2.c | |||
| @@ -108,6 +108,26 @@ static void tauros2_flush_range(unsigned long start, unsigned long end) | |||
| 108 | 108 | ||
| 109 | dsb(); | 109 | dsb(); |
| 110 | } | 110 | } |
| 111 | |||
| 112 | static void tauros2_disable(void) | ||
| 113 | { | ||
| 114 | __asm__ __volatile__ ( | ||
| 115 | "mcr p15, 1, %0, c7, c11, 0 @L2 Cache Clean All\n\t" | ||
| 116 | "mrc p15, 0, %0, c1, c0, 0\n\t" | ||
| 117 | "bic %0, %0, #(1 << 26)\n\t" | ||
| 118 | "mcr p15, 0, %0, c1, c0, 0 @Disable L2 Cache\n\t" | ||
| 119 | : : "r" (0x0)); | ||
| 120 | } | ||
| 121 | |||
| 122 | static void tauros2_resume(void) | ||
| 123 | { | ||
| 124 | __asm__ __volatile__ ( | ||
| 125 | "mcr p15, 1, %0, c7, c7, 0 @L2 Cache Invalidate All\n\t" | ||
| 126 | "mrc p15, 0, %0, c1, c0, 0\n\t" | ||
| 127 | "orr %0, %0, #(1 << 26)\n\t" | ||
| 128 | "mcr p15, 0, %0, c1, c0, 0 @Enable L2 Cache\n\t" | ||
| 129 | : : "r" (0x0)); | ||
| 130 | } | ||
| 111 | #endif | 131 | #endif |
| 112 | 132 | ||
| 113 | static inline u32 __init read_extra_features(void) | 133 | static inline u32 __init read_extra_features(void) |
| @@ -194,6 +214,8 @@ void __init tauros2_init(void) | |||
| 194 | outer_cache.inv_range = tauros2_inv_range; | 214 | outer_cache.inv_range = tauros2_inv_range; |
| 195 | outer_cache.clean_range = tauros2_clean_range; | 215 | outer_cache.clean_range = tauros2_clean_range; |
| 196 | outer_cache.flush_range = tauros2_flush_range; | 216 | outer_cache.flush_range = tauros2_flush_range; |
| 217 | outer_cache.disable = tauros2_disable; | ||
| 218 | outer_cache.resume = tauros2_resume; | ||
| 197 | } | 219 | } |
| 198 | #endif | 220 | #endif |
| 199 | 221 | ||
| @@ -219,6 +241,8 @@ void __init tauros2_init(void) | |||
| 219 | outer_cache.inv_range = tauros2_inv_range; | 241 | outer_cache.inv_range = tauros2_inv_range; |
| 220 | outer_cache.clean_range = tauros2_clean_range; | 242 | outer_cache.clean_range = tauros2_clean_range; |
| 221 | outer_cache.flush_range = tauros2_flush_range; | 243 | outer_cache.flush_range = tauros2_flush_range; |
| 244 | outer_cache.disable = tauros2_disable; | ||
| 245 | outer_cache.resume = tauros2_resume; | ||
| 222 | } | 246 | } |
| 223 | #endif | 247 | #endif |
| 224 | 248 | ||
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S index cdfedc5b8ad8..6a050b19cdf5 100644 --- a/arch/arm/mm/proc-mohawk.S +++ b/arch/arm/mm/proc-mohawk.S | |||
| @@ -344,6 +344,41 @@ ENTRY(cpu_mohawk_set_pte_ext) | |||
| 344 | mcr p15, 0, r0, c7, c10, 4 @ drain WB | 344 | mcr p15, 0, r0, c7, c10, 4 @ drain WB |
| 345 | mov pc, lr | 345 | mov pc, lr |
| 346 | 346 | ||
| 347 | .globl cpu_mohawk_suspend_size | ||
| 348 | .equ cpu_mohawk_suspend_size, 4 * 6 | ||
| 349 | #ifdef CONFIG_PM_SLEEP | ||
| 350 | ENTRY(cpu_mohawk_do_suspend) | ||
| 351 | stmfd sp!, {r4 - r9, lr} | ||
| 352 | mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode | ||
| 353 | mrc p15, 0, r5, c15, c1, 0 @ CP access reg | ||
| 354 | mrc p15, 0, r6, c13, c0, 0 @ PID | ||
| 355 | mrc p15, 0, r7, c3, c0, 0 @ domain ID | ||
| 356 | mrc p15, 0, r8, c1, c0, 1 @ auxiliary control reg | ||
| 357 | mrc p15, 0, r9, c1, c0, 0 @ control reg | ||
| 358 | bic r4, r4, #2 @ clear frequency change bit | ||
| 359 | stmia r0, {r4 - r9} @ store cp regs | ||
| 360 | ldmia sp!, {r4 - r9, pc} | ||
| 361 | ENDPROC(cpu_mohawk_do_suspend) | ||
| 362 | |||
| 363 | ENTRY(cpu_mohawk_do_resume) | ||
| 364 | ldmia r0, {r4 - r9} @ load cp regs | ||
| 365 | mov ip, #0 | ||
| 366 | mcr p15, 0, ip, c7, c7, 0 @ invalidate I & D caches, BTB | ||
| 367 | mcr p15, 0, ip, c7, c10, 4 @ drain write (&fill) buffer | ||
| 368 | mcr p15, 0, ip, c7, c5, 4 @ flush prefetch buffer | ||
| 369 | mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs | ||
| 370 | mcr p14, 0, r4, c6, c0, 0 @ clock configuration, turbo mode. | ||
| 371 | mcr p15, 0, r5, c15, c1, 0 @ CP access reg | ||
| 372 | mcr p15, 0, r6, c13, c0, 0 @ PID | ||
| 373 | mcr p15, 0, r7, c3, c0, 0 @ domain ID | ||
| 374 | orr r1, r1, #0x18 @ cache the page table in L2 | ||
| 375 | mcr p15, 0, r1, c2, c0, 0 @ translation table base addr | ||
| 376 | mcr p15, 0, r8, c1, c0, 1 @ auxiliary control reg | ||
| 377 | mov r0, r9 @ control register | ||
| 378 | b cpu_resume_mmu | ||
| 379 | ENDPROC(cpu_mohawk_do_resume) | ||
| 380 | #endif | ||
| 381 | |||
| 347 | __CPUINIT | 382 | __CPUINIT |
| 348 | 383 | ||
| 349 | .type __mohawk_setup, #function | 384 | .type __mohawk_setup, #function |
