From 528eae6c14a45f40809733862675f6cf03998d17 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 18 Mar 2015 02:12:23 +0900 Subject: [PATCH 01/10] ARM: EXYNOS: add support for async-bridge clocks for pm_domains Since Exynos5420 there are async-bridges (ASB) between different IPs. These bridges must be operational during power domain on/off, ie. clocks used by these bridges should be enabled. This patch enabled these clocks during domain on/off. Signed-off-by: Andrzej Hajda Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Reviewed-by: Sylwester Nawrocki Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/pm_domains.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index 20f267121b3e..ccdcacbd1cd9 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c @@ -37,6 +37,7 @@ struct exynos_pm_domain { struct clk *oscclk; struct clk *clk[MAX_CLK_PER_DOMAIN]; struct clk *pclk[MAX_CLK_PER_DOMAIN]; + struct clk *asb_clk[MAX_CLK_PER_DOMAIN]; }; static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) @@ -45,14 +46,19 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) void __iomem *base; u32 timeout, pwr; char *op; + int i; pd = container_of(domain, struct exynos_pm_domain, pd); base = pd->base; + for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { + if (IS_ERR(pd->asb_clk[i])) + break; + clk_prepare_enable(pd->asb_clk[i]); + } + /* Set oscclk before powering off a domain*/ if (!power_on) { - int i; - for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { if (IS_ERR(pd->clk[i])) break; @@ -81,8 +87,6 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) /* Restore clocks after powering on a domain*/ if (power_on) { - int i; - for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { if (IS_ERR(pd->clk[i])) break; @@ -92,6 +96,12 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) } } + for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { + if (IS_ERR(pd->asb_clk[i])) + break; + clk_disable_unprepare(pd->asb_clk[i]); + } + return 0; } @@ -131,6 +141,15 @@ static __init int exynos4_pm_init_power_domain(void) pd->pd.power_off = exynos_pd_power_off; pd->pd.power_on = exynos_pd_power_on; + for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { + char clk_name[8]; + + snprintf(clk_name, sizeof(clk_name), "asb%d", i); + pd->asb_clk[i] = clk_get(dev, clk_name); + if (IS_ERR(pd->asb_clk[i])) + break; + } + pd->oscclk = clk_get(dev, "oscclk"); if (IS_ERR(pd->oscclk)) goto no_clk; From 70e9d7b59f5d56cb83ace31380ac75531fbbb591 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 18 Mar 2015 02:19:24 +0900 Subject: [PATCH 02/10] ARM: EXYNOS: Use platform device name as power domain name The power domain nodes in DTS may be very generic (e.g. "power-domain" for Exynos 5420) making it very hard to debug: $ cat /sys/kernel/debug/pm_genpd/pm_genpd_summary domain status slaves power-domain on Use platform device name instead so the names will be a little more user friendly: domain status slaves 100440e0.power-domain on Signed-off-by: Krzysztof Kozlowski Suggested-by: Javier Martinez Canillas Suggested-by: Sergei Shtylyov Reviewed-by: Javier Martinez Canillas Reviewed-by: Chanwoo Choi Reviewed-by: Kevin Hilman Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/pm_domains.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index ccdcacbd1cd9..a80d15d97df9 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c @@ -135,7 +135,7 @@ static __init int exynos4_pm_init_power_domain(void) return -ENOMEM; } - pd->pd.name = kstrdup(np->name, GFP_KERNEL); + pd->pd.name = kstrdup(dev_name(dev), GFP_KERNEL); pd->name = pd->pd.name; pd->base = of_iomap(np, 0); pd->pd.power_off = exynos_pd_power_off; From 8c8a251130f173a69b7df4c3225668e39708f743 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 18 Mar 2015 02:32:40 +0900 Subject: [PATCH 03/10] ARM: EXYNOS: use static in suspend.c The 'pm_data', 'exynos_release_ret_regs', 'exynos3250_release_ret_regs' and 'exynos5420_release_ret_regs' are not exported nor used outside of suspend.c file. Make them static. This fixes following sparse warnings: arch/arm/mach-exynos/suspend.c:83:23: warning: symbol 'pm_data' was not declared. Should it be static? arch/arm/mach-exynos/suspend.c:106:14: warning: symbol 'exynos_release_ret_regs' was not declared. Should it be static? arch/arm/mach-exynos/suspend.c:117:14: warning: symbol 'exynos5420_release_ret_regs' was not declared. Should it be static? Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pankaj Dubey Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/suspend.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index 52e2b1a2fddb..f2f1201d8d33 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -75,7 +75,7 @@ struct exynos_pm_data { int (*cpu_suspend)(unsigned long); }; -struct exynos_pm_data *pm_data; +static struct exynos_pm_data *pm_data; static int exynos5420_cpu_state; static unsigned int exynos_pmu_spare3; @@ -104,7 +104,7 @@ static const struct exynos_wkup_irq exynos5250_wkup_irq[] = { { /* sentinel */ }, }; -unsigned int exynos_release_ret_regs[] = { +static unsigned int exynos_release_ret_regs[] = { S5P_PAD_RET_MAUDIO_OPTION, S5P_PAD_RET_GPIO_OPTION, S5P_PAD_RET_UART_OPTION, @@ -115,7 +115,7 @@ unsigned int exynos_release_ret_regs[] = { REG_TABLE_END, }; -unsigned int exynos3250_release_ret_regs[] = { +static unsigned int exynos3250_release_ret_regs[] = { S5P_PAD_RET_MAUDIO_OPTION, S5P_PAD_RET_GPIO_OPTION, S5P_PAD_RET_UART_OPTION, @@ -128,7 +128,7 @@ unsigned int exynos3250_release_ret_regs[] = { REG_TABLE_END, }; -unsigned int exynos5420_release_ret_regs[] = { +static unsigned int exynos5420_release_ret_regs[] = { EXYNOS_PAD_RET_DRAM_OPTION, EXYNOS_PAD_RET_MAUDIO_OPTION, EXYNOS_PAD_RET_JTAG_OPTION, From 7383833784e9ce894563d4827ea79ab41fadfbd7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 18 Mar 2015 02:34:37 +0900 Subject: [PATCH 04/10] ARM: EXYNOS: Constify exynos_pm_data array The 'exynos5420_pm_data' is not modified and can be made const. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pankaj Dubey Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/suspend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index f2f1201d8d33..3800fd3d7760 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -576,7 +576,7 @@ static const struct exynos_pm_data exynos5250_pm_data = { .cpu_suspend = exynos_cpu_suspend, }; -static struct exynos_pm_data exynos5420_pm_data = { +static const struct exynos_pm_data exynos5420_pm_data = { .wkup_irq = exynos5250_wkup_irq, .wake_disable_mask = (0x7F << 7) | (0x1F << 1), .release_ret_regs = exynos5420_release_ret_regs, From 1cd3de0a27687e07457fd561e61480d2d2278875 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 18 Mar 2015 02:34:38 +0900 Subject: [PATCH 05/10] ARM: EXYNOS: Remove left over 'extra_save' Since 32b0aa9aaeb4 ("ARM: EXYNOS: Remove i2c sys configuration related code") the Exynos 5250 no longer saves additional registers under 'exynos_pm_data.extra_save' field. No one else uses this code so get rid of it making also 'exynos_pm_data' const everywhere. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pankaj Dubey Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/suspend.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index 3800fd3d7760..89a6d3fb3284 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -63,8 +63,6 @@ static struct sleep_save exynos_core_save[] = { struct exynos_pm_data { const struct exynos_wkup_irq *wkup_irq; - struct sleep_save *extra_save; - int num_extra_save; unsigned int wake_disable_mask; unsigned int *release_ret_regs; @@ -75,7 +73,7 @@ struct exynos_pm_data { int (*cpu_suspend)(unsigned long); }; -static struct exynos_pm_data *pm_data; +static const struct exynos_pm_data *pm_data; static int exynos5420_cpu_state; static unsigned int exynos_pmu_spare3; @@ -240,10 +238,6 @@ static void exynos_pm_prepare(void) s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save)); - if (pm_data->extra_save) - s3c_pm_do_save(pm_data->extra_save, - pm_data->num_extra_save); - exynos_pm_enter_sleep_mode(); /* ensure at least INFORM0 has the resume address */ @@ -366,10 +360,6 @@ static void exynos_pm_resume(void) /* For release retention */ exynos_pm_release_retention(); - if (pm_data->extra_save) - s3c_pm_do_restore_core(pm_data->extra_save, - pm_data->num_extra_save); - s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); if (cpuid == ARM_CPU_PART_CORTEX_A9) @@ -622,7 +612,7 @@ void __init exynos_pm_init(void) pr_err("Failed to find PMU node\n"); return; } - pm_data = (struct exynos_pm_data *) match->data; + pm_data = (const struct exynos_pm_data *) match->data; /* Platform-specific GIC callback */ gic_arch_extn.irq_set_wake = exynos_irq_set_wake; From 4e330ae4ab2915444f1e6dca1358a910aa259362 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 27 Mar 2015 01:58:08 +0900 Subject: [PATCH 06/10] ARM: S3C64XX: Use fixed IRQ bases to avoid conflicts on Cragganmore There are two PMICs on Cragganmore, currently one dynamically assign its IRQ base and the other uses a fixed base. It is possible for the statically assigned PMIC to fail if its IRQ is taken by the dynamically assigned one. Fix this by statically assigning both the IRQ bases. Signed-off-by: Charles Keepax Cc: Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/crag6410.h | 1 + arch/arm/mach-s3c64xx/mach-crag6410.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/mach-s3c64xx/crag6410.h b/arch/arm/mach-s3c64xx/crag6410.h index 7bc66682687e..dcbe17f5e5f8 100644 --- a/arch/arm/mach-s3c64xx/crag6410.h +++ b/arch/arm/mach-s3c64xx/crag6410.h @@ -14,6 +14,7 @@ #include #define GLENFARCLAS_PMIC_IRQ_BASE IRQ_BOARD_START +#define BANFF_PMIC_IRQ_BASE (IRQ_BOARD_START + 64) #define PCA935X_GPIO_BASE GPIO_BOARD_START #define CODEC_GPIO_BASE (GPIO_BOARD_START + 8) diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index 10b913baab28..65c426bc45f7 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -554,6 +554,7 @@ static struct wm831x_touch_pdata touch_pdata = { static struct wm831x_pdata crag_pmic_pdata = { .wm831x_num = 1, + .irq_base = BANFF_PMIC_IRQ_BASE, .gpio_base = BANFF_PMIC_GPIO_BASE, .soft_shutdown = true, From 497ab3b30c7687f52e6711e2ac72d1b696ec7685 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 27 Mar 2015 02:32:56 +0900 Subject: [PATCH 07/10] ARM: EXYNOS: fix CPU1 hotplug on Exynos3250 CPU1 hotplug may hang when AFTR is used. Fix it by: - setting AUTOWAKEUP_EN bit in ARM_COREx_CONFIGURATION register in exynos_cpu_power_up() - not clearing reserved bits of ARM_COREx_CONFIGURATION register in exynos_cpu_power_down() - waiting while an undocumented register 0x0908 becomes non-zero in exynos_core_restart() - using dsb_sev() instead of IPI in exynos_boot_secondary() on Exynos3250 This patch also fixes hotplug issues during resume from S2R: $ echo mem > /sys/power/state [ 156.517266] Disabling non-boot CPUs ... [ 156.517781] IRQ18 no longer affine to CPU1 [ 156.518043] CPU1: shutdown [ 156.544718] Enabling non-boot CPUs ... [ 156.554925] CPU1: Software reset [ 158.552631] CPU1: failed to come online [ 158.552753] Error taking CPU1 up: -5 Cc: Daniel Lezcano Signed-off-by: Chanwoo Choi Signed-off-by: Krzysztof Kozlowski Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Krzysztof Kozlowski Tested-by: Krzysztof Kozlowski Acked-by: Kyungmin Park Tested-by: Chanwoo Choi Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/platsmp.c | 23 ++++++++++++++++++++--- arch/arm/mach-exynos/regs-pmu.h | 2 ++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 3f32c47a6d74..511b81ac2a18 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -126,6 +126,8 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious) */ void exynos_cpu_power_down(int cpu) { + u32 core_conf; + if (cpu == 0 && (of_machine_is_compatible("samsung,exynos5420") || of_machine_is_compatible("samsung,exynos5800"))) { /* @@ -138,7 +140,10 @@ void exynos_cpu_power_down(int cpu) if (!(val & S5P_CORE_LOCAL_PWR_EN)) return; } - pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu)); + + core_conf = pmu_raw_readl(EXYNOS_ARM_CORE_CONFIGURATION(cpu)); + core_conf &= ~S5P_CORE_LOCAL_PWR_EN; + pmu_raw_writel(core_conf, EXYNOS_ARM_CORE_CONFIGURATION(cpu)); } /** @@ -149,7 +154,12 @@ void exynos_cpu_power_down(int cpu) */ void exynos_cpu_power_up(int cpu) { - pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN, + u32 core_conf = S5P_CORE_LOCAL_PWR_EN; + + if (soc_is_exynos3250()) + core_conf |= S5P_CORE_AUTOWAKEUP_EN; + + pmu_raw_writel(core_conf, EXYNOS_ARM_CORE_CONFIGURATION(cpu)); } @@ -227,6 +237,10 @@ static void exynos_core_restart(u32 core_id) if (!of_machine_is_compatible("samsung,exynos3250")) return; + while (!pmu_raw_readl(S5P_PMU_SPARE2)) + udelay(10); + udelay(10); + val = pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(core_id)); val |= S5P_CORE_WAKEUP_FROM_LOCAL_CFG; pmu_raw_writel(val, EXYNOS_ARM_CORE_STATUS(core_id)); @@ -347,7 +361,10 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) call_firmware_op(cpu_boot, core_id); - arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + if (soc_is_exynos3250()) + dsb_sev(); + else + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); if (pen_release == -1) break; diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index eb461e1c325a..84ddce142ab1 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -49,6 +49,7 @@ #define S5P_INFORM5 0x0814 #define S5P_INFORM6 0x0818 #define S5P_INFORM7 0x081C +#define S5P_PMU_SPARE2 0x0908 #define S5P_PMU_SPARE3 0x090C #define EXYNOS_IROM_DATA2 0x0988 @@ -182,6 +183,7 @@ #define S5P_CORE_LOCAL_PWR_EN 0x3 #define S5P_CORE_WAKEUP_FROM_LOCAL_CFG (0x3 << 8) +#define S5P_CORE_AUTOWAKEUP_EN (1 << 31) /* Only for EXYNOS4210 */ #define S5P_CMU_CLKSTOP_LCD1_LOWPWR 0x1154 From dc1b9448d23deb51ad74a873392402560955dbc2 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 27 Mar 2015 02:32:56 +0900 Subject: [PATCH 08/10] ARM: EXYNOS: add code for setting/clearing boot flag This code is needed for cpuidle (W-)AFTR mode support on Exynos3250. Cc: Daniel Lezcano Signed-off-by: Bartlomiej Zolnierkiewicz Acked-by: Kyungmin Park Tested-by: Chanwoo Choi Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.h | 6 ++++++ arch/arm/mach-exynos/firmware.c | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index f70eca7ee705..acd5b560b728 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -126,6 +126,12 @@ enum { void exynos_firmware_init(void); +/* CPU BOOT mode flag for Exynos3250 SoC bootloader */ +#define C2_STATE (1 << 3) + +void exynos_set_boot_flag(unsigned int cpu, unsigned int mode); +void exynos_clear_boot_flag(unsigned int cpu, unsigned int mode); + extern u32 exynos_get_eint_wake_mask(void); #ifdef CONFIG_PM_SLEEP diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c index 4791a3cc00f9..27b8ae3e1f89 100644 --- a/arch/arm/mach-exynos/firmware.c +++ b/arch/arm/mach-exynos/firmware.c @@ -206,3 +206,28 @@ void __init exynos_firmware_init(void) outer_cache.configure = exynos_l2_configure; } } + +#define REG_CPU_STATE_ADDR (sysram_ns_base_addr + 0x28) +#define BOOT_MODE_MASK 0x1f + +void exynos_set_boot_flag(unsigned int cpu, unsigned int mode) +{ + unsigned int tmp; + + tmp = __raw_readl(REG_CPU_STATE_ADDR + cpu * 4); + + if (mode & BOOT_MODE_MASK) + tmp &= ~BOOT_MODE_MASK; + + tmp |= mode; + __raw_writel(tmp, REG_CPU_STATE_ADDR + cpu * 4); +} + +void exynos_clear_boot_flag(unsigned int cpu, unsigned int mode) +{ + unsigned int tmp; + + tmp = __raw_readl(REG_CPU_STATE_ADDR + cpu * 4); + tmp &= ~mode; + __raw_writel(tmp, REG_CPU_STATE_ADDR + cpu * 4); +} From 89366409748c2de0521cf4303bfb1247676882df Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 27 Mar 2015 02:35:48 +0900 Subject: [PATCH 09/10] ARM: EXYNOS: add AFTR mode support for Exynos3250 AFTR mode support brings reduced energy consumption and is a prerequisite for more advanced W-AFTR/LPA power saving modes. AFTR mode has been already supported on other Exynos SoCs for few years and this patch adds its support for Exynos3250 SoC. The differences in Exynos3250 SoC AFTR mode support when compared to Exynos4x12 SoCs are: - different secure firmware calls are used - different S5P_WAKEUP_MASK wakeup mask is used - S5P_WAKEUP_MASK2 wakeup mask needs to be set in addition to the standard S5P_WAKEUP_MASK one - C2_STATE BOOT mode flag needs to be set/cleared pre/post AFTR Cc: Daniel Lezcano Signed-off-by: Bartlomiej Zolnierkiewicz Acked-by: Kyungmin Park Tested-by: Chanwoo Choi Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/firmware.c | 8 +++++++- arch/arm/mach-exynos/pm.c | 12 +++++++++++- arch/arm/mach-exynos/regs-pmu.h | 1 + arch/arm/mach-exynos/smc.h | 9 +++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c index 27b8ae3e1f89..1bd35763f12e 100644 --- a/arch/arm/mach-exynos/firmware.c +++ b/arch/arm/mach-exynos/firmware.c @@ -48,7 +48,13 @@ static int exynos_do_idle(unsigned long mode) __raw_writel(virt_to_phys(exynos_cpu_resume_ns), sysram_ns_base_addr + 0x24); __raw_writel(EXYNOS_AFTR_MAGIC, sysram_ns_base_addr + 0x20); - exynos_smc(SMC_CMD_CPU0AFTR, 0, 0, 0); + if (soc_is_exynos3250()) { + exynos_smc(SMC_CMD_SAVE, OP_TYPE_CORE, + SMC_POWERSTATE_IDLE, 0); + exynos_smc(SMC_CMD_SHUTDOWN, OP_TYPE_CLUSTER, + SMC_POWERSTATE_IDLE, 0); + } else + exynos_smc(SMC_CMD_CPU0AFTR, 0, 0, 0); break; case FW_DO_IDLE_SLEEP: exynos_smc(SMC_CMD_SLEEP, 0, 0, 0); diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index e6209dadc00d..0a7e3afd6fc7 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -127,6 +127,8 @@ int exynos_pm_central_resume(void) static void exynos_set_wakeupmask(long mask) { pmu_raw_writel(mask, S5P_WAKEUP_MASK); + if (soc_is_exynos3250()) + pmu_raw_writel(0x0, S5P_WAKEUP_MASK2); } static void exynos_cpu_set_boot_vector(long flags) @@ -140,7 +142,7 @@ static int exynos_aftr_finisher(unsigned long flags) { int ret; - exynos_set_wakeupmask(0x0000ff3e); + exynos_set_wakeupmask(soc_is_exynos3250() ? 0x40003ffe : 0x0000ff3e); /* Set value of power down register for aftr mode */ exynos_sys_powerdown_conf(SYS_AFTR); @@ -157,8 +159,13 @@ static int exynos_aftr_finisher(unsigned long flags) void exynos_enter_aftr(void) { + unsigned int cpuid = smp_processor_id(); + cpu_pm_enter(); + if (soc_is_exynos3250()) + exynos_set_boot_flag(cpuid, C2_STATE); + exynos_pm_central_suspend(); if (of_machine_is_compatible("samsung,exynos4212") || @@ -178,6 +185,9 @@ void exynos_enter_aftr(void) exynos_pm_central_resume(); + if (soc_is_exynos3250()) + exynos_clear_boot_flag(cpuid, C2_STATE); + cpu_pm_exit(); } diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index 84ddce142ab1..b7614333d296 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -43,6 +43,7 @@ #define S5P_WAKEUP_STAT 0x0600 #define S5P_EINT_WAKEUP_MASK 0x0604 #define S5P_WAKEUP_MASK 0x0608 +#define S5P_WAKEUP_MASK2 0x0614 #define S5P_INFORM0 0x0800 #define S5P_INFORM1 0x0804 diff --git a/arch/arm/mach-exynos/smc.h b/arch/arm/mach-exynos/smc.h index f7b82f9c1e21..c2845717bc8f 100644 --- a/arch/arm/mach-exynos/smc.h +++ b/arch/arm/mach-exynos/smc.h @@ -17,6 +17,8 @@ #define SMC_CMD_SLEEP (-3) #define SMC_CMD_CPU1BOOT (-4) #define SMC_CMD_CPU0AFTR (-5) +#define SMC_CMD_SAVE (-6) +#define SMC_CMD_SHUTDOWN (-7) /* For CP15 Access */ #define SMC_CMD_C15RESUME (-11) /* For L2 Cache Access */ @@ -32,4 +34,11 @@ extern void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3); #endif /* __ASSEMBLY__ */ +/* op type for SMC_CMD_SAVE and SMC_CMD_SHUTDOWN */ +#define OP_TYPE_CORE 0x0 +#define OP_TYPE_CLUSTER 0x1 + +/* Power State required for SMC_CMD_SAVE and SMC_CMD_SHUTDOWN */ +#define SMC_POWERSTATE_IDLE 0x1 + #endif From bd0d888c4f7f125b7c7168f51039142150d9d1cc Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 27 Mar 2015 02:35:52 +0900 Subject: [PATCH 10/10] ARM: EXYNOS: allow cpuidle driver usage on Exynos3250 SoC Register cpuidle platform device on Exynos3250 SoC allowing EXYNOS cpuidle driver usage on this SoC. Cc: Daniel Lezcano Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Krzysztof Kozlowski Acked-by: Kyungmin Park Tested-by: Chanwoo Choi Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/exynos.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 9e9dfdfad9d7..3e45bcb4f003 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -219,6 +219,7 @@ static void __init exynos_dt_machine_init(void) of_machine_is_compatible("samsung,exynos4212") || (of_machine_is_compatible("samsung,exynos4412") && of_machine_is_compatible("samsung,trats2")) || + of_machine_is_compatible("samsung,exynos3250") || of_machine_is_compatible("samsung,exynos5250")) platform_device_register(&exynos_cpuidle);