From patchwork Mon Jan 28 23:06:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stuart Menefy X-Patchwork-Id: 10785075 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E4B53184E for ; Mon, 28 Jan 2019 23:07:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D27862B47D for ; Mon, 28 Jan 2019 23:07:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C6AFD2B505; Mon, 28 Jan 2019 23:07:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B6D982B4D5 for ; Mon, 28 Jan 2019 23:07:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727095AbfA1XHV (ORCPT ); Mon, 28 Jan 2019 18:07:21 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:32894 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727075AbfA1XHV (ORCPT ); Mon, 28 Jan 2019 18:07:21 -0500 Received: by mail-wm1-f66.google.com with SMTP id r24so11596488wmh.0 for ; Mon, 28 Jan 2019 15:07:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mathembedded-com.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id:in-reply-to:references; bh=ou/eQR0HvGLT2EyPZWKwQD9KGAJv3udxhmtohHcoDwE=; b=UVNFocp7ZkocBE5S+6ACzN7PYGtyS3C6xzTmVbCJ5SL3N/kekasWhymF5Nrs947guz 4Rglzs842L6dqWAtiDESZw10ZWEb7jBniXS8KGFxULdms17sV1P3QgmmBYpkebR6bRYp 6a9i3n/izSjmYSbBckHhN/+meNDcu2wWiT0c39biRd6hQvh7NcfduJFz6i3dXZeveEb7 JF64zmUD6HsI81HKyhvK58w1s716MaFTUGBcbCj6cYdYKZU2zvmRyEuLCL8K5apOXFF5 H2eUWhcJCgX9acrwUk3f/ATlOyoH6PqKFUCKs+b3Jk1SSXX4+dajChOEYkdCE511+Ubr dCrQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=ou/eQR0HvGLT2EyPZWKwQD9KGAJv3udxhmtohHcoDwE=; b=CiuVJ8HpZcBmZ4bQLrnFniwlOqalCZnJ/pnBLhAax25cL2mPgZhUOnoKGwuDbgZn5o KpSQ1uFTyBx7lC+LmdjMjtqHzm2Si00bFXuYBhv1dZU0Y0s4NFFhs7oa8UA0x0ssmFmg bdW9Ac2yX8M5t6rv0uhXv+NVw34SPm4tb4VWk8HsTGcJOoK/WTWIJZQANixEByOIUFyb fFobt9CxWJxF3M5VulM4WoFRm1SxDjz65SCkhhvgEJC5JdfX5OsHoEe+8+oIbX0264ZH 46rNnLeYcuf8j27t3H+D60u9d/4ZBvrYUulsB0FEGFfKn84CeL/WBAFDC+nuXzp5I5QG 5PvA== X-Gm-Message-State: AJcUukf3N3sKHr77u2m7rLgIsJ1tgv9Vs2HJkPLbr/sWJRZAlUQUArQY NvsulsYP3LFd9WkJ7tSi8eQR63ajoA3qxQ== X-Google-Smtp-Source: ALg8bN6mojDryQRp6SgJ49KXa655X++o6mH/YWmOgaWFoyfSx53WolWLHpSLtD8WN1Dwh1GbAPaD1g== X-Received: by 2002:a1c:f605:: with SMTP id w5mr19625297wmc.116.1548716837025; Mon, 28 Jan 2019 15:07:17 -0800 (PST) Received: from diamond.mathembedded.com (host86-176-243-190.range86-176.btcentralplus.com. [86.176.243.190]) by smtp.gmail.com with ESMTPSA id o64sm506765wmo.47.2019.01.28.15.07.15 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 28 Jan 2019 15:07:16 -0800 (PST) From: Stuart Menefy To: linux-samsung-soc@vger.kernel.org Subject: [PATCH 14/17] ARM: EXYNOS: Switch SMP support for Exynos5260 to use MCPM Date: Mon, 28 Jan 2019 23:06:57 +0000 Message-Id: <20190128230700.7325-15-stuart.menefy@mathembedded.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20190128230700.7325-1-stuart.menefy@mathembedded.com> References: <20190128230700.7325-1-stuart.menefy@mathembedded.com> Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Switch the SMP support for the Exynos5260 to use the MCPM infrastructure, including support for suspend/resume. As far as possible this replicates the operations performed by the last 3.4 kernel released by Samsung. Signed-off-by: Stuart Menefy --- arch/arm/boot/dts/exynos5260.dtsi | 21 +++++++ arch/arm/mach-exynos/common.h | 1 + arch/arm/mach-exynos/exynos.c | 1 - arch/arm/mach-exynos/mcpm-exynos.c | 118 +++++++++++++++++++++++++++++-------- arch/arm/mach-exynos/platsmp.c | 37 ++++++++++-- arch/arm/mach-exynos/suspend.c | 86 ++++++++++++++++++++++++--- 6 files changed, 227 insertions(+), 37 deletions(-) diff --git a/arch/arm/boot/dts/exynos5260.dtsi b/arch/arm/boot/dts/exynos5260.dtsi index 84c9b4443dc6..e8a5c8715b94 100644 --- a/arch/arm/boot/dts/exynos5260.dtsi +++ b/arch/arm/boot/dts/exynos5260.dtsi @@ -233,6 +233,24 @@ status = "disabled"; }; + sysram@2020000 { + compatible = "mmio-sram"; + reg = <0x02020000 0x54000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x02020000 0x54000>; + + smp-sysram@0 { + compatible = "samsung,exynos4210-sysram"; + reg = <0x0 0x1000>; + }; + + smp-sysram@53000 { + compatible = "samsung,exynos4210-sysram-ns"; + reg = <0x53000 0x1000>; + }; + }; + mct: mct@100b0000 { compatible = "samsung,exynos4210-mct"; reg = <0x100B0000 0x1000>; @@ -299,6 +317,9 @@ pmu_system_controller: system-controller@10d50000 { compatible = "samsung,exynos5260-pmu", "syscon"; reg = <0x10D50000 0x10000>; + interrupt-controller; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; }; uart0: serial@12c00000 { diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 58e6014e3578..ede449bc73f1 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -110,6 +110,7 @@ enum { void exynos_firmware_init(void); /* CPU BOOT mode flag for Exynos3250 SoC bootloader */ +#define HOTPLUG (1 << 2) /* 5260 */ #define C2_STATE (1 << 3) /* * Magic values for bootloader indicating chosen low power mode. diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 865dcc4c3181..2866cb0ff51a 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -119,7 +119,6 @@ void exynos_set_delayed_reset_assertion(bool enable) * feat, the matches below should be moved to suspend.c. */ static const struct of_device_id exynos_dt_pmu_match[] = { - { .compatible = "samsung,exynos5260-pmu" }, { .compatible = "samsung,exynos5410-pmu" }, { /*sentinel*/ }, }; diff --git a/arch/arm/mach-exynos/mcpm-exynos.c b/arch/arm/mach-exynos/mcpm-exynos.c index 571349e1e02e..e5e8d1f27995 100644 --- a/arch/arm/mach-exynos/mcpm-exynos.c +++ b/arch/arm/mach-exynos/mcpm-exynos.c @@ -17,10 +17,15 @@ #include #include "common.h" +#include "smc.h" #define EXYNOS5420_CPUS_PER_CLUSTER 4 #define EXYNOS5420_NR_CLUSTERS 2 +#define EXYNOS5260_CPUS_PER_BIG_CLUSTER 2 +#define EXYNOS5260_CPUS_PER_LITTLE_CLUSTER 4 +#define EXYNOS5260_NR_CLUSTERS 2 + #define EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN BIT(9) #define EXYNOS5420_USE_ARM_CORE_DOWN_STATE BIT(29) #define EXYNOS5420_USE_L2_COMMON_UP_STATE BIT(30) @@ -57,6 +62,17 @@ static void __iomem *ns_sram_base_addr __ro_after_init; static int exynos_cpunr(unsigned int cpu, unsigned int cluster) { + if (soc_is_exynos5260()) { + static const int cpus_per_cluster[EXYNOS5260_NR_CLUSTERS] = { + EXYNOS5260_CPUS_PER_BIG_CLUSTER, + EXYNOS5260_CPUS_PER_LITTLE_CLUSTER + }; + if (cluster >= EXYNOS5260_NR_CLUSTERS || + cpu >= cpus_per_cluster[cluster]) + return -EINVAL; + return cpu + (cluster * 4); + } + if (cpu >= EXYNOS5420_CPUS_PER_CLUSTER || cluster >= EXYNOS5420_NR_CLUSTERS) return -EINVAL; @@ -92,8 +108,20 @@ static int exynos_cpu_powerup(unsigned int cpu, unsigned int cluster) while (!pmu_raw_readl(S5P_PMU_SPARE2)) udelay(10); - pmu_raw_writel(EXYNOS5420_KFC_CORE_RESET(cpu), - EXYNOS_SWRESET); + if (soc_is_exynos5260()) { + u32 val, offset; + + offset = EXYNOS_ARM_CORE_STATUS(cpunr); + val = pmu_raw_readl(offset); + val |= EXYNOS5260_STATUS_WAKEUP_FROM_LOCAL_CFG; + pmu_raw_writel(val, offset); + + pmu_raw_writel(EXYNOS5260_SWRESET_PORESET, + EXYNOS_ARM_CORE_RESET(cpunr)); + } else { + pmu_raw_writel(EXYNOS5420_KFC_CORE_RESET(cpu), + EXYNOS_SWRESET); + } } } @@ -106,6 +134,9 @@ static int exynos_cluster_powerup(unsigned int cluster) if (cluster >= EXYNOS5420_NR_CLUSTERS) return -EINVAL; + if (soc_is_exynos5260()) + return 0; + exynos_cluster_power_up(cluster); return 0; } @@ -119,21 +150,44 @@ static void exynos_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster) exynos_cpu_power_down(cpunr); } +static void exynos_wfi_alternative(bool last_man) +{ + if (soc_is_exynos5260()) { + exynos_smc(SMC_CMD_SHUTDOWN, + last_man ? OP_TYPE_CLUSTER : OP_TYPE_CORE, + SMC_POWERSTATE_IDLE, + 0); + return; + } + + wfi(); +} + static void exynos_cluster_powerdown_prepare(unsigned int cluster) { pr_debug("%s: cluster %u\n", __func__, cluster); BUG_ON(cluster >= EXYNOS5420_NR_CLUSTERS); + + if (soc_is_exynos5260()) + return; + exynos_cluster_power_down(cluster); } static void exynos_cpu_cache_disable(void) { + if (soc_is_exynos5260()) + return; + /* Disable and flush the local CPU cache. */ exynos_v7_exit_coherency_flush(louis); } static void exynos_cluster_cache_disable(void) { + if (soc_is_exynos5260()) + return; + if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) { /* * On the Cortex-A15 we need to disable @@ -180,12 +234,20 @@ static void exynos_cpu_is_up(unsigned int cpu, unsigned int cluster) { /* especially when resuming: make sure power control is set */ exynos_cpu_powerup(cpu, cluster); + + if (soc_is_exynos5260()) { + /* Note this is different to exynos_cpunr() */ + int cpunr = cpu + (cluster ? 0 : 4); + + exynos_clear_boot_flag(cpunr, HOTPLUG); + } } static const struct mcpm_platform_ops exynos_power_ops = { .cpu_powerup = exynos_cpu_powerup, .cluster_powerup = exynos_cluster_powerup, .cpu_powerdown_prepare = exynos_cpu_powerdown_prepare, + .wfi_alternative = exynos_wfi_alternative, .cluster_powerdown_prepare = exynos_cluster_powerdown_prepare, .cpu_cache_disable = exynos_cpu_cache_disable, .cluster_cache_disable = exynos_cluster_cache_disable, @@ -205,6 +267,7 @@ static void __naked exynos_pm_power_up_setup(unsigned int affinity_level) } static const struct of_device_id exynos_dt_mcpm_match[] = { + { .compatible = "samsung,exynos5260" }, { .compatible = "samsung,exynos5420" }, { .compatible = "samsung,exynos5800" }, {}, @@ -253,11 +316,13 @@ static int __init exynos_mcpm_init(void) return -ENOMEM; } - /* - * To increase the stability of KFC reset we need to program - * the PMU SPARE3 register - */ - pmu_raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3); + if (soc_is_exynos5420() || soc_is_exynos5800()) { + /* + * To increase the stability of KFC reset we need to program + * the PMU SPARE3 register. + */ + pmu_raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3); + } ret = mcpm_platform_register(&exynos_power_ops); if (!ret) @@ -273,24 +338,27 @@ static int __init exynos_mcpm_init(void) pr_info("Exynos MCPM support installed\n"); - /* - * On Exynos5420/5800 for the A15 and A7 clusters: - * - * EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN ensures that all the cores - * in a cluster are turned off before turning off the cluster L2. - * - * EXYNOS5420_USE_ARM_CORE_DOWN_STATE ensures that a cores is powered - * off before waking it up. - * - * EXYNOS5420_USE_L2_COMMON_UP_STATE ensures that cluster L2 will be - * turned on before the first man is powered up. - */ - for (i = 0; i < EXYNOS5420_NR_CLUSTERS; i++) { - value = pmu_raw_readl(EXYNOS_COMMON_OPTION(i)); - value |= EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN | - EXYNOS5420_USE_ARM_CORE_DOWN_STATE | - EXYNOS5420_USE_L2_COMMON_UP_STATE; - pmu_raw_writel(value, EXYNOS_COMMON_OPTION(i)); + if (soc_is_exynos5420() || soc_is_exynos5800()) { + /* + * On Exynos5420/5800 for the A15 and A7 clusters: + * + * EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN ensures that all the + * cores in a cluster are turned off before turning off the + * cluster L2. + * + * EXYNOS5420_USE_ARM_CORE_DOWN_STATE ensures that a cores is + * powered off before waking it up. + * + * EXYNOS5420_USE_L2_COMMON_UP_STATE ensures that cluster L2 + * will be turned on before the first man is powered up. + */ + for (i = 0; i < EXYNOS5420_NR_CLUSTERS; i++) { + value = pmu_raw_readl(EXYNOS_COMMON_OPTION(i)); + value |= EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN | + EXYNOS5420_USE_ARM_CORE_DOWN_STATE | + EXYNOS5420_USE_L2_COMMON_UP_STATE; + pmu_raw_writel(value, EXYNOS_COMMON_OPTION(i)); + } } exynos_mcpm_setup_entry_point(); diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index b6da7edbbd2f..07c21b2afc11 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -100,6 +100,23 @@ void exynos_cpu_power_down(int cpu) return; } + if (cpu == 4 && (soc_is_exynos5260())) { + /* + * Bypass power down for CPU4 (KFC0) during suspend. Check for + * the SYS_PWR_REG value to decide if we are suspending + * the system. + */ + int val = pmu_raw_readl(EXYNOS5260_KFC_CORE0_SYS_PWR_REG); + + if ((val & 0xf) == 8) + return; + } + + if (soc_is_exynos5260()) { + pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu)); + return; + } + 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)); @@ -117,6 +134,9 @@ void exynos_cpu_power_up(int cpu) if (soc_is_exynos3250()) core_conf |= S5P_CORE_AUTOWAKEUP_EN; + else if (soc_is_exynos5260()) + core_conf = EXYNOS5260_CONFIGURATION_LOCAL_POWER_CFG | + EXYNOS5260_CONFIGURATION_INITIATE_WAKEUP_FROM_LOWPOWER; pmu_raw_writel(core_conf, EXYNOS_ARM_CORE_CONFIGURATION(cpu)); @@ -129,8 +149,17 @@ void exynos_cpu_power_up(int cpu) */ int exynos_cpu_power_state(int cpu) { - return (pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(cpu)) & - S5P_CORE_LOCAL_PWR_EN); + u32 status = pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(cpu)); + + if (soc_is_exynos5260()) { + if ((status & EXYNOS5260_STATUS_STATES) == + EXYNOS5260_STATUS_STATES_NORMAL) + return S5P_CORE_LOCAL_PWR_EN; + else + return 0; + } + + return status & S5P_CORE_LOCAL_PWR_EN; } /** @@ -197,7 +226,7 @@ static inline void __iomem *cpu_boot_reg(int cpu) boot_reg = cpu_boot_reg_base(); if (!boot_reg) return IOMEM_ERR_PTR(-ENODEV); - if (soc_is_exynos4412()) + if (soc_is_exynos4412() || soc_is_exynos5260()) boot_reg += 4*cpu; else if (soc_is_exynos5420() || soc_is_exynos5800()) boot_reg += 4; @@ -371,7 +400,7 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) call_firmware_op(cpu_boot, core_id); - if (soc_is_exynos3250()) + if (soc_is_exynos3250() /* || soc_is_exynos5260() */) dsb_sev(); else arch_send_wakeup_ipi_mask(cpumask_of(cpu)); diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index 0850505ac78b..174b8064a655 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -230,6 +230,7 @@ EXYNOS_PMU_IRQ(exynos3250_pmu_irq, "samsung,exynos3250-pmu"); EXYNOS_PMU_IRQ(exynos4210_pmu_irq, "samsung,exynos4210-pmu"); EXYNOS_PMU_IRQ(exynos4412_pmu_irq, "samsung,exynos4412-pmu"); EXYNOS_PMU_IRQ(exynos5250_pmu_irq, "samsung,exynos5250-pmu"); +EXYNOS_PMU_IRQ(exynos5260_pmu_irq, "samsung,exynos5260-pmu"); EXYNOS_PMU_IRQ(exynos5420_pmu_irq, "samsung,exynos5420-pmu"); static int exynos_cpu_do_idle(void) @@ -258,6 +259,24 @@ static int exynos3250_cpu_suspend(unsigned long arg) return exynos_cpu_do_idle(); } +static int exynos5260_cpu_suspend(unsigned long arg) +{ + /* MCPM works with HW CPU identifiers */ + unsigned int mpidr = read_cpuid_mpidr(); + unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); + unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); + + if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) { + mcpm_set_entry_vector(cpu, cluster, exynos_cpu_resume); + mcpm_cpu_suspend(); + } + + pr_info("Failed to suspend the system\n"); + + /* return value != 0 means failure */ + return 1; +} + static int exynos5420_cpu_suspend(unsigned long arg) { /* MCPM works with HW CPU identifiers */ @@ -324,6 +343,17 @@ static void exynos3250_pm_prepare(void) pmu_raw_writel(__pa_symbol(exynos_cpu_resume), S5P_INFORM0); } +static void exynos5260_pm_prepare(void) +{ + /* Set wake-up mask registers */ + pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), + EXYNOS5260_WAKEUP_MASK1); + /* EXYNOS5260_EINT_WAKEUP_MASK is set by pinctrl */ + + /* Set value of power down register for sleep mode */ + exynos_sys_powerdown_conf(SYS_SLEEP); +} + static void exynos5420_pm_prepare(void) { unsigned int tmp; @@ -369,14 +399,18 @@ static void exynos5420_pm_prepare(void) pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION); } - static int exynos_pm_suspend(void) { + int val; exynos_pm_central_suspend(); /* Setting SEQ_OPTION register */ - pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0, - S5P_CENTRAL_SEQ_OPTION); + if (soc_is_exynos5260()) + val = EXYNOS5260_USE_STANDBYWFI_KFC_CORE0 | + EXYNOS5260_USE_PROLOGNED_LOGIC_RESET; + else + val = S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0; + pmu_raw_writel(val, S5P_CENTRAL_SEQ_OPTION); if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) exynos_cpu_save_register(); @@ -384,6 +418,17 @@ static int exynos_pm_suspend(void) return 0; } +static int exynos5260_pm_suspend(void) +{ + pmu_raw_writel(EXYNOS5260_USE_STANDBYWFI_KFC_CORE0 | + EXYNOS5260_USE_PROLOGNED_LOGIC_RESET, + S5P_CENTRAL_SEQ_OPTION); + + exynos_pm_central_suspend(); + + return 0; +} + static int exynos5420_pm_suspend(void) { u32 this_cluster; @@ -442,6 +487,19 @@ static void exynos3250_pm_resume(void) pmu_raw_writel(0x0, S5P_INFORM1); } +static void exynos5260_pm_resume(void) +{ + pmu_raw_writel(EXYNOS5260_USE_STANDBY_WFI_ALL | + EXYNOS5260_USE_PROLOGNED_LOGIC_RESET, + S5P_CENTRAL_SEQ_OPTION); + + if (exynos_pm_central_resume()) + goto early_wakeup; + +early_wakeup: + return; +} + static void exynos5420_prepare_pm_resume(void) { if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) @@ -593,6 +651,15 @@ static const struct exynos_pm_data exynos5250_pm_data = { .cpu_suspend = exynos_cpu_suspend, }; +static const struct exynos_pm_data exynos5260_pm_data = { + .wkup_irq = exynos3250_wkup_irq, + .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)), + .pm_suspend = exynos5260_pm_suspend, + .pm_resume = exynos5260_pm_resume, + .pm_prepare = exynos5260_pm_prepare, + .cpu_suspend = exynos5260_cpu_suspend, +}; + static const struct exynos_pm_data exynos5420_pm_data = { .wkup_irq = exynos5250_wkup_irq, .wake_disable_mask = (0x7F << 7) | (0x1F << 1), @@ -617,6 +684,9 @@ static const struct of_device_id exynos_pmu_of_device_ids[] __initconst = { .compatible = "samsung,exynos5250-pmu", .data = &exynos5250_pm_data, }, { + .compatible = "samsung,exynos5260-pmu", + .data = &exynos5260_pm_data, + }, { .compatible = "samsung,exynos5420-pmu", .data = &exynos5420_pm_data, }, @@ -644,10 +714,12 @@ void __init exynos_pm_init(void) pm_data = (const struct exynos_pm_data *) match->data; - /* All wakeup disable */ - tmp = pmu_raw_readl(S5P_WAKEUP_MASK); - tmp |= pm_data->wake_disable_mask; - pmu_raw_writel(tmp, S5P_WAKEUP_MASK); + if (!soc_is_exynos5260()) { + /* All wakeup disable */ + tmp = pmu_raw_readl(S5P_WAKEUP_MASK); + tmp |= pm_data->wake_disable_mask; + pmu_raw_writel(tmp, S5P_WAKEUP_MASK); + } exynos_pm_syscore_ops.suspend = pm_data->pm_suspend; exynos_pm_syscore_ops.resume = pm_data->pm_resume;