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

Geert Uytterhoeven
2026-04-21T18:12:02Z

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@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