Commit c1dbe9a1 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'thermal-5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull thermal control updates from Rafael Wysocki:
 "These start a rework of the handling of trip points in the thermal
  core, improve the cpufreq/devfreq cooling device handling, update some
  thermal control drivers and the tmon utility and clean up code.

  Specifics:

   - Consolidate the thermal core code by beginning to move the thermal
     trip structure from the thermal OF code as a generic structure to
     be used by the different sensors when registering a thermal zone
     (Daniel Lezcano).

   - Make per cpufreq / devfreq cooling device ops instead of using a
     global variable, fix comments and rework the trace information
     (Lukasz Luba).

   - Add the include/dt-bindings/thermal.h under the area covered by the
     thermal maintainer in the MAINTAINERS file (Lukas Bulwahn).

   - Improve the error output by giving the sensor identification when a
     thermal zone failed to initialize, the DT bindings by changing the
     positive logic and adding the r8a779f0 support on the rcar3
     (Wolfram Sang).

   - Convert the QCom tsens DT binding to the dtsformat format
     (Krzysztof Kozlowski).

   - Remove the pointless get_trend() function in the QCom, Ux500 and
     tegra thermal drivers, along with the unused DROP_FULL and
     RAISE_FULL trends definitions. Simplify the code by using clamp()
     macros (Daniel Lezcano).

   - Fix ref_table memory leak at probe time on the k3_j72xx bandgap
     (Bryan Brattlof).

   - Fix array underflow in prep_lookup_table (Dan Carpenter).

   - Add static annotation to the k3_j72xx_bandgap_j7* data structure
     (Jin Xiaoyun).

   - Fix typos in comments detected on sun8i by Coccinelle (Julia
     Lawall).

   - Fix typos in comments on rzg2l (Biju Das).

   - Remove as unnecessary call to dev_err() as the error is already
     printed by the failing function on u8500 (Yang Li).

   - Register the thermal zones as hwmon sensors for the Qcom thermal
     sensors (Dmitry Baryshkov).

   - Fix 'tmon' tool compilation issue by adding phtread.h include
     (Markus Mayer).

   - Fix typo in the comments for the 'tmon' tool (Slark Xiao).

   - Make the thermal core use ida_alloc()/free() directly instead of
     ida_simple_get()/ida_simple_remove() that have been deprecated
     (keliu).

   - Drop ACPI_FADT_LOW_POWER_S0 check from the Intel PCH thermal
     control driver (Rafael Wysocki)"

* tag 'thermal-5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (39 commits)
  thermal/of: Initialize trip points separately
  thermal/of: Use thermal trips stored in the thermal zone
  thermal/core: Add thermal_trip in thermal_zone
  thermal/core: Rename 'trips' to 'num_trips'
  thermal/core: Move thermal_set_delay_jiffies to static
  thermal/core: Remove unneeded EXPORT_SYMBOLS
  thermal/of: Move thermal_trip structure to thermal.h
  thermal/of: Remove the device node pointer for thermal_trip
  thermal/of: Replace device node match with device node search
  thermal/core: Remove duplicate information when an error occurs
  thermal/core: Avoid calling ->get_trip_temp() unnecessarily
  thermal/tools/tmon: Fix typo 'the the' in comment
  thermal/tools/tmon: Include pthread and time headers in tmon.h
  thermal/ti-soc-thermal: Fix comment typo
  thermal/drivers/qcom/spmi-adc-tm5: Register thermal zones as hwmon sensors
  thermal/drivers/qcom/temp-alarm: Register thermal zones as hwmon sensors
  thermal/drivers/u8500: Remove unnecessary print function dev_err()
  thermal/drivers/rzg2l: Fix comments
  thermal/drivers/sun8i: Fix typo in comment
  thermal/drivers/k3_j72xx_bandgap: Make k3_j72xx_bandgap_j721e_data and k3_j72xx_bandgap_j7200_data static
  ...
