From patchwork Wed Mar 14 16:58:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 131688 Delivered-To: patches@linaro.org Received: by 10.80.210.197 with SMTP id q5csp410781edg; Wed, 14 Mar 2018 09:59:37 -0700 (PDT) X-Received: by 10.46.0.168 with SMTP id e40mr3726394lji.77.1521046777866; Wed, 14 Mar 2018 09:59:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521046777; cv=none; d=google.com; s=arc-20160816; b=wuJwP2l9PyWxaNBveR8RDdpZSEhFuHjq+dQkV6FvqLUgjOKcYBTs/2iAozcnF38jbA nAz7+EeFxOtNBNFSWydLHhwFpc94YNo31FeenhC82HJ3ClfY7dLei14rvFeG0EwiAqF0 3ih0WKB1LFZR7eItkIj3ieSMw8rCA+4fgvR8q7HoxopB4Tg+qLF1Svqax0eykkkgLFER KqlB1/a5+rR9XsONatH6gyLCq2BA2RhbYKIHfP7qwg9d55Bi5ie7mVz0SZ3dF2mby/l3 VjePjshuQ7e0irbZEF6v6L7+JM8Fh6HyKWLLXLnJtm/SZj4jBR53E+i1Myv8FNnHei8U fffg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=baoVvASgwd+2H4g9KqvrNrRIEeGoT2TGHJcb5gqN/9k=; b=HbhAmxaMUdOac8kXi6kV/kn3NPUgLcLKVi0J6JSb4LX+hYDwpgP8Oeza10adsdJjuS 0egdN+0FlkNC1N5brvTNRn7mHkd8prOs0/BgMlxfOqFDYMF4YOXPMHKbvvQHgTGJ5vgl Dn8MAkyqD2aFktxon0XMz0h5HX5aHPgh7kB1kIIfPMKIO2udyUAlToRpcu4dXRUqAeXl MpXCmia6rm01rajVOFHWCb+IQ7l2TS5S86SQIL/4oZ9sfgYnz681R5SbxrWbih0vtcPd uy/RfAz2hKCekL3G3kXhsonA3lX1mZR0Xa5Wl2qr4vB0Am3X5bQdEtb5O7VUr+8MK0wz oB+g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=QFfTsBvk; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id b76-v6sor432105lfb.24.2018.03.14.09.59.37 for (Google Transport Security); Wed, 14 Mar 2018 09:59:37 -0700 (PDT) Received-SPF: pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=QFfTsBvk; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=baoVvASgwd+2H4g9KqvrNrRIEeGoT2TGHJcb5gqN/9k=; b=QFfTsBvkEoqRltUrONwBdpkpi5SgSXHB7zOdDifuxzWll/UJXz3Lskh5ziPDU+DDm3 ZRLdo8F+tXPVGdjreJgSY5vsMz0ZPMTMHhY9kp+riv7N0hDTk94uRPuLHbnLwuHNQ06B Aa1FiESLXhk8b8R1Of13qfAHOSSYVKay6idvg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=baoVvASgwd+2H4g9KqvrNrRIEeGoT2TGHJcb5gqN/9k=; b=VoNa3TowWdCvOiyM5B+KJyEScKKpboy+AdKKY68yGW3SZA+dIVUZxo3Mkkri9vQgmX L1U9rUBc8h2UaYI89nPf2JQBpiA1VgfC3sPzFPa2fYp/35xxbkwMPfFfQ6b9NEyQkI9e Zje4Tb8hpAEIIljfWgfAN8dGp+QU0gUQpry7ZhRTVcFm5oIIDfv0C9LJ4AOV2FjBWkBt 1Q3oaoCXgl5qJEQ9jo7cYlWF07qJewln6VKltxuwjQSX30z0PgFWruMWjk7/r55C4qRf cGRwbeyHzhmKnkN/qsVe/DgrK7TUfAfRNkVSJLKxXXKaOvSJrewfc7VzZwv8prMWDGpd ucvQ== X-Gm-Message-State: AElRT7EpK0kTS7ZmI6KRMsMokqk/3ykn3OAh+IzKxVpOmfImZ+yTAN7Z mTge2QgIQiwm9mOoTcYPZg7VMHzi X-Google-Smtp-Source: AG47ELsq6Bq+2JKmbqM8uWYjtuOYty3bj1VsBUI6Vo7RCmXn0m9B5DAQUy0ddRrDAZC9Ex2+rVPvlA== X-Received: by 2002:a19:d5c2:: with SMTP id m185-v6mr3794214lfg.5.1521046777415; Wed, 14 Mar 2018 09:59:37 -0700 (PDT) Return-Path: Received: from uffe-XPS-13-9360.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id t24-v6sm724849lfi.30.2018.03.14.09.59.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 14 Mar 2018 09:59:36 -0700 (PDT) From: Ulf Hansson To: "Rafael J . Wysocki" , Sudeep Holla , Lorenzo Pieralisi , linux-pm@vger.kernel.org Cc: Kevin Hilman , Lina Iyer , Lina Iyer , Ulf Hansson , Rob Herring , Daniel Lezcano , Thomas Gleixner , Vincent Guittot , Stephen Boyd , Juri Lelli , Geert Uytterhoeven , linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v6 19/25] drivers: firmware: psci: Add support for PM domains using genpd Date: Wed, 14 Mar 2018 17:58:29 +0100 Message-Id: <1521046715-30683-20-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521046715-30683-1-git-send-email-ulf.hansson@linaro.org> References: <1521046715-30683-1-git-send-email-ulf.hansson@linaro.org> When the hierarchical layout is used in DT, as to describe the PM topology for the CPUs, which are managed by PSCI, we want to be able to initialize and setup the corresponding PM domain data structures. Let's make this possible via adding a new file, psci_pm_domains.c and implement the needed interface towards the generic PM domain (aka genpd). Share a helper function, psci_dt_init_pm_domains(), which the regular PSCI firmware driver may call when it needs to initialize the PM topology using genpd. In principle, the implementation consists of allocating/initializing the genpd data structures, parsing the domain-idle states DT bindings via calling of_genpd_parse_idle_states() and to call pm_genpd_init() for the allocated genpds. Finally, one genpd OF provider is added per genpd. Via DT, this enables devices, including CPU devices, to be attached to the created genpds. Cc: Lina Iyer Co-developed-by: Lina Iyer Signed-off-by: Ulf Hansson --- drivers/firmware/Makefile | 2 +- drivers/firmware/psci.h | 6 ++ drivers/firmware/psci_pm_domain.c | 180 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/psci_pm_domain.c -- 2.7.4 diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index b248238..877260e 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -2,7 +2,7 @@ # # Makefile for the linux kernel. # -obj-$(CONFIG_ARM_PSCI_FW) += psci.o +obj-$(CONFIG_ARM_PSCI_FW) += psci.o psci_pm_domain.o obj-$(CONFIG_ARM_PSCI_CHECKER) += psci_checker.o obj-$(CONFIG_ARM_SCPI_PROTOCOL) += arm_scpi.o obj-$(CONFIG_ARM_SCPI_POWER_DOMAIN) += scpi_pm_domain.o diff --git a/drivers/firmware/psci.h b/drivers/firmware/psci.h index a2b4be5..8b6fe51 100644 --- a/drivers/firmware/psci.h +++ b/drivers/firmware/psci.h @@ -10,4 +10,10 @@ void psci_set_domain_state(u32 state); int psci_dt_parse_state_node(struct device_node *np, u32 *state); +#ifdef CONFIG_PM_GENERIC_DOMAINS_OF +int psci_dt_init_pm_domains(struct device_node *np); +#else +static inline int psci_dt_init_pm_domains(struct device_node *np) { return 0; } +#endif + #endif /* __PSCI_H */ diff --git a/drivers/firmware/psci_pm_domain.c b/drivers/firmware/psci_pm_domain.c new file mode 100644 index 0000000..f54819e --- /dev/null +++ b/drivers/firmware/psci_pm_domain.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PM domains for CPUs via genpd - managed by PSCI. + * + * Copyright (C) 2018 Linaro Ltd. + * Author: Ulf Hansson + * + */ + +#define pr_fmt(fmt) "psci: " fmt + +#include +#include +#include +#include +#include + +#include "psci.h" + +#ifdef CONFIG_PM_GENERIC_DOMAINS_OF +static int psci_pd_power_off(struct generic_pm_domain *pd) +{ + struct genpd_power_state *state = &pd->states[pd->state_idx]; + u32 *pd_state; + u32 composite_pd_state; + + if (!state->data) + return 0; + + pd_state = state->data; + composite_pd_state = *pd_state | psci_get_domain_state(); + psci_set_domain_state(composite_pd_state); + + return 0; +} + +static int psci_dt_parse_pd_states(struct genpd_power_state *states, + int state_count) +{ + int i, err; + u32 *psci_states; + + if (!state_count) + return 0; + + psci_states = kcalloc(state_count, sizeof(psci_states), GFP_KERNEL); + if (!psci_states) + return -ENOMEM; + + for (i = 0; i < state_count; i++) { + err = psci_dt_parse_state_node(to_of_node(states[i].fwnode), + &psci_states[i]); + if (err) { + kfree(psci_states); + return err; + } + } + + for (i = 0; i < state_count; i++) + states[i].data = &psci_states[i]; + + return 0; +} + +static int psci_dt_init_genpd(struct device_node *np, + struct genpd_power_state *states, + unsigned int state_count) +{ + struct generic_pm_domain *pd; + struct dev_power_governor *pd_gov; + int ret = -ENOMEM; + + pd = kzalloc(sizeof(*pd), GFP_KERNEL); + if (!pd) + return -ENOMEM; + + pd->name = kasprintf(GFP_KERNEL, "%pOF", np); + if (!pd->name) + goto free_pd; + + pd->name = kbasename(pd->name); + pd->power_off = psci_pd_power_off; + pd->states = states; + pd->state_count = state_count; + pd->flags |= GENPD_FLAG_IRQ_SAFE | GENPD_FLAG_CPU_DOMAIN; + + /* Use governor for CPU PM domains if it has some states to manage. */ + pd_gov = state_count > 0 ? &pm_domain_cpu_gov : NULL; + + ret = pm_genpd_init(pd, pd_gov, false); + if (ret) + goto free_name; + + ret = of_genpd_add_provider_simple(np, pd); + if (ret) + goto remove_pd; + + pr_info("init PM domain %s\n", pd->name); + return 0; + +remove_pd: + pm_genpd_remove(pd); +free_name: + kfree(pd->name); +free_pd: + kfree(pd); + pr_err("failed to init PM domain ret=%d %pOF\n", ret, np); + return ret; +} + +static int psci_dt_set_genpd_topology(struct device_node *np) +{ + struct device_node *node; + struct of_phandle_args child, parent; + int ret; + + for_each_child_of_node(np, node) { + if (of_parse_phandle_with_args(node, "power-domains", + "#power-domain-cells", 0, + &parent)) + continue; + + child.np = node; + child.args_count = 0; + + ret = of_genpd_add_subdomain(&parent, &child); + of_node_put(parent.np); + if (ret) { + of_node_put(node); + return ret; + } + } + + return 0; +} + +int psci_dt_init_pm_domains(struct device_node *np) +{ + struct device_node *node; + struct genpd_power_state *states; + int state_count; + int pd_count = 0; + int ret; + + /* Parse child nodes for "#power-domain-cells". */ + for_each_child_of_node(np, node) { + if (!of_find_property(node, "#power-domain-cells", NULL)) + continue; + + ret = of_genpd_parse_idle_states(node, &states, &state_count); + if (ret) + goto err_put; + + ret = psci_dt_parse_pd_states(states, state_count); + if (ret) + goto err_put; + + ret = psci_dt_init_genpd(node, states, state_count); + if (ret) + goto err_put; + + pd_count++; + } + + if (!pd_count) + return 0; + + ret = psci_dt_set_genpd_topology(np); + if (ret) + goto err_msg; + + return pd_count; + +err_put: + of_node_put(node); +err_msg: + pr_err("failed to create PM domains ret=%d\n", ret); + return ret; +} +#endif