mirror of
https://github.com/torvalds/linux.git
synced 2024-11-28 07:01:32 +00:00
ARM: EXYNOS: Support suspend and resume for EXYNOS5250
This patch adds function for suspend and resume of Exynos5250. Signed-off-by: Jongpill Lee <boyko.lee@samsung.com> [kgene.kim@samsung.com: re-worked on top of v3.4-rc7] Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
This commit is contained in:
parent
a2fa3041b6
commit
60e49ca654
@ -62,6 +62,8 @@ config SOC_EXYNOS5250
|
||||
default y
|
||||
depends on ARCH_EXYNOS5
|
||||
select SAMSUNG_DMADEV
|
||||
select S5P_PM if PM
|
||||
select S5P_SLEEP if PM
|
||||
help
|
||||
Enable EXYNOS5250 SoC support
|
||||
|
||||
|
@ -33,7 +33,7 @@ static inline void s3c_pm_arch_prepare_irqs(void)
|
||||
__raw_writel(tmp, S5P_WAKEUP_MASK);
|
||||
|
||||
__raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK);
|
||||
__raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK);
|
||||
__raw_writel(s3c_irqwake_eintmask & 0xFFFFFFFE, S5P_EINT_WAKEUP_MASK);
|
||||
}
|
||||
|
||||
static inline void s3c_pm_arch_stop_clocks(void)
|
||||
|
@ -77,7 +77,9 @@ static unsigned int save_arm_register[2];
|
||||
|
||||
static int exynos_cpu_suspend(unsigned long arg)
|
||||
{
|
||||
#ifdef CONFIG_CACHE_L2X0
|
||||
outer_flush_all();
|
||||
#endif
|
||||
|
||||
/* issue the standby signal into the pm unit. */
|
||||
cpu_do_idle();
|
||||
@ -88,13 +90,19 @@ static int exynos_cpu_suspend(unsigned long arg)
|
||||
|
||||
static void exynos_pm_prepare(void)
|
||||
{
|
||||
u32 tmp;
|
||||
unsigned int tmp;
|
||||
|
||||
s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
|
||||
s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
|
||||
s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
|
||||
|
||||
tmp = __raw_readl(S5P_INFORM1);
|
||||
if (!soc_is_exynos5250()) {
|
||||
s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
|
||||
s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
|
||||
} else {
|
||||
/* Disable USE_RETENTION of JPEG_MEM_OPTION */
|
||||
tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION);
|
||||
tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
|
||||
__raw_writel(tmp, EXYNOS5_JPEG_MEM_OPTION);
|
||||
}
|
||||
|
||||
/* Set value of power down register for sleep mode */
|
||||
|
||||
@ -107,7 +115,8 @@ static void exynos_pm_prepare(void)
|
||||
|
||||
/* Before enter central sequence mode, clock src register have to set */
|
||||
|
||||
s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
|
||||
if (!soc_is_exynos5250())
|
||||
s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
|
||||
|
||||
if (soc_is_exynos4210())
|
||||
s3c_pm_do_restore_core(exynos4210_set_clksrc, ARRAY_SIZE(exynos4210_set_clksrc));
|
||||
@ -190,7 +199,7 @@ static void exynos4_restore_pll(void)
|
||||
}
|
||||
|
||||
static struct subsys_interface exynos_pm_interface = {
|
||||
.name = "exynos4_pm",
|
||||
.name = "exynos_pm",
|
||||
.subsys = &exynos_subsys,
|
||||
.add_dev = exynos_pm_add,
|
||||
};
|
||||
@ -231,23 +240,23 @@ static int exynos_pm_suspend(void)
|
||||
tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
|
||||
__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
|
||||
|
||||
if (soc_is_exynos4212() || soc_is_exynos4412()) {
|
||||
tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
|
||||
tmp &= ~(S5P_USE_STANDBYWFI_ISP_ARM |
|
||||
S5P_USE_STANDBYWFE_ISP_ARM);
|
||||
__raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
|
||||
/* Setting SEQ_OPTION register */
|
||||
|
||||
tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0);
|
||||
__raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
|
||||
|
||||
if (!soc_is_exynos5250()) {
|
||||
/* Save Power control register */
|
||||
asm ("mrc p15, 0, %0, c15, c0, 0"
|
||||
: "=r" (tmp) : : "cc");
|
||||
save_arm_register[0] = tmp;
|
||||
|
||||
/* Save Diagnostic register */
|
||||
asm ("mrc p15, 0, %0, c15, c0, 1"
|
||||
: "=r" (tmp) : : "cc");
|
||||
save_arm_register[1] = tmp;
|
||||
}
|
||||
|
||||
/* Save Power control register */
|
||||
asm ("mrc p15, 0, %0, c15, c0, 0"
|
||||
: "=r" (tmp) : : "cc");
|
||||
save_arm_register[0] = tmp;
|
||||
|
||||
/* Save Diagnostic register */
|
||||
asm ("mrc p15, 0, %0, c15, c0, 1"
|
||||
: "=r" (tmp) : : "cc");
|
||||
save_arm_register[1] = tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -268,17 +277,19 @@ static void exynos_pm_resume(void)
|
||||
/* No need to perform below restore code */
|
||||
goto early_wakeup;
|
||||
}
|
||||
/* Restore Power control register */
|
||||
tmp = save_arm_register[0];
|
||||
asm volatile ("mcr p15, 0, %0, c15, c0, 0"
|
||||
: : "r" (tmp)
|
||||
: "cc");
|
||||
if (!soc_is_exynos5250()) {
|
||||
/* Restore Power control register */
|
||||
tmp = save_arm_register[0];
|
||||
asm volatile ("mcr p15, 0, %0, c15, c0, 0"
|
||||
: : "r" (tmp)
|
||||
: "cc");
|
||||
|
||||
/* Restore Diagnostic register */
|
||||
tmp = save_arm_register[1];
|
||||
asm volatile ("mcr p15, 0, %0, c15, c0, 1"
|
||||
: : "r" (tmp)
|
||||
: "cc");
|
||||
/* Restore Diagnostic register */
|
||||
tmp = save_arm_register[1];
|
||||
asm volatile ("mcr p15, 0, %0, c15, c0, 1"
|
||||
: : "r" (tmp)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
/* For release retention */
|
||||
|
||||
@ -292,11 +303,13 @@ static void exynos_pm_resume(void)
|
||||
|
||||
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
|
||||
|
||||
exynos4_restore_pll();
|
||||
if (!soc_is_exynos5250()) {
|
||||
exynos4_restore_pll();
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
scu_enable(S5P_VA_SCU);
|
||||
scu_enable(S5P_VA_SCU);
|
||||
#endif
|
||||
}
|
||||
|
||||
early_wakeup:
|
||||
return;
|
||||
@ -307,9 +320,9 @@ static struct syscore_ops exynos_pm_syscore_ops = {
|
||||
.resume = exynos_pm_resume,
|
||||
};
|
||||
|
||||
static __init int exynos4_pm_syscore_init(void)
|
||||
static __init int exynos_pm_syscore_init(void)
|
||||
{
|
||||
register_syscore_ops(&exynos_pm_syscore_ops);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(exynos4_pm_syscore_init);
|
||||
arch_initcall(exynos_pm_syscore_init);
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/bug.h>
|
||||
|
||||
#include <mach/regs-clock.h>
|
||||
#include <mach/pmu.h>
|
||||
@ -314,10 +315,68 @@ static struct exynos_pmu_conf exynos5250_pmu_config[] = {
|
||||
{ PMU_TABLE_END,},
|
||||
};
|
||||
|
||||
void __iomem *exynos5_list_both_cnt_feed[] = {
|
||||
EXYNOS5_ARM_CORE0_OPTION,
|
||||
EXYNOS5_ARM_CORE1_OPTION,
|
||||
EXYNOS5_ARM_COMMON_OPTION,
|
||||
EXYNOS5_GSCL_OPTION,
|
||||
EXYNOS5_ISP_OPTION,
|
||||
EXYNOS5_MFC_OPTION,
|
||||
EXYNOS5_G3D_OPTION,
|
||||
EXYNOS5_DISP1_OPTION,
|
||||
EXYNOS5_MAU_OPTION,
|
||||
EXYNOS5_TOP_PWR_OPTION,
|
||||
EXYNOS5_TOP_PWR_SYSMEM_OPTION,
|
||||
};
|
||||
|
||||
void __iomem *exynos5_list_diable_wfi_wfe[] = {
|
||||
EXYNOS5_ARM_CORE1_OPTION,
|
||||
EXYNOS5_FSYS_ARM_OPTION,
|
||||
EXYNOS5_ISP_ARM_OPTION,
|
||||
};
|
||||
|
||||
static void exynos5_init_pmu(void)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int tmp;
|
||||
|
||||
/*
|
||||
* Enable both SC_FEEDBACK and SC_COUNTER
|
||||
*/
|
||||
for (i = 0 ; i < ARRAY_SIZE(exynos5_list_both_cnt_feed) ; i++) {
|
||||
tmp = __raw_readl(exynos5_list_both_cnt_feed[i]);
|
||||
tmp |= (EXYNOS5_USE_SC_FEEDBACK |
|
||||
EXYNOS5_USE_SC_COUNTER);
|
||||
__raw_writel(tmp, exynos5_list_both_cnt_feed[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* SKIP_DEACTIVATE_ACEACP_IN_PWDN_BITFIELD Enable
|
||||
* MANUAL_L2RSTDISABLE_CONTROL_BITFIELD Enable
|
||||
*/
|
||||
tmp = __raw_readl(EXYNOS5_ARM_COMMON_OPTION);
|
||||
tmp |= (EXYNOS5_MANUAL_L2RSTDISABLE_CONTROL |
|
||||
EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN);
|
||||
__raw_writel(tmp, EXYNOS5_ARM_COMMON_OPTION);
|
||||
|
||||
/*
|
||||
* Disable WFI/WFE on XXX_OPTION
|
||||
*/
|
||||
for (i = 0 ; i < ARRAY_SIZE(exynos5_list_diable_wfi_wfe) ; i++) {
|
||||
tmp = __raw_readl(exynos5_list_diable_wfi_wfe[i]);
|
||||
tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE |
|
||||
EXYNOS5_OPTION_USE_STANDBYWFI);
|
||||
__raw_writel(tmp, exynos5_list_diable_wfi_wfe[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void exynos_sys_powerdown_conf(enum sys_powerdown mode)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (soc_is_exynos5250())
|
||||
exynos5_init_pmu();
|
||||
|
||||
for (i = 0; (exynos_pmu_config[i].reg != PMU_TABLE_END) ; i++)
|
||||
__raw_writel(exynos_pmu_config[i].val[mode],
|
||||
exynos_pmu_config[i].reg);
|
||||
|
Loading…
Reference in New Issue
Block a user