Received: by 10.192.165.156 with SMTP id m28csp1826766imm; Thu, 12 Apr 2018 04:18:59 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+hNzVWvTOqy+kgO+MPWzMWy8mVlM8tG57gvsaOoQkeVFAB7QThi23MNr2GfPeTAdOsOn8v X-Received: by 10.101.96.65 with SMTP id b1mr394673pgv.340.1523531939262; Thu, 12 Apr 2018 04:18:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523531939; cv=none; d=google.com; s=arc-20160816; b=okvhDcrfZmxTzXmWgQOKfNLcfM3idGneGMKxtIVNqkRku4Yf/+4fWJgGIGvhKQW08E rU3n9VkhCrInh/EVknAdi0BhsypKdwp2CQXdQno6J2a5dHdOrYrGRgCNXQiE7F709STT 0KxW/e4J2XCCBl+c8QiAFOkfod/gqHQTqyXjGj5CPFAi95Gj0VE3NVxcExw1l4pq7mIZ oFQEJ3CxAVYoO5Zkqr/FuEeynif3z50elDAlTT6kc8v8oeSYvXbQolIEicST0ehf4ZCE gJBV1X435nyiFvbnA+9nAhT5KrYd8dA4her4xYIpqVMkdOzPf7DlvRQx7aJg8KS0pI3N v74g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=sUDYgpzj5UEmCSSCZ9crCjUGiIscG774f2rkxIW5KB4=; b=XIxIcYE6+eP0D3e27CQ5Pbjqu2nTYxNBv7kSGNl6YexyTVZuDgs+dJMPVEwkDHRwX9 n+JVzjCW6Ui8oBFrdQJaEIQUUxj78qb3Qv+0mKhHzT7KkF+s3md/gAreemCjaoBASwfH uj0uFNwTtxkz5MXqOdI1T8ogT+/0/ib6V5kRVMDKk8h2lCk/yds1hHZLYCB7IrR1YFa2 0fwo8iA2EibjAcXKnU1q/yhvAQ5xN/jpUA4Mq0Xt6e3ySBI8qG3HtxKR4kw5MyRtp9v6 m3Z2hatANnS5tAFSHuxQKPvzm4QbBVqY1yIDx/IJqgdnlyKvpUWqyrKrRZLZSpnPSBOC +9pg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YlhQTWH8; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m12si2160867pgd.240.2018.04.12.04.18.21; Thu, 12 Apr 2018 04:18:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YlhQTWH8; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753353AbeDLLP2 (ORCPT + 99 others); Thu, 12 Apr 2018 07:15:28 -0400 Received: from mail-lf0-f68.google.com ([209.85.215.68]:45744 "EHLO mail-lf0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753238AbeDLLPR (ORCPT ); Thu, 12 Apr 2018 07:15:17 -0400 Received: by mail-lf0-f68.google.com with SMTP id q5-v6so7098473lff.12 for ; Thu, 12 Apr 2018 04:15:16 -0700 (PDT) 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=sUDYgpzj5UEmCSSCZ9crCjUGiIscG774f2rkxIW5KB4=; b=YlhQTWH8cln8qYjbcsgLR/SNd5P/HvcUQHKLvJtPfdLxF16O6UxC5Pmlmae6mOXFed in0xdh846+EH2TrpIhMljitdh13P6X01+XeatB6IPLnTaYMqP4o/hiNSiK4nlxVFMPE5 Kk6V+GNngd1lSS20oh/X+39CH2JXgoq8KEV1c= 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=sUDYgpzj5UEmCSSCZ9crCjUGiIscG774f2rkxIW5KB4=; b=ossp6RvasFNzHmZ13l0YmnLEpBDHBkwrvPh4ROWYZeQflVi02L+GgYLMhdDf9z/oLK DbWQxm1m17wUlJMNI+tGmeOUNeS+/XhDxHcphvxrfOwNHmm31dOnuCVd8Yc15f9iFV4T NkNLo+vXF0KHAeCgn7c54Vj5+EWzKawsOiicuXJkET77Z38LOV8tsR/5kreSHFKnbZbn bT+A0tdpP2OTay7uZoZ4I32oJwVAS6yMqaa6jG0W7patwMg362PlhK72apNndyaEeJ6k JS4Syoi+z0CRPOdXF1UNLS7LJs2R39PnSuI03AEGvljpnqNgFAO8t/dY42xc9/lYV8RY G9ag== X-Gm-Message-State: ALQs6tBDosB4cRtW8b1/Ur22wAsOenuxa9xuTeQ5JO8Oo9UDBBnRPtRq XGCMsqeUqCSgpK3Px+21CvNw8A== X-Received: by 10.46.137.71 with SMTP id b7mr365006ljk.39.1523531715432; Thu, 12 Apr 2018 04:15:15 -0700 (PDT) Received: from localhost.localdomain (h-158-174-22-210.NA.cust.bahnhof.se. [158.174.22.210]) by smtp.gmail.com with ESMTPSA id r29sm543187lje.72.2018.04.12.04.15.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 12 Apr 2018 04:15:14 -0700 (PDT) From: Ulf Hansson To: "Rafael J . Wysocki" , Sudeep Holla , Lorenzo Pieralisi , Mark Rutland , 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 v7 21/26] drivers: firmware: psci: Add support for PM domains using genpd Date: Thu, 12 Apr 2018 13:14:26 +0200 Message-Id: <1523531671-27491-22-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1523531671-27491-1-git-send-email-ulf.hansson@linaro.org> References: <1523531671-27491-1-git-send-email-ulf.hansson@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.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/psci/Makefile | 2 +- drivers/firmware/psci/psci.h | 6 ++ drivers/firmware/psci/psci_pm_domain.c | 180 +++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/psci/psci_pm_domain.c diff --git a/drivers/firmware/psci/Makefile b/drivers/firmware/psci/Makefile index 1956b88..ff300f1 100644 --- a/drivers/firmware/psci/Makefile +++ b/drivers/firmware/psci/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 # -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 diff --git a/drivers/firmware/psci/psci.h b/drivers/firmware/psci/psci.h index a2b4be5..8b6fe51 100644 --- a/drivers/firmware/psci/psci.h +++ b/drivers/firmware/psci/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/psci_pm_domain.c b/drivers/firmware/psci/psci_pm_domain.c new file mode 100644 index 0000000..f54819e --- /dev/null +++ b/drivers/firmware/psci/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 -- 2.7.4