kernel_optimize_test/drivers/cpufreq/cpufreq-dt.c

394 lines
9.6 KiB
C
Raw Normal View History

/*
* Copyright (C) 2012 Freescale Semiconductor, Inc.
*
* Copyright (C) 2014 Linaro.
* Viresh Kumar <viresh.kumar@linaro.org>
*
* The OPP code in function set_target() is reused from
* drivers/cpufreq/omap-cpufreq.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/clk.h>
#include <linux/cpu.h>
#include <linux/cpu_cooling.h>
#include <linux/cpufreq.h>
#include <linux/cpufreq-dt.h>
#include <linux/cpumask.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_opp.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/thermal.h>
struct private_data {
struct device *cpu_dev;
struct regulator *cpu_reg;
struct thermal_cooling_device *cdev;
unsigned int voltage_tolerance; /* in percentage */
};
static int set_target(struct cpufreq_policy *policy, unsigned int index)
{
struct dev_pm_opp *opp;
struct cpufreq_frequency_table *freq_table = policy->freq_table;
struct clk *cpu_clk = policy->clk;
struct private_data *priv = policy->driver_data;
struct device *cpu_dev = priv->cpu_dev;
struct regulator *cpu_reg = priv->cpu_reg;
unsigned long volt = 0, volt_old = 0, tol = 0;
unsigned int old_freq, new_freq;
long freq_Hz, freq_exact;
int ret;
freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
if (freq_Hz <= 0)
freq_Hz = freq_table[index].frequency * 1000;
freq_exact = freq_Hz;
new_freq = freq_Hz / 1000;
old_freq = clk_get_rate(cpu_clk) / 1000;
if (!IS_ERR(cpu_reg)) {
rcu_read_lock();
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
if (IS_ERR(opp)) {
rcu_read_unlock();
dev_err(cpu_dev, "failed to find OPP for %ld\n",
freq_Hz);
return PTR_ERR(opp);
}
volt = dev_pm_opp_get_voltage(opp);
rcu_read_unlock();
tol = volt * priv->voltage_tolerance / 100;
volt_old = regulator_get_voltage(cpu_reg);
}
dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
old_freq / 1000, volt_old ? volt_old / 1000 : -1,
new_freq / 1000, volt ? volt / 1000 : -1);
/* scaling up? scale voltage before frequency */
if (!IS_ERR(cpu_reg) && new_freq > old_freq) {
ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
if (ret) {
dev_err(cpu_dev, "failed to scale voltage up: %d\n",
ret);
return ret;
}
}
ret = clk_set_rate(cpu_clk, freq_exact);
if (ret) {
dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
if (!IS_ERR(cpu_reg))
regulator_set_voltage_tol(cpu_reg, volt_old, tol);
return ret;
}
/* scaling down? scale voltage after frequency */
if (!IS_ERR(cpu_reg) && new_freq < old_freq) {
ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
if (ret) {
dev_err(cpu_dev, "failed to scale voltage down: %d\n",
ret);
clk_set_rate(cpu_clk, old_freq * 1000);
}
}
return ret;
}
static int allocate_resources(int cpu, struct device **cdev,
struct regulator **creg, struct clk **cclk)
{
struct device *cpu_dev;
struct regulator *cpu_reg;
struct clk *cpu_clk;
int ret = 0;
char *reg_cpu0 = "cpu0", *reg_cpu = "cpu", *reg;
cpu_dev = get_cpu_device(cpu);
if (!cpu_dev) {
pr_err("failed to get cpu%d device\n", cpu);
return -ENODEV;
}
/* Try "cpu0" for older DTs */
if (!cpu)
reg = reg_cpu0;
else
reg = reg_cpu;
try_again:
cpu_reg = regulator_get_optional(cpu_dev, reg);
cpufreq: cpufreq-cpu0: defer probe when regulator is not ready With commit 1e4b545, regulator_get will now return -EPROBE_DEFER when the cpu0-supply node is present, but the regulator is not yet registered. It is possible for this to occur when the regulator registration by itself might be defered due to some dependent interface not yet instantiated. For example: an regulator which uses I2C and GPIO might need both systems available before proceeding, in this case, the regulator might defer it's registration. However, the cpufreq-cpu0 driver assumes that any un-successful return result is equivalent of failure. When the regulator_get returns failure other than -EPROBE_DEFER, it makes sense to assume that supply node is not present and proceed with the assumption that only clock control is necessary in the platform. With this change, we can now handle the following conditions: a) cpu0-supply binding is not present, regulator_get will return appropriate error result, resulting in cpufreq-cpu0 driver controlling just the clock. b) cpu0-supply binding is present, regulator_get returns -EPROBE_DEFER, we retry resulting in cpufreq-cpu0 driver registering later once the regulator is available. c) cpu0-supply binding is present, regulator_get returns -EPROBE_DEFER, however, regulator never registers, we retry until cpufreq-cpu0 driver fails to register pointing at device tree information bug. However, in this case, the fact that cpufreq-cpu0 operates with clock only when the DT binding clearly indicates need of a supply is a bug of it's own. d) cpu0-supply gets an regulator at probe - cpufreq-cpu0 driver controls both the clock and regulator Signed-off-by: Nishanth Menon <nm@ti.com> Acked-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2013-05-01 21:38:12 +08:00
if (IS_ERR(cpu_reg)) {
/*
* If cpu's regulator supply node is present, but regulator is
cpufreq: cpufreq-cpu0: defer probe when regulator is not ready With commit 1e4b545, regulator_get will now return -EPROBE_DEFER when the cpu0-supply node is present, but the regulator is not yet registered. It is possible for this to occur when the regulator registration by itself might be defered due to some dependent interface not yet instantiated. For example: an regulator which uses I2C and GPIO might need both systems available before proceeding, in this case, the regulator might defer it's registration. However, the cpufreq-cpu0 driver assumes that any un-successful return result is equivalent of failure. When the regulator_get returns failure other than -EPROBE_DEFER, it makes sense to assume that supply node is not present and proceed with the assumption that only clock control is necessary in the platform. With this change, we can now handle the following conditions: a) cpu0-supply binding is not present, regulator_get will return appropriate error result, resulting in cpufreq-cpu0 driver controlling just the clock. b) cpu0-supply binding is present, regulator_get returns -EPROBE_DEFER, we retry resulting in cpufreq-cpu0 driver registering later once the regulator is available. c) cpu0-supply binding is present, regulator_get returns -EPROBE_DEFER, however, regulator never registers, we retry until cpufreq-cpu0 driver fails to register pointing at device tree information bug. However, in this case, the fact that cpufreq-cpu0 operates with clock only when the DT binding clearly indicates need of a supply is a bug of it's own. d) cpu0-supply gets an regulator at probe - cpufreq-cpu0 driver controls both the clock and regulator Signed-off-by: Nishanth Menon <nm@ti.com> Acked-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2013-05-01 21:38:12 +08:00
* not yet registered, we should try defering probe.
*/
if (PTR_ERR(cpu_reg) == -EPROBE_DEFER) {
dev_dbg(cpu_dev, "cpu%d regulator not ready, retry\n",
cpu);
return -EPROBE_DEFER;
cpufreq: cpufreq-cpu0: defer probe when regulator is not ready With commit 1e4b545, regulator_get will now return -EPROBE_DEFER when the cpu0-supply node is present, but the regulator is not yet registered. It is possible for this to occur when the regulator registration by itself might be defered due to some dependent interface not yet instantiated. For example: an regulator which uses I2C and GPIO might need both systems available before proceeding, in this case, the regulator might defer it's registration. However, the cpufreq-cpu0 driver assumes that any un-successful return result is equivalent of failure. When the regulator_get returns failure other than -EPROBE_DEFER, it makes sense to assume that supply node is not present and proceed with the assumption that only clock control is necessary in the platform. With this change, we can now handle the following conditions: a) cpu0-supply binding is not present, regulator_get will return appropriate error result, resulting in cpufreq-cpu0 driver controlling just the clock. b) cpu0-supply binding is present, regulator_get returns -EPROBE_DEFER, we retry resulting in cpufreq-cpu0 driver registering later once the regulator is available. c) cpu0-supply binding is present, regulator_get returns -EPROBE_DEFER, however, regulator never registers, we retry until cpufreq-cpu0 driver fails to register pointing at device tree information bug. However, in this case, the fact that cpufreq-cpu0 operates with clock only when the DT binding clearly indicates need of a supply is a bug of it's own. d) cpu0-supply gets an regulator at probe - cpufreq-cpu0 driver controls both the clock and regulator Signed-off-by: Nishanth Menon <nm@ti.com> Acked-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2013-05-01 21:38:12 +08:00
}
/* Try with "cpu-supply" */
if (reg == reg_cpu0) {
reg = reg_cpu;
goto try_again;
}
dev_dbg(cpu_dev, "no regulator for cpu%d: %ld\n",
cpu, PTR_ERR(cpu_reg));
cpufreq: cpufreq-cpu0: defer probe when regulator is not ready With commit 1e4b545, regulator_get will now return -EPROBE_DEFER when the cpu0-supply node is present, but the regulator is not yet registered. It is possible for this to occur when the regulator registration by itself might be defered due to some dependent interface not yet instantiated. For example: an regulator which uses I2C and GPIO might need both systems available before proceeding, in this case, the regulator might defer it's registration. However, the cpufreq-cpu0 driver assumes that any un-successful return result is equivalent of failure. When the regulator_get returns failure other than -EPROBE_DEFER, it makes sense to assume that supply node is not present and proceed with the assumption that only clock control is necessary in the platform. With this change, we can now handle the following conditions: a) cpu0-supply binding is not present, regulator_get will return appropriate error result, resulting in cpufreq-cpu0 driver controlling just the clock. b) cpu0-supply binding is present, regulator_get returns -EPROBE_DEFER, we retry resulting in cpufreq-cpu0 driver registering later once the regulator is available. c) cpu0-supply binding is present, regulator_get returns -EPROBE_DEFER, however, regulator never registers, we retry until cpufreq-cpu0 driver fails to register pointing at device tree information bug. However, in this case, the fact that cpufreq-cpu0 operates with clock only when the DT binding clearly indicates need of a supply is a bug of it's own. d) cpu0-supply gets an regulator at probe - cpufreq-cpu0 driver controls both the clock and regulator Signed-off-by: Nishanth Menon <nm@ti.com> Acked-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2013-05-01 21:38:12 +08:00
}
cpu_clk = clk_get(cpu_dev, NULL);
if (IS_ERR(cpu_clk)) {
/* put regulator */
if (!IS_ERR(cpu_reg))
regulator_put(cpu_reg);
ret = PTR_ERR(cpu_clk);
/*
* If cpu's clk node is present, but clock is not yet
* registered, we should try defering probe.
*/
if (ret == -EPROBE_DEFER)
dev_dbg(cpu_dev, "cpu%d clock not ready, retry\n", cpu);
else
dev_err(cpu_dev, "failed to get cpu%d clock: %d\n", cpu,
ret);
} else {
*cdev = cpu_dev;
*creg = cpu_reg;
*cclk = cpu_clk;
}
return ret;
}
static int cpufreq_init(struct cpufreq_policy *policy)
{
struct cpufreq_dt_platform_data *pd;
struct cpufreq_frequency_table *freq_table;
struct thermal_cooling_device *cdev;
struct device_node *np;
struct private_data *priv;
struct device *cpu_dev;
struct regulator *cpu_reg;
struct clk *cpu_clk;
unsigned long min_uV = ~0, max_uV = 0;
unsigned int transition_latency;
int ret;
ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk);
if (ret) {
pr_err("%s: Failed to allocate resources\n: %d", __func__, ret);
return ret;
}
np = of_node_get(cpu_dev->of_node);
if (!np) {
dev_err(cpu_dev, "failed to find cpu%d node\n", policy->cpu);
ret = -ENOENT;
goto out_put_reg_clk;
}
/* OPPs might be populated at runtime, don't check for error here */
of_init_opp_table(cpu_dev);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
ret = -ENOMEM;
goto out_put_node;
}
of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
if (of_property_read_u32(np, "clock-latency", &transition_latency))
transition_latency = CPUFREQ_ETERNAL;
if (!IS_ERR(cpu_reg)) {
unsigned long opp_freq = 0;
/*
* Disable any OPPs where the connected regulator isn't able to
* provide the specified voltage and record minimum and maximum
* voltage levels.
*/
while (1) {
struct dev_pm_opp *opp;
unsigned long opp_uV, tol_uV;
rcu_read_lock();
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &opp_freq);
if (IS_ERR(opp)) {
rcu_read_unlock();
break;
}
opp_uV = dev_pm_opp_get_voltage(opp);
rcu_read_unlock();
tol_uV = opp_uV * priv->voltage_tolerance / 100;
if (regulator_is_supported_voltage(cpu_reg, opp_uV,
opp_uV + tol_uV)) {
if (opp_uV < min_uV)
min_uV = opp_uV;
if (opp_uV > max_uV)
max_uV = opp_uV;
} else {
dev_pm_opp_disable(cpu_dev, opp_freq);
}
opp_freq++;
}
ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV);
if (ret > 0)
transition_latency += ret * 1000;
}
ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
if (ret) {
pr_err("failed to init cpufreq table: %d\n", ret);
goto out_free_priv;
}
/*
* For now, just loading the cooling device;
* thermal DT code takes care of matching them.
*/
if (of_find_property(np, "#cooling-cells", NULL)) {
cdev = of_cpufreq_cooling_register(np, cpu_present_mask);
if (IS_ERR(cdev))
dev_err(cpu_dev,
"running cpufreq without cooling device: %ld\n",
PTR_ERR(cdev));
else
priv->cdev = cdev;
}
priv->cpu_dev = cpu_dev;
priv->cpu_reg = cpu_reg;
policy->driver_data = priv;
policy->clk = cpu_clk;
ret = cpufreq_table_validate_and_show(policy, freq_table);
if (ret) {
dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__,
ret);
goto out_cooling_unregister;
}
policy->cpuinfo.transition_latency = transition_latency;
pd = cpufreq_get_driver_data();
cpufreq: cpufreq-dt: Restore default cpumask_setall(policy->cpus) Commit 34e5a5273d6aa0ee ("cpufreq: cpufreq-dt: extend with platform_data") changed cpufreq_init() to only call cpumask_setall(policy->cpus) if the platform data indicates that all CPUs share the same clock. Before, cpufreq_generic_init() did this unconditionally. This causes a crash on r8a7791/koelsch when resuming from s2ram: Enabling non-boot CPUs ... CPU1: Booted secondary processor Unable to handle kernel NULL pointer dereference at virtual address 0000003c pgd = ee71f980 [0000003c] *pgd=6eeb6003, *pmd=6e0e9003, *pte=00000000 Internal error: Oops: a07 [#1] SMP ARM Modules linked in: CPU: 0 PID: 1397 Comm: s2ram Tainted: G W 3.18.0-rc2-koelsch-00762-g7eed2a4e61d2d978 #581 task: ee6b76c0 ti: ee7f0000 task.ti: ee7f0000 PC is at __cpufreq_add_dev.isra.24+0x24c/0x77c LR is at __cpufreq_add_dev.isra.24+0x244/0x77c pc : [<c029e084>] lr : [<c029e07c>] psr: 60000153 sp : ee7f1d48 ip : ee7f1d48 fp : ee7f1d84 r10: c04e8448 r9 : 00000000 r8 : 00000001 r7 : c054a8c4 r6 : 00000001 r5 : 00000001 r4 : 00000000 r3 : 00000000 r2 : 00000000 r1 : 20000153 r0 : c054a950 Flags: nZCv IRQs on FIQs off Mode SVC_32 ISA ARM Segment user Control: 30c5307d Table: 6e71f980 DAC: fffffffd Process s2ram (pid: 1397, stack limit = 0xee7f0240) ... Backtrace: [<c029de38>] (__cpufreq_add_dev.isra.24) from [<c029e620>] (cpufreq_cpu_callback+0x6c/0x74) r10:eec75240 r9:c04e8448 r8:c04ef3a0 r7:00000001 r6:00000012 r5:00000000 r4:00000012 [<c029e5b4>] (cpufreq_cpu_callback) from [<c003f20c>] (notifier_call_chain+0x48/0x70) r4:ffffffdd r3:c029e5b4 [<c003f1c4>] (notifier_call_chain) from [<c003f2cc>] (__raw_notifier_call_chain+0x1c/0x24) r8:00000001 r7:00000010 r6:00000000 r5:00000000 r4:00000012 r3:ffffffff [<c003f2b0>] (__raw_notifier_call_chain) from [<c0026a00>] (__cpu_notify+0x34/0x50) [<c00269cc>] (__cpu_notify) from [<c0026a34>] (cpu_notify+0x18/0x1c) r4:00000001 [<c0026a1c>] (cpu_notify) from [<c0026c44>] (_cpu_up+0x108/0x144) [<c0026b3c>] (_cpu_up) from [<c0381c68>] (enable_nonboot_cpus+0x68/0xb8) r10:00000000 r9:c04e8ee6 r8:00000000 r7:00000003 r6:c04e8528 r5:c0506248 r4:00000001 [<c0381c00>] (enable_nonboot_cpus) from [<c0059038>] (suspend_devices_and_enter+0x29c/0x3e8) r6:c0506e70 r5:00000000 r4:00000000 r3:60000153 Restore the old default of calling cpumask_setall(policy->cpus) if no platform data is available to fix this. Fixes: 34e5a5273d6aa0ee (cpufreq: cpufreq-dt: extend with platform_data) Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Reviewed-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2014-10-27 21:44:40 +08:00
if (!pd || !pd->independent_clocks)
cpumask_setall(policy->cpus);
of_node_put(np);
return 0;
out_cooling_unregister:
cpufreq_cooling_unregister(priv->cdev);
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
out_free_priv:
kfree(priv);
out_put_node:
of_node_put(np);
out_put_reg_clk:
clk_put(cpu_clk);
if (!IS_ERR(cpu_reg))
regulator_put(cpu_reg);
return ret;
}
static int cpufreq_exit(struct cpufreq_policy *policy)
{
struct private_data *priv = policy->driver_data;
cpufreq_cooling_unregister(priv->cdev);
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
clk_put(policy->clk);
if (!IS_ERR(priv->cpu_reg))
regulator_put(priv->cpu_reg);
kfree(priv);
return 0;
}
static struct cpufreq_driver dt_cpufreq_driver = {
.flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = set_target,
.get = cpufreq_generic_get,
.init = cpufreq_init,
.exit = cpufreq_exit,
.name = "cpufreq-dt",
.attr = cpufreq_generic_attr,
};
static int dt_cpufreq_probe(struct platform_device *pdev)
{
struct device *cpu_dev;
struct regulator *cpu_reg;
struct clk *cpu_clk;
int ret;
/*
* All per-cluster (CPUs sharing clock/voltages) initialization is done
* from ->init(). In probe(), we just need to make sure that clk and
* regulators are available. Else defer probe and retry.
*
* FIXME: Is checking this only for CPU0 sufficient ?
*/
ret = allocate_resources(0, &cpu_dev, &cpu_reg, &cpu_clk);
if (ret)
return ret;
clk_put(cpu_clk);
if (!IS_ERR(cpu_reg))
regulator_put(cpu_reg);
dt_cpufreq_driver.driver_data = dev_get_platdata(&pdev->dev);
ret = cpufreq_register_driver(&dt_cpufreq_driver);
if (ret)
dev_err(cpu_dev, "failed register driver: %d\n", ret);
return ret;
}
static int dt_cpufreq_remove(struct platform_device *pdev)
{
cpufreq_unregister_driver(&dt_cpufreq_driver);
return 0;
}
static struct platform_driver dt_cpufreq_platdrv = {
.driver = {
.name = "cpufreq-dt",
.owner = THIS_MODULE,
},
.probe = dt_cpufreq_probe,
.remove = dt_cpufreq_remove,
};
module_platform_driver(dt_cpufreq_platdrv);
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
MODULE_DESCRIPTION("Generic cpufreq driver");
MODULE_LICENSE("GPL");