* [PATCH/RFC 1/9] firmware: arm_scmi: Replace scmi_power_proto_ops.name_get() by .info_get()
2026-06-11 13:02 [PATCH/RFC 0/9] R-Car X5H Ironhide pure SCMI proof-of-concept Geert Uytterhoeven
@ 2026-06-11 13:02 ` Geert Uytterhoeven
2026-06-11 13:02 ` [PATCH/RFC 2/9] firmware: arm_scmi: Advertize always-on power domains Geert Uytterhoeven
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Geert Uytterhoeven @ 2026-06-11 13:02 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Brian Masney,
Ulf Hansson
Cc: arm-scmi, linux-arm-kernel, devicetree, linux-clk, linux-pm,
linux-renesas-soc, linux-kernel, Geert Uytterhoeven
The SCMI power domain protocol operations structure does not provide a
.info_get() method, unlike most other protocols. Instead, it provides
a .name_get() method.
Replace the .name_get() method by the .info_get() method, to increase
uniformity, and to prepare for returning more information.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/firmware/arm_scmi/power.c | 17 ++++++++---------
drivers/pmdomain/arm/scmi_pm_domain.c | 9 ++++++++-
include/linux/scmi_protocol.h | 10 +++++++---
3 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index 28ef63a4ecc2e1df..a00f7c298efb74f9 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -63,7 +63,7 @@ struct power_dom_info {
bool state_set_sync;
bool state_set_async;
bool state_set_notify;
- char name[SCMI_MAX_STR_SIZE];
+ struct scmi_power_domain_info info;
};
struct scmi_power_info {
@@ -132,7 +132,7 @@ scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph,
SUPPORTS_STATE_SET_NOTIFY(flags);
dom_info->state_set_async = SUPPORTS_STATE_SET_ASYNC(flags);
dom_info->state_set_sync = SUPPORTS_STATE_SET_SYNC(flags);
- strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
+ strscpy(dom_info->info.name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
}
ph->xops->xfer_put(ph, t);
@@ -143,7 +143,7 @@ scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph,
if (!ret && PROTOCOL_REV_MAJOR(ph->version) >= 0x3 &&
SUPPORTS_EXTENDED_NAMES(flags)) {
ph->hops->extended_name_get(ph, POWER_DOMAIN_NAME_GET,
- domain, NULL, dom_info->name,
+ domain, NULL, dom_info->info.name,
SCMI_MAX_STR_SIZE);
}
@@ -199,23 +199,22 @@ static int scmi_power_num_domains_get(const struct scmi_protocol_handle *ph)
return pi->num_domains;
}
-static const char *
-scmi_power_name_get(const struct scmi_protocol_handle *ph,
- u32 domain)
+static const struct scmi_power_domain_info *
+scmi_power_info_get(const struct scmi_protocol_handle *ph, u32 domain)
{
struct scmi_power_info *pi = ph->get_priv(ph);
struct power_dom_info *dom;
if (domain >= pi->num_domains)
- return "unknown";
+ return NULL;
dom = pi->dom_info + domain;
- return dom->name;
+ return &dom->info;
}
static const struct scmi_power_proto_ops power_proto_ops = {
.num_domains_get = scmi_power_num_domains_get,
- .name_get = scmi_power_name_get,
+ .info_get = scmi_power_info_get,
.state_set = scmi_power_state_set,
.state_get = scmi_power_state_get,
};
diff --git a/drivers/pmdomain/arm/scmi_pm_domain.c b/drivers/pmdomain/arm/scmi_pm_domain.c
index 3d73aef21d2f9942..965592e828741b11 100644
--- a/drivers/pmdomain/arm/scmi_pm_domain.c
+++ b/drivers/pmdomain/arm/scmi_pm_domain.c
@@ -76,8 +76,15 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
return -ENOMEM;
for (i = 0; i < num_domains; i++, scmi_pd++) {
+ const struct scmi_power_domain_info *info;
u32 state;
+ info = power_ops->info_get(ph, i);
+ if (!info) {
+ dev_warn(dev, "failed to get info for domain %d\n", i);
+ continue;
+ }
+
if (power_ops->state_get(ph, i, &state)) {
dev_warn(dev, "failed to get state for domain %d\n", i);
continue;
@@ -93,7 +100,7 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
scmi_pd->domain = i;
scmi_pd->ph = ph;
- scmi_pd->name = power_ops->name_get(ph, i);
+ scmi_pd->name = info->name;
scmi_pd->genpd.name = scmi_pd->name;
scmi_pd->genpd.power_off = scmi_pd_power_off;
scmi_pd->genpd.power_on = scmi_pd_power_on;
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 5ab73b1ab9aa4fa8..1c17515ba45d1fd4 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -191,19 +191,23 @@ struct scmi_perf_proto_ops {
enum scmi_power_scale (*power_scale_get)(const struct scmi_protocol_handle *ph);
};
+struct scmi_power_domain_info {
+ char name[SCMI_MAX_STR_SIZE];
+};
+
/**
* struct scmi_power_proto_ops - represents the various operations provided
* by SCMI Power Protocol
*
* @num_domains_get: get the count of power domains provided by SCMI
- * @name_get: gets the name of a power domain
+ * @info_get: gets the information of the specified power domain
* @state_set: sets the power state of a power domain
* @state_get: gets the power state of a power domain
*/
struct scmi_power_proto_ops {
int (*num_domains_get)(const struct scmi_protocol_handle *ph);
- const char *(*name_get)(const struct scmi_protocol_handle *ph,
- u32 domain);
+ const struct scmi_power_domain_info __must_check *(*info_get)
+ (const struct scmi_protocol_handle *ph, u32 domain);
#define SCMI_POWER_STATE_TYPE_SHIFT 30
#define SCMI_POWER_STATE_ID_MASK (BIT(28) - 1)
#define SCMI_POWER_STATE_PARAM(type, id) \
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH/RFC 2/9] firmware: arm_scmi: Advertize always-on power domains
2026-06-11 13:02 [PATCH/RFC 0/9] R-Car X5H Ironhide pure SCMI proof-of-concept Geert Uytterhoeven
2026-06-11 13:02 ` [PATCH/RFC 1/9] firmware: arm_scmi: Replace scmi_power_proto_ops.name_get() by .info_get() Geert Uytterhoeven
@ 2026-06-11 13:02 ` Geert Uytterhoeven
2026-06-11 13:02 ` [PATCH/RFC 3/9] pmdomain: arm: scmi: Add always-on support Geert Uytterhoeven
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Geert Uytterhoeven @ 2026-06-11 13:02 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Brian Masney,
Ulf Hansson
Cc: arm-scmi, linux-arm-kernel, devicetree, linux-clk, linux-pm,
linux-renesas-soc, linux-kernel, Geert Uytterhoeven
A power domains indicates in its attribute flags if it supports setting
its power state synchronously and/or asynchronously. If none of them is
supported, it must be an always-on power domain.
Make this information available to SCMI protocol drivers, so they can
make use of it.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/firmware/arm_scmi/power.c | 4 ++++
include/linux/scmi_protocol.h | 1 +
2 files changed, 5 insertions(+)
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index a00f7c298efb74f9..11ca8c9965110b5a 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -8,6 +8,7 @@
#define pr_fmt(fmt) "SCMI Notifications POWER - " fmt
#include <linux/module.h>
+#include <linux/pm_domain.h>
#include <linux/scmi_protocol.h>
#include "protocols.h"
@@ -147,6 +148,9 @@ scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph,
SCMI_MAX_STR_SIZE);
}
+ if (!ret && !dom_info->state_set_async && !dom_info->state_set_sync)
+ dom_info->info.genpd_flags |= GENPD_FLAG_ALWAYS_ON;
+
return ret;
}
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 1c17515ba45d1fd4..1d55374bc8cdcc72 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -193,6 +193,7 @@ struct scmi_perf_proto_ops {
struct scmi_power_domain_info {
char name[SCMI_MAX_STR_SIZE];
+ unsigned int genpd_flags;
};
/**
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH/RFC 3/9] pmdomain: arm: scmi: Add always-on support
2026-06-11 13:02 [PATCH/RFC 0/9] R-Car X5H Ironhide pure SCMI proof-of-concept Geert Uytterhoeven
2026-06-11 13:02 ` [PATCH/RFC 1/9] firmware: arm_scmi: Replace scmi_power_proto_ops.name_get() by .info_get() Geert Uytterhoeven
2026-06-11 13:02 ` [PATCH/RFC 2/9] firmware: arm_scmi: Advertize always-on power domains Geert Uytterhoeven
@ 2026-06-11 13:02 ` Geert Uytterhoeven
2026-06-11 13:02 ` [PATCH/RFC 4/9] firmware: arm_scmi: Add a flag for power-management clocks Geert Uytterhoeven
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Geert Uytterhoeven @ 2026-06-11 13:02 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Brian Masney,
Ulf Hansson
Cc: arm-scmi, linux-arm-kernel, devicetree, linux-clk, linux-pm,
linux-renesas-soc, linux-kernel, Geert Uytterhoeven
Extend the PM domain flags with the flags advertized by the SCMI core.
For now this is limited to GENPD_FLAG_ALWAYS_ON.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Questions:
- Should the power_ops->state_get() call be skipped in case of an
always-on domain, and state just be force to
SCMI_POWER_STATE_GENERIC_ON instead?
- Should the power_ops->state_set() call be skipped in case of an
always-on domain? Or might this cause issues with some firmware
implementations?
Skipping these calls may avoid adding quirk code later...
---
drivers/pmdomain/arm/scmi_pm_domain.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/pmdomain/arm/scmi_pm_domain.c b/drivers/pmdomain/arm/scmi_pm_domain.c
index 965592e828741b11..8e67f971c707e121 100644
--- a/drivers/pmdomain/arm/scmi_pm_domain.c
+++ b/drivers/pmdomain/arm/scmi_pm_domain.c
@@ -104,7 +104,8 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
scmi_pd->genpd.name = scmi_pd->name;
scmi_pd->genpd.power_off = scmi_pd_power_off;
scmi_pd->genpd.power_on = scmi_pd_power_on;
- scmi_pd->genpd.flags = GENPD_FLAG_ACTIVE_WAKEUP;
+ scmi_pd->genpd.flags = GENPD_FLAG_ACTIVE_WAKEUP |
+ info->genpd_flags;
pm_genpd_init(&scmi_pd->genpd, NULL,
state == SCMI_POWER_STATE_GENERIC_OFF);
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH/RFC 4/9] firmware: arm_scmi: Add a flag for power-management clocks
2026-06-11 13:02 [PATCH/RFC 0/9] R-Car X5H Ironhide pure SCMI proof-of-concept Geert Uytterhoeven
` (2 preceding siblings ...)
2026-06-11 13:02 ` [PATCH/RFC 3/9] pmdomain: arm: scmi: Add always-on support Geert Uytterhoeven
@ 2026-06-11 13:02 ` Geert Uytterhoeven
2026-06-11 13:02 ` [PATCH/RFC 5/9] clk: scmi: Add scmi_clk_is_pm_clk() Geert Uytterhoeven
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Geert Uytterhoeven @ 2026-06-11 13:02 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Brian Masney,
Ulf Hansson
Cc: arm-scmi, linux-arm-kernel, devicetree, linux-clk, linux-pm,
linux-renesas-soc, linux-kernel, Geert Uytterhoeven
Power management of on-SoC modules is typically handled through two
methods: module power control and module clock gating. The former is
exposed as an SCMI power domain, the latter as an SCMI clock.
Add a flag to indicate if a clock is intended for power-management of a
hardware module.
As the SCMI clock protocol does not support advertizing power-management
clocks yet, this flag can only be set by a quirk.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
include/linux/scmi_protocol.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 1d55374bc8cdcc72..c98e0add25f0c6c6 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -55,6 +55,7 @@ struct scmi_clock_info {
bool rate_ctrl_forbidden;
bool parent_ctrl_forbidden;
bool extended_config;
+ bool pm_clk;
u64 min_rate;
u64 max_rate;
int num_parents;
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH/RFC 5/9] clk: scmi: Add scmi_clk_is_pm_clk()
2026-06-11 13:02 [PATCH/RFC 0/9] R-Car X5H Ironhide pure SCMI proof-of-concept Geert Uytterhoeven
` (3 preceding siblings ...)
2026-06-11 13:02 ` [PATCH/RFC 4/9] firmware: arm_scmi: Add a flag for power-management clocks Geert Uytterhoeven
@ 2026-06-11 13:02 ` Geert Uytterhoeven
2026-06-11 13:02 ` [PATCH/RFC 6/9] dt-bindings: firmware: arm,scmi: Document arm,clock-domain Geert Uytterhoeven
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Geert Uytterhoeven @ 2026-06-11 13:02 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Brian Masney,
Ulf Hansson
Cc: arm-scmi, linux-arm-kernel, devicetree, linux-clk, linux-pm,
linux-renesas-soc, linux-kernel, Geert Uytterhoeven
Add a helper for querying if an SCMI clock can be used for
power-management.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/clk/clk-scmi.c | 9 +++++++++
include/linux/clk/scmi.h | 17 +++++++++++++++++
2 files changed, 26 insertions(+)
create mode 100644 include/linux/clk/scmi.h
diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
index 7c562559ad8bb47f..20e6da1859290b75 100644
--- a/drivers/clk/clk-scmi.c
+++ b/drivers/clk/clk-scmi.c
@@ -7,6 +7,7 @@
#include <linux/bits.h>
#include <linux/clk-provider.h>
+#include <linux/clk/scmi.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/of.h>
@@ -364,6 +365,14 @@ scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable,
return ops;
}
+bool scmi_clk_is_pm_clk(struct clk *clk)
+{
+ struct clk_hw *hw = __clk_get_hw(clk);
+
+ return hw && to_scmi_clk(hw)->info->pm_clk;
+}
+EXPORT_SYMBOL_GPL(scmi_clk_is_pm_clk);
+
static int scmi_clocks_probe(struct scmi_device *sdev)
{
int idx, count, err;
diff --git a/include/linux/clk/scmi.h b/include/linux/clk/scmi.h
new file mode 100644
index 0000000000000000..12c338598d09296f
--- /dev/null
+++ b/include/linux/clk/scmi.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __LINUX_CLK_SCMI_H_
+#define __LINUX_CLK_SCMI_H_
+
+#include <linux/types.h>
+
+struct clk;
+
+#if IS_ENABLED(CONFIG_COMMON_CLK_SCMI)
+bool scmi_clk_is_pm_clk(struct clk *clk);
+#else
+static inline bool scmi_clk_is_pm_clk(struct clk *clk) { return false; }
+#endif
+
+#endif /* __LINUX_CLK_SCMI_H_ */
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH/RFC 6/9] dt-bindings: firmware: arm,scmi: Document arm,clock-domain
2026-06-11 13:02 [PATCH/RFC 0/9] R-Car X5H Ironhide pure SCMI proof-of-concept Geert Uytterhoeven
` (4 preceding siblings ...)
2026-06-11 13:02 ` [PATCH/RFC 5/9] clk: scmi: Add scmi_clk_is_pm_clk() Geert Uytterhoeven
@ 2026-06-11 13:02 ` Geert Uytterhoeven
2026-06-11 13:02 ` [PATCH/RFC 7/9] pmdomain: arm: scmi: Add clock domain support Geert Uytterhoeven
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Geert Uytterhoeven @ 2026-06-11 13:02 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Brian Masney,
Ulf Hansson
Cc: arm-scmi, linux-arm-kernel, devicetree, linux-clk, linux-pm,
linux-renesas-soc, linux-kernel, Geert Uytterhoeven
Power management of on-SoC modules is typically handled through two
methods: module power control and module clock gating. The former is
exposed as an SCMI power domain, the latter as an SCMI clock.
Document the new arm,clock-domain property, to link the SCMI power domain
provider to the clock domain provider that is responsible for module
clock gating.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Documentation/devicetree/bindings/firmware/arm,scmi.yaml | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
index d06cca9273c483c0..18e4da3884c4c12e 100644
--- a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
+++ b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
@@ -174,6 +174,13 @@ properties:
'#power-domain-cells':
const: 1
+ arm,clock-domain:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ When PM domain consumer devices are also part of a clock domain, this
+ property should be a reference to the SCMI clock protocol node for
+ the power management clocks in the clock domain.
+
required:
- '#power-domain-cells'
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH/RFC 7/9] pmdomain: arm: scmi: Add clock domain support
2026-06-11 13:02 [PATCH/RFC 0/9] R-Car X5H Ironhide pure SCMI proof-of-concept Geert Uytterhoeven
` (5 preceding siblings ...)
2026-06-11 13:02 ` [PATCH/RFC 6/9] dt-bindings: firmware: arm,scmi: Document arm,clock-domain Geert Uytterhoeven
@ 2026-06-11 13:02 ` Geert Uytterhoeven
2026-06-11 13:02 ` [PATCH/RFC 8/9] firmware: arm_scmi: quirk: Handle power management clocks on R-Car X5H Geert Uytterhoeven
2026-06-11 13:02 ` [PATCH/RFC 9/9] arm64: dts: renesas: ironhide: Switch to pure SCMI Geert Uytterhoeven
8 siblings, 0 replies; 10+ messages in thread
From: Geert Uytterhoeven @ 2026-06-11 13:02 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Brian Masney,
Ulf Hansson
Cc: arm-scmi, linux-arm-kernel, devicetree, linux-clk, linux-pm,
linux-renesas-soc, linux-kernel, Geert Uytterhoeven
PM domain consumer devices may also part of a clock domain.
Add support for managing power management clocks in a clock domain
through Runtime PM.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/pmdomain/arm/Kconfig | 1 +
drivers/pmdomain/arm/scmi_pm_domain.c | 81 ++++++++++++++++++++++++++-
2 files changed, 81 insertions(+), 1 deletion(-)
diff --git a/drivers/pmdomain/arm/Kconfig b/drivers/pmdomain/arm/Kconfig
index afed10d382ad7f66..11c4db47c1eadab0 100644
--- a/drivers/pmdomain/arm/Kconfig
+++ b/drivers/pmdomain/arm/Kconfig
@@ -14,6 +14,7 @@ config ARM_SCMI_PERF_DOMAIN
config ARM_SCMI_POWER_DOMAIN
tristate "SCMI power domain driver"
depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+ depends on COMMON_CLK_SCMI || !COMMON_CLK_SCMI
default ARM_SCMI_PROTOCOL
select PM_GENERIC_DOMAINS if PM
help
diff --git a/drivers/pmdomain/arm/scmi_pm_domain.c b/drivers/pmdomain/arm/scmi_pm_domain.c
index 8e67f971c707e121..838917d3b236e3aa 100644
--- a/drivers/pmdomain/arm/scmi_pm_domain.c
+++ b/drivers/pmdomain/arm/scmi_pm_domain.c
@@ -5,9 +5,12 @@
* Copyright (C) 2018-2021 ARM Ltd.
*/
+#include <linux/clk.h>
+#include <linux/clk/scmi.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/pm_clock.h>
#include <linux/pm_domain.h>
#include <linux/scmi_protocol.h>
@@ -16,6 +19,7 @@ static const struct scmi_power_proto_ops *power_ops;
struct scmi_pm_domain {
struct generic_pm_domain genpd;
const struct scmi_protocol_handle *ph;
+ struct device_node *clock_domain;
const char *name;
u32 domain;
};
@@ -39,6 +43,67 @@ static int scmi_pd_power_off(struct generic_pm_domain *domain)
return scmi_pd_power(domain, SCMI_POWER_STATE_GENERIC_OFF);
}
+static int scmi_pd_attach_dev(struct generic_pm_domain *domain,
+ struct device *dev)
+{
+ struct scmi_pm_domain *pd = to_scmi_pd(domain);
+ struct device_node *np = dev->of_node;
+ struct of_phandle_args clkspec;
+ bool once = true;
+ struct clk *clk;
+ int ret;
+
+ for (int i = 0;
+ !of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, &clkspec);
+ i++) {
+ if (clkspec.np != pd->clock_domain || clkspec.args_count != 1) {
+ of_node_put(clkspec.np);
+ continue;
+ }
+
+ clk = of_clk_get_from_provider(&clkspec);
+ of_node_put(clkspec.np);
+ if (!clk)
+ continue;
+
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ clk = NULL;
+ goto fail;
+ }
+
+ if (!scmi_clk_is_pm_clk(clk)) {
+ clk_put(clk);
+ continue;
+ }
+
+ if (once) {
+ once = false;
+ ret = pm_clk_create(dev);
+ if (ret)
+ goto fail;
+ }
+
+ ret = pm_clk_add_clk(dev, clk);
+ if (ret)
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ pm_clk_destroy(dev);
+ clk_put(clk);
+ return ret;
+}
+
+static void scmi_pd_detach_dev(struct generic_pm_domain *domain,
+ struct device *dev)
+{
+ if (!pm_clk_no_clocks(dev))
+ pm_clk_destroy(dev);
+}
+
static int scmi_pm_domain_probe(struct scmi_device *sdev)
{
int num_domains, i, ret;
@@ -48,6 +113,7 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
struct genpd_onecell_data *scmi_pd_data;
struct generic_pm_domain **domains;
const struct scmi_handle *handle = sdev->handle;
+ struct device_node *clock_domain;
struct scmi_protocol_handle *ph;
if (!handle)
@@ -75,6 +141,8 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
if (!domains)
return -ENOMEM;
+ clock_domain = of_parse_phandle(np, "arm,clock-domain", 0);
+
for (i = 0; i < num_domains; i++, scmi_pd++) {
const struct scmi_power_domain_info *info;
u32 state;
@@ -106,6 +174,12 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
scmi_pd->genpd.power_on = scmi_pd_power_on;
scmi_pd->genpd.flags = GENPD_FLAG_ACTIVE_WAKEUP |
info->genpd_flags;
+ if (clock_domain) {
+ scmi_pd->clock_domain = of_node_get(clock_domain);
+ scmi_pd->genpd.attach_dev = scmi_pd_attach_dev;
+ scmi_pd->genpd.detach_dev = scmi_pd_detach_dev;
+ scmi_pd->genpd.flags |= GENPD_FLAG_PM_CLK;
+ }
pm_genpd_init(&scmi_pd->genpd, NULL,
state == SCMI_POWER_STATE_GENERIC_OFF);
@@ -113,6 +187,8 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
domains[i] = &scmi_pd->genpd;
}
+ of_node_put(clock_domain);
+
scmi_pd_data->domains = domains;
scmi_pd_data->num_domains = num_domains;
@@ -134,8 +210,10 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
return 0;
err_rm_genpds:
- for (i = num_domains - 1; i >= 0; i--)
+ for (i = num_domains - 1; i >= 0; i--) {
pm_genpd_remove(domains[i]);
+ of_node_put(to_scmi_pd(domains[i])->clock_domain);
+ }
return ret;
}
@@ -158,6 +236,7 @@ static void scmi_pm_domain_remove(struct scmi_device *sdev)
if (!scmi_pd_data->domains[i])
continue;
pm_genpd_remove(scmi_pd_data->domains[i]);
+ of_node_put(to_scmi_pd(scmi_pd_data->domains[i])->clock_domain);
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH/RFC 8/9] firmware: arm_scmi: quirk: Handle power management clocks on R-Car X5H
2026-06-11 13:02 [PATCH/RFC 0/9] R-Car X5H Ironhide pure SCMI proof-of-concept Geert Uytterhoeven
` (6 preceding siblings ...)
2026-06-11 13:02 ` [PATCH/RFC 7/9] pmdomain: arm: scmi: Add clock domain support Geert Uytterhoeven
@ 2026-06-11 13:02 ` Geert Uytterhoeven
2026-06-11 13:02 ` [PATCH/RFC 9/9] arm64: dts: renesas: ironhide: Switch to pure SCMI Geert Uytterhoeven
8 siblings, 0 replies; 10+ messages in thread
From: Geert Uytterhoeven @ 2026-06-11 13:02 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Brian Masney,
Ulf Hansson
Cc: arm-scmi, linux-arm-kernel, devicetree, linux-clk, linux-pm,
linux-renesas-soc, linux-kernel, Geert Uytterhoeven
On Renesas R-Car X5H, power management of on-SoC modules is handled
through two methods: module power control and module clock gating. The
former is exposed as an SCMI power domain, the latter as an SCMI clock.
Currently the SCMI clock protocol does not support advertizing
power-management clocks yet. Add quirks to mark all module clocks
suitable for power management, reusing the existing clock_rcar_x5h_4_28
and clock_rcar_x5h_4_31 quirk keys.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
This patch is included as a PoC.
This does not build as the quirk keys are not added in this series.
---
drivers/firmware/arm_scmi/clock.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index 42e666a628c732e5..c2648f9f283f2488 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -355,6 +355,18 @@ scmi_clock_get_permissions(const struct scmi_protocol_handle *ph, u32 clk_id,
return ret;
}
+#define QUIRK_RCAR_X5H_4_28_PM_CLK \
+ ({ \
+ if (clk_id <= 818 /* Last MDLC clock MDLC_GPIODM3 */) \
+ clk->pm_clk = true; \
+ })
+
+#define QUIRK_RCAR_X5H_4_31_PM_CLK \
+ ({ \
+ if (clk_id <= 814 /* Last MDLC clock MDLC_GPIODM3 */) \
+ clk->pm_clk = true; \
+ })
+
static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
u32 clk_id, struct clock_info *cinfo)
{
@@ -410,6 +422,9 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
if (SUPPORTS_EXTENDED_CONFIG(attributes))
clk->extended_config = true;
}
+
+ SCMI_QUIRK(clock_rcar_x5h_4_28, QUIRK_RCAR_X5H_4_28_PM_CLK);
+ SCMI_QUIRK(clock_rcar_x5h_4_31, QUIRK_RCAR_X5H_4_31_PM_CLK);
}
return ret;
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH/RFC 9/9] arm64: dts: renesas: ironhide: Switch to pure SCMI
2026-06-11 13:02 [PATCH/RFC 0/9] R-Car X5H Ironhide pure SCMI proof-of-concept Geert Uytterhoeven
` (7 preceding siblings ...)
2026-06-11 13:02 ` [PATCH/RFC 8/9] firmware: arm_scmi: quirk: Handle power management clocks on R-Car X5H Geert Uytterhoeven
@ 2026-06-11 13:02 ` Geert Uytterhoeven
8 siblings, 0 replies; 10+ messages in thread
From: Geert Uytterhoeven @ 2026-06-11 13:02 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Brian Masney,
Ulf Hansson
Cc: arm-scmi, linux-arm-kernel, devicetree, linux-clk, linux-pm,
linux-renesas-soc, linux-kernel, Geert Uytterhoeven
Switch from CPG/MDLC remapping to pure SCMI:
- Add SCMI IDs for selected devices, supporting SCP FW SDK v4.28,
v4.31, and v4.32,
- Enable SCMI clock domain support,
- Replace clocks, power-domains, and resets properties by pure SCMI
references.
Note that the user must uncomment the line that defines
R_CAR_X5H_SCP_FW_SDK_VERSION to the SCP FW SDK version being used.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
This patch is included as a PoC.
This fails to apply, as the SCMI protocol subnodes are not added in this
series.
---
.../boot/dts/renesas/r8a78000-ironhide.dts | 44 +++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/r8a78000-ironhide.dts b/arch/arm64/boot/dts/renesas/r8a78000-ironhide.dts
index 00b5a010b7247722..f4093c359b21379e 100644
--- a/arch/arm64/boot/dts/renesas/r8a78000-ironhide.dts
+++ b/arch/arm64/boot/dts/renesas/r8a78000-ironhide.dts
@@ -9,6 +9,45 @@
#include <dt-bindings/soc/renesas,r8a78000-mfis.h>
#include "r8a78000.dtsi"
+#define V4_28 4028
+#define V4_31 4031 // Supports v4.31 and v4.32
+
+//#define R_CAR_X5H_SCP_FW_SDK_VERSION V4_28
+#define R_CAR_X5H_SCP_FW_SDK_VERSION V4_31
+
+#if R_CAR_X5H_SCP_FW_SDK_VERSION == V4_28
+
+#define CLK_SGD4_PERW_BUS 1661
+#define MDLC_HSCIF0 228
+#define MDLC_HSCIF1 229
+#define MDLC_SCIF0 209
+#define MDLC_SCIF1 210
+#define MDLC_UFS1 203
+#define RESET_HSCIF0 228
+#define RESET_HSCIF1 229
+#define RESET_SCIF0 209
+#define RESET_SCIF1 210
+#define RESET_UFS1 203
+
+#elif R_CAR_X5H_SCP_FW_SDK_VERSION == V4_31
+
+#define CLK_SGD4_PERW_BUS 1657
+#define MDLC_HSCIF0 224
+#define MDLC_HSCIF1 225
+#define MDLC_SCIF0 205
+#define MDLC_SCIF1 206
+#define MDLC_UFS1 199
+#define RESET_HSCIF0 224
+#define RESET_HSCIF1 225
+#define RESET_SCIF0 205
+#define RESET_SCIF1 206
+#define RESET_UFS1 199
+
+#endif
+
+#define PD_APL 257
+#define PD_UFS1 13
+
/ {
model = "Renesas Ironhide board based on r8a78000";
compatible = "renesas,ironhide", "renesas,r8a78000";
@@ -35,6 +74,7 @@ scmi: scmi {
scmi_devpd: protocol@11 {
reg = <0x11>;
#power-domain-cells = <1>;
+ arm,clock-domain = <&scmi_clk>;
};
scmi_sys: protocol@12 {
@@ -138,6 +178,10 @@ &extalr_clk {
};
&hscif0 {
+ clocks = <&scmi_clk MDLC_HSCIF0>, <&scmi_clk CLK_SGD4_PERW_BUS>,
+ <&scif_clk>;
+ power-domains = <&scmi_devpd PD_APL>;
+ resets = <&scmi_reset RESET_HSCIF0>;
uart-has-rtscts;
status = "okay";
};
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread