From patchwork Thu Mar 20 00:54:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ashwin Chaugule X-Patchwork-Id: 26622 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pb0-f72.google.com (mail-pb0-f72.google.com [209.85.160.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 21DD8203C3 for ; Thu, 20 Mar 2014 00:56:41 +0000 (UTC) Received: by mail-pb0-f72.google.com with SMTP id jt11sf369309pbb.7 for ; Wed, 19 Mar 2014 17:56:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:subject:date:message-id:cc :precedence:list-id:list-unsubscribe:list-archive:list-post :list-help:list-subscribe:mime-version:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list :content-type:content-transfer-encoding; bh=ybQ21X0WFg/AmgrHFj2HFJXinZvrSg5Qs/suVVFLOUE=; b=mI+XxliKv85ZJhR7ez//bV5UmNrxp72JjKqxrqUZMC7Phdog7WF2IBC62Kz/xaK0R+ om7T5UZwcb4JgitluDtFou9FQO6pRHrmxTHkqPuXfwj/aXxNj5xmtO6kvT/1LA/hBdnk +ZQh+8vi61vXrK/gbYoOATA9ZX1CXBZIYV87078HdGfzM1DrSS6nSVP1cUHiUSBO7rEQ q08+a5IhJNvTRh5A9x7uHVc1bIbL7QQUrtGDqSd7lwdXYRujTfZo9mXY8xQdeQVdbYSN OTbnaqMx+RjL8i1fZ6S+TKXP3zeCf37GBSVEiYbKLEAXdTuA9x6nKN73HYJycotSLTpQ Q/Ww== X-Gm-Message-State: ALoCoQmfMjZgnJjTgXKAWmvuHqp2vVOQ9PfRDnldO8liyatctgXcXGtRrcXkTX9cT/MC/BHRhmJc X-Received: by 10.68.197.73 with SMTP id is9mr16215763pbc.0.1395277000248; Wed, 19 Mar 2014 17:56:40 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.24.226 with SMTP id 89ls34740qgr.14.gmail; Wed, 19 Mar 2014 17:56:40 -0700 (PDT) X-Received: by 10.221.37.1 with SMTP id tc1mr2387659vcb.32.1395276999995; Wed, 19 Mar 2014 17:56:39 -0700 (PDT) Received: from mail-vc0-f179.google.com (mail-vc0-f179.google.com [209.85.220.179]) by mx.google.com with ESMTPS id sq9si71104vdc.35.2014.03.19.17.56.39 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 19 Mar 2014 17:56:39 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.179 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.179; Received: by mail-vc0-f179.google.com with SMTP id ij19so140054vcb.38 for ; Wed, 19 Mar 2014 17:56:39 -0700 (PDT) X-Received: by 10.58.248.5 with SMTP id yi5mr125342vec.42.1395276999886; Wed, 19 Mar 2014 17:56:39 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.78.9 with SMTP id i9csp347521vck; Wed, 19 Mar 2014 17:56:39 -0700 (PDT) X-Received: by 10.180.185.197 with SMTP id fe5mr19981wic.56.1395276998881; Wed, 19 Mar 2014 17:56:38 -0700 (PDT) Received: from casper.infradead.org (casper.infradead.org. [2001:770:15f::2]) by mx.google.com with ESMTPS id j10si141604wjw.161.2014.03.19.17.56.38 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 19 Mar 2014 17:56:38 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:770:15f::2 as permitted sender) client-ip=2001:770:15f::2; Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WQRGn-0004aa-6w; Thu, 20 Mar 2014 00:55:41 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WQRGa-0006oJ-2s; Thu, 20 Mar 2014 00:55:28 +0000 Received: from mail-qg0-f46.google.com ([209.85.192.46]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WQRGL-0006n9-Al for linux-arm-kernel@lists.infradead.org; Thu, 20 Mar 2014 00:55:15 +0000 Received: by mail-qg0-f46.google.com with SMTP id e89so434265qgf.5 for ; Wed, 19 Mar 2014 17:54:48 -0700 (PDT) X-Received: by 10.224.128.138 with SMTP id k10mr47916290qas.68.1395276888000; Wed, 19 Mar 2014 17:54:48 -0700 (PDT) Received: from localhost.localdomain (cpe-098-027-049-158.nc.res.rr.com. [98.27.49.158]) by mx.google.com with ESMTPSA id i14sm509019qaj.11.2014.03.19.17.54.45 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 19 Mar 2014 17:54:46 -0700 (PDT) From: Ashwin Chaugule To: linaro-acpi@lists.linaro.org Subject: [PATCH v1 1/2] PSCI: Use DT Function ID values only for old versions of spec Date: Wed, 19 Mar 2014 20:54:24 -0400 Message-Id: <1395276865-6868-1-git-send-email-ashwin.chaugule@linaro.org> X-Mailer: git-send-email 1.8.3.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140319_205513_448841_67426591 X-CRM114-Status: GOOD ( 17.21 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [209.85.192.46 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: mark.rutland@arm.com, rob.herring@linaro.org, anup.patel@linaro.org, marc.zyngier@arm.com, Ashwin Chaugule , linux-arm-kernel@lists.infradead.org, christoffer.dall@linaro.org, Charles.Garcia-Tobin@arm.com X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 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+patch=linaro.org@lists.infradead.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ashwin.chaugule@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.179 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 The PSCI v0.2+ spec mandates specific values of Function IDs for ARM32 and ARM64. Use DT bindings of Function IDs only when using older versions. Use static values otherwise. This patch also prepares the code to easily use the ACPI API which is based off of PSCI v0.2+. Signed-off-by: Ashwin Chaugule --- arch/arm/include/asm/psci.h | 15 ++++++ arch/arm/kernel/psci.c | 110 +++++++++++++++++++++++++++++++++++++----- arch/arm64/include/asm/psci.h | 12 +++++ arch/arm64/kernel/psci.c | 106 +++++++++++++++++++++++++++++++++++----- 4 files changed, 218 insertions(+), 25 deletions(-) diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h index c4ae171..3f8ebf9 100644 --- a/arch/arm/include/asm/psci.h +++ b/arch/arm/include/asm/psci.h @@ -17,6 +17,19 @@ #define PSCI_POWER_STATE_TYPE_STANDBY 0 #define PSCI_POWER_STATE_TYPE_POWER_DOWN 1 +/* PSCI Function ID's for ARM32 as per PSCI spec v0.2 */ + +#define PSCI_ID_VERSION 0x84000000 +#define PSCI_ID_CPU_SUSPEND 0x84000001 +#define PSCI_ID_CPU_OFF 0x84000002 +#define PSCI_ID_CPU_ON 0x84000003 +#define PSCI_ID_AFFINITY_INFO 0x84000004 +#define PSCI_ID_CPU_MIGRATE 0x84000005 +#define PSCI_ID_MIGRATE_INFO_TYPE 0x84000006 +#define PSCI_ID_MIGRATE_INFO_UP_CPU 0x84000007 +#define PSCI_ID_SYSTEM_OFF 0x84000008 +#define PSCI_ID_SYSTEM_RESET 0x84000009 + struct psci_power_state { u16 id; u8 type; @@ -36,9 +49,11 @@ extern struct smp_operations psci_smp_ops; #ifdef CONFIG_ARM_PSCI void psci_init(void); +int psci_get_version(void); bool psci_smp_available(void); #else static inline void psci_init(void) { } +static inline int psci_get_version(void) { } static inline bool psci_smp_available(void) { return false; } #endif diff --git a/arch/arm/kernel/psci.c b/arch/arm/kernel/psci.c index 4693188..48e0b0a 100644 --- a/arch/arm/kernel/psci.c +++ b/arch/arm/kernel/psci.c @@ -27,6 +27,7 @@ struct psci_operations psci_ops; static int (*invoke_psci_fn)(u32, u32, u32, u32); +typedef int (*psci_initcall_t)(const struct device_node *); enum psci_function { PSCI_FN_CPU_SUSPEND, @@ -110,6 +111,20 @@ static noinline int __invoke_psci_fn_smc(u32 function_id, u32 arg0, u32 arg1, return function_id; } +#define PSCI_VER_MAJOR_MASK 0xffff0000 +#define PSCI_VER_MINOR_MASK 0x0000ffff +#define PSCI_VER_MAJOR_SHIFT 16 + +static int psci_get_version(void) +{ + int err; + u32 fn; + + fn = PSCI_ID_VERSION; + err = invoke_psci_fn(fn, 0, 0, 0); + return err; +} + static int psci_cpu_suspend(struct psci_power_state state, unsigned long entry_point) { @@ -153,25 +168,65 @@ static int psci_migrate(unsigned long cpuid) return psci_to_linux_errno(err); } -static const struct of_device_id psci_of_match[] __initconst = { - { .compatible = "arm,psci", }, - {}, -}; +/* + * PSCI Function ID's for v0.2+ are well defined so use + * static values. + */ +static int psci_static_init(struct device_node *np) +{ + const char *method; + int err = 0; + + pr_info("probing for conduit method from DT.\n"); + + if (of_property_read_string(np, "method", &method)) { + pr_warn("missing \"method\" property\n"); + err = -ENXIO; + goto out_put_node; + } + + if (!strcmp("hvc", method)) { + invoke_psci_fn = __invoke_psci_fn_hvc; + } else if (!strcmp("smc", method)) { + invoke_psci_fn = __invoke_psci_fn_smc; + } else { + pr_warn("invalid \"method\" property: %s\n", method); + err = -EINVAL; + goto out_put_node; + } -void __init psci_init(void) + pr_info("Using static PSCIv0.2+ function IDs\n"); + psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_ID_CPU_SUSPEND; + psci_ops.cpu_suspend = psci_cpu_suspend; + + psci_function_id[PSCI_FN_CPU_OFF] = PSCI_ID_CPU_OFF; + psci_ops.cpu_off = psci_cpu_off; + + psci_function_id[PSCI_FN_CPU_ON] = PSCI_ID_CPU_ON; + psci_ops.cpu_on = psci_cpu_on; + + psci_function_id[PSCI_FN_MIGRATE] = PSCI_ID_CPU_MIGRATE; + psci_ops.migrate = psci_migrate; + +out_put_node: + of_node_put(np); + return err; +} + +/* + * PSCI < v0.2 can override PSCI function ID's via DT. + */ +static int psci_of_init(struct device_node *np) { - struct device_node *np; const char *method; u32 id; - - np = of_find_matching_node(NULL, psci_of_match); - if (!np) - return; + int err = 0; pr_info("probing function IDs from device-tree\n"); if (of_property_read_string(np, "method", &method)) { - pr_warning("missing \"method\" property\n"); + pr_warn("missing \"method\" property\n"); + err = -EINVAL; goto out_put_node; } @@ -180,7 +235,8 @@ void __init psci_init(void) } else if (!strcmp("smc", method)) { invoke_psci_fn = __invoke_psci_fn_smc; } else { - pr_warning("invalid \"method\" property: %s\n", method); + pr_warn("invalid \"method\" property: %s\n", method); + err = -ENXIO; goto out_put_node; } @@ -206,5 +262,33 @@ void __init psci_init(void) out_put_node: of_node_put(np); - return; + return err; +} + +static const struct of_device_id psci_of_match[] __initconst = { + { .compatible = "arm,psci", .data = psci_of_init}, + { .compatible = "arm,psci-0.2", .data = psci_static_init}, + {}, +}; + +int __init psci_init(void) +{ + struct device_node *np; + const struct of_device_id *matched_np; + psci_initcall_t init_fn; + int ver = 0; + + np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np); + if (!np) + return -ENODEV; + + ver = psci_get_version(); + + pr_info("using static PSCIv%d.%d Function IDs\n", + (ver & PSCI_VER_MAJOR_MASK) >> PSCI_VER_MAJOR_SHIFT, + (ver & PSCI_VER_MINOR_MASK)); + + + init_fn = (psci_initcall_t)matched_np->data; + return init_fn(np); } diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h index e5312ea..b72678f 100644 --- a/arch/arm64/include/asm/psci.h +++ b/arch/arm64/include/asm/psci.h @@ -16,4 +16,16 @@ int psci_init(void); +/* PSCI Function ID's for ARM64 as per PSCI spec v0.2 */ +#define PSCI_ID_VERSION 0x84000000 +#define PSCI_ID_CPU_SUSPEND 0xc4000001 +#define PSCI_ID_CPU_OFF 0x84000002 +#define PSCI_ID_CPU_ON 0xc4000003 +#define PSCI_ID_AFFINITY_INFO 0xc4000004 +#define PSCI_ID_CPU_MIGRATE 0xc4000005 +#define PSCI_ID_MIGRATE_INFO_TYPE 0x84000006 +#define PSCI_ID_MIGRATE_INFO_UP_CPU 0xc4000007 +#define PSCI_ID_SYSTEM_OFF 0x84000008 +#define PSCI_ID_SYSTEM_RESET 0x84000009 + #endif /* __ASM_PSCI_H */ diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c index 4f97db3..d4cff4e 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c @@ -45,12 +45,14 @@ struct psci_operations { static struct psci_operations psci_ops; static int (*invoke_psci_fn)(u64, u64, u64, u64); +typedef int (*psci_initcall_t)(const struct device_node *); enum psci_function { PSCI_FN_CPU_SUSPEND, PSCI_FN_CPU_ON, PSCI_FN_CPU_OFF, PSCI_FN_MIGRATE, + PSCI_FN_AFFINITY_INFO, PSCI_FN_MAX, }; @@ -128,6 +130,20 @@ static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1, return function_id; } +#define PSCI_VER_MAJOR_MASK 0xffff0000 +#define PSCI_VER_MINOR_MASK 0x0000ffff +#define PSCI_VER_MAJOR_SHIFT 16 + +static int psci_get_version(void) +{ + int err; + u32 fn; + + fn = PSCI_ID_VERSION; + err = invoke_psci_fn(fn, 0, 0, 0); + return err; +} + static int psci_cpu_suspend(struct psci_power_state state, unsigned long entry_point) { @@ -171,26 +187,64 @@ static int psci_migrate(unsigned long cpuid) return psci_to_linux_errno(err); } -static const struct of_device_id psci_of_match[] __initconst = { - { .compatible = "arm,psci", }, - {}, -}; +/* + * PSCI Function ID's for v0.2+ are well defined so use + * static values. + */ +static int psci_static_init(struct device_node *np) +{ + const char *method; + int err = 0; -int __init psci_init(void) + pr_info("probing for conduit method from DT.\n"); + + if (of_property_read_string(np, "method", &method)) { + pr_warn("missing \"method\" property\n"); + err = -ENXIO; + goto out_put_node; + } + + if (!strcmp("hvc", method)) { + invoke_psci_fn = __invoke_psci_fn_hvc; + } else if (!strcmp("smc", method)) { + invoke_psci_fn = __invoke_psci_fn_smc; + } else { + pr_warn("invalid \"method\" property: %s\n", method); + err = -EINVAL; + goto out_put_node; + } + + pr_info("Using static PSCIv0.2+ function IDs\n"); + psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_ID_CPU_SUSPEND; + psci_ops.cpu_suspend = psci_cpu_suspend; + + psci_function_id[PSCI_FN_CPU_OFF] = PSCI_ID_CPU_OFF; + psci_ops.cpu_off = psci_cpu_off; + + psci_function_id[PSCI_FN_CPU_ON] = PSCI_ID_CPU_ON; + psci_ops.cpu_on = psci_cpu_on; + + psci_function_id[PSCI_FN_MIGRATE] = PSCI_ID_CPU_MIGRATE; + psci_ops.migrate = psci_migrate; + +out_put_node: + of_node_put(np); + return err; +} + +/* + * PSCI < v0.2 can override PSCI function ID's via DT. + */ +static int psci_of_init(struct device_node *np) { - struct device_node *np; const char *method; u32 id; int err = 0; - np = of_find_matching_node(NULL, psci_of_match); - if (!np) - return -ENODEV; - pr_info("probing function IDs from device-tree\n"); if (of_property_read_string(np, "method", &method)) { - pr_warning("missing \"method\" property\n"); + pr_warn("missing \"method\" property\n"); err = -ENXIO; goto out_put_node; } @@ -200,7 +254,7 @@ int __init psci_init(void) } else if (!strcmp("smc", method)) { invoke_psci_fn = __invoke_psci_fn_smc; } else { - pr_warning("invalid \"method\" property: %s\n", method); + pr_warn("invalid \"method\" property: %s\n", method); err = -EINVAL; goto out_put_node; } @@ -230,6 +284,34 @@ out_put_node: return err; } +static const struct of_device_id psci_of_match[] __initconst = { + { .compatible = "arm,psci", .data = psci_of_init}, + { .compatible = "arm,psci-0.2", .data = psci_static_init}, + {}, +}; + +int __init psci_init(void) +{ + struct device_node *np; + const struct of_device_id *matched_np; + psci_initcall_t init_fn; + int ver = 0; + + np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np); + + if (!np) + return -ENODEV; + + ver = psci_get_version(); + + pr_info("PSCIv%d.%d detected in firmware.\n", + (ver & PSCI_VER_MAJOR_MASK) >> PSCI_VER_MAJOR_SHIFT, + (ver & PSCI_VER_MINOR_MASK)); + + init_fn = (psci_initcall_t)matched_np->data; + return init_fn(np); +} + #ifdef CONFIG_SMP static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu)