From patchwork Wed Jan 21 11:35:55 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sudeep Holla X-Patchwork-Id: 5676561 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 213B5C058D for ; Wed, 21 Jan 2015 11:38:05 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 36E6B200D0 for ; Wed, 21 Jan 2015 11:38:04 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E755D20504 for ; Wed, 21 Jan 2015 11:38:01 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YDtZs-0001nT-49; Wed, 21 Jan 2015 11:36:04 +0000 Received: from foss-mx-na.foss.arm.com ([217.140.108.86]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YDtZe-0001hf-GO for linux-arm-kernel@lists.infradead.org; Wed, 21 Jan 2015 11:35:51 +0000 Received: from foss-smtp-na-1.foss.arm.com (unknown [10.80.61.8]) by foss-mx-na.foss.arm.com (Postfix) with ESMTP id 6829F28E; Wed, 21 Jan 2015 05:35:24 -0600 (CST) Received: from collaborate-mta1.arm.com (highbank-bc01-b06.austin.arm.com [10.112.81.134]) by foss-smtp-na-1.foss.arm.com (Postfix) with ESMTP id 203135FAD7; Wed, 21 Jan 2015 05:35:22 -0600 (CST) Received: from e103737-lin.cambridge.arm.com (e103737-lin.cambridge.arm.com [10.1.207.156]) by collaborate-mta1.arm.com (Postfix) with ESMTP id 8AB7E13F824; Wed, 21 Jan 2015 05:35:20 -0600 (CST) From: Sudeep Holla To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org Subject: [PATCH RFC 2/2] ARM64: psci: implement system suspend using PSCI v0.2 CPU SUSPEND Date: Wed, 21 Jan 2015 11:35:55 +0000 Message-Id: <1421840155-18990-3-git-send-email-sudeep.holla@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1421840155-18990-1-git-send-email-sudeep.holla@arm.com> References: <1421840155-18990-1-git-send-email-sudeep.holla@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150121_033550_594825_FF5BF4E2 X-CRM114-Status: GOOD ( 14.42 ) X-Spam-Score: -0.0 (/) Cc: Mark Rutland , Jisheng Zhang , Jonghwa Lee , Lorenzo Pieralisi , Catalin Marinas , Leo Yan , Amit Daniel Kachhap , Rob Herring , Sudeep Holla X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP PSCI specifications upto v0.2 and the related kernel back-end implementation lack a method to enter system wide suspend state. This patch implements suspend to RAM support for all ARM64 systems with PSCIv0.2 support using CPU SUSPEND and the new system state DT bindings. Signed-off-by: Sudeep Holla --- arch/arm64/kernel/psci.c | 83 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c index f1dbca7d5c96..8be464747dd6 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -304,6 +305,75 @@ static void psci_sys_poweroff(void) invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0); } +static int psci_suspend_finisher(unsigned long arg) +{ + return psci_ops.cpu_suspend(*(struct psci_power_state *)arg, + virt_to_phys(cpu_resume)); +} + +#ifdef CONFIG_SUSPEND +static struct psci_power_state psci_system_suspend_state; + +static int psci_system_suspend_enter(suspend_state_t state) +{ + if (state != PM_SUSPEND_MEM) + return 0; + + /* + * TODO remove pack/unpacking of power_state to do away with + * these ugly type conversions + */ + return __cpu_suspend((unsigned long)&psci_system_suspend_state, + psci_suspend_finisher); +} + +static const struct platform_suspend_ops psci_suspend_ops = { + .valid = suspend_valid_only_mem, + .enter = psci_system_suspend_enter, +}; + +static void __init psci_0_2_system_suspend_init(void) +{ + int ret; + u32 psci_power_state; + const char *entry_method; + struct device_node *node; + + if (!psci_ops.cpu_suspend) + return; /* -EOPNOTSUPP */ + + node = of_find_compatible_node(NULL, NULL, "arm,system-suspend"); + if (!node || !of_device_is_available(node)) + return; /* -EOPNOTSUPP */ + + if (of_property_read_string(node, "entry-method", &entry_method)) { + pr_warn(" * %s missing entry-method property\n", node->full_name); + goto exit; + } + + if (strcmp(entry_method, "arm,psci")) + goto exit; /* out of PSCI scope ignore */ + + ret = of_property_read_u32(node, "arm,psci-suspend-param", + &psci_power_state); + if (ret) { + pr_warn(" * %s missing arm,psci-suspend-param property\n", + node->full_name); + goto exit; + } + + pr_debug("psci-power-state for system suspend %#x\n", psci_power_state); + + psci_power_state_unpack(psci_power_state, &psci_system_suspend_state); + + suspend_set_ops(&psci_suspend_ops); +exit: + of_node_put(node); +} +#else +static void __init psci_0_2_system_suspend_init(void) { } +#endif + /* * PSCI Function IDs for v0.2+ are well defined so use * standard values. @@ -361,6 +431,8 @@ static int __init psci_0_2_init(struct device_node *np) pm_power_off = psci_sys_poweroff; + psci_0_2_system_suspend_init(); + out_put_node: of_node_put(np); return err; @@ -509,14 +581,6 @@ static int cpu_psci_cpu_kill(unsigned int cpu) #endif #endif -static int psci_suspend_finisher(unsigned long index) -{ - struct psci_power_state *state = __this_cpu_read(psci_power_state); - - return psci_ops.cpu_suspend(state[index - 1], - virt_to_phys(cpu_resume)); -} - static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index) { int ret; @@ -531,7 +595,8 @@ static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index) if (state[index - 1].type == PSCI_POWER_STATE_TYPE_STANDBY) ret = psci_ops.cpu_suspend(state[index - 1], 0); else - ret = __cpu_suspend(index, psci_suspend_finisher); + ret = __cpu_suspend((unsigned long)&state[index - 1], + psci_suspend_finisher); return ret; }