Commit 93c452f5 authored by Olof Johansson's avatar Olof Johansson

Merge tag 'scpi-updates-4.13' of...

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: default avatarOlof Johansson <olof@lixom.net>
parents 8c2f8a2f c0f2e219
......@@ -30,46 +30,20 @@
static struct scpi_ops *scpi_ops;
static struct scpi_dvfs_info *scpi_get_dvfs_info(struct device *cpu_dev)
{
int domain = topology_physical_package_id(cpu_dev->id);
if (domain < 0)
return ERR_PTR(-EINVAL);
return scpi_ops->dvfs_get_info(domain);
}
static int scpi_get_transition_latency(struct device *cpu_dev)
{
struct scpi_dvfs_info *info = scpi_get_dvfs_info(cpu_dev);
if (IS_ERR(info))
return PTR_ERR(info);
return info->latency;
return scpi_ops->get_transition_latency(cpu_dev);
}
static int scpi_init_opp_table(const struct cpumask *cpumask)
{
int idx, ret;
struct scpi_opp *opp;
int ret;
struct device *cpu_dev = get_cpu_device(cpumask_first(cpumask));
struct scpi_dvfs_info *info = scpi_get_dvfs_info(cpu_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(cpu_dev, opp->freq, opp->m_volt * 1000);
if (ret) {
dev_warn(cpu_dev, "failed to add opp %uHz %umV\n",
opp->freq, opp->m_volt);
while (idx-- > 0)
dev_pm_opp_remove(cpu_dev, (--opp)->freq);
return ret;
}
ret = scpi_ops->add_opps_to_device(cpu_dev);
if (ret) {
dev_warn(cpu_dev, "failed to add opps to the device\n");
return ret;
}
ret = dev_pm_opp_set_sharing_cpus(cpu_dev, cpumask);
......
......@@ -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,
......
......@@ -67,6 +67,9 @@ struct scpi_ops {
int (*dvfs_get_idx)(u8);
int (*dvfs_set_idx)(u8, u8);
struct scpi_dvfs_info *(*dvfs_get_info)(u8);
int (*device_domain_id)(struct device *);
int (*get_transition_latency)(struct device *);
int (*add_opps_to_device)(struct device *);
int (*sensor_get_capability)(u16 *sensors);
int (*sensor_get_info)(u16 sensor_id, struct scpi_sensor_info *);
int (*sensor_get_value)(u16, u64 *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment