From patchwork Tue Aug 4 23:35:36 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lina Iyer X-Patchwork-Id: 6945281 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 345599F38B for ; Tue, 4 Aug 2015 23:40:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 05CA72042A for ; Tue, 4 Aug 2015 23:40:56 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CCE5C203DC for ; Tue, 4 Aug 2015 23:40:54 +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 1ZMlmr-0007Ls-GT; Tue, 04 Aug 2015 23:38:25 +0000 Received: from casper.infradead.org ([2001:770:15f::2]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZMllF-0006D5-1u for linux-arm-kernel@bombadil.infradead.org; Tue, 04 Aug 2015 23:36:45 +0000 Received: from mail-pa0-f45.google.com ([209.85.220.45]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZMllA-0001Y9-Ur for linux-arm-kernel@lists.infradead.org; Tue, 04 Aug 2015 23:36:42 +0000 Received: by pabxd6 with SMTP id xd6so2468207pab.2 for ; Tue, 04 Aug 2015 16:36:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=KJBLYRT6ZB+rC7bkWgRj43eeYabFIpDmPMMkoIxePis=; b=LFlSn4+4wyzfPFJheZ+zKwoziJ7hSufqhriPp/glQCJZ8RFEhE+ofSzplVVR62CQFE oDzMx9lGlLmKjlvDKcGnanVlSkFbNRONtlhhYkoZYR27BaqPWGSOKpRS8QbywISIMLsb JcQkc3HBI6YSmLzwD1dXcsZF+FE1NeT0CfhCpqa2zjZcviRVqUkUlMCGzkhL+3d13wBI k6YL/kko1PAJNxNtnicSsyUGDiXYiONx/wrbf3Kk3CtGyGZiAufjg3IoipIAH5WIU6NB cnDXjh9B+yD43khzExV7wV1v2P8QZu+TuA2LDETKemAEbv36VrKG97iPsHEM2VwohvA+ NXjw== X-Gm-Message-State: ALoCoQkEFTbe6uxCYIQMKj+li6CLSXzEqyVuLqh0L7OL1QtkKmOjvHBNrA9aAJ1uJLmOEs2y0FO2 X-Received: by 10.66.97.105 with SMTP id dz9mr12901647pab.23.1438731374840; Tue, 04 Aug 2015 16:36:14 -0700 (PDT) Received: from ubuntu.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id to5sm527525pac.33.2015.08.04.16.36.12 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 04 Aug 2015 16:36:14 -0700 (PDT) From: Lina Iyer To: rjw@rjwysocki.net, ulf.hansson@linaro.org, khilman@linaro.org Subject: [PATCH 6/9] ARM: domain: Add platform handlers for CPU PM domains Date: Tue, 4 Aug 2015 17:35:36 -0600 Message-Id: <1438731339-58317-7-git-send-email-lina.iyer@linaro.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1438731339-58317-1-git-send-email-lina.iyer@linaro.org> References: <1438731339-58317-1-git-send-email-lina.iyer@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150805_003641_282700_F12D7250 X-CRM114-Status: GOOD ( 34.75 ) X-Spam-Score: -2.6 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Rob Herring , k.kozlowski@samsung.com, Lorenzo Pieralisi , linux-pm@vger.kernel.org, Catalin Marinas , sboyd@codeaurora.org, msivasub@codeaurora.org, geert@linux-m68k.org, Lina Iyer , agross@codeaurora.org, linux-arm-kernel@lists.infradead.org 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.3 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, 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 In addition to the common power up/down actions of CPU PM domain core, platforms may have additional configuration before the CPU domain can be powered off or considered active. Allow platform drivers to register handlers for CPU PM domains. Platform drivers may register their callbacks against a compatible string defined by their PM domain provider device node in the DT. At domain init, the platform driver can initialize the platform specific genpd attributes. The init callback would need to return successfully, for the platform power_on/off handlers to be registered with the CPU PM domain. The code uses __init section to reduce memory needed for platform handlers and therefore can be freed after the driver is initialized, a desirable outcome for single kernel image. Cc: Rob Herring Cc: Stephen Boyd Cc: Kevin Hilman Cc: Ulf Hansson Cc: Catalin Marinas Cc: Mark Rutland Cc: Lorenzo Pieralisi Signed-off-by: Lina Iyer --- Documentation/arm/cpu-domains.txt | 26 ++++++++++++++++++++++++++ arch/arm/common/domains.c | 37 +++++++++++++++++++++++++++++++++++++ arch/arm/include/asm/arm-pd.h | 30 ++++++++++++++++++++++++++++++ include/asm-generic/vmlinux.lds.h | 2 ++ 4 files changed, 95 insertions(+) create mode 100644 arch/arm/include/asm/arm-pd.h diff --git a/Documentation/arm/cpu-domains.txt b/Documentation/arm/cpu-domains.txt index 3e535b7..a0b98f3 100644 --- a/Documentation/arm/cpu-domains.txt +++ b/Documentation/arm/cpu-domains.txt @@ -47,3 +47,29 @@ attaches the domains' CPU devices to as specified in the DT. This happens automatically at kernel init, when the domain is specified as compatible with "arm,pd". Powering on/off the common cluster hardware would also be done when the PM domain is runtime suspended or resumed. + +SoCs may have additional configuration for the CPU PM domain. The ARM code +provides a way for the platform driver to add those properties to the genpd +before the genpd object is initialized. Additionally, platform driver may also +register for CPU domain power_on/power_off callbacks. + +Platform drivers may register the callbacks using the __init section macro +ARM_PD_METHOD_OF_DECLARE. The callbacks in of_arm_pd_ops, can be specified +against a compatible flag for the domain provider. + +Callback for platform drivers - + +int (*init)(struct device_node *dn, struct generic_pm_domain *d) +The init() callback is called before the generic PM domain is registered with +the GenPD framework. The device node is provided to identify the domain that +is being initialized. The init function must return 0, in order for the +power_on and power_off callbacks to be registered with the CPU PD framework. + +int (*power_on)(struct generic_pm_domain *d); +The power_on() callback is called when the first CPU in the cluster is ready +to resume execution. The domain may be considered active at this point. + +int (*power_off)(struct generic_pm_domain *d); +The power_off() callback is called when the last CPU in the cluster enters +idle. The domain may be configured to power off and wait for a CPU's wakeup +interrupt. diff --git a/arch/arm/common/domains.c b/arch/arm/common/domains.c index 15981e9..bbffeed 100644 --- a/arch/arm/common/domains.c +++ b/arch/arm/common/domains.c @@ -18,12 +18,19 @@ #include #include +#include + #define NAME_MAX 36 struct arm_pm_domain { struct generic_pm_domain genpd; + struct of_arm_pd_ops platform_ops; }; +extern struct of_arm_pd_method __arm_pd_method_of_table[]; +static const struct of_arm_pd_method __arm_pd_method_of_table_sentinel + __used __section(__arm_pd_method_of_table_end); + static inline struct arm_pm_domain *to_arm_pd(struct generic_pm_domain *d) { @@ -32,20 +39,30 @@ struct arm_pm_domain *to_arm_pd(struct generic_pm_domain *d) static int arm_pd_power_down(struct generic_pm_domain *genpd) { + struct arm_pm_domain *pd = to_arm_pd(genpd); + /* * Notify CPU PM domain power down * TODO: Call the notificated directly from here. */ cpu_cluster_pm_enter(); + if (pd->platform_ops.power_off) + return pd->platform_ops.power_off(genpd); + return 0; } static int arm_pd_power_up(struct generic_pm_domain *genpd) { + struct arm_pm_domain *pd = to_arm_pd(genpd); + /* Notify CPU PM domain power up */ cpu_cluster_pm_exit(); + if (pd->platform_ops.power_on) + return pd->platform_ops.power_on(genpd); + return 0; } @@ -134,6 +151,7 @@ static int __init arm_domain_init(void) { struct device_node *np; int count = 0; + struct of_arm_pd_method *m = __arm_pd_method_of_table; for_each_compatible_node(np, NULL, "arm,pd") { struct arm_pm_domain *pd; @@ -145,6 +163,25 @@ static int __init arm_domain_init(void) if (!pd) return -ENOMEM; + /* Invoke platform initialization for the PM domain */ + for (; m->handle; m++) { + int ret; + + if (of_device_is_compatible(np, m->handle)) { + ret = m->ops->init(np, &pd->genpd); + if (!ret) { + pr_debug("CPU PD ops found for %s\n", + m->handle); + pd->platform_ops.power_on = + m->ops->power_on; + pd->platform_ops.power_off = + m->ops->power_off; + } + break; + } + } + + /* Initialize rest of CPU PM domain specifics */ pd->genpd.name = kstrndup(np->name, NAME_MAX, GFP_KERNEL); pd->genpd.power_off = arm_pd_power_down; pd->genpd.power_on = arm_pd_power_up; diff --git a/arch/arm/include/asm/arm-pd.h b/arch/arm/include/asm/arm-pd.h new file mode 100644 index 0000000..fc44abf --- /dev/null +++ b/arch/arm/include/asm/arm-pd.h @@ -0,0 +1,30 @@ +/* + * linux/arch/arm/include/asm/arm-pd.h + * + * Copyright (C) 2015 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ARM_PD_H__ +#define __ARM_PD_H__ + +struct of_arm_pd_ops { + int (*init)(struct device_node *dn, struct generic_pm_domain *d); + int (*power_on)(struct generic_pm_domain *d); + int (*power_off)(struct generic_pm_domain *d); +}; + +struct of_arm_pd_method { + const char *handle; + struct of_arm_pd_ops *ops; +}; + +#define ARM_PD_METHOD_OF_DECLARE(_name, _handle, _ops) \ + static const struct of_arm_pd_method __arm_pd_method_of_table_##_name \ + __used __section(__arm_pd_method_of_table) \ + = { .handle = _handle, .ops = _ops } + +#endif /* __ARM_PD_H__ */ diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 8bd374d..bd97a69 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -179,6 +179,7 @@ #define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem) #define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method) #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method) +#define ARM_PD_METHOD_OF_TABLES() OF_TABLE(CONFIG_PM_GENERIC_DOMAINS, arm_pd_method) #define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon) #define KERNEL_DTB() \ @@ -514,6 +515,7 @@ IOMMU_OF_TABLES() \ CPU_METHOD_OF_TABLES() \ CPUIDLE_METHOD_OF_TABLES() \ + ARM_PD_METHOD_OF_TABLES() \ KERNEL_DTB() \ IRQCHIP_OF_MATCH_TABLE() \ EARLYCON_TABLE() \