diff options
Diffstat (limited to 'drivers/firmware/arm_scmi/power.c')
-rw-r--r-- | drivers/firmware/arm_scmi/power.c | 134 |
1 files changed, 76 insertions, 58 deletions
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index 1f37258e9bee..ad2ab080f344 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -2,11 +2,12 @@ /* * System Control and Management Interface (SCMI) Power Protocol * - * Copyright (C) 2018 ARM Ltd. + * Copyright (C) 2018-2021 ARM Ltd. */ #define pr_fmt(fmt) "SCMI Notifications POWER - " fmt +#include <linux/module.h> #include <linux/scmi_protocol.h> #include "common.h" @@ -68,21 +69,21 @@ struct scmi_power_info { struct power_dom_info *dom_info; }; -static int scmi_power_attributes_get(const struct scmi_handle *handle, +static int scmi_power_attributes_get(const struct scmi_protocol_handle *ph, struct scmi_power_info *pi) { int ret; struct scmi_xfer *t; struct scmi_msg_resp_power_attributes *attr; - ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES, - SCMI_PROTOCOL_POWER, 0, sizeof(*attr), &t); + ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, + 0, sizeof(*attr), &t); if (ret) return ret; attr = t->rx.buf; - ret = scmi_do_xfer(handle, t); + ret = ph->xops->do_xfer(ph, t); if (!ret) { pi->num_domains = le16_to_cpu(attr->num_domains); pi->stats_addr = le32_to_cpu(attr->stats_addr_low) | @@ -90,28 +91,27 @@ static int scmi_power_attributes_get(const struct scmi_handle *handle, pi->stats_size = le32_to_cpu(attr->stats_size); } - scmi_xfer_put(handle, t); + ph->xops->xfer_put(ph, t); return ret; } static int -scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain, - struct power_dom_info *dom_info) +scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph, + u32 domain, struct power_dom_info *dom_info) { int ret; struct scmi_xfer *t; struct scmi_msg_resp_power_domain_attributes *attr; - ret = scmi_xfer_get_init(handle, POWER_DOMAIN_ATTRIBUTES, - SCMI_PROTOCOL_POWER, sizeof(domain), - sizeof(*attr), &t); + ret = ph->xops->xfer_get_init(ph, POWER_DOMAIN_ATTRIBUTES, + sizeof(domain), sizeof(*attr), &t); if (ret) return ret; put_unaligned_le32(domain, t->tx.buf); attr = t->rx.buf; - ret = scmi_do_xfer(handle, t); + ret = ph->xops->do_xfer(ph, t); if (!ret) { u32 flags = le32_to_cpu(attr->flags); @@ -121,19 +121,18 @@ scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain, strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); } - scmi_xfer_put(handle, t); + ph->xops->xfer_put(ph, t); return ret; } -static int -scmi_power_state_set(const struct scmi_handle *handle, u32 domain, u32 state) +static int scmi_power_state_set(const struct scmi_protocol_handle *ph, + u32 domain, u32 state) { int ret; struct scmi_xfer *t; struct scmi_power_set_state *st; - ret = scmi_xfer_get_init(handle, POWER_STATE_SET, SCMI_PROTOCOL_POWER, - sizeof(*st), 0, &t); + ret = ph->xops->xfer_get_init(ph, POWER_STATE_SET, sizeof(*st), 0, &t); if (ret) return ret; @@ -142,64 +141,64 @@ scmi_power_state_set(const struct scmi_handle *handle, u32 domain, u32 state) st->domain = cpu_to_le32(domain); st->state = cpu_to_le32(state); - ret = scmi_do_xfer(handle, t); + ret = ph->xops->do_xfer(ph, t); - scmi_xfer_put(handle, t); + ph->xops->xfer_put(ph, t); return ret; } -static int -scmi_power_state_get(const struct scmi_handle *handle, u32 domain, u32 *state) +static int scmi_power_state_get(const struct scmi_protocol_handle *ph, + u32 domain, u32 *state) { int ret; struct scmi_xfer *t; - ret = scmi_xfer_get_init(handle, POWER_STATE_GET, SCMI_PROTOCOL_POWER, - sizeof(u32), sizeof(u32), &t); + ret = ph->xops->xfer_get_init(ph, POWER_STATE_GET, sizeof(u32), sizeof(u32), &t); if (ret) return ret; put_unaligned_le32(domain, t->tx.buf); - ret = scmi_do_xfer(handle, t); + ret = ph->xops->do_xfer(ph, t); if (!ret) *state = get_unaligned_le32(t->rx.buf); - scmi_xfer_put(handle, t); + ph->xops->xfer_put(ph, t); return ret; } -static int scmi_power_num_domains_get(const struct scmi_handle *handle) +static int scmi_power_num_domains_get(const struct scmi_protocol_handle *ph) { - struct scmi_power_info *pi = handle->power_priv; + struct scmi_power_info *pi = ph->get_priv(ph); return pi->num_domains; } -static char *scmi_power_name_get(const struct scmi_handle *handle, u32 domain) +static char *scmi_power_name_get(const struct scmi_protocol_handle *ph, + u32 domain) { - struct scmi_power_info *pi = handle->power_priv; + struct scmi_power_info *pi = ph->get_priv(ph); struct power_dom_info *dom = pi->dom_info + domain; return dom->name; } -static const struct scmi_power_ops power_ops = { +static const struct scmi_power_proto_ops power_proto_ops = { .num_domains_get = scmi_power_num_domains_get, .name_get = scmi_power_name_get, .state_set = scmi_power_state_set, .state_get = scmi_power_state_get, }; -static int scmi_power_request_notify(const struct scmi_handle *handle, +static int scmi_power_request_notify(const struct scmi_protocol_handle *ph, u32 domain, bool enable) { int ret; struct scmi_xfer *t; struct scmi_power_state_notify *notify; - ret = scmi_xfer_get_init(handle, POWER_STATE_NOTIFY, - SCMI_PROTOCOL_POWER, sizeof(*notify), 0, &t); + ret = ph->xops->xfer_get_init(ph, POWER_STATE_NOTIFY, + sizeof(*notify), 0, &t); if (ret) return ret; @@ -207,18 +206,18 @@ static int scmi_power_request_notify(const struct scmi_handle *handle, notify->domain = cpu_to_le32(domain); notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; - ret = scmi_do_xfer(handle, t); + ret = ph->xops->do_xfer(ph, t); - scmi_xfer_put(handle, t); + ph->xops->xfer_put(ph, t); return ret; } -static int scmi_power_set_notify_enabled(const struct scmi_handle *handle, +static int scmi_power_set_notify_enabled(const struct scmi_protocol_handle *ph, u8 evt_id, u32 src_id, bool enable) { int ret; - ret = scmi_power_request_notify(handle, src_id, enable); + ret = scmi_power_request_notify(ph, src_id, enable); if (ret) pr_debug("FAIL_ENABLE - evt[%X] dom[%d] - ret:%d\n", evt_id, src_id, ret); @@ -226,10 +225,11 @@ static int scmi_power_set_notify_enabled(const struct scmi_handle *handle, return ret; } -static void *scmi_power_fill_custom_report(const struct scmi_handle *handle, - u8 evt_id, ktime_t timestamp, - const void *payld, size_t payld_sz, - void *report, u32 *src_id) +static void * +scmi_power_fill_custom_report(const struct scmi_protocol_handle *ph, + u8 evt_id, ktime_t timestamp, + const void *payld, size_t payld_sz, + void *report, u32 *src_id) { const struct scmi_power_state_notify_payld *p = payld; struct scmi_power_state_changed_report *r = report; @@ -246,6 +246,16 @@ static void *scmi_power_fill_custom_report(const struct scmi_handle *handle, return r; } +static int scmi_power_get_num_sources(const struct scmi_protocol_handle *ph) +{ + struct scmi_power_info *pinfo = ph->get_priv(ph); + + if (!pinfo) + return -EINVAL; + + return pinfo->num_domains; +} + static const struct scmi_event power_events[] = { { .id = SCMI_EVENT_POWER_STATE_CHANGED, @@ -256,28 +266,36 @@ static const struct scmi_event power_events[] = { }; static const struct scmi_event_ops power_event_ops = { + .get_num_sources = scmi_power_get_num_sources, .set_notify_enabled = scmi_power_set_notify_enabled, .fill_custom_report = scmi_power_fill_custom_report, }; -static int scmi_power_protocol_init(struct scmi_handle *handle) +static const struct scmi_protocol_events power_protocol_events = { + .queue_sz = SCMI_PROTO_QUEUE_SZ, + .ops = &power_event_ops, + .evts = power_events, + .num_events = ARRAY_SIZE(power_events), +}; + +static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph) { int domain; u32 version; struct scmi_power_info *pinfo; - scmi_version_get(handle, SCMI_PROTOCOL_POWER, &version); + ph->xops->version_get(ph, &version); - dev_dbg(handle->dev, "Power Version %d.%d\n", + dev_dbg(ph->dev, "Power Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); - pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL); + pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL); if (!pinfo) return -ENOMEM; - scmi_power_attributes_get(handle, pinfo); + scmi_power_attributes_get(ph, pinfo); - pinfo->dom_info = devm_kcalloc(handle->dev, pinfo->num_domains, + pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains, sizeof(*pinfo->dom_info), GFP_KERNEL); if (!pinfo->dom_info) return -ENOMEM; @@ -285,20 +303,20 @@ static int scmi_power_protocol_init(struct scmi_handle *handle) for (domain = 0; domain < pinfo->num_domains; domain++) { struct power_dom_info *dom = pinfo->dom_info + domain; - scmi_power_domain_attributes_get(handle, domain, dom); + scmi_power_domain_attributes_get(ph, domain, dom); } - scmi_register_protocol_events(handle, - SCMI_PROTOCOL_POWER, SCMI_PROTO_QUEUE_SZ, - &power_event_ops, power_events, - ARRAY_SIZE(power_events), - pinfo->num_domains); - pinfo->version = version; - handle->power_ops = &power_ops; - handle->power_priv = pinfo; - return 0; + return ph->set_priv(ph, pinfo); } -DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_POWER, power) +static const struct scmi_protocol scmi_power = { + .id = SCMI_PROTOCOL_POWER, + .owner = THIS_MODULE, + .instance_init = &scmi_power_protocol_init, + .ops = &power_proto_ops, + .events = &power_protocol_events, +}; + +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(power, scmi_power) |