diff options
31 files changed, 387 insertions, 430 deletions
diff --git a/Documentation/devicetree/bindings/thermal/qcom,spmi-temp-alarm.yaml b/Documentation/devicetree/bindings/thermal/qcom,spmi-temp-alarm.yaml new file mode 100644 index 000000000000..5f08b6e59b8a --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/qcom,spmi-temp-alarm.yaml @@ -0,0 +1,85 @@ +# 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"; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/thermal/qcom-spmi-temp-alarm.txt b/Documentation/devicetree/bindings/thermal/qcom-spmi-temp-alarm.txt deleted file mode 100644 index 2d5b2ad03314..000000000000 --- a/Documentation/devicetree/bindings/thermal/qcom-spmi-temp-alarm.txt +++ /dev/null @@ -1,51 +0,0 @@ -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"; - }; - }; - }; - }; - diff --git a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml index 1368d90da0e8..0f05f5c886c5 100644 --- a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml @@ -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 diff --git a/MAINTAINERS b/MAINTAINERS index f679152bdbad..045e09c902a8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19893,6 +19893,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 diff --git a/drivers/thermal/cpufreq_cooling.c b/drivers/thermal/cpufreq_cooling.c index b8151d95a806..50f8b90abba6 100644 --- a/drivers/thermal/cpufreq_cooling.c +++ b/drivers/thermal/cpufreq_cooling.c @@ -59,6 +59,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 * @@ -71,6 +72,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 @@ -204,7 +206,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) @@ -214,16 +216,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; @@ -233,22 +228,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; } @@ -263,9 +249,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) @@ -295,15 +280,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) @@ -415,7 +396,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) @@ -434,7 +415,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) @@ -485,14 +466,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 @@ -501,7 +474,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. * @@ -554,7 +527,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)) { @@ -609,8 +585,8 @@ free_cdev: * @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(). @@ -627,17 +603,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. */ @@ -673,7 +646,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) { diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c index 21d4d6e6409a..121cf853e545 100644 --- a/drivers/thermal/db8500_thermal.c +++ b/drivers/thermal/db8500_thermal.c @@ -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; diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c index 8c76f9655e57..67b618b1afc8 100644 --- a/drivers/thermal/devfreq_cooling.c +++ b/drivers/thermal/devfreq_cooling.c @@ -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; @@ -290,12 +292,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. @@ -363,18 +359,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; @@ -437,8 +433,6 @@ free_table: kfree(dfc->freq_table); free_dfc: kfree(dfc); -free_ops: - kfree(ops); return ERR_PTR(err); } @@ -520,13 +514,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; @@ -537,6 +529,5 @@ void devfreq_cooling_unregister(struct thermal_cooling_device *cdev) kfree(dfc->freq_table); kfree(dfc); - kfree(ops); } EXPORT_SYMBOL_GPL(devfreq_cooling_unregister); diff --git a/drivers/thermal/gov_fair_share.c b/drivers/thermal/gov_fair_share.c index 1e5abf4822be..6a2abcfc648f 100644 --- a/drivers/thermal/gov_fair_share.c +++ b/drivers/thermal/gov_fair_share.c @@ -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); } /** diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c index 13e375751d22..1d5052470967 100644 --- a/drivers/thermal/gov_power_allocator.c +++ b/drivers/thermal/gov_power_allocator.c @@ -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); diff --git a/drivers/thermal/gov_step_wise.c b/drivers/thermal/gov_step_wise.c index 12acb12aac50..9729b46d0258 100644 --- a/drivers/thermal/gov_step_wise.c +++ b/drivers/thermal/gov_step_wise.c @@ -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; } diff --git a/drivers/thermal/k3_j72xx_bandgap.c b/drivers/thermal/k3_j72xx_bandgap.c index 64e323158952..115a44eb4fbf 100644 --- a/drivers/thermal/k3_j72xx_bandgap.c +++ b/drivers/thermal/k3_j72xx_bandgap.c @@ -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, }; diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c index d9c9c975f931..073943cbcc2b 100644 --- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c +++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c @@ -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; diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c index 7419e196dbb0..770f82cc9bca 100644 --- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c +++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c @@ -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) diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 7963ee33bf75..e49f58e83513 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -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, }; diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index 1471a2c00f15..ba05c8233356 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -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) \ diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 43eb25b167bc..e2020c6308cc 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -507,7 +507,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; } @@ -529,7 +529,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) { diff --git a/drivers/thermal/rzg2l_thermal.c b/drivers/thermal/rzg2l_thermal.c index be07e04c6926..51ae80eda6af 100644 --- a/drivers/thermal/rzg2l_thermal.c +++ b/drivers/thermal/rzg2l_thermal.c @@ -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; diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index d9cd23cbb671..212c87e63a66 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -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. diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 210325f92559..825eab526619 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c @@ -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, }; diff --git a/drivers/thermal/tegra/tegra30-tsensor.c b/drivers/thermal/tegra/tegra30-tsensor.c index 9b6b693cbcf8..05886684f429 100644 --- a/drivers/thermal/tegra/tegra30-tsensor.c +++ b/drivers/thermal/tegra/tegra30-tsensor.c @@ -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; diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 4c11a7965979..6a5d0ae5d7a4 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -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) { @@ -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; @@ -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); } @@ -1159,10 +1155,18 @@ exit: 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 @@ exit: * 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); @@ -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) @@ -1324,6 +1329,16 @@ 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); /** diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 726e327b4205..c991bb290512 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -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); diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c index 3edd047e144f..690890f054a3 100644 --- a/drivers/thermal/thermal_helpers.c +++ b/drivers/thermal/thermal_helpers.c @@ -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 @@ exit: 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 diff --git a/drivers/thermal/thermal_netlink.c b/drivers/thermal/thermal_netlink.c index 32fea5174cc0..050d243a5fa1 100644 --- a/drivers/thermal/thermal_netlink.c +++ b/drivers/thermal/thermal_netlink.c @@ -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; diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index b65d435cb92f..802c30b72a92 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -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 @@ free_tbps: 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)); diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index 1c4aac8464a7..5018459e8dd9 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -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); diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index ea0603b59309..67050a1a5b07 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -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; diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 365733b428d8..1386c713885d 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -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, diff --git a/include/trace/events/thermal.h b/include/trace/events/thermal.h index 8a5f04888abd..e58bf3072f32 100644 --- a/include/trace/events/thermal.h +++ b/include/trace/events/thermal.h @@ -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, diff --git a/tools/thermal/tmon/pid.c b/tools/thermal/tmon/pid.c index 296f69c00c57..da20088285bd 100644 --- a/tools/thermal/tmon/pid.c +++ b/tools/thermal/tmon/pid.c @@ -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 diff --git a/tools/thermal/tmon/tmon.h b/tools/thermal/tmon/tmon.h index c9066ec104dd..44d16d778f04 100644 --- a/tools/thermal/tmon/tmon.h +++ b/tools/thermal/tmon/tmon.h @@ -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; |