To enable support for performance scaling (DVFS) for generic devices with
the SCMI performance protocol, let's add an SCMI performance domain. This
is being modelled as a genpd provider, with support for performance scaling
through genpd's ->set_performance_state() callback.
Note that, this adds the initial support that allows consumer drivers for
attached devices, to vote for a new performance state via calling the
dev_pm_genpd_set_performance_state(). However, this should be avoided as
it's in most cases preferred to use the OPP library to vote for a new OPP
instead. The support using the OPP library isn't part of this change, but
needs to be implemented from subsequent changes.
Signed-off-by: Ulf Hansson <[email protected]>
---
Sudeep, Cristian,
I decided to just send this a single patch, rather than a new version of the
complete series. If you prefer a new version of the series, please let me know.
Kind regards
Uffe
Changes in v4:
- Rebased on v6.6-rc2 to be able to put the files in the new pmdomain
subsystem (was genpd in v6.6-rc1).
Changes in v3:
- Move files to drivers/genpd/arm/ and update MAINTAINERS.
- Updated the commit msg header.
- Prevent setting performance level 0.
- Initialize the genpd as always-on.
- Note, the corresponding Kconfigs should be placed in the genpd dir
too, but that's better suited on top or through a later-version.
---
MAINTAINERS | 1 +
drivers/firmware/arm_scmi/Kconfig | 12 ++
drivers/pmdomain/Makefile | 1 +
drivers/pmdomain/arm/Makefile | 3 +
drivers/pmdomain/arm/scmi_perf_domain.c | 150 ++++++++++++++++++++++++
5 files changed, 167 insertions(+)
create mode 100644 drivers/pmdomain/arm/Makefile
create mode 100644 drivers/pmdomain/arm/scmi_perf_domain.c
diff --git a/MAINTAINERS b/MAINTAINERS
index bf0f54c24f81..aa8c58b16416 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20902,6 +20902,7 @@ F: drivers/clk/clk-sc[mp]i.c
F: drivers/cpufreq/sc[mp]i-cpufreq.c
F: drivers/firmware/arm_scmi/
F: drivers/firmware/arm_scpi.c
+F: drivers/pmdomain/arm/
F: drivers/powercap/arm_scmi_powercap.c
F: drivers/regulator/scmi-regulator.c
F: drivers/reset/reset-scmi.c
diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/Kconfig
index ea0f5083ac47..706d1264d038 100644
--- a/drivers/firmware/arm_scmi/Kconfig
+++ b/drivers/firmware/arm_scmi/Kconfig
@@ -181,6 +181,18 @@ config ARM_SCMI_POWER_DOMAIN
will be called scmi_pm_domain. Note this may needed early in boot
before rootfs may be available.
+config ARM_SCMI_PERF_DOMAIN
+ tristate "SCMI performance domain driver"
+ depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+ default y
+ select PM_GENERIC_DOMAINS if PM
+ help
+ This enables support for the SCMI performance domains which can be
+ enabled or disabled via the SCP firmware.
+
+ This driver can also be built as a module. If so, the module will be
+ called scmi_perf_domain.
+
config ARM_SCMI_POWER_CONTROL
tristate "SCMI system power control driver"
depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
diff --git a/drivers/pmdomain/Makefile b/drivers/pmdomain/Makefile
index 666753676e5c..f0326b27b30b 100644
--- a/drivers/pmdomain/Makefile
+++ b/drivers/pmdomain/Makefile
@@ -2,6 +2,7 @@
obj-y += actions/
obj-y += amlogic/
obj-y += apple/
+obj-y += arm/
obj-y += bcm/
obj-y += imx/
obj-y += mediatek/
diff --git a/drivers/pmdomain/arm/Makefile b/drivers/pmdomain/arm/Makefile
new file mode 100644
index 000000000000..7128db96deac
--- /dev/null
+++ b/drivers/pmdomain/arm/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_ARM_SCMI_PERF_DOMAIN) += scmi_perf_domain.o
diff --git a/drivers/pmdomain/arm/scmi_perf_domain.c b/drivers/pmdomain/arm/scmi_perf_domain.c
new file mode 100644
index 000000000000..aa100270500f
--- /dev/null
+++ b/drivers/pmdomain/arm/scmi_perf_domain.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI performance domain support.
+ *
+ * Copyright (C) 2023 Linaro Ltd.
+ */
+
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pm_domain.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+
+struct scmi_perf_domain {
+ struct generic_pm_domain genpd;
+ const struct scmi_perf_proto_ops *perf_ops;
+ const struct scmi_protocol_handle *ph;
+ const struct scmi_perf_domain_info *info;
+ u32 domain_id;
+};
+
+#define to_scmi_pd(pd) container_of(pd, struct scmi_perf_domain, genpd)
+
+static int
+scmi_pd_set_perf_state(struct generic_pm_domain *genpd, unsigned int state)
+{
+ struct scmi_perf_domain *pd = to_scmi_pd(genpd);
+ int ret;
+
+ if (!pd->info->set_perf)
+ return 0;
+
+ if (!state)
+ return -EINVAL;
+
+ ret = pd->perf_ops->level_set(pd->ph, pd->domain_id, state, true);
+ if (ret)
+ dev_warn(&genpd->dev, "Failed with %d when trying to set %d perf level",
+ ret, state);
+
+ return ret;
+}
+
+static int scmi_perf_domain_probe(struct scmi_device *sdev)
+{
+ struct device *dev = &sdev->dev;
+ const struct scmi_handle *handle = sdev->handle;
+ const struct scmi_perf_proto_ops *perf_ops;
+ struct scmi_protocol_handle *ph;
+ struct scmi_perf_domain *scmi_pd;
+ struct genpd_onecell_data *scmi_pd_data;
+ struct generic_pm_domain **domains;
+ int num_domains, i, ret = 0;
+
+ if (!handle)
+ return -ENODEV;
+
+ /* The OF node must specify us as a power-domain provider. */
+ if (!of_find_property(dev->of_node, "#power-domain-cells", NULL))
+ return 0;
+
+ perf_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_PERF, &ph);
+ if (IS_ERR(perf_ops))
+ return PTR_ERR(perf_ops);
+
+ num_domains = perf_ops->num_domains_get(ph);
+ if (num_domains < 0) {
+ dev_warn(dev, "Failed with %d when getting num perf domains\n",
+ num_domains);
+ return num_domains;
+ } else if (!num_domains) {
+ return 0;
+ }
+
+ scmi_pd = devm_kcalloc(dev, num_domains, sizeof(*scmi_pd), GFP_KERNEL);
+ if (!scmi_pd)
+ return -ENOMEM;
+
+ scmi_pd_data = devm_kzalloc(dev, sizeof(*scmi_pd_data), GFP_KERNEL);
+ if (!scmi_pd_data)
+ return -ENOMEM;
+
+ domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
+ if (!domains)
+ return -ENOMEM;
+
+ for (i = 0; i < num_domains; i++, scmi_pd++) {
+ scmi_pd->info = perf_ops->info_get(ph, i);
+
+ scmi_pd->domain_id = i;
+ scmi_pd->perf_ops = perf_ops;
+ scmi_pd->ph = ph;
+ scmi_pd->genpd.name = scmi_pd->info->name;
+ scmi_pd->genpd.flags = GENPD_FLAG_ALWAYS_ON |
+ GENPD_FLAG_OPP_TABLE_FW;
+ scmi_pd->genpd.set_performance_state = scmi_pd_set_perf_state;
+
+ ret = pm_genpd_init(&scmi_pd->genpd, NULL, false);
+ if (ret)
+ goto err;
+
+ domains[i] = &scmi_pd->genpd;
+ }
+
+ scmi_pd_data->domains = domains;
+ scmi_pd_data->num_domains = num_domains;
+
+ ret = of_genpd_add_provider_onecell(dev->of_node, scmi_pd_data);
+ if (ret)
+ goto err;
+
+ dev_set_drvdata(dev, scmi_pd_data);
+ dev_info(dev, "Initialized %d performance domains", num_domains);
+ return 0;
+err:
+ for (i--; i >= 0; i--)
+ pm_genpd_remove(domains[i]);
+ return ret;
+}
+
+static void scmi_perf_domain_remove(struct scmi_device *sdev)
+{
+ struct device *dev = &sdev->dev;
+ struct genpd_onecell_data *scmi_pd_data = dev_get_drvdata(dev);
+ int i;
+
+ of_genpd_del_provider(dev->of_node);
+
+ for (i = 0; i < scmi_pd_data->num_domains; i++)
+ pm_genpd_remove(scmi_pd_data->domains[i]);
+}
+
+static const struct scmi_device_id scmi_id_table[] = {
+ { SCMI_PROTOCOL_PERF, "perf" },
+ { },
+};
+MODULE_DEVICE_TABLE(scmi, scmi_id_table);
+
+static struct scmi_driver scmi_perf_domain_driver = {
+ .name = "scmi-perf-domain",
+ .probe = scmi_perf_domain_probe,
+ .remove = scmi_perf_domain_remove,
+ .id_table = scmi_id_table,
+};
+module_scmi_driver(scmi_perf_domain_driver);
+
+MODULE_AUTHOR("Ulf Hansson <[email protected]>");
+MODULE_DESCRIPTION("ARM SCMI perf domain driver");
+MODULE_LICENSE("GPL v2");
--
2.34.1
To simplify with maintenance let's move the Arm SCMI power-domain driver
to the new pmdomain directory.
Cc: Ulf Hansson <[email protected]>
Cc: Cristian Marussi <[email protected]>
Signed-off-by: Sudeep Holla <[email protected]>
---
Hi Ulf,
If you are happy with this, please cck. I would like to take this along
with your scmi_perf_domain change as part of you series.
Regards,
Sudeep
drivers/firmware/arm_scmi/Makefile | 1 -
drivers/pmdomain/arm/Makefile | 1 +
drivers/{firmware/arm_scmi => pmdomain/arm}/scmi_pm_domain.c | 0
3 files changed, 1 insertion(+), 1 deletion(-)
rename drivers/{firmware/arm_scmi => pmdomain/arm}/scmi_pm_domain.c (100%)
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index b31d78fa66cc..a7bc4796519c 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -16,7 +16,6 @@ scmi-module-objs := $(scmi-driver-y) $(scmi-protocols-y) $(scmi-transport-y)
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-core.o
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o
-obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
obj-$(CONFIG_ARM_SCMI_POWER_CONTROL) += scmi_power_control.o
ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
diff --git a/drivers/pmdomain/arm/Makefile b/drivers/pmdomain/arm/Makefile
index 7128db96deac..cfcb1f6cdd90 100644
--- a/drivers/pmdomain/arm/Makefile
+++ b/drivers/pmdomain/arm/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_ARM_SCMI_PERF_DOMAIN) += scmi_perf_domain.o
+obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/pmdomain/arm/scmi_pm_domain.c
similarity index 100%
rename from drivers/firmware/arm_scmi/scmi_pm_domain.c
rename to drivers/pmdomain/arm/scmi_pm_domain.c
--
2.42.0
On Thu, 21 Sept 2023 at 13:33, Sudeep Holla <[email protected]> wrote:
>
> To simplify with maintenance let's move the Arm SCMI power-domain driver
> to the new pmdomain directory.
>
> Cc: Ulf Hansson <[email protected]>
> Cc: Cristian Marussi <[email protected]>
> Signed-off-by: Sudeep Holla <[email protected]>
Reviewed-by: Ulf Hansson <[email protected]>
Feel free to take it through your scmi tree!
Note that, we should move the Kconfig options too, but that requires
changes that I am carrying in my pmdomain tree. We can either wait
until the next cycle or you could send your pull-request to me this
time (instead of through arm-soc), then we can fix this as a late
minute change. The decision is yours.
Kind regards
Uffe
> ---
>
> Hi Ulf,
>
> If you are happy with this, please cck. I would like to take this along
> with your scmi_perf_domain change as part of you series.
>
> Regards,
> Sudeep
>
> drivers/firmware/arm_scmi/Makefile | 1 -
> drivers/pmdomain/arm/Makefile | 1 +
> drivers/{firmware/arm_scmi => pmdomain/arm}/scmi_pm_domain.c | 0
> 3 files changed, 1 insertion(+), 1 deletion(-)
> rename drivers/{firmware/arm_scmi => pmdomain/arm}/scmi_pm_domain.c (100%)
>
> diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
> index b31d78fa66cc..a7bc4796519c 100644
> --- a/drivers/firmware/arm_scmi/Makefile
> +++ b/drivers/firmware/arm_scmi/Makefile
> @@ -16,7 +16,6 @@ scmi-module-objs := $(scmi-driver-y) $(scmi-protocols-y) $(scmi-transport-y)
> obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-core.o
> obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o
>
> -obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
> obj-$(CONFIG_ARM_SCMI_POWER_CONTROL) += scmi_power_control.o
>
> ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
> diff --git a/drivers/pmdomain/arm/Makefile b/drivers/pmdomain/arm/Makefile
> index 7128db96deac..cfcb1f6cdd90 100644
> --- a/drivers/pmdomain/arm/Makefile
> +++ b/drivers/pmdomain/arm/Makefile
> @@ -1,3 +1,4 @@
> # SPDX-License-Identifier: GPL-2.0-only
>
> obj-$(CONFIG_ARM_SCMI_PERF_DOMAIN) += scmi_perf_domain.o
> +obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
> diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/pmdomain/arm/scmi_pm_domain.c
> similarity index 100%
> rename from drivers/firmware/arm_scmi/scmi_pm_domain.c
> rename to drivers/pmdomain/arm/scmi_pm_domain.c
> --
> 2.42.0
>
On Tue, 19 Sep 2023 14:16:05 +0200, Ulf Hansson wrote:
> To enable support for performance scaling (DVFS) for generic devices with
> the SCMI performance protocol, let's add an SCMI performance domain. This
> is being modelled as a genpd provider, with support for performance scaling
> through genpd's ->set_performance_state() callback.
>
> Note that, this adds the initial support that allows consumer drivers for
> attached devices, to vote for a new performance state via calling the
> dev_pm_genpd_set_performance_state(). However, this should be avoided as
> it's in most cases preferred to use the OPP library to vote for a new OPP
> instead. The support using the OPP library isn't part of this change, but
> needs to be implemented from subsequent changes.
>
> [...]
Applied to sudeep.holla/linux (for-next/scmi/updates), thanks!
[13/13] pmdomain: arm: Add the SCMI performance domain
https://git.kernel.org/sudeep.holla/c/2af23ceb8624
--
Regards,
Sudeep
On Thu, Sep 21, 2023 at 12:33:28PM +0100, Sudeep Holla wrote:
> To simplify with maintenance let's move the Arm SCMI power-domain driver
> to the new pmdomain directory.
>
> Cc: Ulf Hansson <[email protected]>
> Cc: Cristian Marussi <[email protected]>
> Signed-off-by: Sudeep Holla <[email protected]>
> ---
>
> Hi Ulf,
>
> If you are happy with this, please cck. I would like to take this along
> with your scmi_perf_domain change as part of you series.
>
> Regards,
> Sudeep
>
> drivers/firmware/arm_scmi/Makefile | 1 -
> drivers/pmdomain/arm/Makefile | 1 +
> drivers/{firmware/arm_scmi => pmdomain/arm}/scmi_pm_domain.c | 0
> 3 files changed, 1 insertion(+), 1 deletion(-)
> rename drivers/{firmware/arm_scmi => pmdomain/arm}/scmi_pm_domain.c (100%)
>
Applied to sudeep.holla/linux (for-next/scmi/updates), thanks!
[1/1] firmware: arm_scmi: firmware: arm_scmi: Move power-domain driver to thepmdomain dir
https://git.kernel.org/sudeep.holla/c/af78e5c309c4
--
Regards,
Sudeep