From patchwork Tue Mar 3 12:29:33 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 45363 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wg0-f70.google.com (mail-wg0-f70.google.com [74.125.82.70]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 7EA542142B for ; Tue, 3 Mar 2015 12:31:31 +0000 (UTC) Received: by wghl18 with SMTP id l18sf28507347wgh.3 for ; Tue, 03 Mar 2015 04:31:30 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=Qvc+baqD34GwoUTCFBAblUyqwvaz3vS1PILNeLmoHVM=; b=aNHgN02/fpPxaPxvWXEFWcHUyW1IwUKDl1CETENoEFKNWABd+EWk8vR90qZuc2mLQY aedhdVg1XfY1G0En0T8dJ6Gpn93Y4QkNt4TngeZJ3XCIwAia7PWA8gTSCmmhfOwQoz2O 4AT4nirjxnrCVsE9+yOFSM2+gLjCAH1n+eugEWJmmpBxwb20XNYq4CK/ej50sVJVDGrR IzJ2asp6dQhT5HllcYYPufD5G5IUZcFww5kRqoSeL8k+59E3R3iLDlr2w9w6RFintXpH ivoGlBw4FOQNaAZ1EMdar+jvg/982J8JYbqC1x+ev5Lflj/y2IxV4hq4SURKCqGbw2lG odkw== X-Gm-Message-State: ALoCoQnTUIYuljmXv18nPoPulZe5PeLMVxE0f3Wvk0PLfwiZYlizDhgdsjnz2EVYlNQpUAObljCI X-Received: by 10.112.199.69 with SMTP id ji5mr4506744lbc.0.1425385890572; Tue, 03 Mar 2015 04:31:30 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.28.100 with SMTP id a4ls32116lah.23.gmail; Tue, 03 Mar 2015 04:31:30 -0800 (PST) X-Received: by 10.112.188.227 with SMTP id gd3mr28155853lbc.22.1425385890390; Tue, 03 Mar 2015 04:31:30 -0800 (PST) Received: from mail-lb0-f178.google.com (mail-lb0-f178.google.com. [209.85.217.178]) by mx.google.com with ESMTPS id mk4si376643lbc.143.2015.03.03.04.31.30 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 Mar 2015 04:31:30 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.178 as permitted sender) client-ip=209.85.217.178; Received: by lbvp9 with SMTP id p9so13756368lbv.8 for ; Tue, 03 Mar 2015 04:31:30 -0800 (PST) X-Received: by 10.152.116.18 with SMTP id js18mr28859364lab.106.1425385890090; Tue, 03 Mar 2015 04:31:30 -0800 (PST) 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.112.35.133 with SMTP id h5csp531494lbj; Tue, 3 Mar 2015 04:31:29 -0800 (PST) X-Received: by 10.66.159.167 with SMTP id xd7mr56062161pab.54.1425385888256; Tue, 03 Mar 2015 04:31:28 -0800 (PST) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l2si878056pdk.79.2015.03.03.04.31.26; Tue, 03 Mar 2015 04:31:28 -0800 (PST) Received-SPF: none (google.com: linux-kernel-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756632AbbCCMbW (ORCPT + 28 others); Tue, 3 Mar 2015 07:31:22 -0500 Received: from mail-wi0-f178.google.com ([209.85.212.178]:40575 "EHLO mail-wi0-f178.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756315AbbCCM3r (ORCPT ); Tue, 3 Mar 2015 07:29:47 -0500 Received: by wiwl15 with SMTP id l15so22387935wiw.5 for ; Tue, 03 Mar 2015 04:29:45 -0800 (PST) X-Received: by 10.180.149.205 with SMTP id uc13mr2593089wib.0.1425385785498; Tue, 03 Mar 2015 04:29:45 -0800 (PST) Received: from mai.lan (135-224-190-109.dsl.ovh.fr. [109.190.224.135]) by mx.google.com with ESMTPSA id h11sm20366995wic.14.2015.03.03.04.29.43 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 03 Mar 2015 04:29:44 -0800 (PST) From: Daniel Lezcano To: lorenzo.pieralisi@arm.com, rjw@rjwysocki.net Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Catalin.Marinas@arm.com, robherring2@gmail.com, arnd@arndb.de, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, lina.iyer@linaro.org Subject: [PATCH 2/6] ARM: cpuidle: Add a cpuidle ops structure to be used for DT Date: Tue, 3 Mar 2015 13:29:33 +0100 Message-Id: <1425385777-14766-3-git-send-email-daniel.lezcano@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1425385777-14766-1-git-send-email-daniel.lezcano@linaro.org> References: <1425385777-14766-1-git-send-email-daniel.lezcano@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: daniel.lezcano@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.178 as permitted sender) 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 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , The current state of the different cpuidle drivers is the different PM operations are passed via the platform_data using the platform driver paradigm. This approach allowed to split the low level PM code from the arch specific and the generic cpuidle code. Unfortunately there are complains about this approach as, in the context of the single kernel image, we have multiple drivers loaded in memory for nothing and the platform driver is not adequate for cpuidle. This patch provides a common interface via cpuidle ops for all new cpuidle driver and a definition for the device tree. It will allow with the next patches to a have a common definition with ARM64 and share the same cpuidle driver. The code is optimized to use the __init section intensively in order to reduce the memory footprint after the driver is initialized and unify the function names with ARM64. In order to prevent multiple declarations and the specific cpuidle ops to be spread across the different headers, a mechanism, similar to the cgroup subsys, has been introduced. A new platform willing to add its cpuidle ops must add an entry in the file cpuidle_ops.h in the current form: #if IS_ENABLED(CONFIG_ARM_FOO_CPUIDLE) CPUIDLE_OPS(foo) #endif ... and use the variable name in the specific low level code: struct cpuidle_ops foo_cpuidle_ops; The CPUIDLE_OPS macro will be processed in different way in the cpuidle.c file, thus allowing to keep untouched the arm cpuidle core code in the future when a new platform is added. Signed-off-by: Daniel Lezcano --- arch/arm/include/asm/cpuidle.h | 10 +++++ arch/arm/include/asm/cpuidle_ops.h | 3 ++ arch/arm/kernel/cpuidle.c | 85 ++++++++++++++++++++++++++++++++++++++ arch/arm64/include/asm/cpuidle.h | 5 ++- 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 arch/arm/include/asm/cpuidle_ops.h diff --git a/arch/arm/include/asm/cpuidle.h b/arch/arm/include/asm/cpuidle.h index 348dc81..3d31459 100644 --- a/arch/arm/include/asm/cpuidle.h +++ b/arch/arm/include/asm/cpuidle.h @@ -27,4 +27,14 @@ static inline int arm_cpuidle_simple_enter(struct cpuidle_device *dev, */ #define ARM_CPUIDLE_WFI_STATE ARM_CPUIDLE_WFI_STATE_PWR(UINT_MAX) +struct cpuidle_ops { + const char *name; + int (*suspend)(int cpu, unsigned long arg); + int (*init)(struct device_node *, int cpu); +}; + +extern int arm_cpuidle_suspend(int index); + +extern int arm_cpuidle_init(int cpu); + #endif diff --git a/arch/arm/include/asm/cpuidle_ops.h b/arch/arm/include/asm/cpuidle_ops.h new file mode 100644 index 0000000..be0a612 --- /dev/null +++ b/arch/arm/include/asm/cpuidle_ops.h @@ -0,0 +1,3 @@ +/* + * List of cpuidle operations + */ diff --git a/arch/arm/kernel/cpuidle.c b/arch/arm/kernel/cpuidle.c index 45969f8..25e9789c 100644 --- a/arch/arm/kernel/cpuidle.c +++ b/arch/arm/kernel/cpuidle.c @@ -10,8 +10,29 @@ */ #include +#include +#include #include +#define CPUIDLE_OPS(__x) extern struct cpuidle_ops __x ## _cpuidle_ops; +#include +#undef CPUIDLE_OPS + +#define CPUIDLE_OPS(__x) __x ## _cpuidle_ops_id, +enum cpuidle_ops_id { +#include + CPUIDLE_OPS_COUNT, +}; +#undef CPUIDLE_OPS + +#define CPUIDLE_OPS(__x) [__x ## _cpuidle_ops_id ] = &__x ## _cpuidle_ops, +static struct cpuidle_ops *supported_cpuidle_ops[] __initconst = { +#include +}; +#undef CPUIDLE_OPS + +static struct cpuidle_ops cpuidle_ops[NR_CPUS]; + int arm_cpuidle_simple_enter(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { @@ -19,3 +40,67 @@ int arm_cpuidle_simple_enter(struct cpuidle_device *dev, return index; } + +int arm_cpuidle_suspend(int index) +{ + int ret = -EOPNOTSUPP; + int cpu = smp_processor_id(); + + if (cpuidle_ops[cpu].suspend) + ret = cpuidle_ops[cpu].suspend(cpu, index); + + return ret; +} + +static struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *name) +{ + int i; + + for (i = 0; i < CPUIDLE_OPS_COUNT; i++) { + if (!strcmp(name, supported_cpuidle_ops[i]->name)) + return supported_cpuidle_ops[i]; + } + + return NULL; +} + +static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu) +{ + const char *enable_method; + struct cpuidle_ops *ops; + + enable_method = of_get_property(dn, "enable-method", NULL); + if (!enable_method) + return -ENOENT; + + ops = arm_cpuidle_get_ops(enable_method); + if (!ops) { + pr_warn("%s: unsupported enable-method property: %s\n", + dn->full_name, enable_method); + return -EOPNOTSUPP; + } + + cpuidle_ops[cpu] = *ops; /* structure copy */ + + pr_notice("cpuidle: enable-method property '%s'" + " found operations\n", ops->name); + + return 0; +} + +int __init arm_cpuidle_init(int cpu) +{ + int ret = -EOPNOTSUPP; + struct device_node *cpu_node = of_cpu_device_node_get(cpu); + + if (!cpu_node) + return -ENODEV; + + ret = arm_cpuidle_read_ops(cpu_node, cpu); + if (!ret && cpuidle_ops[cpu].init) + ret = cpuidle_ops[cpu].init(cpu_node, cpu); + + of_node_put(cpu_node); + + return ret; +} diff --git a/arch/arm64/include/asm/cpuidle.h b/arch/arm64/include/asm/cpuidle.h index 0710654..1bee287 100644 --- a/arch/arm64/include/asm/cpuidle.h +++ b/arch/arm64/include/asm/cpuidle.h @@ -15,5 +15,8 @@ static inline int cpu_suspend(unsigned long arg) return -EOPNOTSUPP; } #endif - +static inline int arm_cpuidle_suspend(int index) +{ + return cpu_suspend(index); +} #endif