parents a771ea64 da9d0179
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/thermal/qcom,spmi-temp-alarm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QPNP PMIC Temperature Alarm
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
description:
QPNP temperature alarm peripherals are found inside of Qualcomm PMIC chips
that utilize the Qualcomm SPMI implementation. These peripherals provide an
interrupt signal and status register to identify high PMIC die temperature.
allOf:
- $ref: thermal-sensor.yaml#
properties:
compatible:
const: qcom,spmi-temp-alarm
reg:
maxItems: 1
interrupts:
maxItems: 1
io-channels:
items:
- description: ADC channel, which reports chip die temperature
io-channel-names:
items:
- const: thermal
'#thermal-sensor-cells':
const: 0
required:
- compatible
- reg
- interrupts
- '#thermal-sensor-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
pmic {
#address-cells = <1>;
#size-cells = <0>;
pm8350_temp_alarm: temperature-sensor@a00 {
compatible = "qcom,spmi-temp-alarm";
reg = <0xa00>;
interrupts = <0x1 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
#thermal-sensor-cells = <0>;
};
};
thermal-zones {
pm8350_thermal: pm8350c-thermal {
polling-delay-passive = <100>;
polling-delay = <0>;
thermal-sensors = <&pm8350_temp_alarm>;
trips {
pm8350_trip0: trip0 {
temperature = <95000>;
hysteresis = <0>;
type = "passive";
};
pm8350_crit: pm8350c-crit {
temperature = <115000>;
hysteresis = <0>;
type = "critical";
};
};
};
};
Qualcomm QPNP PMIC Temperature Alarm
QPNP temperature alarm peripherals are found inside of Qualcomm PMIC chips
that utilize the Qualcomm SPMI implementation. These peripherals provide an
interrupt signal and status register to identify high PMIC die temperature.
Required properties:
- compatible: Should contain "qcom,spmi-temp-alarm".
- reg: Specifies the SPMI address.
- interrupts: PMIC temperature alarm interrupt.
- #thermal-sensor-cells: Should be 0. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description.
Optional properties:
- io-channels: Should contain IIO channel specifier for the ADC channel,
which report chip die temperature.
- io-channel-names: Should contain "thermal".
Example:
pm8941_temp: thermal-alarm@2400 {
compatible = "qcom,spmi-temp-alarm";
reg = <0x2400>;
interrupts = <0 0x24 0 IRQ_TYPE_EDGE_RISING>;
#thermal-sensor-cells = <0>;
io-channels = <&pm8941_vadc VADC_DIE_TEMP>;
io-channel-names = "thermal";
};
thermal-zones {
pm8941 {
polling-delay-passive = <250>;
polling-delay = <1000>;
thermal-sensors = <&pm8941_temp>;
trips {
stage1 {
temperature = <105000>;
hysteresis = <2000>;
type = "passive";
};
stage2 {
temperature = <125000>;
hysteresis = <2000>;
type = "critical";
};
};
};
};
......@@ -8,9 +8,9 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas R-Car Gen3 Thermal Sensor
description:
On R-Car Gen3 SoCs, the thermal sensor controllers (TSC) control the thermal
sensors (THS) which are the analog circuits for measuring temperature (Tj)
inside the LSI.
On most R-Car Gen3 and later SoCs, the thermal sensor controllers (TSC)
control the thermal sensors (THS) which are the analog circuits for
measuring temperature (Tj) inside the LSI.
maintainers:
- Niklas Söderlund <niklas.soderlund@ragnatech.se>
......@@ -27,6 +27,7 @@ properties:
- renesas,r8a77965-thermal # R-Car M3-N
- renesas,r8a77980-thermal # R-Car V3H
- renesas,r8a779a0-thermal # R-Car V3U
- renesas,r8a779f0-thermal # R-Car S4-8
reg: true
......@@ -57,31 +58,38 @@ required:
- "#thermal-sensor-cells"
if:
not:
properties:
compatible:
contains:
enum:
- renesas,r8a779a0-thermal
properties:
compatible:
contains:
enum:
- renesas,r8a779a0-thermal
then:
properties:
reg:
minItems: 2
items:
- description: TSC0 registers
- description: TSC1 registers
- description: TSC2 registers
- description: TSC3 registers
required:
- interrupts
- description: TSC4 registers
else:
properties:
reg:
minItems: 2
items:
- description: TSC0 registers
- description: TSC1 registers
- description: TSC2 registers
- description: TSC3 registers
- description: TSC4 registers
if:
not:
properties:
compatible:
contains:
enum:
- renesas,r8a779f0-thermal
then:
required:
- interrupts
additionalProperties: false
......
......@@ -19949,6 +19949,7 @@ F: Documentation/ABI/testing/sysfs-class-thermal
F: Documentation/devicetree/bindings/thermal/
F: Documentation/driver-api/thermal/
F: drivers/thermal/
F: include/dt-bindings/thermal/
F: include/linux/cpu_cooling.h
F: include/linux/thermal.h
F: include/uapi/linux/thermal.h
......
......@@ -60,6 +60,7 @@ struct time_in_idle {
* @cdev: thermal_cooling_device pointer to keep track of the
* registered cooling device.
* @policy: cpufreq policy.
* @cooling_ops: cpufreq callbacks to thermal cooling device ops
* @idle_time: idle time stats
* @qos_req: PM QoS contraint to apply
*
......@@ -72,6 +73,7 @@ struct cpufreq_cooling_device {
unsigned int max_level;
struct em_perf_domain *em;
struct cpufreq_policy *policy;
struct thermal_cooling_device_ops cooling_ops;
#ifndef CONFIG_SMP
struct time_in_idle *idle_time;
#endif
......@@ -211,7 +213,7 @@ static u32 get_dynamic_power(struct cpufreq_cooling_device *cpufreq_cdev,
* complex code may be needed if experiments show that it's not
* accurate enough.
*
* Return: 0 on success, -E* if getting the static power failed.
* Return: 0 on success, this function doesn't fail.
*/
static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
u32 *power)
......@@ -221,16 +223,9 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
u32 total_load = 0;
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
struct cpufreq_policy *policy = cpufreq_cdev->policy;
u32 *load_cpu = NULL;
freq = cpufreq_quick_get(policy->cpu);
if (trace_thermal_power_cpu_get_power_enabled()) {
u32 ncpus = cpumask_weight(policy->related_cpus);
load_cpu = kcalloc(ncpus, sizeof(*load_cpu), GFP_KERNEL);
}
for_each_cpu(cpu, policy->related_cpus) {
u32 load;
......@@ -240,22 +235,13 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
load = 0;
total_load += load;
if (load_cpu)
load_cpu[i] = load;
i++;
}
cpufreq_cdev->last_load = total_load;
*power = get_dynamic_power(cpufreq_cdev, freq);
if (load_cpu) {
trace_thermal_power_cpu_get_power(policy->related_cpus, freq,
load_cpu, i, *power);
kfree(load_cpu);
}
trace_thermal_power_cpu_get_power_simple(policy->cpu, *power);
return 0;
}
......@@ -270,9 +256,8 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
* milliwatts assuming 100% load. Store the calculated power in
* @power.
*
* Return: 0 on success, -EINVAL if the cooling device state could not
* be converted into a frequency or other -E* if there was an error
* when calculating the static power.
* Return: 0 on success, -EINVAL if the cooling device state is bigger
* than maximum allowed.
*/
static int cpufreq_state2power(struct thermal_cooling_device *cdev,
unsigned long state, u32 *power)
......@@ -302,15 +287,11 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev,
* Calculate a cooling device state for the cpus described by @cdev
* that would allow them to consume at most @power mW and store it in
* @state. Note that this calculation depends on external factors
* such as the cpu load or the current static power. Calling this
* function with the same power as input can yield different cooling
* device states depending on those external factors.
*
* Return: 0 on success, -ENODEV if no cpus are online or -EINVAL if
* the calculated frequency could not be converted to a valid state.
* The latter should not happen unless the frequencies available to
* cpufreq have changed since the initialization of the cpu cooling
* device.
* such as the CPUs load. Calling this function with the same power
* as input can yield different cooling device states depending on those
* external factors.
*
* Return: 0 on success, this function doesn't fail.
*/
static int cpufreq_power2state(struct thermal_cooling_device *cdev,
u32 power, unsigned long *state)
......@@ -422,7 +403,7 @@ static unsigned int get_state_freq(struct cpufreq_cooling_device *cpufreq_cdev,
* Callback for the thermal cooling device to return the cpufreq
* max cooling state.
*
* Return: 0 on success, an error code otherwise.
* Return: 0 on success, this function doesn't fail.
*/
static int cpufreq_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *state)
......@@ -441,7 +422,7 @@ static int cpufreq_get_max_state(struct thermal_cooling_device *cdev,
* Callback for the thermal cooling device to return the cpufreq
* current cooling state.
*
* Return: 0 on success, an error code otherwise.
* Return: 0 on success, this function doesn't fail.
*/
static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
unsigned long *state)
......@@ -492,14 +473,6 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
return ret;
}
/* Bind cpufreq callbacks to thermal cooling device ops */
static struct thermal_cooling_device_ops cpufreq_cooling_ops = {
.get_max_state = cpufreq_get_max_state,
.get_cur_state = cpufreq_get_cur_state,
.set_cur_state = cpufreq_set_cur_state,
};
/**
* __cpufreq_cooling_register - helper function to create cpufreq cooling device
* @np: a valid struct device_node to the cooling device device tree node
......@@ -508,7 +481,7 @@ static struct thermal_cooling_device_ops cpufreq_cooling_ops = {
* @em: Energy Model of the cpufreq policy
*
* This interface function registers the cpufreq cooling device with the name
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
* "cpufreq-%s". This API can support multiple instances of cpufreq
* cooling devices. It also gives the opportunity to link the cooling device
* with a device tree node, in order to bind it via the thermal DT code.
*
......@@ -561,7 +534,10 @@ __cpufreq_cooling_register(struct device_node *np,
/* max_level is an index, not a counter */
cpufreq_cdev->max_level = i - 1;
cooling_ops = &cpufreq_cooling_ops;
cooling_ops = &cpufreq_cdev->cooling_ops;
cooling_ops->get_max_state = cpufreq_get_max_state;
cooling_ops->get_cur_state = cpufreq_get_cur_state;
cooling_ops->set_cur_state = cpufreq_set_cur_state;
#ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
if (em_is_sane(cpufreq_cdev, em)) {
......@@ -616,8 +592,8 @@ __cpufreq_cooling_register(struct device_node *np,
* @policy: cpufreq policy
*
* This interface function registers the cpufreq cooling device with the name
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
* cooling devices.
* "cpufreq-%s". This API can support multiple instances of cpufreq cooling
* devices.
*
* Return: a valid struct thermal_cooling_device pointer on success,
* on failure, it returns a corresponding ERR_PTR().
......@@ -634,17 +610,14 @@ EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
* @policy: cpufreq policy
*
* This interface function registers the cpufreq cooling device with the name
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
* cooling devices. Using this API, the cpufreq cooling device will be
* linked to the device tree node provided.
* "cpufreq-%s". This API can support multiple instances of cpufreq cooling
* devices. Using this API, the cpufreq cooling device will be linked to the
* device tree node provided.
*
* Using this function, the cooling device will implement the power
* extensions by using a simple cpu power model. The cpus must have
* extensions by using the Energy Model (if present). The cpus must have
* registered their OPPs using the OPP library.
*
* It also takes into account, if property present in policy CPU node, the
* static power consumed by the cpu.
*
* Return: a valid struct thermal_cooling_device pointer on success,
* and NULL on failure.
*/
......@@ -680,7 +653,7 @@ EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register);
* cpufreq_cooling_unregister - function to remove cpufreq cooling device.
* @cdev: thermal cooling device pointer.
*
* This interface function unregisters the "thermal-cpufreq-%x" cooling device.
* This interface function unregisters the "cpufreq-%x" cooling device.
*/
void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
{
......
......@@ -53,7 +53,6 @@ static const unsigned long db8500_thermal_points[] = {
struct db8500_thermal_zone {
struct thermal_zone_device *tz;
enum thermal_trend trend;
unsigned long interpolated_temp;
unsigned int cur_index;
};
......@@ -73,24 +72,12 @@ static int db8500_thermal_get_temp(void *data, int *temp)
return 0;
}
/* Callback to get temperature changing trend */
static int db8500_thermal_get_trend(void *data, int trip, enum thermal_trend *trend)
{
struct db8500_thermal_zone *th = data;
*trend = th->trend;
return 0;
}
static struct thermal_zone_of_device_ops thdev_ops = {
.get_temp = db8500_thermal_get_temp,
.get_trend = db8500_thermal_get_trend,
};
static void db8500_thermal_update_config(struct db8500_thermal_zone *th,
unsigned int idx,
enum thermal_trend trend,
unsigned long next_low,
unsigned long next_high)
{
......@@ -98,7 +85,6 @@ static void db8500_thermal_update_config(struct db8500_thermal_zone *th,
th->cur_index = idx;
th->interpolated_temp = (next_low + next_high)/2;
th->trend = trend;
/*
* The PRCMU accept absolute temperatures in celsius so divide
......@@ -127,8 +113,7 @@ static irqreturn_t prcmu_low_irq_handler(int irq, void *irq_data)
}
idx -= 1;
db8500_thermal_update_config(th, idx, THERMAL_TREND_DROPPING,
next_low, next_high);
db8500_thermal_update_config(th, idx, next_low, next_high);
dev_dbg(&th->tz->device,
"PRCMU set max %ld, min %ld\n", next_high, next_low);
......@@ -149,8 +134,7 @@ static irqreturn_t prcmu_high_irq_handler(int irq, void *irq_data)
next_low = db8500_thermal_points[idx];
idx += 1;
db8500_thermal_update_config(th, idx, THERMAL_TREND_RAISING,
next_low, next_high);
db8500_thermal_update_config(th, idx, next_low, next_high);
dev_dbg(&th->tz->device,
"PRCMU set max %ld, min %ld\n", next_high, next_low);
......@@ -174,10 +158,8 @@ static int db8500_thermal_probe(struct platform_device *pdev)
return -ENOMEM;
low_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_LOW");
if (low_irq < 0) {
dev_err(dev, "Get IRQ_HOTMON_LOW failed\n");
if (low_irq < 0)
return low_irq;
}
ret = devm_request_threaded_irq(dev, low_irq, NULL,
prcmu_low_irq_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
......@@ -188,10 +170,8 @@ static int db8500_thermal_probe(struct platform_device *pdev)
}
high_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_HIGH");
if (high_irq < 0) {
dev_err(dev, "Get IRQ_HOTMON_HIGH failed\n");
if (high_irq < 0)
return high_irq;
}
ret = devm_request_threaded_irq(dev, high_irq, NULL,
prcmu_high_irq_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
......@@ -210,8 +190,7 @@ static int db8500_thermal_probe(struct platform_device *pdev)
dev_info(dev, "thermal zone sensor registered\n");
/* Start measuring at the lowest point */
db8500_thermal_update_config(th, 0, THERMAL_TREND_STABLE,
PRCMU_DEFAULT_LOW_TEMP,
db8500_thermal_update_config(th, 0, PRCMU_DEFAULT_LOW_TEMP,
db8500_thermal_points[0]);
platform_set_drvdata(pdev, th);
......@@ -232,8 +211,7 @@ static int db8500_thermal_resume(struct platform_device *pdev)
struct db8500_thermal_zone *th = platform_get_drvdata(pdev);
/* Resume and start measuring at the lowest point */
db8500_thermal_update_config(th, 0, THERMAL_TREND_STABLE,
PRCMU_DEFAULT_LOW_TEMP,
db8500_thermal_update_config(th, 0, PRCMU_DEFAULT_LOW_TEMP,
db8500_thermal_points[0]);
return 0;
......
......@@ -28,6 +28,7 @@
* struct devfreq_cooling_device - Devfreq cooling device
* devfreq_cooling_device registered.
* @cdev: Pointer to associated thermal cooling device.
* @cooling_ops: devfreq callbacks to thermal cooling device ops
* @devfreq: Pointer to associated devfreq device.
* @cooling_state: Current cooling state.
* @freq_table: Pointer to a table with the frequencies sorted in descending
......@@ -48,6 +49,7 @@
*/
struct devfreq_cooling_device {
struct thermal_cooling_device *cdev;
struct thermal_cooling_device_ops cooling_ops;
struct devfreq *devfreq;
unsigned long cooling_state;
u32 *freq_table;
......@@ -301,12 +303,6 @@ static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev,
return 0;
}
static struct thermal_cooling_device_ops devfreq_cooling_ops = {
.get_max_state = devfreq_cooling_get_max_state,
.get_cur_state = devfreq_cooling_get_cur_state,
.set_cur_state = devfreq_cooling_set_cur_state,
};
/**
* devfreq_cooling_gen_tables() - Generate frequency table.
* @dfc: Pointer to devfreq cooling device.
......@@ -374,18 +370,18 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
char *name;
int err, num_opps;
ops = kmemdup(&devfreq_cooling_ops, sizeof(*ops), GFP_KERNEL);
if (!ops)
return ERR_PTR(-ENOMEM);
dfc = kzalloc(sizeof(*dfc), GFP_KERNEL);
if (!dfc) {
err = -ENOMEM;
goto free_ops;
}
if (!dfc)
return ERR_PTR(-ENOMEM);
dfc->devfreq = df;
ops = &dfc->cooling_ops;
ops->get_max_state = devfreq_cooling_get_max_state;
ops->get_cur_state = devfreq_cooling_get_cur_state;
ops->set_cur_state = devfreq_cooling_set_cur_state;
em = em_pd_get(dev);
if (em && !em_is_artificial(em)) {
dfc->em_pd = em;
......@@ -448,8 +444,6 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
kfree(dfc->freq_table);
free_dfc:
kfree(dfc);
free_ops:
kfree(ops);
return ERR_PTR(err);
}
......@@ -531,13 +525,11 @@ EXPORT_SYMBOL_GPL(devfreq_cooling_em_register);
void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
{
struct devfreq_cooling_device *dfc;
const struct thermal_cooling_device_ops *ops;
struct device *dev;
if (IS_ERR_OR_NULL(cdev))
return;
ops = cdev->ops;
dfc = cdev->devdata;
dev = dfc->devfreq->dev.parent;
......@@ -548,6 +540,5 @@ void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
kfree(dfc->freq_table);
kfree(dfc);
kfree(ops);
}
EXPORT_SYMBOL_GPL(devfreq_cooling_unregister);
......@@ -25,10 +25,10 @@ static int get_trip_level(struct thermal_zone_device *tz)
int trip_temp;
enum thermal_trip_type trip_type;
if (tz->trips == 0 || !tz->ops->get_trip_temp)
if (tz->num_trips == 0 || !tz->ops->get_trip_temp)
return 0;
for (count = 0; count < tz->trips; count++) {
for (count = 0; count < tz->num_trips; count++) {
tz->ops->get_trip_temp(tz, count, &trip_temp);
if (tz->temperature < trip_temp)
break;
......@@ -53,7 +53,7 @@ static long get_target_state(struct thermal_zone_device *tz,
cdev->ops->get_max_state(cdev, &max_state);
return (long)(percentage * level * max_state) / (100 * tz->trips);
return (long)(percentage * level * max_state) / (100 * tz->num_trips);
}
/**
......
......@@ -527,7 +527,7 @@ static void get_governor_trips(struct thermal_zone_device *tz,
last_active = INVALID_TRIP;
last_passive = INVALID_TRIP;
for (i = 0; i < tz->trips; i++) {
for (i = 0; i < tz->num_trips; i++) {
enum thermal_trip_type type;
int ret;
......@@ -668,7 +668,7 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
get_governor_trips(tz, params);
if (tz->trips > 0) {
if (tz->num_trips > 0) {
ret = tz->ops->get_trip_temp(tz,
params->trip_max_desired_temperature,
&control_temp);
......
......@@ -11,6 +11,7 @@
*/
#include <linux/thermal.h>
#include <linux/minmax.h>
#include <trace/events/thermal.h>
#include "thermal_core.h"
......@@ -52,10 +53,7 @@ static unsigned long get_target_state(struct thermal_instance *instance,
if (!instance->initialized) {
if (throttle) {
next_target = (cur_state + 1) >= instance->upper ?
instance->upper :
((cur_state + 1) < instance->lower ?
instance->lower : (cur_state + 1));
next_target = clamp((cur_state + 1), instance->lower, instance->upper);
} else {
next_target = THERMAL_NO_TARGET;
}
......@@ -66,35 +64,19 @@ static unsigned long get_target_state(struct thermal_instance *instance,
switch (trend) {
case THERMAL_TREND_RAISING:
if (throttle) {
next_target = cur_state < instance->upper ?
(cur_state + 1) : instance->upper;
if (next_target < instance->lower)
next_target = instance->lower;
next_target = clamp((cur_state + 1), instance->lower, instance->upper);
}
break;
case THERMAL_TREND_RAISE_FULL:
if (throttle)
next_target = instance->upper;
break;
case THERMAL_TREND_DROPPING:
if (cur_state <= instance->lower) {
if (!throttle)
next_target = THERMAL_NO_TARGET;
} else {
if (!throttle) {
next_target = cur_state - 1;
if (next_target > instance->upper)
next_target = instance->upper;
next_target = clamp((cur_state - 1), instance->lower, instance->upper);
}
}
break;
case THERMAL_TREND_DROP_FULL:
if (cur_state == instance->lower) {
if (!throttle)
next_target = THERMAL_NO_TARGET;
} else
next_target = instance->lower;
break;
default:
break;
}
......
......@@ -207,14 +207,6 @@ static int pch_wpt_suspend(struct pch_thermal_device *ptd)
return 0;
}
/* Do not check temperature if it is not a S0ix capable platform */
#ifdef CONFIG_ACPI
if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
return 0;
#else
return 0;
#endif
/* Do not check temperature if it is not s2idle */
if (pm_suspend_via_firmware())
return 0;
......
......@@ -105,7 +105,7 @@ static struct zone_device *pkg_temp_thermal_get_dev(unsigned int cpu)
}
/*
* tj-max is is interesting because threshold is set relative to this
* tj-max is interesting because threshold is set relative to this
* temperature.
*/
static int get_tj_max(int cpu, u32 *tj_max)
......
......@@ -151,8 +151,6 @@ static int prep_lookup_table(struct err_values *err_vals, int *ref_table)
/* 300 milli celsius steps */
while (i--)
derived_table[i] = derived_table[i + 1] - 300;
/* case 0 */
derived_table[i] = derived_table[i + 1] - 300;
}
/*
......@@ -433,7 +431,7 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
GFP_KERNEL);
if (!derived_table) {
ret = -ENOMEM;
goto err_alloc;
goto err_free_ref_table;
}
/* Workaround not needed if bit30/bit31 is set even for J721e */
......@@ -483,7 +481,7 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
if (IS_ERR(ti_thermal)) {
dev_err(bgp->dev, "thermal zone device is NULL\n");
ret = PTR_ERR(ti_thermal);
goto err_alloc;
goto err_free_ref_table;
}
}
......@@ -514,6 +512,9 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
return 0;
err_free_ref_table:
kfree(ref_table);
err_alloc:
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
......@@ -529,11 +530,11 @@ static int k3_j72xx_bandgap_remove(struct platform_device *pdev)
return 0;
}
const struct k3_j72xx_bandgap_data k3_j72xx_bandgap_j721e_data = {
static const struct k3_j72xx_bandgap_data k3_j72xx_bandgap_j721e_data = {
.has_errata_i2128 = 1,
};
const struct k3_j72xx_bandgap_data k3_j72xx_bandgap_j7200_data = {
static const struct k3_j72xx_bandgap_data k3_j72xx_bandgap_j7200_data = {
.has_errata_i2128 = 0,
};
......
......@@ -20,6 +20,8 @@
#include <linux/thermal.h>
#include <asm-generic/unaligned.h>
#include "../thermal_hwmon.h"
/*
* Thermal monitoring block consists of 8 (ADC_TM5_NUM_CHANNELS) channels. Each
* channel is programmed to use one of ADC channels for voltage comparison.
......@@ -687,6 +689,9 @@ static int adc_tm5_register_tzd(struct adc_tm5_chip *adc_tm)
return PTR_ERR(tzd);
}
adc_tm->channels[i].tzd = tzd;
if (devm_thermal_add_hwmon_sysfs(tzd))
dev_warn(adc_tm->dev,
"Failed to add hwmon sysfs attributes\n");
}
return 0;
......
......@@ -16,6 +16,7 @@
#include <linux/thermal.h>
#include "../thermal_core.h"
#include "../thermal_hwmon.h"
#define QPNP_TM_REG_DIG_MAJOR 0x01
#define QPNP_TM_REG_TYPE 0x04
......@@ -458,6 +459,10 @@ static int qpnp_tm_probe(struct platform_device *pdev)
return ret;
}
if (devm_thermal_add_hwmon_sysfs(chip->tz_dev))
dev_warn(&pdev->dev,
"Failed to add hwmon sysfs attributes\n");
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, qpnp_tm_isr,
IRQF_ONESHOT, node->name, chip);
if (ret < 0)
......
......@@ -933,17 +933,6 @@ static int tsens_get_temp(void *data, int *temp)
return priv->ops->get_temp(s, temp);
}
static int tsens_get_trend(void *data, int trip, enum thermal_trend *trend)
{
struct tsens_sensor *s = data;
struct tsens_priv *priv = s->priv;
if (priv->ops->get_trend)
return priv->ops->get_trend(s, trend);
return -ENOTSUPP;
}
static int __maybe_unused tsens_suspend(struct device *dev)
{
struct tsens_priv *priv = dev_get_drvdata(dev);
......@@ -1004,7 +993,6 @@ MODULE_DEVICE_TABLE(of, tsens_table);
static const struct thermal_zone_of_device_ops tsens_of_ops = {
.get_temp = tsens_get_temp,
.get_trend = tsens_get_trend,
.set_trips = tsens_set_trips,
};
......
......@@ -65,7 +65,6 @@ struct tsens_sensor {
* @disable: Function to disable the tsens device
* @suspend: Function to suspend the tsens device
* @resume: Function to resume the tsens device
* @get_trend: Function to get the thermal/temp trend
*/
struct tsens_ops {
/* mandatory callbacks */
......@@ -77,7 +76,6 @@ struct tsens_ops {
void (*disable)(struct tsens_priv *priv);
int (*suspend)(struct tsens_priv *priv);
int (*resume)(struct tsens_priv *priv);
int (*get_trend)(struct tsens_sensor *s, enum thermal_trend *trend);
};
#define REG_FIELD_FOR_EACH_SENSOR11(_name, _offset, _startbit, _stopbit) \
......
......@@ -511,7 +511,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,
&rcar_gen3_tz_of_ops);
if (IS_ERR(zone)) {
dev_err(dev, "Can't register thermal zone\n");
dev_err(dev, "Sensor %u: Can't register thermal zone\n", i);
ret = PTR_ERR(zone);
goto error_unregister;
}
......@@ -533,7 +533,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
if (ret < 0)
goto error_unregister;
dev_info(dev, "TSC%u: Loaded %d trip points\n", i, ret);
dev_info(dev, "Sensor %u: Loaded %d trip points\n", i, ret);
}
if (!priv->num_tscs) {
......
......@@ -47,7 +47,7 @@
#define TS_CODE_AVE_SCALE(x) ((x) * 1000000)
#define MCELSIUS(temp) ((temp) * MILLIDEGREE_PER_DEGREE)
#define TS_CODE_CAP_TIMES 8 /* Capture times */
#define TS_CODE_CAP_TIMES 8 /* Total number of ADC data samples */
#define RZG2L_THERMAL_GRAN 500 /* milli Celsius */
#define RZG2L_TSU_SS_TIMEOUT_US 1000
......@@ -80,7 +80,8 @@ static int rzg2l_thermal_get_temp(void *devdata, int *temp)
int val, i;
for (i = 0; i < TS_CODE_CAP_TIMES ; i++) {
/* TSU repeats measurement at 20 microseconds intervals and
/*
* TSU repeats measurement at 20 microseconds intervals and
* automatically updates the results of measurement. As per
* the HW manual for measuring temperature we need to read 8
* values consecutively and then take the average.
......@@ -92,16 +93,18 @@ static int rzg2l_thermal_get_temp(void *devdata, int *temp)
ts_code_ave = result / TS_CODE_CAP_TIMES;
/* Calculate actual sensor value by applying curvature correction formula
/*
* Calculate actual sensor value by applying curvature correction formula
* dsensor = ts_code_ave / (1 + ts_code_ave * 0.000013). Here we are doing
* integer calculation by scaling all the values by 1000000.
*/
dsensor = TS_CODE_AVE_SCALE(ts_code_ave) /
(TS_CODE_AVE_SCALE(1) + (ts_code_ave * CURVATURE_CORRECTION_CONST));
/* The temperature Tj is calculated by the formula
/*
* The temperature Tj is calculated by the formula
* Tj = (dsensor − calib1) * 165/ (calib0 − calib1) − 40
* where calib0 and calib1 are the caliberation values.
* where calib0 and calib1 are the calibration values.
*/
val = ((dsensor - priv->calib1) * (MCELSIUS(165) /
(priv->calib0 - priv->calib1))) - MCELSIUS(40);
......@@ -122,7 +125,8 @@ static int rzg2l_thermal_init(struct rzg2l_thermal_priv *priv)
rzg2l_thermal_write(priv, TSU_SM, TSU_SM_NORMAL_MODE);
rzg2l_thermal_write(priv, TSU_ST, 0);
/* Before setting the START bit, TSU should be in normal operating
/*
* Before setting the START bit, TSU should be in normal operating
* mode. As per the HW manual, it will take 60 µs to place the TSU
* into normal operating mode.
*/
......@@ -217,7 +221,7 @@ static int rzg2l_thermal_probe(struct platform_device *pdev)
if (ret)
goto err;
dev_dbg(dev, "TSU probed with %s caliberation values",
dev_dbg(dev, "TSU probed with %s calibration values",
rzg2l_thermal_read(priv, OTPTSUTRIM_REG(0)) ? "hw" : "sw");
return 0;
......
......@@ -237,7 +237,7 @@ static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
* The calibration data on the H6 is the ambient temperature and
* sensor values that are filled during the factory test stage.
*
* The unit of stored FT temperature is 0.1 degreee celusis.
* The unit of stored FT temperature is 0.1 degree celsius.
*
* We need to calculate a delta between measured and caluclated
* register values and this will become a calibration offset.
......
......@@ -633,37 +633,6 @@ static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
return 0;
}
static int tegra_thermctl_get_trend(void *data, int trip,
enum thermal_trend *trend)
{
struct tegra_thermctl_zone *zone = data;
struct thermal_zone_device *tz = zone->tz;
int trip_temp, temp, last_temp, ret;
if (!tz)
return -EINVAL;
ret = tz->ops->get_trip_temp(zone->tz, trip, &trip_temp);
if (ret)
return ret;
temp = READ_ONCE(tz->temperature);
last_temp = READ_ONCE(tz->last_temperature);
if (temp > trip_temp) {
if (temp >= last_temp)
*trend = THERMAL_TREND_RAISING;
else
*trend = THERMAL_TREND_STABLE;
} else if (temp < trip_temp) {
*trend = THERMAL_TREND_DROPPING;
} else {
*trend = THERMAL_TREND_STABLE;
}
return 0;
}
static void thermal_irq_enable(struct tegra_thermctl_zone *zn)
{
u32 r;
......@@ -716,7 +685,6 @@ static int tegra_thermctl_set_trips(void *data, int lo, int hi)
static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = {
.get_temp = tegra_thermctl_get_temp,
.set_trip_temp = tegra_thermctl_set_trip_temp,
.get_trend = tegra_thermctl_get_trend,
.set_trips = tegra_thermctl_set_trips,
};
......
......@@ -316,7 +316,7 @@ static void tegra_tsensor_get_hw_channel_trips(struct thermal_zone_device *tzd,
*hot_trip = 85000;
*crit_trip = 90000;
for (i = 0; i < tzd->trips; i++) {
for (i = 0; i < tzd->num_trips; i++) {
enum thermal_trip_type type;
int trip_temp;
......
......@@ -340,12 +340,8 @@ void thermal_zone_device_critical(struct thermal_zone_device *tz)
EXPORT_SYMBOL(thermal_zone_device_critical);
static void handle_critical_trips(struct thermal_zone_device *tz,
int trip, enum thermal_trip_type trip_type)
int trip, int trip_temp, enum thermal_trip_type trip_type)
{
int trip_temp;
tz->ops->get_trip_temp(tz, trip, &trip_temp);
/* If we have not crossed the trip_temp, we do not care. */
if (trip_temp <= 0 || tz->temperature < trip_temp)
return;
......@@ -384,7 +380,7 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
}
if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
handle_critical_trips(tz, trip, type);
handle_critical_trips(tz, trip, trip_temp, type);
else
handle_non_critical_trips(tz, trip);
/*
......@@ -505,7 +501,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz,
tz->notify_event = event;
for (count = 0; count < tz->trips; count++)
for (count = 0; count < tz->num_trips; count++)
handle_thermal_trip(tz, count);
}
EXPORT_SYMBOL_GPL(thermal_zone_device_update);
......@@ -630,7 +626,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
unsigned long max_state;
int result, ret;
if (trip >= tz->trips || trip < 0)
if (trip >= tz->num_trips || trip < 0)
return -EINVAL;
list_for_each_entry(pos1, &thermal_tz_list, node) {
......@@ -667,7 +663,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
dev->target = THERMAL_NO_TARGET;
dev->weight = weight;
result = ida_simple_get(&tz->ida, 0, 0, GFP_KERNEL);
result = ida_alloc(&tz->ida, GFP_KERNEL);
if (result < 0)
goto free_mem;
......@@ -721,7 +717,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
remove_symbol_link:
sysfs_remove_link(&tz->device.kobj, dev->name);
release_ida:
ida_simple_remove(&tz->ida, dev->id);
ida_free(&tz->ida, dev->id);
free_mem:
kfree(dev);
return result;
......@@ -768,7 +764,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
device_remove_file(&tz->device, &pos->weight_attr);
device_remove_file(&tz->device, &pos->attr);
sysfs_remove_link(&tz->device.kobj, pos->name);
ida_simple_remove(&tz->ida, pos->id);
ida_free(&tz->ida, pos->id);
kfree(pos);
return 0;
}
......@@ -811,7 +807,7 @@ static void __bind(struct thermal_zone_device *tz, int mask,
{
int i, ret;
for (i = 0; i < tz->trips; i++) {
for (i = 0; i < tz->num_trips; i++) {
if (mask & (1 << i)) {
unsigned long upper, lower;
......@@ -901,7 +897,7 @@ __thermal_cooling_device_register(struct device_node *np,
if (!cdev)
return ERR_PTR(-ENOMEM);
ret = ida_simple_get(&thermal_cdev_ida, 0, 0, GFP_KERNEL);
ret = ida_alloc(&thermal_cdev_ida, GFP_KERNEL);
if (ret < 0)
goto out_kfree_cdev;
cdev->id = ret;
......@@ -952,7 +948,7 @@ __thermal_cooling_device_register(struct device_node *np,
put_device(&cdev->device);
cdev = NULL;
out_ida_remove:
ida_simple_remove(&thermal_cdev_ida, id);
ida_free(&thermal_cdev_ida, id);
out_kfree_cdev:
kfree(cdev);
return ERR_PTR(ret);
......@@ -1057,7 +1053,7 @@ static void __unbind(struct thermal_zone_device *tz, int mask,
{
int i;
for (i = 0; i < tz->trips; i++)
for (i = 0; i < tz->num_trips; i++)
if (mask & (1 << i))
thermal_zone_unbind_cooling_device(tz, i, cdev);
}
......@@ -1111,7 +1107,7 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
mutex_unlock(&thermal_list_lock);
ida_simple_remove(&thermal_cdev_ida, cdev->id);
ida_free(&thermal_cdev_ida, cdev->id);
device_del(&cdev->device);
thermal_cooling_device_destroy_sysfs(cdev);
kfree(cdev->type);
......@@ -1159,10 +1155,18 @@ static void bind_tz(struct thermal_zone_device *tz)
mutex_unlock(&thermal_list_lock);
}
static void thermal_set_delay_jiffies(unsigned long *delay_jiffies, int delay_ms)
{
*delay_jiffies = msecs_to_jiffies(delay_ms);
if (delay_ms > 1000)
*delay_jiffies = round_jiffies(*delay_jiffies);
}
/**
* thermal_zone_device_register() - register a new thermal zone device
* thermal_zone_device_register_with_trips() - register a new thermal zone device
* @type: the thermal zone device type
* @trips: the number of trip points the thermal zone support
* @trips: a pointer to an array of thermal trips
* @num_trips: the number of trip points the thermal zone support
* @mask: a bit string indicating the writeablility of trip points
* @devdata: private device data
* @ops: standard thermal zone device callbacks
......@@ -1184,10 +1188,10 @@ static void bind_tz(struct thermal_zone_device *tz)
* IS_ERR*() helpers.
*/
struct thermal_zone_device *
thermal_zone_device_register(const char *type, int trips, int mask,
void *devdata, struct thermal_zone_device_ops *ops,
struct thermal_zone_params *tzp, int passive_delay,
int polling_delay)
thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *trips, int num_trips, int mask,
void *devdata, struct thermal_zone_device_ops *ops,
struct thermal_zone_params *tzp, int passive_delay,
int polling_delay)
{
struct thermal_zone_device *tz;
enum thermal_trip_type trip_type;
......@@ -1198,27 +1202,27 @@ thermal_zone_device_register(const char *type, int trips, int mask,
struct thermal_governor *governor;
if (!type || strlen(type) == 0) {
pr_err("Error: No thermal zone type defined\n");
pr_err("No thermal zone type defined\n");
return ERR_PTR(-EINVAL);
}
if (type && strlen(type) >= THERMAL_NAME_LENGTH) {
pr_err("Error: Thermal zone name (%s) too long, should be under %d chars\n",
pr_err("Thermal zone name (%s) too long, should be under %d chars\n",
type, THERMAL_NAME_LENGTH);
return ERR_PTR(-EINVAL);
}
if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips) {
pr_err("Error: Incorrect number of thermal trips\n");
if (num_trips > THERMAL_MAX_TRIPS || num_trips < 0 || mask >> num_trips) {
pr_err("Incorrect number of thermal trips\n");
return ERR_PTR(-EINVAL);
}
if (!ops) {
pr_err("Error: Thermal zone device ops not defined\n");
pr_err("Thermal zone device ops not defined\n");
return ERR_PTR(-EINVAL);
}
if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp))
if (num_trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp))
return ERR_PTR(-EINVAL);
tz = kzalloc(sizeof(*tz), GFP_KERNEL);
......@@ -1228,7 +1232,7 @@ thermal_zone_device_register(const char *type, int trips, int mask,
INIT_LIST_HEAD(&tz->thermal_instances);
ida_init(&tz->ida);
mutex_init(&tz->lock);
id = ida_simple_get(&thermal_tz_ida, 0, 0, GFP_KERNEL);
id = ida_alloc(&thermal_tz_ida, GFP_KERNEL);
if (id < 0) {
result = id;
goto free_tz;
......@@ -1249,6 +1253,7 @@ thermal_zone_device_register(const char *type, int trips, int mask,
tz->device.class = &thermal_class;
tz->devdata = devdata;
tz->trips = trips;
tz->num_trips = num_trips;
thermal_set_delay_jiffies(&tz->passive_delay_jiffies, passive_delay);
thermal_set_delay_jiffies(&tz->polling_delay_jiffies, polling_delay);
......@@ -1266,7 +1271,7 @@ thermal_zone_device_register(const char *type, int trips, int mask,
if (result)
goto release_device;
for (count = 0; count < trips; count++) {
for (count = 0; count < num_trips; count++) {
if (tz->ops->get_trip_type(tz, count, &trip_type) ||
tz->ops->get_trip_temp(tz, count, &trip_temp) ||
!trip_temp)
......@@ -1319,11 +1324,21 @@ thermal_zone_device_register(const char *type, int trips, int mask,
put_device(&tz->device);
tz = NULL;
remove_id:
ida_simple_remove(&thermal_tz_ida, id);
ida_free(&thermal_tz_ida, id);
free_tz:
kfree(tz);
return ERR_PTR(result);
}
struct thermal_zone_device *thermal_zone_device_register(const char *type, int ntrips, int mask,
void *devdata, struct thermal_zone_device_ops *ops,
struct thermal_zone_params *tzp, int passive_delay,
int polling_delay)
{
return thermal_zone_device_register_with_trips(type, NULL, ntrips, mask,
devdata, ops, tzp,
passive_delay, polling_delay);
}
EXPORT_SYMBOL_GPL(thermal_zone_device_register);
/**
......@@ -1379,7 +1394,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
thermal_set_governor(tz, NULL);
thermal_remove_hwmon_sysfs(tz);
ida_simple_remove(&thermal_tz_ida, tz->id);
ida_free(&thermal_tz_ida, tz->id);
ida_destroy(&tz->ida);
mutex_destroy(&tz->lock);
device_unregister(&tz->device);
......
......@@ -68,20 +68,6 @@ static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev)
void thermal_cdev_update(struct thermal_cooling_device *);
void __thermal_cdev_update(struct thermal_cooling_device *cdev);
/**
* struct thermal_trip - representation of a point in temperature domain
* @np: pointer to struct device_node that this trip point was created from
* @temperature: temperature value in miliCelsius
* @hysteresis: relative hysteresis in miliCelsius
* @type: trip point type
*/
struct thermal_trip {
struct device_node *np;
int temperature;
int hysteresis;
enum thermal_trip_type type;
};
int get_tz_trend(struct thermal_zone_device *tz, int trip);
struct thermal_instance *
......@@ -126,7 +112,6 @@ int thermal_build_list_of_policies(char *buf);
/* Helpers */
void thermal_zone_set_trips(struct thermal_zone_device *tz);
void thermal_set_delay_jiffies(unsigned long *delay_jiffies, int delay_ms);
/* sysfs I/F */
int thermal_zone_create_device_groups(struct thermal_zone_device *, int);
......
......@@ -39,7 +39,6 @@ int get_tz_trend(struct thermal_zone_device *tz, int trip)
return trend;
}
EXPORT_SYMBOL(get_tz_trend);
struct thermal_instance *
get_thermal_instance(struct thermal_zone_device *tz,
......@@ -90,7 +89,7 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
ret = tz->ops->get_temp(tz, temp);
if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) {
for (count = 0; count < tz->trips; count++) {
for (count = 0; count < tz->num_trips; count++) {
ret = tz->ops->get_trip_type(tz, count, &type);
if (!ret && type == THERMAL_TRIP_CRITICAL) {
ret = tz->ops->get_trip_temp(tz, count,
......@@ -138,7 +137,7 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz)
if (!tz->ops->set_trips || !tz->ops->get_trip_hyst)
goto exit;
for (i = 0; i < tz->trips; i++) {
for (i = 0; i < tz->num_trips; i++) {
int trip_low;
tz->ops->get_trip_temp(tz, i, &trip_temp);
......@@ -175,13 +174,6 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz)
mutex_unlock(&tz->lock);
}
void thermal_set_delay_jiffies(unsigned long *delay_jiffies, int delay_ms)
{
*delay_jiffies = msecs_to_jiffies(delay_ms);
if (delay_ms > 1000)
*delay_jiffies = round_jiffies(*delay_jiffies);
}
static void thermal_cdev_set_cur_state(struct thermal_cooling_device *cdev,
int target)
{
......@@ -228,7 +220,6 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
}
mutex_unlock(&cdev->lock);
}
EXPORT_SYMBOL(thermal_cdev_update);
/**
* thermal_zone_get_slope - return the slope attribute of the thermal zone
......
......@@ -469,7 +469,7 @@ static int thermal_genl_cmd_tz_get_trip(struct param *p)
mutex_lock(&tz->lock);
for (i = 0; i < tz->trips; i++) {
for (i = 0; i < tz->num_trips; i++) {
enum thermal_trip_type type;
int temp, hyst = 0;
......
......@@ -118,12 +118,7 @@ static int of_thermal_set_trips(struct thermal_zone_device *tz,
*/
int of_thermal_get_ntrips(struct thermal_zone_device *tz)
{
struct __thermal_zone *data = tz->devdata;
if (!data || IS_ERR(data))
return -ENODEV;
return data->ntrips;
return tz->num_trips;
}
EXPORT_SYMBOL_GPL(of_thermal_get_ntrips);
......@@ -139,9 +134,7 @@ EXPORT_SYMBOL_GPL(of_thermal_get_ntrips);
*/
bool of_thermal_is_trip_valid(struct thermal_zone_device *tz, int trip)
{
struct __thermal_zone *data = tz->devdata;
if (!data || trip >= data->ntrips || trip < 0)
if (trip >= tz->num_trips || trip < 0)
return false;
return true;
......@@ -161,12 +154,7 @@ EXPORT_SYMBOL_GPL(of_thermal_is_trip_valid);
const struct thermal_trip *
of_thermal_get_trip_points(struct thermal_zone_device *tz)
{
struct __thermal_zone *data = tz->devdata;
if (!data)
return NULL;
return data->trips;
return tz->trips;
}
EXPORT_SYMBOL_GPL(of_thermal_get_trip_points);
......@@ -281,12 +269,10 @@ static int of_thermal_unbind(struct thermal_zone_device *thermal,
static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
enum thermal_trip_type *type)
{
struct __thermal_zone *data = tz->devdata;
if (trip >= data->ntrips || trip < 0)
if (trip >= tz->num_trips || trip < 0)
return -EDOM;
*type = data->trips[trip].type;
*type = tz->trips[trip].type;
return 0;
}
......@@ -294,12 +280,10 @@ static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
int *temp)
{
struct __thermal_zone *data = tz->devdata;
if (trip >= data->ntrips || trip < 0)
if (trip >= tz->num_trips || trip < 0)
return -EDOM;
*temp = data->trips[trip].temperature;
*temp = tz->trips[trip].temperature;
return 0;
}
......@@ -309,7 +293,7 @@ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
{
struct __thermal_zone *data = tz->devdata;
if (trip >= data->ntrips || trip < 0)
if (trip >= tz->num_trips || trip < 0)
return -EDOM;
if (data->ops && data->ops->set_trip_temp) {
......@@ -321,7 +305,7 @@ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
}
/* thermal framework should take care of data->mask & (1 << trip) */
data->trips[trip].temperature = temp;
tz->trips[trip].temperature = temp;
return 0;
}
......@@ -329,12 +313,10 @@ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
int *hyst)
{
struct __thermal_zone *data = tz->devdata;
if (trip >= data->ntrips || trip < 0)
if (trip >= tz->num_trips || trip < 0)
return -EDOM;
*hyst = data->trips[trip].hysteresis;
*hyst = tz->trips[trip].hysteresis;
return 0;
}
......@@ -342,13 +324,11 @@ static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
int hyst)
{
struct __thermal_zone *data = tz->devdata;
if (trip >= data->ntrips || trip < 0)
if (trip >= tz->num_trips || trip < 0)
return -EDOM;
/* thermal framework should take care of data->mask & (1 << trip) */
data->trips[trip].hysteresis = hyst;
tz->trips[trip].hysteresis = hyst;
return 0;
}
......@@ -356,12 +336,11 @@ static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
int *temp)
{
struct __thermal_zone *data = tz->devdata;
int i;
for (i = 0; i < data->ntrips; i++)
if (data->trips[i].type == THERMAL_TRIP_CRITICAL) {
*temp = data->trips[i].temperature;
for (i = 0; i < tz->num_trips; i++)
if (tz->trips[i].type == THERMAL_TRIP_CRITICAL) {
*temp = tz->trips[i].temperature;
return 0;
}
......@@ -671,6 +650,35 @@ EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_unregister);
/*** functions parsing device tree nodes ***/
static int of_find_trip_id(struct device_node *np, struct device_node *trip)
{
struct device_node *trips;
struct device_node *t;
int i = 0;
trips = of_get_child_by_name(np, "trips");
if (!trips) {
pr_err("Failed to find 'trips' node\n");
return -EINVAL;
}
/*
* Find the trip id point associated with the cooling device map
*/
for_each_child_of_node(trips, t) {
if (t == trip)
goto out;
i++;
}
i = -ENXIO;
out:
of_node_put(trips);
return i;
}
/**
* thermal_of_populate_bind_params - parse and fill cooling map data
* @np: DT node containing a cooling-map node
......@@ -685,15 +693,15 @@ EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_unregister);
*
* Return: 0 on success, proper error code otherwise
*/
static int thermal_of_populate_bind_params(struct device_node *np,
struct __thermal_bind_params *__tbp,
struct thermal_trip *trips,
int ntrips)
static int thermal_of_populate_bind_params(struct device_node *tz_np,
struct device_node *np,
struct __thermal_bind_params *__tbp)
{
struct of_phandle_args cooling_spec;
struct __thermal_cooling_bind_param *__tcbp;
struct device_node *trip;
int ret, i, count;
int trip_id;
u32 prop;
/* Default weight. Usage is optional */
......@@ -708,18 +716,14 @@ static int thermal_of_populate_bind_params(struct device_node *np,
return -ENODEV;
}
/* match using device_node */
for (i = 0; i < ntrips; i++)
if (trip == trips[i].np) {
__tbp->trip_id = i;
break;
}
if (i == ntrips) {
ret = -ENODEV;
trip_id = of_find_trip_id(tz_np, trip);
if (trip_id < 0) {
ret = trip_id;
goto end;
}
__tbp->trip_id = trip_id;
count = of_count_phandle_with_args(np, "cooling-device",
"#cooling-cells");
if (count <= 0) {
......@@ -843,13 +847,56 @@ static int thermal_of_populate_trip(struct device_node *np,
return ret;
}
/* Required for cooling map matching */
trip->np = np;
of_node_get(np);
return 0;
}
static struct thermal_trip *thermal_of_trips_init(struct device_node *np, int *ntrips)
{
struct thermal_trip *tt;
struct device_node *trips, *trip;
int ret, count;
trips = of_get_child_by_name(np, "trips");
if (!trips) {
pr_err("Failed to find 'trips' node\n");
return ERR_PTR(-EINVAL);
}
count = of_get_child_count(trips);
if (!count) {
pr_err("No trip point defined\n");
ret = -EINVAL;
goto out_of_node_put;
}
tt = kzalloc(sizeof(*tt) * count, GFP_KERNEL);
if (!tt) {
ret = -ENOMEM;
goto out_of_node_put;
}
*ntrips = count;
count = 0;
for_each_child_of_node(trips, trip) {
ret = thermal_of_populate_trip(trip, &tt[count++]);
if (ret)
goto out_kfree;
}
of_node_put(trips);
return tt;
out_kfree:
kfree(tt);
*ntrips = 0;
out_of_node_put:
of_node_put(trips);
return ERR_PTR(ret);
}
/**
* thermal_of_build_thermal_zone - parse and fill one thermal zone data
* @np: DT node containing a thermal zone node
......@@ -909,32 +956,12 @@ __init *thermal_of_build_thermal_zone(struct device_node *np)
tz->offset = 0;
}
/* trips */
child = of_get_child_by_name(np, "trips");
/* No trips provided */
if (!child)
tz->trips = thermal_of_trips_init(np, &tz->ntrips);
if (IS_ERR(tz->trips)) {
ret = PTR_ERR(tz->trips);
goto finish;
tz->ntrips = of_get_child_count(child);
if (tz->ntrips == 0) /* must have at least one child */
goto finish;
tz->trips = kcalloc(tz->ntrips, sizeof(*tz->trips), GFP_KERNEL);
if (!tz->trips) {
ret = -ENOMEM;
goto free_tz;
}
i = 0;
for_each_child_of_node(child, gchild) {
ret = thermal_of_populate_trip(gchild, &tz->trips[i++]);
if (ret)
goto free_trips;
}
of_node_put(child);
/* cooling-maps */
child = of_get_child_by_name(np, "cooling-maps");
......@@ -954,10 +981,11 @@ __init *thermal_of_build_thermal_zone(struct device_node *np)
i = 0;
for_each_child_of_node(child, gchild) {
ret = thermal_of_populate_bind_params(gchild, &tz->tbps[i++],
tz->trips, tz->ntrips);
if (ret)
ret = thermal_of_populate_bind_params(np, gchild, &tz->tbps[i++]);
if (ret) {
of_node_put(gchild);
goto free_tbps;
}
}
finish:
......@@ -978,10 +1006,7 @@ __init *thermal_of_build_thermal_zone(struct device_node *np)
kfree(tz->tbps);
free_trips:
for (i = 0; i < tz->ntrips; i++)
of_node_put(tz->trips[i].np);
kfree(tz->trips);
of_node_put(gchild);
free_tz:
kfree(tz);
of_node_put(child);
......@@ -1004,8 +1029,6 @@ static __init void of_thermal_free_zone(struct __thermal_zone *tz)
}
kfree(tz->tbps);
for (i = 0; i < tz->ntrips; i++)
of_node_put(tz->trips[i].np);
kfree(tz->trips);
kfree(tz);
}
......@@ -1103,11 +1126,9 @@ int __init of_parse_thermal_zones(void)
tzp->slope = tz->slope;
tzp->offset = tz->offset;
zone = thermal_zone_device_register(child->name, tz->ntrips,
mask, tz,
ops, tzp,
tz->passive_delay,
tz->polling_delay);
zone = thermal_zone_device_register_with_trips(child->name, tz->trips, tz->ntrips,
mask, tz, ops, tzp, tz->passive_delay,
tz->polling_delay);
if (IS_ERR(zone)) {
pr_err("Failed to build %pOFn zone %ld\n", child,
PTR_ERR(zone));
......
......@@ -416,15 +416,15 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
int indx;
/* This function works only for zones with at least one trip */
if (tz->trips <= 0)
if (tz->num_trips <= 0)
return -EINVAL;
tz->trip_type_attrs = kcalloc(tz->trips, sizeof(*tz->trip_type_attrs),
tz->trip_type_attrs = kcalloc(tz->num_trips, sizeof(*tz->trip_type_attrs),
GFP_KERNEL);
if (!tz->trip_type_attrs)
return -ENOMEM;
tz->trip_temp_attrs = kcalloc(tz->trips, sizeof(*tz->trip_temp_attrs),
tz->trip_temp_attrs = kcalloc(tz->num_trips, sizeof(*tz->trip_temp_attrs),
GFP_KERNEL);
if (!tz->trip_temp_attrs) {
kfree(tz->trip_type_attrs);
......@@ -432,7 +432,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
}
if (tz->ops->get_trip_hyst) {
tz->trip_hyst_attrs = kcalloc(tz->trips,
tz->trip_hyst_attrs = kcalloc(tz->num_trips,
sizeof(*tz->trip_hyst_attrs),
GFP_KERNEL);
if (!tz->trip_hyst_attrs) {
......@@ -442,7 +442,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
}
}
attrs = kcalloc(tz->trips * 3 + 1, sizeof(*attrs), GFP_KERNEL);
attrs = kcalloc(tz->num_trips * 3 + 1, sizeof(*attrs), GFP_KERNEL);
if (!attrs) {
kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs);
......@@ -451,7 +451,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
return -ENOMEM;
}
for (indx = 0; indx < tz->trips; indx++) {
for (indx = 0; indx < tz->num_trips; indx++) {
/* create trip type attribute */
snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
"trip_point_%d_type", indx);
......@@ -478,7 +478,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
tz->trip_temp_attrs[indx].attr.store =
trip_point_temp_store;
}
attrs[indx + tz->trips] = &tz->trip_temp_attrs[indx].attr.attr;
attrs[indx + tz->num_trips] = &tz->trip_temp_attrs[indx].attr.attr;
/* create Optional trip hyst attribute */
if (!tz->ops->get_trip_hyst)
......@@ -496,10 +496,10 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
tz->trip_hyst_attrs[indx].attr.store =
trip_point_hyst_store;
}
attrs[indx + tz->trips * 2] =
attrs[indx + tz->num_trips * 2] =
&tz->trip_hyst_attrs[indx].attr.attr;
}
attrs[tz->trips * 3] = NULL;
attrs[tz->num_trips * 3] = NULL;
tz->trips_attribute_group.attrs = attrs;
......@@ -540,7 +540,7 @@ int thermal_zone_create_device_groups(struct thermal_zone_device *tz,
for (i = 0; i < size - 2; i++)
groups[i] = thermal_zone_attribute_groups[i];
if (tz->trips) {
if (tz->num_trips) {
result = create_trip_attrs(tz, mask);
if (result) {
kfree(groups);
......@@ -561,7 +561,7 @@ void thermal_zone_destroy_device_groups(struct thermal_zone_device *tz)
if (!tz)
return;
if (tz->trips)
if (tz->num_trips)
destroy_trip_attrs(tz);
kfree(tz->device.groups);
......
......@@ -226,7 +226,7 @@ static irqreturn_t ti_bandgap_talert_irq_handler(int irq, void *data)
/*
* One TALERT interrupt: Two sources
* If the interrupt is due to t_hot then mask t_hot and
* and unmask t_cold else mask t_cold and unmask t_hot
* unmask t_cold else mask t_cold and unmask t_hot
*/
if (t_hot) {
ctrl &= ~tsr->mask_hot_mask;
......
......@@ -40,8 +40,6 @@ enum thermal_trend {
THERMAL_TREND_STABLE, /* temperature is stable */
THERMAL_TREND_RAISING, /* temperature is raising */
THERMAL_TREND_DROPPING, /* temperature is dropping */
THERMAL_TREND_RAISE_FULL, /* apply highest cooling action */
THERMAL_TREND_DROP_FULL, /* apply lowest cooling action */
};
/* Thermal notification reason */
......@@ -80,6 +78,18 @@ struct thermal_zone_device_ops {
void (*critical)(struct thermal_zone_device *);
};
/**
* struct thermal_trip - representation of a point in temperature domain
* @temperature: temperature value in miliCelsius
* @hysteresis: relative hysteresis in miliCelsius
* @type: trip point type
*/
struct thermal_trip {
int temperature;
int hysteresis;
enum thermal_trip_type type;
};
struct thermal_cooling_device_ops {
int (*get_max_state) (struct thermal_cooling_device *, unsigned long *);
int (*get_cur_state) (struct thermal_cooling_device *, unsigned long *);
......@@ -113,7 +123,8 @@ struct thermal_cooling_device {
* @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis
* @mode: current mode of this thermal zone
* @devdata: private pointer for device private data
* @trips: number of trip points the thermal zone supports
* @trips: an array of struct thermal_trip
* @num_trips: number of trip points the thermal zone supports
* @trips_disabled; bitmap for disabled trips
* @passive_delay_jiffies: number of jiffies to wait between polls when
* performing passive cooling.
......@@ -153,7 +164,8 @@ struct thermal_zone_device {
struct thermal_attr *trip_hyst_attrs;
enum thermal_device_mode mode;
void *devdata;
int trips;
struct thermal_trip *trips;
int num_trips;
unsigned long trips_disabled; /* bitmap for disabled trips */
unsigned long passive_delay_jiffies;
unsigned long polling_delay_jiffies;
......@@ -366,8 +378,14 @@ void devm_thermal_zone_of_sensor_unregister(struct device *dev,
struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
void *, struct thermal_zone_device_ops *,
struct thermal_zone_params *, int, int);
void thermal_zone_device_unregister(struct thermal_zone_device *);
struct thermal_zone_device *
thermal_zone_device_register_with_trips(const char *, struct thermal_trip *, int, int,
void *, struct thermal_zone_device_ops *,
struct thermal_zone_params *, int, int);
int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
struct thermal_cooling_device *,
unsigned long, unsigned long,
......
......@@ -92,34 +92,22 @@ TRACE_EVENT(thermal_zone_trip,
);
#ifdef CONFIG_CPU_THERMAL
TRACE_EVENT(thermal_power_cpu_get_power,
TP_PROTO(const struct cpumask *cpus, unsigned long freq, u32 *load,
size_t load_len, u32 dynamic_power),
TRACE_EVENT(thermal_power_cpu_get_power_simple,
TP_PROTO(int cpu, u32 power),
TP_ARGS(cpus, freq, load, load_len, dynamic_power),
TP_ARGS(cpu, power),
TP_STRUCT__entry(
__bitmask(cpumask, num_possible_cpus())
__field(unsigned long, freq )
__dynamic_array(u32, load, load_len)
__field(size_t, load_len )
__field(u32, dynamic_power )
__field(int, cpu)
__field(u32, power)
),
TP_fast_assign(
__assign_bitmask(cpumask, cpumask_bits(cpus),
num_possible_cpus());
__entry->freq = freq;
memcpy(__get_dynamic_array(load), load,
load_len * sizeof(*load));
__entry->load_len = load_len;
__entry->dynamic_power = dynamic_power;
__entry->cpu = cpu;
__entry->power = power;
),
TP_printk("cpus=%s freq=%lu load={%s} dynamic_power=%d",
__get_bitmask(cpumask), __entry->freq,
__print_array(__get_dynamic_array(load), __entry->load_len, 4),
__entry->dynamic_power)
TP_printk("cpu=%d power=%u", __entry->cpu, __entry->power)
);
TRACE_EVENT(thermal_power_cpu_limit,
......
......@@ -27,7 +27,7 @@
/**************************************************************************
* PID (Proportional-Integral-Derivative) controller is commonly used in
* linear control system, consider the the process.
* linear control system, consider the process.
* G(s) = U(s)/E(s)
* kp = proportional gain
* ki = integral gain
......
......@@ -27,6 +27,9 @@
#define NR_LINES_TZDATA 1
#define TMON_LOG_FILE "/var/tmp/tmon.log"
#include <sys/time.h>
#include <pthread.h>
extern unsigned long ticktime;
extern double time_elapsed;
extern unsigned long target_temp_user;
......
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