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) | 
