Commit 4617c220 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal

Pull thermal management fixes from Eduardo Valentin:
 "Specifics in this pull request:

   - Compilation fixes on SPEAR, and U8500 thermal drivers.
   - RCAR thermal driver now recognizes OF-thermal based thermal zones.
   - Small code rework on OF-thermal.
   - These change have been CI tested using KernelCI bot [1,2].  \o/

  I am taking over on Rui's behalf while he is out.  Happy New Chinese
  Year!

  [1] - https://kernelci.org/build/evalenti/kernel/v4.5-rc3-16-ga53b8394ec3c/
  [2] - https://kernelci.org/boot/all/job/evalenti/kernel/v4.5-rc3-16-ga53b8394ec3c/"

* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal:
  thermal: cpu_cooling: fix out of bounds access in time_in_idle
  thermal: allow u8500-thermal driver to be a module
  thermal: allow spear-thermal driver to be a module
  thermal: spear: use __maybe_unused for PM functions
  thermal: rcar: enable to use thermal-zone on DT
  thermal: of: use for_each_available_child_of_node for child iterator
parents b4e4334d a53b8394
* Renesas R-Car Thermal * Renesas R-Car Thermal
Required properties: Required properties:
- compatible : "renesas,thermal-<soctype>", "renesas,rcar-thermal" - compatible : "renesas,thermal-<soctype>",
as fallback. "renesas,rcar-gen2-thermal" (with thermal-zone) or
"renesas,rcar-thermal" (without thermal-zone) as fallback.
Examples with soctypes are: Examples with soctypes are:
- "renesas,thermal-r8a73a4" (R-Mobile APE6) - "renesas,thermal-r8a73a4" (R-Mobile APE6)
- "renesas,thermal-r8a7779" (R-Car H1) - "renesas,thermal-r8a7779" (R-Car H1)
...@@ -36,3 +37,35 @@ thermal@e61f0000 { ...@@ -36,3 +37,35 @@ thermal@e61f0000 {
0xe61f0300 0x38>; 0xe61f0300 0x38>;
interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
}; };
Example (with thermal-zone):
thermal-zones {
cpu_thermal: cpu-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&thermal>;
trips {
cpu-crit {
temperature = <115000>;
hysteresis = <0>;
type = "critical";
};
};
cooling-maps {
};
};
};
thermal: thermal@e61f0000 {
compatible = "renesas,thermal-r8a7790",
"renesas,rcar-gen2-thermal",
"renesas,rcar-thermal";
reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>;
interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp5_clks R8A7790_CLK_THERMAL>;
power-domains = <&cpg_clocks>;
#thermal-sensor-cells = <0>;
};
...@@ -2048,6 +2048,7 @@ int db8500_prcmu_config_hotmon(u8 low, u8 high) ...@@ -2048,6 +2048,7 @@ int db8500_prcmu_config_hotmon(u8 low, u8 high)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(db8500_prcmu_config_hotmon);
static int config_hot_period(u16 val) static int config_hot_period(u16 val)
{ {
...@@ -2074,11 +2075,13 @@ int db8500_prcmu_start_temp_sense(u16 cycles32k) ...@@ -2074,11 +2075,13 @@ int db8500_prcmu_start_temp_sense(u16 cycles32k)
return config_hot_period(cycles32k); return config_hot_period(cycles32k);
} }
EXPORT_SYMBOL_GPL(db8500_prcmu_start_temp_sense);
int db8500_prcmu_stop_temp_sense(void) int db8500_prcmu_stop_temp_sense(void)
{ {
return config_hot_period(0xFFFF); return config_hot_period(0xFFFF);
} }
EXPORT_SYMBOL_GPL(db8500_prcmu_stop_temp_sense);
static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3) static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
{ {
......
...@@ -195,7 +195,7 @@ config IMX_THERMAL ...@@ -195,7 +195,7 @@ config IMX_THERMAL
passive trip is crossed. passive trip is crossed.
config SPEAR_THERMAL config SPEAR_THERMAL
bool "SPEAr thermal sensor driver" tristate "SPEAr thermal sensor driver"
depends on PLAT_SPEAR || COMPILE_TEST depends on PLAT_SPEAR || COMPILE_TEST
depends on OF depends on OF
help help
...@@ -237,8 +237,8 @@ config DOVE_THERMAL ...@@ -237,8 +237,8 @@ config DOVE_THERMAL
framework. framework.
config DB8500_THERMAL config DB8500_THERMAL
bool "DB8500 thermal management" tristate "DB8500 thermal management"
depends on ARCH_U8500 depends on MFD_DB8500_PRCMU
default y default y
help help
Adds DB8500 thermal management implementation according to the thermal Adds DB8500 thermal management implementation according to the thermal
......
...@@ -377,26 +377,28 @@ static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_device, ...@@ -377,26 +377,28 @@ static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_device,
* get_load() - get load for a cpu since last updated * get_load() - get load for a cpu since last updated
* @cpufreq_device: &struct cpufreq_cooling_device for this cpu * @cpufreq_device: &struct cpufreq_cooling_device for this cpu
* @cpu: cpu number * @cpu: cpu number
* @cpu_idx: index of the cpu in cpufreq_device->allowed_cpus
* *
* Return: The average load of cpu @cpu in percentage since this * Return: The average load of cpu @cpu in percentage since this
* function was last called. * function was last called.
*/ */
static u32 get_load(struct cpufreq_cooling_device *cpufreq_device, int cpu) static u32 get_load(struct cpufreq_cooling_device *cpufreq_device, int cpu,
int cpu_idx)
{ {
u32 load; u32 load;
u64 now, now_idle, delta_time, delta_idle; u64 now, now_idle, delta_time, delta_idle;
now_idle = get_cpu_idle_time(cpu, &now, 0); now_idle = get_cpu_idle_time(cpu, &now, 0);
delta_idle = now_idle - cpufreq_device->time_in_idle[cpu]; delta_idle = now_idle - cpufreq_device->time_in_idle[cpu_idx];
delta_time = now - cpufreq_device->time_in_idle_timestamp[cpu]; delta_time = now - cpufreq_device->time_in_idle_timestamp[cpu_idx];
if (delta_time <= delta_idle) if (delta_time <= delta_idle)
load = 0; load = 0;
else else
load = div64_u64(100 * (delta_time - delta_idle), delta_time); load = div64_u64(100 * (delta_time - delta_idle), delta_time);
cpufreq_device->time_in_idle[cpu] = now_idle; cpufreq_device->time_in_idle[cpu_idx] = now_idle;
cpufreq_device->time_in_idle_timestamp[cpu] = now; cpufreq_device->time_in_idle_timestamp[cpu_idx] = now;
return load; return load;
} }
...@@ -598,7 +600,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, ...@@ -598,7 +600,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
u32 load; u32 load;
if (cpu_online(cpu)) if (cpu_online(cpu))
load = get_load(cpufreq_device, cpu); load = get_load(cpufreq_device, cpu, i);
else else
load = 0; load = 0;
......
...@@ -475,14 +475,10 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data, ...@@ -475,14 +475,10 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,
sensor_np = of_node_get(dev->of_node); sensor_np = of_node_get(dev->of_node);
for_each_child_of_node(np, child) { for_each_available_child_of_node(np, child) {
struct of_phandle_args sensor_specs; struct of_phandle_args sensor_specs;
int ret, id; int ret, id;
/* Check whether child is enabled or not */
if (!of_device_is_available(child))
continue;
/* For now, thermal framework supports only 1 sensor per zone */ /* For now, thermal framework supports only 1 sensor per zone */
ret = of_parse_phandle_with_args(child, "thermal-sensors", ret = of_parse_phandle_with_args(child, "thermal-sensors",
"#thermal-sensor-cells", "#thermal-sensor-cells",
...@@ -881,16 +877,12 @@ int __init of_parse_thermal_zones(void) ...@@ -881,16 +877,12 @@ int __init of_parse_thermal_zones(void)
return 0; /* Run successfully on systems without thermal DT */ return 0; /* Run successfully on systems without thermal DT */
} }
for_each_child_of_node(np, child) { for_each_available_child_of_node(np, child) {
struct thermal_zone_device *zone; struct thermal_zone_device *zone;
struct thermal_zone_params *tzp; struct thermal_zone_params *tzp;
int i, mask = 0; int i, mask = 0;
u32 prop; u32 prop;
/* Check whether child is enabled or not */
if (!of_device_is_available(child))
continue;
tz = thermal_of_build_thermal_zone(child); tz = thermal_of_build_thermal_zone(child);
if (IS_ERR(tz)) { if (IS_ERR(tz)) {
pr_err("failed to build thermal zone %s: %ld\n", pr_err("failed to build thermal zone %s: %ld\n",
...@@ -968,13 +960,9 @@ void of_thermal_destroy_zones(void) ...@@ -968,13 +960,9 @@ void of_thermal_destroy_zones(void)
return; return;
} }
for_each_child_of_node(np, child) { for_each_available_child_of_node(np, child) {
struct thermal_zone_device *zone; struct thermal_zone_device *zone;
/* Check whether child is enabled or not */
if (!of_device_is_available(child))
continue;
zone = thermal_zone_get_zone_by_name(child->name); zone = thermal_zone_get_zone_by_name(child->name);
if (IS_ERR(zone)) if (IS_ERR(zone))
continue; continue;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/reboot.h> #include <linux/reboot.h>
...@@ -75,8 +76,10 @@ struct rcar_thermal_priv { ...@@ -75,8 +76,10 @@ struct rcar_thermal_priv {
#define rcar_has_irq_support(priv) ((priv)->common->base) #define rcar_has_irq_support(priv) ((priv)->common->base)
#define rcar_id_to_shift(priv) ((priv)->id * 8) #define rcar_id_to_shift(priv) ((priv)->id * 8)
#define USE_OF_THERMAL 1
static const struct of_device_id rcar_thermal_dt_ids[] = { static const struct of_device_id rcar_thermal_dt_ids[] = {
{ .compatible = "renesas,rcar-thermal", }, { .compatible = "renesas,rcar-thermal", },
{ .compatible = "renesas,rcar-gen2-thermal", .data = (void *)USE_OF_THERMAL },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids);
...@@ -200,9 +203,9 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv) ...@@ -200,9 +203,9 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv)
return ret; return ret;
} }
static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) static int rcar_thermal_get_current_temp(struct rcar_thermal_priv *priv,
int *temp)
{ {
struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
int tmp; int tmp;
int ret; int ret;
...@@ -226,6 +229,20 @@ static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) ...@@ -226,6 +229,20 @@ static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
return 0; return 0;
} }
static int rcar_thermal_of_get_temp(void *data, int *temp)
{
struct rcar_thermal_priv *priv = data;
return rcar_thermal_get_current_temp(priv, temp);
}
static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
{
struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
return rcar_thermal_get_current_temp(priv, temp);
}
static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone, static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone,
int trip, enum thermal_trip_type *type) int trip, enum thermal_trip_type *type)
{ {
...@@ -282,6 +299,10 @@ static int rcar_thermal_notify(struct thermal_zone_device *zone, ...@@ -282,6 +299,10 @@ static int rcar_thermal_notify(struct thermal_zone_device *zone,
return 0; return 0;
} }
static const struct thermal_zone_of_device_ops rcar_thermal_zone_of_ops = {
.get_temp = rcar_thermal_of_get_temp,
};
static struct thermal_zone_device_ops rcar_thermal_zone_ops = { static struct thermal_zone_device_ops rcar_thermal_zone_ops = {
.get_temp = rcar_thermal_get_temp, .get_temp = rcar_thermal_get_temp,
.get_trip_type = rcar_thermal_get_trip_type, .get_trip_type = rcar_thermal_get_trip_type,
...@@ -318,14 +339,20 @@ static void rcar_thermal_work(struct work_struct *work) ...@@ -318,14 +339,20 @@ static void rcar_thermal_work(struct work_struct *work)
priv = container_of(work, struct rcar_thermal_priv, work.work); priv = container_of(work, struct rcar_thermal_priv, work.work);
rcar_thermal_get_temp(priv->zone, &cctemp); ret = rcar_thermal_get_current_temp(priv, &cctemp);
if (ret < 0)
return;
ret = rcar_thermal_update_temp(priv); ret = rcar_thermal_update_temp(priv);
if (ret < 0) if (ret < 0)
return; return;
rcar_thermal_irq_enable(priv); rcar_thermal_irq_enable(priv);
rcar_thermal_get_temp(priv->zone, &nctemp); ret = rcar_thermal_get_current_temp(priv, &nctemp);
if (ret < 0)
return;
if (nctemp != cctemp) if (nctemp != cctemp)
thermal_zone_device_update(priv->zone); thermal_zone_device_update(priv->zone);
} }
...@@ -403,6 +430,8 @@ static int rcar_thermal_probe(struct platform_device *pdev) ...@@ -403,6 +430,8 @@ static int rcar_thermal_probe(struct platform_device *pdev)
struct rcar_thermal_priv *priv; struct rcar_thermal_priv *priv;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct resource *res, *irq; struct resource *res, *irq;
const struct of_device_id *of_id = of_match_device(rcar_thermal_dt_ids, dev);
unsigned long of_data = (unsigned long)of_id->data;
int mres = 0; int mres = 0;
int i; int i;
int ret = -ENODEV; int ret = -ENODEV;
...@@ -463,7 +492,13 @@ static int rcar_thermal_probe(struct platform_device *pdev) ...@@ -463,7 +492,13 @@ static int rcar_thermal_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto error_unregister; goto error_unregister;
priv->zone = thermal_zone_device_register("rcar_thermal", if (of_data == USE_OF_THERMAL)
priv->zone = thermal_zone_of_sensor_register(
dev, i, priv,
&rcar_thermal_zone_of_ops);
else
priv->zone = thermal_zone_device_register(
"rcar_thermal",
1, 0, priv, 1, 0, priv,
&rcar_thermal_zone_ops, NULL, 0, &rcar_thermal_zone_ops, NULL, 0,
idle); idle);
......
...@@ -54,8 +54,7 @@ static struct thermal_zone_device_ops ops = { ...@@ -54,8 +54,7 @@ static struct thermal_zone_device_ops ops = {
.get_temp = thermal_get_temp, .get_temp = thermal_get_temp,
}; };
#ifdef CONFIG_PM static int __maybe_unused spear_thermal_suspend(struct device *dev)
static int spear_thermal_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev); struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev);
...@@ -72,7 +71,7 @@ static int spear_thermal_suspend(struct device *dev) ...@@ -72,7 +71,7 @@ static int spear_thermal_suspend(struct device *dev)
return 0; return 0;
} }
static int spear_thermal_resume(struct device *dev) static int __maybe_unused spear_thermal_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev); struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev);
...@@ -94,7 +93,6 @@ static int spear_thermal_resume(struct device *dev) ...@@ -94,7 +93,6 @@ static int spear_thermal_resume(struct device *dev)
return 0; return 0;
} }
#endif
static SIMPLE_DEV_PM_OPS(spear_thermal_pm_ops, spear_thermal_suspend, static SIMPLE_DEV_PM_OPS(spear_thermal_pm_ops, spear_thermal_suspend,
spear_thermal_resume); spear_thermal_resume);
......
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