Merge tag 'scpi-updates-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into next/drivers

SCPI update for v4.13

Adds support to get DVFS transition latency and OPP for any device whose
DVFS are managed by SCPI. This avoids code duplication in both cpufreq
and devfreq SCPI drivers.

* tag 'scpi-updates-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
  cpufreq: scpi: use new scpi_ops functions to remove duplicate code
  firmware: arm_scpi: add support to populate OPPs and get transition latency

Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Olof Johansson
2017-06-18 20:55:07 -07:00
3 changed files with 72 additions and 32 deletions

View File

@@ -39,6 +39,7 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/printk.h>
#include <linux/pm_opp.h>
#include <linux/scpi_protocol.h>
#include <linux/slab.h>
#include <linux/sort.h>
@@ -684,6 +685,65 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
return info;
}
static int scpi_dev_domain_id(struct device *dev)
{
struct of_phandle_args clkspec;
if (of_parse_phandle_with_args(dev->of_node, "clocks", "#clock-cells",
0, &clkspec))
return -EINVAL;
return clkspec.args[0];
}
static struct scpi_dvfs_info *scpi_dvfs_info(struct device *dev)
{
int domain = scpi_dev_domain_id(dev);
if (domain < 0)
return ERR_PTR(domain);
return scpi_dvfs_get_info(domain);
}
static int scpi_dvfs_get_transition_latency(struct device *dev)
{
struct scpi_dvfs_info *info = scpi_dvfs_info(dev);
if (IS_ERR(info))
return PTR_ERR(info);
if (!info->latency)
return 0;
return info->latency;
}
static int scpi_dvfs_add_opps_to_device(struct device *dev)
{
int idx, ret;
struct scpi_opp *opp;
struct scpi_dvfs_info *info = scpi_dvfs_info(dev);
if (IS_ERR(info))
return PTR_ERR(info);
if (!info->opps)
return -EIO;
for (opp = info->opps, idx = 0; idx < info->count; idx++, opp++) {
ret = dev_pm_opp_add(dev, opp->freq, opp->m_volt * 1000);
if (ret) {
dev_warn(dev, "failed to add opp %uHz %umV\n",
opp->freq, opp->m_volt);
while (idx-- > 0)
dev_pm_opp_remove(dev, (--opp)->freq);
return ret;
}
}
return 0;
}
static int scpi_sensor_get_capability(u16 *sensors)
{
struct sensor_capabilities cap_buf;
@@ -765,6 +825,9 @@ static struct scpi_ops scpi_ops = {
.dvfs_get_idx = scpi_dvfs_get_idx,
.dvfs_set_idx = scpi_dvfs_set_idx,
.dvfs_get_info = scpi_dvfs_get_info,
.device_domain_id = scpi_dev_domain_id,
.get_transition_latency = scpi_dvfs_get_transition_latency,
.add_opps_to_device = scpi_dvfs_add_opps_to_device,
.sensor_get_capability = scpi_sensor_get_capability,
.sensor_get_info = scpi_sensor_get_info,
.sensor_get_value = scpi_sensor_get_value,