From b77ca655f343bf85578b24b1a3edfbc08336544c Mon Sep 17 00:00:00 2001 From: Jaecheol Lee Date: Thu, 10 Mar 2011 13:21:51 +0900 Subject: [PATCH 1/3] ARM: EXYNOS4: Add PMU and CMU Registers for PM This patch adds definitions of PMU and CMU registers for EXYNOS4 PM. Signed-off-by: Jaecheol Lee Signed-off-by: Kukjin Kim --- .../mach-exynos4/include/mach/regs-clock.h | 22 ++- arch/arm/mach-exynos4/include/mach/regs-pmu.h | 143 ++++++++++++++++-- 2 files changed, 154 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-exynos4/include/mach/regs-clock.h b/arch/arm/mach-exynos4/include/mach/regs-clock.h index ba8f91c04e19..084c3f05c093 100644 --- a/arch/arm/mach-exynos4/include/mach/regs-clock.h +++ b/arch/arm/mach-exynos4/include/mach/regs-clock.h @@ -17,13 +17,13 @@ #define S5P_CLKREG(x) (S5P_VA_CMU + (x)) -#define S5P_INFORM0 S5P_CLKREG(0x800) - #define S5P_CLKDIV_LEFTBUS S5P_CLKREG(0x04500) #define S5P_CLKDIV_STAT_LEFTBUS S5P_CLKREG(0x04600) +#define S5P_CLKGATE_IP_LEFTBUS S5P_CLKREG(0x04800) #define S5P_CLKDIV_RIGHTBUS S5P_CLKREG(0x08500) #define S5P_CLKDIV_STAT_RIGHTBUS S5P_CLKREG(0x08600) +#define S5P_CLKGATE_IP_RIGHTBUS S5P_CLKREG(0x08800) #define S5P_EPLL_CON0 S5P_CLKREG(0x0C110) #define S5P_EPLL_CON1 S5P_CLKREG(0x0C114) @@ -33,18 +33,24 @@ #define S5P_CLKSRC_TOP0 S5P_CLKREG(0x0C210) #define S5P_CLKSRC_TOP1 S5P_CLKREG(0x0C214) #define S5P_CLKSRC_CAM S5P_CLKREG(0x0C220) +#define S5P_CLKSRC_MFC S5P_CLKREG(0x0C228) #define S5P_CLKSRC_IMAGE S5P_CLKREG(0x0C230) #define S5P_CLKSRC_LCD0 S5P_CLKREG(0x0C234) #define S5P_CLKSRC_LCD1 S5P_CLKREG(0x0C238) +#define S5P_CLKSRC_MAUDIO S5P_CLKREG(0x0C23C) #define S5P_CLKSRC_FSYS S5P_CLKREG(0x0C240) #define S5P_CLKSRC_PERIL0 S5P_CLKREG(0x0C250) #define S5P_CLKSRC_PERIL1 S5P_CLKREG(0x0C254) #define S5P_CLKDIV_TOP S5P_CLKREG(0x0C510) #define S5P_CLKDIV_CAM S5P_CLKREG(0x0C520) +#define S5P_CLKDIV_TV S5P_CLKREG(0x0C524) +#define S5P_CLKDIV_MFC S5P_CLKREG(0x0C528) +#define S5P_CLKDIV_G3D S5P_CLKREG(0x0C52C) #define S5P_CLKDIV_IMAGE S5P_CLKREG(0x0C530) #define S5P_CLKDIV_LCD0 S5P_CLKREG(0x0C534) #define S5P_CLKDIV_LCD1 S5P_CLKREG(0x0C538) +#define S5P_CLKDIV_MAUDIO S5P_CLKREG(0x0C53C) #define S5P_CLKDIV_FSYS0 S5P_CLKREG(0x0C540) #define S5P_CLKDIV_FSYS1 S5P_CLKREG(0x0C544) #define S5P_CLKDIV_FSYS2 S5P_CLKREG(0x0C548) @@ -58,25 +64,36 @@ #define S5P_CLKSRC_MASK_TOP S5P_CLKREG(0x0C310) #define S5P_CLKSRC_MASK_CAM S5P_CLKREG(0x0C320) +#define S5P_CLKSRC_MASK_TV S5P_CLKREG(0x0C324) #define S5P_CLKSRC_MASK_LCD0 S5P_CLKREG(0x0C334) #define S5P_CLKSRC_MASK_LCD1 S5P_CLKREG(0x0C338) +#define S5P_CLKSRC_MASK_MAUDIO S5P_CLKREG(0x0C33C) #define S5P_CLKSRC_MASK_FSYS S5P_CLKREG(0x0C340) #define S5P_CLKSRC_MASK_PERIL0 S5P_CLKREG(0x0C350) #define S5P_CLKSRC_MASK_PERIL1 S5P_CLKREG(0x0C354) #define S5P_CLKDIV_STAT_TOP S5P_CLKREG(0x0C610) +#define S5P_CLKGATE_SCLKCAM S5P_CLKREG(0x0C820) #define S5P_CLKGATE_IP_CAM S5P_CLKREG(0x0C920) +#define S5P_CLKGATE_IP_TV S5P_CLKREG(0x0C924) +#define S5P_CLKGATE_IP_MFC S5P_CLKREG(0x0C928) +#define S5P_CLKGATE_IP_G3D S5P_CLKREG(0x0C92C) #define S5P_CLKGATE_IP_IMAGE S5P_CLKREG(0x0C930) #define S5P_CLKGATE_IP_LCD0 S5P_CLKREG(0x0C934) #define S5P_CLKGATE_IP_LCD1 S5P_CLKREG(0x0C938) #define S5P_CLKGATE_IP_FSYS S5P_CLKREG(0x0C940) +#define S5P_CLKGATE_IP_GPS S5P_CLKREG(0x0C94C) #define S5P_CLKGATE_IP_PERIL S5P_CLKREG(0x0C950) #define S5P_CLKGATE_IP_PERIR S5P_CLKREG(0x0C960) +#define S5P_CLKGATE_BLOCK S5P_CLKREG(0x0C970) +#define S5P_CLKSRC_MASK_DMC S5P_CLKREG(0x10300) #define S5P_CLKSRC_DMC S5P_CLKREG(0x10200) #define S5P_CLKDIV_DMC0 S5P_CLKREG(0x10500) +#define S5P_CLKDIV_DMC1 S5P_CLKREG(0x10504) #define S5P_CLKDIV_STAT_DMC0 S5P_CLKREG(0x10600) +#define S5P_CLKGATE_IP_DMC S5P_CLKREG(0x10900) #define S5P_APLL_LOCK S5P_CLKREG(0x14000) #define S5P_MPLL_LOCK S5P_CLKREG(0x14004) @@ -94,6 +111,7 @@ #define S5P_CLKDIV_STATCPU1 S5P_CLKREG(0x14604) #define S5P_CLKGATE_SCLKCPU S5P_CLKREG(0x14800) +#define S5P_CLKGATE_IP_CPU S5P_CLKREG(0x14900) /* APLL_LOCK */ #define S5P_APLL_LOCKTIME (0x1C20) /* 300us */ diff --git a/arch/arm/mach-exynos4/include/mach/regs-pmu.h b/arch/arm/mach-exynos4/include/mach/regs-pmu.h index 2ddd6175dfa0..84aa17bd4dd8 100644 --- a/arch/arm/mach-exynos4/include/mach/regs-pmu.h +++ b/arch/arm/mach-exynos4/include/mach/regs-pmu.h @@ -15,16 +15,141 @@ #include -#define S5P_PMUREG(x) (S5P_VA_PMU + (x)) +#define S5P_PMUREG(x) (S5P_VA_PMU + (x)) -#define S5P_PMU_CAM_CONF S5P_PMUREG(0x3C00) -#define S5P_PMU_TV_CONF S5P_PMUREG(0x3C20) -#define S5P_PMU_MFC_CONF S5P_PMUREG(0x3C40) -#define S5P_PMU_G3D_CONF S5P_PMUREG(0x3C60) -#define S5P_PMU_LCD0_CONF S5P_PMUREG(0x3C80) -#define S5P_PMU_LCD1_CONF S5P_PMUREG(0x3CA0) -#define S5P_PMU_GPS_CONF S5P_PMUREG(0x3CE0) +#define S5P_CENTRAL_SEQ_CONFIGURATION S5P_PMUREG(0x0200) -#define S5P_INT_LOCAL_PWR_EN 0x7 +#define S5P_CENTRAL_LOWPWR_CFG (1 << 16) + +#define S5P_CENTRAL_SEQ_OPTION S5P_PMUREG(0x0208) + +#define S5P_USE_STANDBY_WFI0 (1 << 16) +#define S5P_USE_STANDBY_WFI1 (1 << 17) +#define S5P_USE_STANDBY_WFE0 (1 << 24) +#define S5P_USE_STANDBY_WFE1 (1 << 25) +#define S5P_USE_MASK ((0x3 << 16) | (0x3 << 24)) + +#define S5P_WAKEUP_STAT S5P_PMUREG(0x0600) +#define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604) +#define S5P_WAKEUP_MASK S5P_PMUREG(0x0608) + +#define S5P_INFORM0 S5P_PMUREG(0x0800) +#define S5P_INFORM1 S5P_PMUREG(0x0804) +#define S5P_INFORM2 S5P_PMUREG(0x0808) +#define S5P_INFORM3 S5P_PMUREG(0x080C) +#define S5P_INFORM4 S5P_PMUREG(0x0810) +#define S5P_INFORM5 S5P_PMUREG(0x0814) +#define S5P_INFORM6 S5P_PMUREG(0x0818) +#define S5P_INFORM7 S5P_PMUREG(0x081C) + +#define S5P_ARM_CORE0_LOWPWR S5P_PMUREG(0x1000) +#define S5P_DIS_IRQ_CORE0 S5P_PMUREG(0x1004) +#define S5P_DIS_IRQ_CENTRAL0 S5P_PMUREG(0x1008) +#define S5P_ARM_CORE1_LOWPWR S5P_PMUREG(0x1010) +#define S5P_DIS_IRQ_CORE1 S5P_PMUREG(0x1014) +#define S5P_DIS_IRQ_CENTRAL1 S5P_PMUREG(0x1018) +#define S5P_ARM_COMMON_LOWPWR S5P_PMUREG(0x1080) +#define S5P_L2_0_LOWPWR S5P_PMUREG(0x10C0) +#define S5P_L2_1_LOWPWR S5P_PMUREG(0x10C4) +#define S5P_CMU_ACLKSTOP_LOWPWR S5P_PMUREG(0x1100) +#define S5P_CMU_SCLKSTOP_LOWPWR S5P_PMUREG(0x1104) +#define S5P_CMU_RESET_LOWPWR S5P_PMUREG(0x110C) +#define S5P_APLL_SYSCLK_LOWPWR S5P_PMUREG(0x1120) +#define S5P_MPLL_SYSCLK_LOWPWR S5P_PMUREG(0x1124) +#define S5P_VPLL_SYSCLK_LOWPWR S5P_PMUREG(0x1128) +#define S5P_EPLL_SYSCLK_LOWPWR S5P_PMUREG(0x112C) +#define S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR S5P_PMUREG(0x1138) +#define S5P_CMU_RESET_GPSALIVE_LOWPWR S5P_PMUREG(0x113C) +#define S5P_CMU_CLKSTOP_CAM_LOWPWR S5P_PMUREG(0x1140) +#define S5P_CMU_CLKSTOP_TV_LOWPWR S5P_PMUREG(0x1144) +#define S5P_CMU_CLKSTOP_MFC_LOWPWR S5P_PMUREG(0x1148) +#define S5P_CMU_CLKSTOP_G3D_LOWPWR S5P_PMUREG(0x114C) +#define S5P_CMU_CLKSTOP_LCD0_LOWPWR S5P_PMUREG(0x1150) +#define S5P_CMU_CLKSTOP_LCD1_LOWPWR S5P_PMUREG(0x1154) +#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR S5P_PMUREG(0x1158) +#define S5P_CMU_CLKSTOP_GPS_LOWPWR S5P_PMUREG(0x115C) +#define S5P_CMU_RESET_CAM_LOWPWR S5P_PMUREG(0x1160) +#define S5P_CMU_RESET_TV_LOWPWR S5P_PMUREG(0x1164) +#define S5P_CMU_RESET_MFC_LOWPWR S5P_PMUREG(0x1168) +#define S5P_CMU_RESET_G3D_LOWPWR S5P_PMUREG(0x116C) +#define S5P_CMU_RESET_LCD0_LOWPWR S5P_PMUREG(0x1170) +#define S5P_CMU_RESET_LCD1_LOWPWR S5P_PMUREG(0x1174) +#define S5P_CMU_RESET_MAUDIO_LOWPWR S5P_PMUREG(0x1178) +#define S5P_CMU_RESET_GPS_LOWPWR S5P_PMUREG(0x117C) +#define S5P_TOP_BUS_LOWPWR S5P_PMUREG(0x1180) +#define S5P_TOP_RETENTION_LOWPWR S5P_PMUREG(0x1184) +#define S5P_TOP_PWR_LOWPWR S5P_PMUREG(0x1188) +#define S5P_LOGIC_RESET_LOWPWR S5P_PMUREG(0x11A0) +#define S5P_ONENAND_MEM_LOWPWR S5P_PMUREG(0x11C0) +#define S5P_MODIMIF_MEM_LOWPWR S5P_PMUREG(0x11C4) +#define S5P_G2D_ACP_MEM_LOWPWR S5P_PMUREG(0x11C8) +#define S5P_USBOTG_MEM_LOWPWR S5P_PMUREG(0x11CC) +#define S5P_HSMMC_MEM_LOWPWR S5P_PMUREG(0x11D0) +#define S5P_CSSYS_MEM_LOWPWR S5P_PMUREG(0x11D4) +#define S5P_SECSS_MEM_LOWPWR S5P_PMUREG(0x11D8) +#define S5P_PCIE_MEM_LOWPWR S5P_PMUREG(0x11E0) +#define S5P_SATA_MEM_LOWPWR S5P_PMUREG(0x11E4) +#define S5P_PAD_RETENTION_DRAM_LOWPWR S5P_PMUREG(0x1200) +#define S5P_PAD_RETENTION_MAUDIO_LOWPWR S5P_PMUREG(0x1204) +#define S5P_PAD_RETENTION_GPIO_LOWPWR S5P_PMUREG(0x1220) +#define S5P_PAD_RETENTION_UART_LOWPWR S5P_PMUREG(0x1224) +#define S5P_PAD_RETENTION_MMCA_LOWPWR S5P_PMUREG(0x1228) +#define S5P_PAD_RETENTION_MMCB_LOWPWR S5P_PMUREG(0x122C) +#define S5P_PAD_RETENTION_EBIA_LOWPWR S5P_PMUREG(0x1230) +#define S5P_PAD_RETENTION_EBIB_LOWPWR S5P_PMUREG(0x1234) +#define S5P_PAD_RETENTION_ISOLATION_LOWPWR S5P_PMUREG(0x1240) +#define S5P_PAD_RETENTION_ALV_SEL_LOWPWR S5P_PMUREG(0x1260) +#define S5P_XUSBXTI_LOWPWR S5P_PMUREG(0x1280) +#define S5P_XXTI_LOWPWR S5P_PMUREG(0x1284) +#define S5P_EXT_REGULATOR_LOWPWR S5P_PMUREG(0x12C0) +#define S5P_GPIO_MODE_LOWPWR S5P_PMUREG(0x1300) +#define S5P_GPIO_MODE_MAUDIO_LOWPWR S5P_PMUREG(0x1340) +#define S5P_CAM_LOWPWR S5P_PMUREG(0x1380) +#define S5P_TV_LOWPWR S5P_PMUREG(0x1384) +#define S5P_MFC_LOWPWR S5P_PMUREG(0x1388) +#define S5P_G3D_LOWPWR S5P_PMUREG(0x138C) +#define S5P_LCD0_LOWPWR S5P_PMUREG(0x1390) +#define S5P_LCD1_LOWPWR S5P_PMUREG(0x1394) +#define S5P_MAUDIO_LOWPWR S5P_PMUREG(0x1398) +#define S5P_GPS_LOWPWR S5P_PMUREG(0x139C) +#define S5P_GPS_ALIVE_LOWPWR S5P_PMUREG(0x13A0) + +#define S5P_ARM_CORE0_CONFIGURATION S5P_PMUREG(0x2000) +#define S5P_ARM_CORE0_OPTION S5P_PMUREG(0x2008) +#define S5P_ARM_CORE1_CONFIGURATION S5P_PMUREG(0x2080) +#define S5P_ARM_CORE1_STATUS S5P_PMUREG(0x2084) +#define S5P_ARM_CORE1_OPTION S5P_PMUREG(0x2088) + +#define S5P_ARM_COMMON_OPTION S5P_PMUREG(0x2408) +#define S5P_TOP_PWR_OPTION S5P_PMUREG(0x2C48) +#define S5P_CAM_OPTION S5P_PMUREG(0x3C08) +#define S5P_TV_OPTION S5P_PMUREG(0x3C28) +#define S5P_MFC_OPTION S5P_PMUREG(0x3C48) +#define S5P_G3D_OPTION S5P_PMUREG(0x3C68) +#define S5P_LCD0_OPTION S5P_PMUREG(0x3C88) +#define S5P_LCD1_OPTION S5P_PMUREG(0x3CA8) +#define S5P_MAUDIO_OPTION S5P_PMUREG(0x3CC8) +#define S5P_GPS_OPTION S5P_PMUREG(0x3CE8) +#define S5P_GPS_ALIVE_OPTION S5P_PMUREG(0x3D08) + +#define S5P_PAD_RET_MAUDIO_OPTION S5P_PMUREG(0x3028) +#define S5P_PAD_RET_GPIO_OPTION S5P_PMUREG(0x3108) +#define S5P_PAD_RET_UART_OPTION S5P_PMUREG(0x3128) +#define S5P_PAD_RET_MMCA_OPTION S5P_PMUREG(0x3148) +#define S5P_PAD_RET_MMCB_OPTION S5P_PMUREG(0x3168) +#define S5P_PAD_RET_EBIA_OPTION S5P_PMUREG(0x3188) +#define S5P_PAD_RET_EBIB_OPTION S5P_PMUREG(0x31A8) + +#define S5P_PMU_CAM_CONF S5P_PMUREG(0x3C00) +#define S5P_PMU_TV_CONF S5P_PMUREG(0x3C20) +#define S5P_PMU_MFC_CONF S5P_PMUREG(0x3C40) +#define S5P_PMU_G3D_CONF S5P_PMUREG(0x3C60) +#define S5P_PMU_LCD0_CONF S5P_PMUREG(0x3C80) +#define S5P_PMU_LCD1_CONF S5P_PMUREG(0x3CA0) +#define S5P_PMU_GPS_CONF S5P_PMUREG(0x3CE0) + +#define S5P_INT_LOCAL_PWR_EN 0x7 + +#define S5P_CHECK_SLEEP 0x00000BAD #endif /* __ASM_ARCH_REGS_PMU_H */ From 1663895cb434b586d022d6414f03316469cf284d Mon Sep 17 00:00:00 2001 From: Jaecheol Lee Date: Thu, 10 Mar 2011 13:33:59 +0900 Subject: [PATCH 2/3] ARM: EXYNOS4: Suspend to RAM Support This patch adds support suspend to ram for EXYNOS4210. As a note, this includes function of outer cache flush because it is used before entering PM. Signed-off-by: Jaecheol Lee Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos4/Makefile | 1 + arch/arm/mach-exynos4/include/mach/pm-core.h | 49 +++ arch/arm/mach-exynos4/pm.c | 420 +++++++++++++++++++ arch/arm/mach-exynos4/sleep.S | 76 ++++ arch/arm/plat-samsung/include/plat/cpu.h | 1 + 5 files changed, 547 insertions(+) create mode 100644 arch/arm/mach-exynos4/include/mach/pm-core.h create mode 100644 arch/arm/mach-exynos4/pm.c create mode 100644 arch/arm/mach-exynos4/sleep.S diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile index 56e367b48fbb..991a4c5f4677 100644 --- a/arch/arm/mach-exynos4/Makefile +++ b/arch/arm/mach-exynos4/Makefile @@ -14,6 +14,7 @@ obj- := obj-$(CONFIG_CPU_EXYNOS4210) += cpu.o init.o clock.o irq-combiner.o obj-$(CONFIG_CPU_EXYNOS4210) += setup-i2c0.o gpiolib.o irq-eint.o dma.o +obj-$(CONFIG_PM) += pm.o sleep.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o diff --git a/arch/arm/mach-exynos4/include/mach/pm-core.h b/arch/arm/mach-exynos4/include/mach/pm-core.h new file mode 100644 index 000000000000..f26e46bc06ca --- /dev/null +++ b/arch/arm/mach-exynos4/include/mach/pm-core.h @@ -0,0 +1,49 @@ +/* linux/arch/arm/mach-exynos4/include/mach/pm-core.h + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Based on arch/arm/mach-s3c2410/include/mach/pm-core.h, + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * EXYNOS4210 - PM core support for arch/arm/plat-s5p/pm.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ +#include + +static inline void s3c_pm_debug_init_uart(void) +{ + /* nothing here yet */ +} + +static inline void s3c_pm_arch_prepare_irqs(void) +{ + unsigned int tmp; + tmp = __raw_readl(S5P_WAKEUP_MASK); + tmp &= ~(1 << 31); + __raw_writel(tmp, S5P_WAKEUP_MASK); + + __raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK); + __raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK); +} + +static inline void s3c_pm_arch_stop_clocks(void) +{ + /* nothing here yet */ +} + +static inline void s3c_pm_arch_show_resume_irqs(void) +{ + /* nothing here yet */ +} + +static inline void s3c_pm_arch_update_uart(void __iomem *regs, + struct pm_uart_save *save) +{ + /* nothing here yet */ +} diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c new file mode 100644 index 000000000000..10d917d9e3ad --- /dev/null +++ b/arch/arm/mach-exynos4/pm.c @@ -0,0 +1,420 @@ +/* linux/arch/arm/mach-exynos4/pm.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * EXYNOS4210 - Power Management support + * + * Based on arch/arm/mach-s3c2410/pm.c + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +static struct sleep_save exynos4_sleep[] = { + { .reg = S5P_ARM_CORE0_LOWPWR , .val = 0x2, }, + { .reg = S5P_DIS_IRQ_CORE0 , .val = 0x0, }, + { .reg = S5P_DIS_IRQ_CENTRAL0 , .val = 0x0, }, + { .reg = S5P_ARM_CORE1_LOWPWR , .val = 0x2, }, + { .reg = S5P_DIS_IRQ_CORE1 , .val = 0x0, }, + { .reg = S5P_DIS_IRQ_CENTRAL1 , .val = 0x0, }, + { .reg = S5P_ARM_COMMON_LOWPWR , .val = 0x2, }, + { .reg = S5P_L2_0_LOWPWR , .val = 0x3, }, + { .reg = S5P_L2_1_LOWPWR , .val = 0x3, }, + { .reg = S5P_CMU_ACLKSTOP_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_SCLKSTOP_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_RESET_LOWPWR , .val = 0x0, }, + { .reg = S5P_APLL_SYSCLK_LOWPWR , .val = 0x0, }, + { .reg = S5P_MPLL_SYSCLK_LOWPWR , .val = 0x0, }, + { .reg = S5P_VPLL_SYSCLK_LOWPWR , .val = 0x0, }, + { .reg = S5P_EPLL_SYSCLK_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_RESET_GPSALIVE_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_CLKSTOP_CAM_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_CLKSTOP_TV_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_CLKSTOP_MFC_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_CLKSTOP_G3D_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_CLKSTOP_LCD0_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_CLKSTOP_LCD1_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_CLKSTOP_MAUDIO_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_CLKSTOP_GPS_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_RESET_CAM_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_RESET_TV_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_RESET_MFC_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_RESET_G3D_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_RESET_LCD0_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_RESET_LCD1_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_RESET_MAUDIO_LOWPWR , .val = 0x0, }, + { .reg = S5P_CMU_RESET_GPS_LOWPWR , .val = 0x0, }, + { .reg = S5P_TOP_BUS_LOWPWR , .val = 0x0, }, + { .reg = S5P_TOP_RETENTION_LOWPWR , .val = 0x1, }, + { .reg = S5P_TOP_PWR_LOWPWR , .val = 0x3, }, + { .reg = S5P_LOGIC_RESET_LOWPWR , .val = 0x0, }, + { .reg = S5P_ONENAND_MEM_LOWPWR , .val = 0x0, }, + { .reg = S5P_MODIMIF_MEM_LOWPWR , .val = 0x0, }, + { .reg = S5P_G2D_ACP_MEM_LOWPWR , .val = 0x0, }, + { .reg = S5P_USBOTG_MEM_LOWPWR , .val = 0x0, }, + { .reg = S5P_HSMMC_MEM_LOWPWR , .val = 0x0, }, + { .reg = S5P_CSSYS_MEM_LOWPWR , .val = 0x0, }, + { .reg = S5P_SECSS_MEM_LOWPWR , .val = 0x0, }, + { .reg = S5P_PCIE_MEM_LOWPWR , .val = 0x0, }, + { .reg = S5P_SATA_MEM_LOWPWR , .val = 0x0, }, + { .reg = S5P_PAD_RETENTION_DRAM_LOWPWR , .val = 0x0, }, + { .reg = S5P_PAD_RETENTION_MAUDIO_LOWPWR , .val = 0x0, }, + { .reg = S5P_PAD_RETENTION_GPIO_LOWPWR , .val = 0x0, }, + { .reg = S5P_PAD_RETENTION_UART_LOWPWR , .val = 0x0, }, + { .reg = S5P_PAD_RETENTION_MMCA_LOWPWR , .val = 0x0, }, + { .reg = S5P_PAD_RETENTION_MMCB_LOWPWR , .val = 0x0, }, + { .reg = S5P_PAD_RETENTION_EBIA_LOWPWR , .val = 0x0, }, + { .reg = S5P_PAD_RETENTION_EBIB_LOWPWR , .val = 0x0, }, + { .reg = S5P_PAD_RETENTION_ISOLATION_LOWPWR , .val = 0x0, }, + { .reg = S5P_PAD_RETENTION_ALV_SEL_LOWPWR , .val = 0x0, }, + { .reg = S5P_XUSBXTI_LOWPWR , .val = 0x0, }, + { .reg = S5P_XXTI_LOWPWR , .val = 0x0, }, + { .reg = S5P_EXT_REGULATOR_LOWPWR , .val = 0x0, }, + { .reg = S5P_GPIO_MODE_LOWPWR , .val = 0x0, }, + { .reg = S5P_GPIO_MODE_MAUDIO_LOWPWR , .val = 0x0, }, + { .reg = S5P_CAM_LOWPWR , .val = 0x0, }, + { .reg = S5P_TV_LOWPWR , .val = 0x0, }, + { .reg = S5P_MFC_LOWPWR , .val = 0x0, }, + { .reg = S5P_G3D_LOWPWR , .val = 0x0, }, + { .reg = S5P_LCD0_LOWPWR , .val = 0x0, }, + { .reg = S5P_LCD1_LOWPWR , .val = 0x0, }, + { .reg = S5P_MAUDIO_LOWPWR , .val = 0x0, }, + { .reg = S5P_GPS_LOWPWR , .val = 0x0, }, + { .reg = S5P_GPS_ALIVE_LOWPWR , .val = 0x0, }, +}; + +static struct sleep_save exynos4_set_clksrc[] = { + { .reg = S5P_CLKSRC_MASK_TOP , .val = 0x00000001, }, + { .reg = S5P_CLKSRC_MASK_CAM , .val = 0x11111111, }, + { .reg = S5P_CLKSRC_MASK_TV , .val = 0x00000111, }, + { .reg = S5P_CLKSRC_MASK_LCD0 , .val = 0x00001111, }, + { .reg = S5P_CLKSRC_MASK_LCD1 , .val = 0x00001111, }, + { .reg = S5P_CLKSRC_MASK_MAUDIO , .val = 0x00000001, }, + { .reg = S5P_CLKSRC_MASK_FSYS , .val = 0x01011111, }, + { .reg = S5P_CLKSRC_MASK_PERIL0 , .val = 0x01111111, }, + { .reg = S5P_CLKSRC_MASK_PERIL1 , .val = 0x01110111, }, + { .reg = S5P_CLKSRC_MASK_DMC , .val = 0x00010000, }, +}; + +static struct sleep_save exynos4_core_save[] = { + /* CMU side */ + SAVE_ITEM(S5P_CLKDIV_LEFTBUS), + SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS), + SAVE_ITEM(S5P_CLKDIV_RIGHTBUS), + SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS), + SAVE_ITEM(S5P_EPLL_CON0), + SAVE_ITEM(S5P_EPLL_CON1), + SAVE_ITEM(S5P_VPLL_CON0), + SAVE_ITEM(S5P_VPLL_CON1), + SAVE_ITEM(S5P_CLKSRC_TOP0), + SAVE_ITEM(S5P_CLKSRC_TOP1), + SAVE_ITEM(S5P_CLKSRC_CAM), + SAVE_ITEM(S5P_CLKSRC_MFC), + SAVE_ITEM(S5P_CLKSRC_IMAGE), + SAVE_ITEM(S5P_CLKSRC_LCD0), + SAVE_ITEM(S5P_CLKSRC_LCD1), + SAVE_ITEM(S5P_CLKSRC_MAUDIO), + SAVE_ITEM(S5P_CLKSRC_FSYS), + SAVE_ITEM(S5P_CLKSRC_PERIL0), + SAVE_ITEM(S5P_CLKSRC_PERIL1), + SAVE_ITEM(S5P_CLKDIV_CAM), + SAVE_ITEM(S5P_CLKDIV_TV), + SAVE_ITEM(S5P_CLKDIV_MFC), + SAVE_ITEM(S5P_CLKDIV_G3D), + SAVE_ITEM(S5P_CLKDIV_IMAGE), + SAVE_ITEM(S5P_CLKDIV_LCD0), + SAVE_ITEM(S5P_CLKDIV_LCD1), + SAVE_ITEM(S5P_CLKDIV_MAUDIO), + SAVE_ITEM(S5P_CLKDIV_FSYS0), + SAVE_ITEM(S5P_CLKDIV_FSYS1), + SAVE_ITEM(S5P_CLKDIV_FSYS2), + SAVE_ITEM(S5P_CLKDIV_FSYS3), + SAVE_ITEM(S5P_CLKDIV_PERIL0), + SAVE_ITEM(S5P_CLKDIV_PERIL1), + SAVE_ITEM(S5P_CLKDIV_PERIL2), + SAVE_ITEM(S5P_CLKDIV_PERIL3), + SAVE_ITEM(S5P_CLKDIV_PERIL4), + SAVE_ITEM(S5P_CLKDIV_PERIL5), + SAVE_ITEM(S5P_CLKDIV_TOP), + SAVE_ITEM(S5P_CLKSRC_MASK_CAM), + SAVE_ITEM(S5P_CLKSRC_MASK_TV), + SAVE_ITEM(S5P_CLKSRC_MASK_LCD0), + SAVE_ITEM(S5P_CLKSRC_MASK_LCD1), + SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO), + SAVE_ITEM(S5P_CLKSRC_MASK_FSYS), + SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0), + SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1), + SAVE_ITEM(S5P_CLKGATE_SCLKCAM), + SAVE_ITEM(S5P_CLKGATE_IP_CAM), + SAVE_ITEM(S5P_CLKGATE_IP_TV), + SAVE_ITEM(S5P_CLKGATE_IP_MFC), + SAVE_ITEM(S5P_CLKGATE_IP_G3D), + SAVE_ITEM(S5P_CLKGATE_IP_IMAGE), + SAVE_ITEM(S5P_CLKGATE_IP_LCD0), + SAVE_ITEM(S5P_CLKGATE_IP_LCD1), + SAVE_ITEM(S5P_CLKGATE_IP_FSYS), + SAVE_ITEM(S5P_CLKGATE_IP_GPS), + SAVE_ITEM(S5P_CLKGATE_IP_PERIL), + SAVE_ITEM(S5P_CLKGATE_IP_PERIR), + SAVE_ITEM(S5P_CLKGATE_BLOCK), + SAVE_ITEM(S5P_CLKSRC_MASK_DMC), + SAVE_ITEM(S5P_CLKSRC_DMC), + SAVE_ITEM(S5P_CLKDIV_DMC0), + SAVE_ITEM(S5P_CLKDIV_DMC1), + SAVE_ITEM(S5P_CLKGATE_IP_DMC), + SAVE_ITEM(S5P_CLKSRC_CPU), + SAVE_ITEM(S5P_CLKDIV_CPU), + SAVE_ITEM(S5P_CLKGATE_SCLKCPU), + SAVE_ITEM(S5P_CLKGATE_IP_CPU), + /* GIC side */ + SAVE_ITEM(S5P_VA_GIC_CPU + 0x000), + SAVE_ITEM(S5P_VA_GIC_CPU + 0x004), + SAVE_ITEM(S5P_VA_GIC_CPU + 0x008), + SAVE_ITEM(S5P_VA_GIC_CPU + 0x00C), + SAVE_ITEM(S5P_VA_GIC_CPU + 0x014), + SAVE_ITEM(S5P_VA_GIC_CPU + 0x018), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x000), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x004), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x100), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x104), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x108), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x300), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x304), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x308), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x400), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x404), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x408), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x40C), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x410), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x414), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x418), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x41C), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x420), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x424), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x428), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x42C), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x430), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x434), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x438), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x43C), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x440), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x444), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x448), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x44C), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x450), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x454), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x458), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x45C), + + SAVE_ITEM(S5P_VA_GIC_DIST + 0x800), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x804), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x808), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x80C), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x810), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x814), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x818), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x81C), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x820), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x824), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x828), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x82C), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x830), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x834), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x838), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x83C), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x840), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x844), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x848), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x84C), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x850), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x854), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x858), + SAVE_ITEM(S5P_VA_GIC_DIST + 0x85C), + + SAVE_ITEM(S5P_VA_GIC_DIST + 0xC00), + SAVE_ITEM(S5P_VA_GIC_DIST + 0xC04), + SAVE_ITEM(S5P_VA_GIC_DIST + 0xC08), + SAVE_ITEM(S5P_VA_GIC_DIST + 0xC0C), + SAVE_ITEM(S5P_VA_GIC_DIST + 0xC10), + SAVE_ITEM(S5P_VA_GIC_DIST + 0xC14), + + SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x000), + SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x010), + SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x020), + SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x030), + SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x040), + SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x050), + SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x060), + SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070), + SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080), + SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090), +}; + +static struct sleep_save exynos4_l2cc_save[] = { + SAVE_ITEM(S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL), + SAVE_ITEM(S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL), + SAVE_ITEM(S5P_VA_L2CC + L2X0_PREFETCH_CTRL), + SAVE_ITEM(S5P_VA_L2CC + L2X0_POWER_CTRL), + SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL), +}; + +void exynos4_cpu_suspend(void) +{ + unsigned long tmp; + unsigned long mask = 0xFFFFFFFF; + + /* Setting Central Sequence Register for power down mode */ + + tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION); + tmp &= ~(S5P_CENTRAL_LOWPWR_CFG); + __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION); + + /* Setting Central Sequence option Register */ + + tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION); + tmp &= ~(S5P_USE_MASK); + tmp |= S5P_USE_STANDBY_WFI0; + __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION); + + /* Clear all interrupt pending to avoid early wakeup */ + + __raw_writel(mask, (S5P_VA_GIC_DIST + 0x280)); + __raw_writel(mask, (S5P_VA_GIC_DIST + 0x284)); + __raw_writel(mask, (S5P_VA_GIC_DIST + 0x288)); + + /* Disable all interrupt */ + + __raw_writel(0x0, (S5P_VA_GIC_CPU + 0x000)); + __raw_writel(0x0, (S5P_VA_GIC_DIST + 0x000)); + __raw_writel(mask, (S5P_VA_GIC_DIST + 0x184)); + __raw_writel(mask, (S5P_VA_GIC_DIST + 0x188)); + + outer_flush_all(); + + /* issue the standby signal into the pm unit. */ + cpu_do_idle(); + + /* we should never get past here */ + panic("sleep resumed to originator?"); +} + +static void exynos4_pm_prepare(void) +{ + u32 tmp; + + s3c_pm_do_save(exynos4_core_save, ARRAY_SIZE(exynos4_core_save)); + s3c_pm_do_save(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save)); + + tmp = __raw_readl(S5P_INFORM1); + + /* Set value of power down register for sleep mode */ + + s3c_pm_do_restore_core(exynos4_sleep, ARRAY_SIZE(exynos4_sleep)); + __raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1); + + /* ensure at least INFORM0 has the resume address */ + + __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0); + + /* Before enter central sequence mode, clock src register have to set */ + + s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc)); + +} + +static int exynos4_pm_add(struct sys_device *sysdev) +{ + pm_cpu_prep = exynos4_pm_prepare; + pm_cpu_sleep = exynos4_cpu_suspend; + + return 0; +} + +/* This function copy from linux/arch/arm/kernel/smp_scu.c */ + +void exynos4_scu_enable(void __iomem *scu_base) +{ + u32 scu_ctrl; + + scu_ctrl = __raw_readl(scu_base); + /* already enabled? */ + if (scu_ctrl & 1) + return; + + scu_ctrl |= 1; + __raw_writel(scu_ctrl, scu_base); + + /* + * Ensure that the data accessed by CPU0 before the SCU was + * initialised is visible to the other CPUs. + */ + flush_cache_all(); +} + +static int exynos4_pm_resume(struct sys_device *dev) +{ + /* For release retention */ + + __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION); + __raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION); + __raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION); + __raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION); + __raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION); + __raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION); + __raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION); + + s3c_pm_do_restore_core(exynos4_core_save, ARRAY_SIZE(exynos4_core_save)); + + exynos4_scu_enable(S5P_VA_SCU); + +#ifdef CONFIG_CACHE_L2X0 + s3c_pm_do_restore_core(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save)); + outer_inv_all(); + /* enable L2X0*/ + writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL); +#endif + + return 0; +} + +static struct sysdev_driver exynos4_pm_driver = { + .add = exynos4_pm_add, + .resume = exynos4_pm_resume, +}; + +static __init int exynos4_pm_drvinit(void) +{ + unsigned int tmp; + + s3c_pm_init(); + + /* All wakeup disable */ + + tmp = __raw_readl(S5P_WAKEUP_MASK); + tmp |= ((0xFF << 8) | (0x1F << 1)); + __raw_writel(tmp, S5P_WAKEUP_MASK); + + return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver); +} +arch_initcall(exynos4_pm_drvinit); diff --git a/arch/arm/mach-exynos4/sleep.S b/arch/arm/mach-exynos4/sleep.S new file mode 100644 index 000000000000..6b62425417a6 --- /dev/null +++ b/arch/arm/mach-exynos4/sleep.S @@ -0,0 +1,76 @@ +/* linux/arch/arm/mach-exynos4/sleep.S + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * EXYNOS4210 power Manager (Suspend-To-RAM) support + * Based on S3C2410 sleep code by: + * Ben Dooks, (c) 2004 Simtec Electronics + * + * Based on PXA/SA1100 sleep code by: + * Nicolas Pitre, (c) 2002 Monta Vista Software Inc + * Cliff Brake, (c) 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + + .text + + /* + * s3c_cpu_save + * + * entry: + * r1 = v:p offset + */ + +ENTRY(s3c_cpu_save) + + stmfd sp!, { r3 - r12, lr } + ldr r3, =resume_with_mmu + bl cpu_suspend + + ldr r0, =pm_cpu_sleep + ldr r0, [ r0 ] + mov pc, r0 + +resume_with_mmu: + ldmfd sp!, { r3 - r12, pc } + + .ltorg + + /* + * sleep magic, to allow the bootloader to check for an valid + * image to resume to. Must be the first word before the + * s3c_cpu_resume entry. + */ + + .word 0x2bedf00d + + /* + * s3c_cpu_resume + * + * resume code entry for bootloader to call + * + * we must put this code here in the data segment as we have no + * other way of restoring the stack pointer after sleep, and we + * must not write to the code segment (code is read-only) + */ + +ENTRY(s3c_cpu_resume) + b cpu_resume diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index 9addb3dfb4bc..cedfff51c82b 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -82,6 +82,7 @@ extern struct sysdev_class s3c64xx_sysclass; extern struct sysdev_class s5p64x0_sysclass; extern struct sysdev_class s5p6442_sysclass; extern struct sysdev_class s5pv210_sysclass; +extern struct sysdev_class exynos4_sysclass; extern void (*s5pc1xx_idle)(void); From 30fe76437bc2463b25e9a64ff1b28f293e3f3413 Mon Sep 17 00:00:00 2001 From: Jaecheol Lee Date: Wed, 9 Mar 2011 08:22:31 +0900 Subject: [PATCH 3/3] ARM: EXYNOS4: Update HRT for supporting PM This patch updates HRT driver for supporting PM. The resume function of PWM4 timer which is used clocksource is needed when kernel is resuming for restarting. Signed-off-by: Jaecheol Lee Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos4/time.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/mach-exynos4/time.c b/arch/arm/mach-exynos4/time.c index e30ac7043095..86b9fa0d3639 100644 --- a/arch/arm/mach-exynos4/time.c +++ b/arch/arm/mach-exynos4/time.c @@ -206,12 +206,28 @@ static cycle_t exynos4_pwm4_read(struct clocksource *cs) return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40)); } +static void exynos4_pwm4_resume(struct clocksource *cs) +{ + unsigned long pclk; + + pclk = clk_get_rate(timerclk); + + clk_set_rate(tdiv4, pclk / 2); + clk_set_parent(tin4, tdiv4); + + exynos4_pwm_init(4, ~0); + exynos4_pwm_start(4, 1); +} + struct clocksource pwm_clocksource = { .name = "pwm_timer4", .rating = 250, .read = exynos4_pwm4_read, .mask = CLOCKSOURCE_MASK(32), .flags = CLOCK_SOURCE_IS_CONTINUOUS , +#ifdef CONFIG_PM + .resume = exynos4_pwm4_resume, +#endif }; static void __init exynos4_clocksource_init(void)