firmware: arm_scmi: Add SCMI v3.1 System Power extensions
authorCristian Marussi <cristian.marussi@arm.com>
Mon, 4 Jul 2022 10:19:31 +0000 (11:19 +0100)
committerSudeep Holla <sudeep.holla@arm.com>
Mon, 4 Jul 2022 13:28:42 +0000 (14:28 +0100)
Add support for SCMIv3.1 System Power optional timeout field while
dispatching SYSTEM_POWER_STATE_NOTIFIER notification.

Link: https://lore.kernel.org/r/20220704101933.2981635-3-cristian.marussi@arm.com
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
drivers/firmware/arm_scmi/system.c
include/linux/scmi_protocol.h

index 220e399..9383d75 100644 (file)
@@ -27,10 +27,12 @@ struct scmi_system_power_state_notifier_payld {
        __le32 agent_id;
        __le32 flags;
        __le32 system_state;
+       __le32 timeout;
 };
 
 struct scmi_system_info {
        u32 version;
+       bool graceful_timeout_supported;
 };
 
 static int scmi_system_request_notify(const struct scmi_protocol_handle *ph,
@@ -72,17 +74,27 @@ scmi_system_fill_custom_report(const struct scmi_protocol_handle *ph,
                               const void *payld, size_t payld_sz,
                               void *report, u32 *src_id)
 {
+       size_t expected_sz;
        const struct scmi_system_power_state_notifier_payld *p = payld;
        struct scmi_system_power_state_notifier_report *r = report;
+       struct scmi_system_info *pinfo = ph->get_priv(ph);
 
+       expected_sz = pinfo->graceful_timeout_supported ?
+                       sizeof(*p) : sizeof(*p) - sizeof(__le32);
        if (evt_id != SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER ||
-           sizeof(*p) != payld_sz)
+           payld_sz != expected_sz)
                return NULL;
 
        r->timestamp = timestamp;
        r->agent_id = le32_to_cpu(p->agent_id);
        r->flags = le32_to_cpu(p->flags);
        r->system_state = le32_to_cpu(p->system_state);
+       if (pinfo->graceful_timeout_supported &&
+           r->system_state == SCMI_SYSTEM_SHUTDOWN &&
+           SCMI_SYSPOWER_IS_REQUEST_GRACEFUL(r->flags))
+               r->timeout = le32_to_cpu(p->timeout);
+       else
+               r->timeout = 0x00;
        *src_id = 0;
 
        return r;
@@ -129,6 +141,9 @@ static int scmi_system_protocol_init(const struct scmi_protocol_handle *ph)
                return -ENOMEM;
 
        pinfo->version = version;
+       if (PROTOCOL_REV_MAJOR(pinfo->version) >= 0x2)
+               pinfo->graceful_timeout_supported = true;
+
        return ph->set_priv(ph, pinfo);
 }
 
index 704111f..311aa3c 100644 (file)
@@ -781,8 +781,10 @@ struct scmi_clock_rate_notif_report {
 struct scmi_system_power_state_notifier_report {
        ktime_t         timestamp;
        unsigned int    agent_id;
+#define SCMI_SYSPOWER_IS_REQUEST_GRACEFUL(flags)       ((flags) & BIT(0))
        unsigned int    flags;
        unsigned int    system_state;
+       unsigned int    timeout;
 };
 
 struct scmi_perf_limits_report {