firmware: arm_scmi: Implement is_notify_supported callback in power protocol
authorCristian Marussi <cristian.marussi@arm.com>
Mon, 12 Feb 2024 12:32:26 +0000 (12:32 +0000)
committerSudeep Holla <sudeep.holla@arm.com>
Tue, 20 Feb 2024 06:35:55 +0000 (06:35 +0000)
Add a preliminary check to verify if the power related notify enable
commands are supported at all by the SCMI platform, and then provide
the callback needed to allow the core SCMI notification subsytem to do
a fine-grain check if a specific resource domain supports notifications.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Link: https://lore.kernel.org/r/20240212123233.1230090-5-cristian.marussi@arm.com
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
drivers/firmware/arm_scmi/power.c

index c2e6b9b..49666bd 100644 (file)
@@ -68,6 +68,7 @@ struct power_dom_info {
 
 struct scmi_power_info {
        u32 version;
+       bool notify_state_change_cmd;
        int num_domains;
        u64 stats_addr;
        u32 stats_size;
@@ -97,13 +98,18 @@ static int scmi_power_attributes_get(const struct scmi_protocol_handle *ph,
        }
 
        ph->xops->xfer_put(ph, t);
+
+       if (!ret)
+               if (!ph->hops->protocol_msg_check(ph, POWER_STATE_NOTIFY, NULL))
+                       pi->notify_state_change_cmd = true;
+
        return ret;
 }
 
 static int
 scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph,
                                 u32 domain, struct power_dom_info *dom_info,
-                                u32 version)
+                                u32 version, bool notify_state_change_cmd)
 {
        int ret;
        u32 flags;
@@ -122,7 +128,9 @@ scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph,
        if (!ret) {
                flags = le32_to_cpu(attr->flags);
 
-               dom_info->state_set_notify = SUPPORTS_STATE_SET_NOTIFY(flags);
+               if (notify_state_change_cmd)
+                       dom_info->state_set_notify =
+                               SUPPORTS_STATE_SET_NOTIFY(flags);
                dom_info->state_set_async = SUPPORTS_STATE_SET_ASYNC(flags);
                dom_info->state_set_sync = SUPPORTS_STATE_SET_SYNC(flags);
                strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
@@ -231,6 +239,20 @@ static int scmi_power_request_notify(const struct scmi_protocol_handle *ph,
        return ret;
 }
 
+static bool scmi_power_notify_supported(const struct scmi_protocol_handle *ph,
+                                       u8 evt_id, u32 src_id)
+{
+       struct power_dom_info *dom;
+       struct scmi_power_info *pinfo = ph->get_priv(ph);
+
+       if (evt_id != SCMI_EVENT_POWER_STATE_CHANGED ||
+           src_id >= pinfo->num_domains)
+               return false;
+
+       dom = pinfo->dom_info + src_id;
+       return dom->state_set_notify;
+}
+
 static int scmi_power_set_notify_enabled(const struct scmi_protocol_handle *ph,
                                         u8 evt_id, u32 src_id, bool enable)
 {
@@ -285,6 +307,7 @@ static const struct scmi_event power_events[] = {
 };
 
 static const struct scmi_event_ops power_event_ops = {
+       .is_notify_supported = scmi_power_notify_supported,
        .get_num_sources = scmi_power_get_num_sources,
        .set_notify_enabled = scmi_power_set_notify_enabled,
        .fill_custom_report = scmi_power_fill_custom_report,
@@ -326,7 +349,8 @@ static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)
        for (domain = 0; domain < pinfo->num_domains; domain++) {
                struct power_dom_info *dom = pinfo->dom_info + domain;
 
-               scmi_power_domain_attributes_get(ph, domain, dom, version);
+               scmi_power_domain_attributes_get(ph, domain, dom, version,
+                                                pinfo->notify_state_change_cmd);
        }
 
        pinfo->version = version;