From patchwork Wed Jun 20 17:22:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 139389 Delivered-To: patches@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp1051020lji; Wed, 20 Jun 2018 10:23:13 -0700 (PDT) X-Received: by 2002:a2e:1dd9:: with SMTP id w86-v6mr14447177lje.110.1529515393947; Wed, 20 Jun 2018 10:23:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529515393; cv=none; d=google.com; s=arc-20160816; b=YWJnujeBsimQZdu4+1fTWIc6cxJbn5lPgugRZsry6+RYezG3mkB4DPPPI8CHSyitYM jPrLakIDm2v9uTw0QJXjWqFazovHet6bpTbfRg7exELZBC9f5uH1V9Tl20mIpHbTm3M9 egS16+NL5pXhyXD/JO4yhsWV7kjoZ9frcVjkyOcNxSZcwioEMGhy4yCzcdr3pk2JWpYt cqJx/0C/PuRrzVnhM0qdyIftBDxKEGYFSL5U7AL5iIFP+mGTmoltcZF14kHx9dMK8i3+ vu4Ts9rsd1Q0S9slBjSUMqmTC5fy6LG9xO6fFmzeCtZMWP52GCpaPJJNBJDkG0RHA5na JTfg== 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=dpRzWZ1lRV3PUFVF54+RtopoI+Qxx4PQOSnHva5FuG0=; b=xZ9OC0Khcsd0J1JBA0i14Sd7zZBUAbN9bo6cPumViPrz5H1q1lCPiY2M0rkJazQSgR 3CyhzwxZMX9Qz40DR8kSiwxMV8m2z8dNRvMR4kCwo7I3r7YCLli1o0rJg6iOMG+gG6I4 f6oFrvKQRoJf2D+Vk/xlhCz4QmXaosaepAgSJDxlWoZkW/W6mlDjc7tm54z4PrO5Q2su FmG1cAE/nbVQTQ3ynDjPW/ImFOAr1OaEGemPUcB/7y4sDR1oFVn6pjzCYOZFvSkqZxLL dH6tnouDJmKF+3AKmyX/EozDcKfP+EKi6cxaa4B4mp2QTrfLuqpKRpI8nnADQpwsNYYd ZO+A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Eg0M4K1y; 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 z8-v6sor721138lji.30.2018.06.20.10.23.13 for (Google Transport Security); Wed, 20 Jun 2018 10:23:13 -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=Eg0M4K1y; 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=dpRzWZ1lRV3PUFVF54+RtopoI+Qxx4PQOSnHva5FuG0=; b=Eg0M4K1y1jPCN7GIdZAXDgAVpLPggcUYsLLm8zmicBLw9lxb5F2rFzBE/Il1E3g8NP 2plsB85rwB3kEaChU/AkeAoo4cKWGeyImYGUir3Nl/kOY9eC7esYJbCMcVJnQS+qccXh 0HOpUo0XXP0iPIig7ion/ai28kav03/03ZtiY= 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=dpRzWZ1lRV3PUFVF54+RtopoI+Qxx4PQOSnHva5FuG0=; b=aVeUInMOJmp7nF0zwBCmduPw8zbthRVT3yxWB8XNwasvthIgU7DFjAYZuJMxTXvxZ8 jTSA8P552216A5drvrgYx2ejltIM1K74jLwFGchmr0ca+eLdDrYvzA3okY2qj8IIkq7m 2mjV9zqjEjH9oHPQm3FpWJNEccKXa7QuQAcuOLwlaNrkuIDshEYSxBTUKlnBxVY6qcXn ULVEtKcW5JF/MFdNy2KftcnZ0NWLKluAqxagN9Bit/s3Y5NWBsY/69IaDqY1ecNn4gyy gIFkvF8N8dx0Aa1qpLkl1e2tAIJUKz1ZECy27H0lSjva30QGV1B1DelLUFIJxuAugKF6 ychQ== X-Gm-Message-State: APt69E3Peg7acOg6ATGoddtOXBftSjtMroSqljoTPHHVock0HokffgQs nHUK067mVwUODxIEjNfK9AAa3qeU X-Google-Smtp-Source: ADUXVKLVvZTFdpj3qKwzqzeDJnvXHNUoiFXlfoS4PQuZNDvYr6YFwfV+WCqsLUvtvRFLb00abw1Qng== X-Received: by 2002:a2e:428e:: with SMTP id h14-v6mr15515102ljf.136.1529515393686; Wed, 20 Jun 2018 10:23:13 -0700 (PDT) Return-Path: Received: from localhost.localdomain (h-158-174-22-210.NA.cust.bahnhof.se. [158.174.22.210]) by smtp.gmail.com with ESMTPSA id b2-v6sm514441lji.85.2018.06.20.10.23.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 20 Jun 2018 10:23:13 -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 v8 21/26] drivers: firmware: psci: Add support for PM domains using genpd Date: Wed, 20 Jun 2018 19:22:21 +0200 Message-Id: <20180620172226.15012-22-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180620172226.15012-1-ulf.hansson@linaro.org> References: <20180620172226.15012-1-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/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 -- 2.17.1 diff --git a/drivers/firmware/psci/Makefile b/drivers/firmware/psci/Makefile index 1956b882470f..ff300f1fec86 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 dc7b596daa2b..a22684b24902 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 000000000000..f54819e7e487 --- /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