summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCristian Marussi <cristian.marussi@arm.com>2022-07-04 13:19:31 +0300
committerSudeep Holla <sudeep.holla@arm.com>2022-07-04 16:28:42 +0300
commit7097f29819bb70374dfae9f705e548a720f16f94 (patch)
treed1f80c6f2f07f8dcdf864c425bdce298b50ab3c9
parenta0db3962fb33564017b067255c20828632145c36 (diff)
downloadlinux-7097f29819bb70374dfae9f705e548a720f16f94.tar.xz
firmware: arm_scmi: Add SCMI v3.1 System Power extensions
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>
-rw-r--r--drivers/firmware/arm_scmi/system.c17
-rw-r--r--include/linux/scmi_protocol.h2
2 files changed, 18 insertions, 1 deletions
diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c
index 220e399118ad..9383d7584539 100644
--- a/drivers/firmware/arm_scmi/system.c
+++ b/drivers/firmware/arm_scmi/system.c
@@ -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);
}
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 704111f63993..311aa3c73aac 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -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 {