[PATCH/RFC 01/14] firmware: arm_scmi: quirk: Handle bad power domains on R-Car X5H

Geert Uytterhoeven geert+renesas at glider.be
Tue Apr 21 11:11:34 PDT 2026


Renesas R-Car X5H SCP FW SDKv4.28.0, v4.31.0, and v4.32.0 advertise a
few power domains that crash the system when touched or powered off.
Add a quirk to prevent such crashes.

As the SCMI power domain IDs are identical for all three versions, the
quirk can be shared.

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
Preventing power off could be handled in the MDLC driver, but no-touch
cannot.
---
 drivers/firmware/arm_scmi/power.c  | 20 ++++++++++++++++++++
 drivers/firmware/arm_scmi/quirks.c |  3 +++
 drivers/firmware/arm_scmi/quirks.h |  1 +
 3 files changed, 24 insertions(+)

diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index bb5062ab8280e02b..81b9035aa5a2eafe 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -12,6 +12,7 @@
 
 #include "protocols.h"
 #include "notify.h"
+#include "quirks.h"
 
 /* Updated only after ALL the mandatory features for that version are merged */
 #define SCMI_PROTOCOL_SUPPORTED_VERSION		0x30001
@@ -150,6 +151,23 @@ scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph,
 	return ret;
 }
 
+#define QUIRK_RCAR_X5H_4_28_BAD_DOMAINS					\
+	({								\
+		switch (domain) {					\
+		/* Do not touch */					\
+		case 29:	/* PD_RC08 */				\
+		case 92:	/* PD_ACL0 */				\
+		case 116:	/* PD_CMN */				\
+			return -EPERM;					\
+									\
+		/* Do not power off */					\
+		case 76:	/* PD_AC00 */				\
+			if (state == SCMI_POWER_STATE_GENERIC_OFF)	\
+				return -EPERM;				\
+			break;						\
+		}							\
+	})
+
 static int scmi_power_state_set(const struct scmi_protocol_handle *ph,
 				u32 domain, u32 state)
 {
@@ -157,6 +175,8 @@ static int scmi_power_state_set(const struct scmi_protocol_handle *ph,
 	struct scmi_xfer *t;
 	struct scmi_power_set_state *st;
 
+	SCMI_QUIRK(power_rcar_x5h_4_28_bad_domains, QUIRK_RCAR_X5H_4_28_BAD_DOMAINS);
+
 	ret = ph->xops->xfer_get_init(ph, POWER_STATE_SET, sizeof(*st), 0, &t);
 	if (ret)
 		return ret;
diff --git a/drivers/firmware/arm_scmi/quirks.c b/drivers/firmware/arm_scmi/quirks.c
index 2b38ba3f59a13c9e..c1a2f58505c1a757 100644
--- a/drivers/firmware/arm_scmi/quirks.c
+++ b/drivers/firmware/arm_scmi/quirks.c
@@ -172,6 +172,8 @@ struct scmi_quirk {
 /* Global Quirks Definitions */
 DEFINE_SCMI_QUIRK(clock_rates_triplet_out_of_spec, NULL, NULL, NULL);
 DEFINE_SCMI_QUIRK(perf_level_get_fc_force, "Qualcomm", NULL, "0x20000-");
+DEFINE_SCMI_QUIRK(power_rcar_x5h_4_28_bad_domains, "Renesas", NULL,
+		  "0x10a0000-0x10e0000", "renesas,r8a78000");
 
 /*
  * Quirks Pointers Array
@@ -182,6 +184,7 @@ DEFINE_SCMI_QUIRK(perf_level_get_fc_force, "Qualcomm", NULL, "0x20000-");
 static struct scmi_quirk *scmi_quirks_table[] = {
 	__DECLARE_SCMI_QUIRK_ENTRY(clock_rates_triplet_out_of_spec),
 	__DECLARE_SCMI_QUIRK_ENTRY(perf_level_get_fc_force),
+	__DECLARE_SCMI_QUIRK_ENTRY(power_rcar_x5h_4_28_bad_domains),
 	NULL
 };
 
diff --git a/drivers/firmware/arm_scmi/quirks.h b/drivers/firmware/arm_scmi/quirks.h
index d8ba60b956522d04..108c8d11f6043a61 100644
--- a/drivers/firmware/arm_scmi/quirks.h
+++ b/drivers/firmware/arm_scmi/quirks.h
@@ -48,5 +48,6 @@ static inline void scmi_quirks_enable(struct device *dev, const char *vend,
 /* Quirk delarations */
 DECLARE_SCMI_QUIRK(clock_rates_triplet_out_of_spec);
 DECLARE_SCMI_QUIRK(perf_level_get_fc_force);
+DECLARE_SCMI_QUIRK(power_rcar_x5h_4_28_bad_domains);
 
 #endif /* _SCMI_QUIRKS_H */
-- 
2.43.0




More information about the linux-arm-kernel mailing list