summaryrefslogtreecommitdiffstats
path: root/drivers/firmware/arm_scmi/reset.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/arm_scmi/reset.c')
-rw-r--r--drivers/firmware/arm_scmi/reset.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
index 19970d9f9e..1b31831653 100644
--- a/drivers/firmware/arm_scmi/reset.c
+++ b/drivers/firmware/arm_scmi/reset.c
@@ -67,6 +67,7 @@ struct reset_dom_info {
struct scmi_reset_info {
u32 version;
int num_domains;
+ bool notify_reset_cmd;
struct reset_dom_info *dom_info;
};
@@ -89,18 +90,24 @@ static int scmi_reset_attributes_get(const struct scmi_protocol_handle *ph,
}
ph->xops->xfer_put(ph, t);
+
+ if (!ret)
+ if (!ph->hops->protocol_msg_check(ph, RESET_NOTIFY, NULL))
+ pi->notify_reset_cmd = true;
+
return ret;
}
static int
scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
- u32 domain, struct reset_dom_info *dom_info,
- u32 version)
+ struct scmi_reset_info *pinfo,
+ u32 domain, u32 version)
{
int ret;
u32 attributes;
struct scmi_xfer *t;
struct scmi_msg_resp_reset_domain_attributes *attr;
+ struct reset_dom_info *dom_info = pinfo->dom_info + domain;
ret = ph->xops->xfer_get_init(ph, RESET_DOMAIN_ATTRIBUTES,
sizeof(domain), sizeof(*attr), &t);
@@ -115,7 +122,9 @@ scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
attributes = le32_to_cpu(attr->attributes);
dom_info->async_reset = SUPPORTS_ASYNC_RESET(attributes);
- dom_info->reset_notify = SUPPORTS_NOTIFY_RESET(attributes);
+ if (pinfo->notify_reset_cmd)
+ dom_info->reset_notify =
+ SUPPORTS_NOTIFY_RESET(attributes);
dom_info->latency_us = le32_to_cpu(attr->latency);
if (dom_info->latency_us == U32_MAX)
dom_info->latency_us = 0;
@@ -226,6 +235,20 @@ static const struct scmi_reset_proto_ops reset_proto_ops = {
.deassert = scmi_reset_domain_deassert,
};
+static bool scmi_reset_notify_supported(const struct scmi_protocol_handle *ph,
+ u8 evt_id, u32 src_id)
+{
+ struct reset_dom_info *dom;
+ struct scmi_reset_info *pi = ph->get_priv(ph);
+
+ if (evt_id != SCMI_EVENT_RESET_ISSUED || src_id >= pi->num_domains)
+ return false;
+
+ dom = pi->dom_info + src_id;
+
+ return dom->reset_notify;
+}
+
static int scmi_reset_notify(const struct scmi_protocol_handle *ph,
u32 domain_id, bool enable)
{
@@ -301,6 +324,7 @@ static const struct scmi_event reset_events[] = {
};
static const struct scmi_event_ops reset_event_ops = {
+ .is_notify_supported = scmi_reset_notify_supported,
.get_num_sources = scmi_reset_get_num_sources,
.set_notify_enabled = scmi_reset_set_notify_enabled,
.fill_custom_report = scmi_reset_fill_custom_report,
@@ -339,11 +363,8 @@ static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)
if (!pinfo->dom_info)
return -ENOMEM;
- for (domain = 0; domain < pinfo->num_domains; domain++) {
- struct reset_dom_info *dom = pinfo->dom_info + domain;
-
- scmi_reset_domain_attributes_get(ph, domain, dom, version);
- }
+ for (domain = 0; domain < pinfo->num_domains; domain++)
+ scmi_reset_domain_attributes_get(ph, pinfo, domain, version);
pinfo->version = version;
return ph->set_priv(ph, pinfo, version);