diff options
author | Quentin Perret <quentin.perret@arm.com> | 2018-09-10 12:28:10 -0400 |
---|---|---|
committer | Sudeep Holla <sudeep.holla@arm.com> | 2018-09-10 12:37:06 -0400 |
commit | 1a63fe9a2b1f47af5b2b7436b41824b14999c17a (patch) | |
tree | b9f7f4b738b24ceb09bccad92b7e7266bbdd55e5 | |
parent | ca64b719a1e665ac7449b6a968059176af7365a8 (diff) |
firmware: arm_scmi: add a getter for power of performance states
The SCMI protocol can be used to get power estimates from firmware
corresponding to each performance state of a device. Although these power
costs are already managed by the SCMI firmware driver, they are not
exposed to any external subsystem yet.
Fix this by adding a new get_power() interface to the exisiting perf_ops
defined for the SCMI protocol.
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
-rw-r--r-- | drivers/firmware/arm_scmi/perf.c | 28 | ||||
-rw-r--r-- | include/linux/scmi_protocol.h | 4 |
2 files changed, 32 insertions, 0 deletions
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index 87c99d296ecd..3c8ae7cc35de 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c | |||
@@ -427,6 +427,33 @@ static int scmi_dvfs_freq_get(const struct scmi_handle *handle, u32 domain, | |||
427 | return ret; | 427 | return ret; |
428 | } | 428 | } |
429 | 429 | ||
430 | static int scmi_dvfs_est_power_get(const struct scmi_handle *handle, u32 domain, | ||
431 | unsigned long *freq, unsigned long *power) | ||
432 | { | ||
433 | struct scmi_perf_info *pi = handle->perf_priv; | ||
434 | struct perf_dom_info *dom; | ||
435 | unsigned long opp_freq; | ||
436 | int idx, ret = -EINVAL; | ||
437 | struct scmi_opp *opp; | ||
438 | |||
439 | dom = pi->dom_info + domain; | ||
440 | if (!dom) | ||
441 | return -EIO; | ||
442 | |||
443 | for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) { | ||
444 | opp_freq = opp->perf * dom->mult_factor; | ||
445 | if (opp_freq < *freq) | ||
446 | continue; | ||
447 | |||
448 | *freq = opp_freq; | ||
449 | *power = opp->power; | ||
450 | ret = 0; | ||
451 | break; | ||
452 | } | ||
453 | |||
454 | return ret; | ||
455 | } | ||
456 | |||
430 | static struct scmi_perf_ops perf_ops = { | 457 | static struct scmi_perf_ops perf_ops = { |
431 | .limits_set = scmi_perf_limits_set, | 458 | .limits_set = scmi_perf_limits_set, |
432 | .limits_get = scmi_perf_limits_get, | 459 | .limits_get = scmi_perf_limits_get, |
@@ -437,6 +464,7 @@ static struct scmi_perf_ops perf_ops = { | |||
437 | .device_opps_add = scmi_dvfs_device_opps_add, | 464 | .device_opps_add = scmi_dvfs_device_opps_add, |
438 | .freq_set = scmi_dvfs_freq_set, | 465 | .freq_set = scmi_dvfs_freq_set, |
439 | .freq_get = scmi_dvfs_freq_get, | 466 | .freq_get = scmi_dvfs_freq_get, |
467 | .est_power_get = scmi_dvfs_est_power_get, | ||
440 | }; | 468 | }; |
441 | 469 | ||
442 | static int scmi_perf_protocol_init(struct scmi_handle *handle) | 470 | static int scmi_perf_protocol_init(struct scmi_handle *handle) |
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index f4c9fc0fc755..3105055c00a7 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h | |||
@@ -91,6 +91,8 @@ struct scmi_clk_ops { | |||
91 | * to sustained performance level mapping | 91 | * to sustained performance level mapping |
92 | * @freq_get: gets the frequency for a given device using sustained frequency | 92 | * @freq_get: gets the frequency for a given device using sustained frequency |
93 | * to sustained performance level mapping | 93 | * to sustained performance level mapping |
94 | * @est_power_get: gets the estimated power cost for a given performance domain | ||
95 | * at a given frequency | ||
94 | */ | 96 | */ |
95 | struct scmi_perf_ops { | 97 | struct scmi_perf_ops { |
96 | int (*limits_set)(const struct scmi_handle *handle, u32 domain, | 98 | int (*limits_set)(const struct scmi_handle *handle, u32 domain, |
@@ -110,6 +112,8 @@ struct scmi_perf_ops { | |||
110 | unsigned long rate, bool poll); | 112 | unsigned long rate, bool poll); |
111 | int (*freq_get)(const struct scmi_handle *handle, u32 domain, | 113 | int (*freq_get)(const struct scmi_handle *handle, u32 domain, |
112 | unsigned long *rate, bool poll); | 114 | unsigned long *rate, bool poll); |
115 | int (*est_power_get)(const struct scmi_handle *handle, u32 domain, | ||
116 | unsigned long *rate, unsigned long *power); | ||
113 | }; | 117 | }; |
114 | 118 | ||
115 | /** | 119 | /** |