[PATCH 15/16] firmware: arm_scmi: Extend perf support with OPP from genpd providers

From: Ulf Hansson
Date: Wed Jun 07 2023 - 08:48:08 EST


To enable a genpd provider to add OPPs for its attached devices, let's
convert into using the dev_pm_opp_add_dynamic() API, in favor of the
current dev_pm_opp_add() API. This allows us to specify the frequency, the
performance level and the OPP provider type for each OPP that it may be
adding.

Moreover, to let callers of the ->device_opps_add() ops, to specify the OPP
provider let's add a new in-parameter to it.

Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx>
---
drivers/cpufreq/scmi-cpufreq.c | 2 +-
drivers/firmware/arm_scmi/perf.c | 15 ++++++++++-----
include/linux/scmi_protocol.h | 2 +-
3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index 78f53e388094..a3f89a4ca899 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -188,7 +188,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
*/
nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
if (nr_opp <= 0) {
- ret = perf_ops->device_opps_add(ph, cpu_dev, domain);
+ ret = perf_ops->device_opps_add(ph, cpu_dev, domain, false);
if (ret) {
dev_warn(cpu_dev, "failed to add opps to the device\n");
goto out_free_cpumask;
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 03a496ccc603..b6cebe45fbc8 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -581,21 +581,26 @@ static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph,
}

static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
- struct device *dev, u32 domain)
+ struct device *dev, u32 domain, bool genpd)
{
int idx, ret;
- unsigned long freq;
+ struct dev_pm_opp_data opp_data;
struct perf_dom_info *dom;
struct scmi_perf_info *pi = ph->get_priv(ph);

dom = pi->dom_info + domain;

for (idx = 0; idx < dom->opp_count; idx++) {
- freq = dom->opp[idx].perf * dom->mult_factor;
+ memset(&opp_data, 0, sizeof(opp_data));
+ opp_data.level = dom->opp[idx].perf;
+ opp_data.freq = dom->opp[idx].perf * dom->mult_factor;
+ opp_data.provider = genpd ? DEV_PM_OPP_TYPE_GENPD :
+ DEV_PM_OPP_TYPE_NONE;

- ret = dev_pm_opp_add(dev, freq, 0);
+ ret = dev_pm_opp_add_dynamic(dev, &opp_data);
if (ret) {
- dev_warn(dev, "failed to add opp %luHz\n", freq);
+ dev_warn(dev, "failed to add opp %luHz\n",
+ opp_data.freq);
dev_pm_opp_remove_all_dynamic(dev);
return ret;
}
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 21aea1b2a355..ec421107f94c 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -136,7 +136,7 @@ struct scmi_perf_proto_ops {
int (*transition_latency_get)(const struct scmi_protocol_handle *ph,
u32 domain);
int (*device_opps_add)(const struct scmi_protocol_handle *ph,
- struct device *dev, u32 domain);
+ struct device *dev, u32 domain, bool genpd);
int (*freq_set)(const struct scmi_protocol_handle *ph, u32 domain,
unsigned long rate, bool poll);
int (*freq_get)(const struct scmi_protocol_handle *ph, u32 domain,
--
2.34.1