Thermal control updates for 5.16-rc1

- Constify a variable in thermal MMIO driver (Rikard Falkeborn).
 
  - Add the current temperature in the netlink message when crossing a
    trip point in order to prevent useless back and forth reading from
    userspace (Daniel Lezcano).
 
  - Add support for the 'HC' variant on PM8998 PMIC in order to support
    VADC channels on recent QCom boards (Bjorn Andersson).
 
  - Add support for calibration values from hardware when they are
    fused (Niklas Söderlund).
 
  - Fix NULL pointer dereference in the thermal_release callback when
    an error occurs in the thermal_zone_device_register() (Yuanzheng
    Song).
 
  - Fix use-after-free in __thermal_cooling_device_register() in the
    error path (Ziyang Xuan).
 
  - Fix compilation of the LMh driver when CONFIG_QCOM_SCM is not set
    (Jackie Liu).
 
  - Add timeout when reading a register that can block forever in
    certain circumstances in the tsens driver (Ansuel Smith).
 
  - Add DT binding for the reset lines and use them in the rockchip
    sensor driver (Johan Jonker).
 
  - Add new uniphier NX1 SoC temperature sensor (Kunihiko Hayashi).
 
  - Save and restore the TCC value in the int340x driver (Antoine
    Tenart).
 
  - Deprecate the writability of the cooling device state sysfs file
    and the user space governor (Daniel Lezcano).
 
  - Delete bogus length check in int340x (Dan Carpenter).
 
  - Use bitmap_zalloc/bitmap_free when applicable in intel_powerclamp
    (Christophe JAILLET).
 
  - Move thermal ABI documentation to Documentation/ABI (Mauro Carvalho
    Chehab).
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAmGBkrwSHHJqd0Byand5
 c29ja2kubmV0AAoJEILEb/54YlRxAXcQAJQC2NOxDrN+QxDiWUW67xUpxg9rcWxg
 pXHq5I9jutk0FqFD0Jky+Qz8ptLOVeColgwaW0GBUWVVWsrsd+Vh091jyN0dfTLz
 Rw6bqsr+N7M5U10uTBOnz7CyIZCLAFpwRbi9/NfzhV2MqwlCMnh+b/GLZzqHoHoh
 2O9rs3SMdYdWatkRuWA5T1EA9+rIKOR1BV+WMQBaF7lUIcL2xcrFUl1lNG2v4GHz
 pjVHoSyexvZyRxqWXH+jq5yl3EEhs4PuTnprQMO2Y+ly0NbKXKE2izihLuGTCRUE
 f5ToXxJRGwl6eQYXIG/IyN01tIXCNQ5e4q4wTN0CLtLOtHkypA7fwJzOJMTZANmv
 PRhx4IPHy1jax7qAoMEUdtDQTVpf9i1oKrk66Ei+FQX7E5R3HeTuLxScq7W9yDu7
 B7jMnqXLFbUcxrAdKA5R9vKc03/QjsOxZHElK41bAdxR6/KqqAtl5fVOhpp5+LtB
 HfFU6NDk/R/6BouhcfV98/ndbICKUQZiifEWz2QToVD5uf07vNp9ZXKz3NIRdgXR
 n/0LsoLAodrllVG/hWy1vLAZYbNuGwOZsnSyh+zAprsKhWzNMAeWfizJzXzl9fjZ
 +PfyMITcd/Mne7jhzz8AXx+eZBy7SltZxDI46c5/y6AEqhgm3micpaKIXs8jhl8/
 Xn9o4RCDN0sf
 =UBs9
 -----END PGP SIGNATURE-----

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

Pull thermal control updates from Rafael Wysocki:
 "These extend the thermal trip point crossing notifications sent via
  netlink to contain the temperature causing the trip point to be
  crossed, deprecate the user space thermal governor, add new DT
  bindings to drivers, move ABI documentation to Documentation/ABI, fix
  assorted issues and clean up code.

  Specifics:

   - Constify a variable in thermal MMIO driver (Rikard Falkeborn).

   - Add the current temperature in the netlink message when crossing a
     trip point in order to prevent useless back and forth reading from
     userspace (Daniel Lezcano).

   - Add support for the 'HC' variant on PM8998 PMIC in order to support
     VADC channels on recent QCom boards (Bjorn Andersson).

   - Add support for calibration values from hardware when they are
     fused (Niklas Söderlund).

   - Fix NULL pointer dereference in the thermal_release callback when
     an error occurs in the thermal_zone_device_register() (Yuanzheng
     Song).

   - Fix use-after-free in __thermal_cooling_device_register() in the
     error path (Ziyang Xuan).

   - Fix compilation of the LMh driver when CONFIG_QCOM_SCM is not set
     (Jackie Liu).

   - Add timeout when reading a register that can block forever in
     certain circumstances in the tsens driver (Ansuel Smith).

   - Add DT binding for the reset lines and use them in the rockchip
     sensor driver (Johan Jonker).

   - Add new uniphier NX1 SoC temperature sensor (Kunihiko Hayashi).

   - Save and restore the TCC value in the int340x driver (Antoine
     Tenart).

   - Deprecate the writability of the cooling device state sysfs file
     and the user space governor (Daniel Lezcano).

   - Delete bogus length check in int340x (Dan Carpenter).

   - Use bitmap_zalloc/bitmap_free when applicable in intel_powerclamp
     (Christophe JAILLET).

   - Move thermal ABI documentation to Documentation/ABI (Mauro Carvalho
     Chehab)"

* tag 'thermal-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (21 commits)
  thermal/core: Deprecate changing cooling device state from userspace
  thermal/core: Make the userspace governor deprecated
  thermal/drivers/int340x: Improve the tcc offset saving for suspend/resume
  thermal/drivers/uniphier: Add compatible string for NX1 SoC
  dt-bindings: thermal: uniphier: Add binding for NX1 SoC
  thermal/drivers/rockchip_thermal: Allow more resets for tsadc node
  dt-bindings: thermal: remove redundant comments from rockchip-thermal.yaml
  dt-bindings: thermal: allow more resets for tsadc node in rockchip-thermal.yaml
  thermal/drivers/tsens: Add timeout to get_temp_tsens_valid
  thermal/drivers/qcom/lmh: make QCOM_LMH depends on QCOM_SCM
  thermal/core: fix a UAF bug in __thermal_cooling_device_register()
  thermal/core: Fix null pointer dereference in thermal_release()
  thermal: rcar_gen3_thermal: Read calibration from hardware
  thermal: rcar_gen3_thermal: Store thcode and ptat in priv data
  thermal/drivers/qcom/spmi-adc-tm5: Add support for HC variant
  dt-bindings: thermal: qcom: add HC variant of adc-thermal monitor bindings
  thermal: Move ABI documentation to Documentation/ABI
  thermal/drivers/netlink: Add the temperature when crossing a trip point
  thermal/drivers/thermal_mmio: Constify static struct thermal_mmio_ops
  thermal: int340x: delete bogus length check
  ...
This commit is contained in:
Linus Torvalds 2021-11-02 16:18:04 -07:00
Родитель 833db72142 46e9f92f31
Коммит f73cd9c951
25 изменённых файлов: 679 добавлений и 314 удалений

Просмотреть файл

@ -0,0 +1,259 @@
What: /sys/class/thermal/thermal_zoneX/type
Description:
Strings which represent the thermal zone type.
This is given by thermal zone driver as part of registration.
E.g: "acpitz" indicates it's an ACPI thermal device.
In order to keep it consistent with hwmon sys attribute; this
shouldbe a short, lowercase string, not containing spaces nor
dashes.
RO, Required
What: /sys/class/thermal/thermal_zoneX/temp
Description:
Current temperature as reported by thermal zone (sensor).
Unit: millidegree Celsius
RO, Required
What: /sys/class/thermal/thermal_zoneX/mode
Description:
One of the predefined values in [enabled, disabled].
This file gives information about the algorithm that is
currently managing the thermal zone. It can be either default
kernel based algorithm or user space application.
enabled
enable Kernel Thermal management.
disabled
Preventing kernel thermal zone driver actions upon
trip points so that user application can take full
charge of the thermal management.
RW, Optional
What: /sys/class/thermal/thermal_zoneX/policy
Description:
One of the various thermal governors used for a particular zone.
RW, Required
What: /sys/class/thermal/thermal_zoneX/available_policies
Description:
Available thermal governors which can be used for a
particular zone.
RO, Required
What: /sys/class/thermal/thermal_zoneX/trip_point_Y_temp
Description:
The temperature above which trip point will be fired.
Unit: millidegree Celsius
RO, Optional
What: /sys/class/thermal/thermal_zoneX/trip_point_Y_type
Description:
Strings which indicate the type of the trip point.
E.g. it can be one of critical, hot, passive, `active[0-*]`
for ACPI thermal zone.
RO, Optional
What: /sys/class/thermal/thermal_zoneX/trip_point_Y_hyst
Description:
The hysteresis value for a trip point, represented as an
integer.
Unit: Celsius
RW, Optional
What: /sys/class/thermal/thermal_zoneX/cdevY
Description:
Sysfs link to the thermal cooling device node where the sys I/F
for cooling device throttling control represents.
RO, Optional
What: /sys/class/thermal/thermal_zoneX/cdevY_trip_point
Description:
The trip point in this thermal zone which `cdev[0-*]` is
associated with; -1 means the cooling device is not
associated with any trip point.
RO, Optional
What: /sys/class/thermal/thermal_zoneX/cdevY_weight
Description:
The influence of `cdev[0-*]` in this thermal zone. This value
is relative to the rest of cooling devices in the thermal
zone. For example, if a cooling device has a weight double
than that of other, it's twice as effective in cooling the
thermal zone.
RW, Optional
What: /sys/class/thermal/thermal_zoneX/emul_temp
Description:
Interface to set the emulated temperature method in thermal zone
(sensor). After setting this temperature, the thermal zone may
pass this temperature to platform emulation function if
registered or cache it locally. This is useful in debugging
different temperature threshold and its associated cooling
action. This is write only node and writing 0 on this node
should disable emulation.
Unit: millidegree Celsius
WO, Optional
WARNING:
Be careful while enabling this option on production systems,
because userland can easily disable the thermal policy by simply
flooding this sysfs node with low temperature values.
What: /sys/class/thermal/thermal_zoneX/k_d
Description:
The derivative term of the power allocator governor's PID
controller. For more information see
Documentation/driver-api/thermal/power_allocator.rst
RW, Optional
What: /sys/class/thermal/thermal_zoneX/k_i
Description:
The integral term of the power allocator governor's PID
controller. This term allows the PID controller to compensate
for long term drift. For more information see
Documentation/driver-api/thermal/power_allocator.rst
RW, Optional
What: /sys/class/thermal/thermal_zoneX/k_po
Description:
The proportional term of the power allocator governor's PID
controller during temperature overshoot. Temperature overshoot
is when the current temperature is above the "desired
temperature" trip point. For more information see
Documentation/driver-api/thermal/power_allocator.rst
RW, Optional
What: /sys/class/thermal/thermal_zoneX/k_pu
Description:
The proportional term of the power allocator governor's PID
controller during temperature undershoot. Temperature undershoot
is when the current temperature is below the "desired
temperature" trip point. For more information see
Documentation/driver-api/thermal/power_allocator.rst
RW, Optional
What: /sys/class/thermal/thermal_zoneX/integral_cutoff
Description:
Temperature offset from the desired temperature trip point
above which the integral term of the power allocator
governor's PID controller starts accumulating errors. For
example, if integral_cutoff is 0, then the integral term only
accumulates error when temperature is above the desired
temperature trip point. For more information see
Documentation/driver-api/thermal/power_allocator.rst
Unit: millidegree Celsius
RW, Optional
What: /sys/class/thermal/thermal_zoneX/slope
Description:
The slope constant used in a linear extrapolation model
to determine a hotspot temperature based off the sensor's
raw readings. It is up to the device driver to determine
the usage of these values.
RW, Optional
What: /sys/class/thermal/thermal_zoneX/offset
Description:
The offset constant used in a linear extrapolation model
to determine a hotspot temperature based off the sensor's
raw readings. It is up to the device driver to determine
the usage of these values.
RW, Optional
What: /sys/class/thermal/thermal_zoneX/sustainable_power
Description:
An estimate of the sustained power that can be dissipated by
the thermal zone. Used by the power allocator governor. For
more information see
Documentation/driver-api/thermal/power_allocator.rst
Unit: milliwatts
RW, Optional
What: /sys/class/thermal/cooling_deviceX/type
Description:
String which represents the type of device, e.g:
- for generic ACPI: should be "Fan", "Processor" or "LCD"
- for memory controller device on intel_menlow platform:
should be "Memory controller".
RO, Required
What: /sys/class/thermal/cooling_deviceX/max_state
Description:
The maximum permissible cooling state of this cooling device.
RO, Required
What: /sys/class/thermal/cooling_deviceX/cur_state
Description:
The current cooling state of this cooling device.
The value can any integer numbers between 0 and max_state:
- cur_state == 0 means no cooling
- cur_state == max_state means the maximum cooling.
RW, Required
What: /sys/class/thermal/cooling_deviceX/stats/reset
Description:
Writing any value resets the cooling device's statistics.
WO, Required
What: /sys/class/thermal/cooling_deviceX/stats/time_in_state_ms:
Description:
The amount of time spent by the cooling device in various
cooling states. The output will have "<state> <time>" pair
in each line, which will mean this cooling device spent <time>
msec of time at <state>.
Output will have one line for each of the supported states.
RO, Required
What: /sys/class/thermal/cooling_deviceX/stats/total_trans
Description:
A single positive value showing the total number of times
the state of a cooling device is changed.
RO, Required
What: /sys/class/thermal/cooling_deviceX/stats/trans_table
Description:
This gives fine grained information about all the cooling state
transitions. The cat output here is a two dimensional matrix,
where an entry <i,j> (row i, column j) represents the number
of transitions from State_i to State_j. If the transition
table is bigger than PAGE_SIZE, reading this will return
an -EFBIG error.
RO, Required

Просмотреть файл

@ -0,0 +1,149 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/thermal/qcom-spmi-adc-tm-hc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm's SPMI PMIC ADC HC Thermal Monitoring
maintainers:
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
properties:
compatible:
const: qcom,spmi-adc-tm-hc
reg:
maxItems: 1
interrupts:
maxItems: 1
"#thermal-sensor-cells":
const: 1
description:
Number of cells required to uniquely identify the thermal sensors. Since
we have multiple sensors this is set to 1
"#address-cells":
const: 1
"#size-cells":
const: 0
qcom,avg-samples:
$ref: /schemas/types.yaml#/definitions/uint32
description: Number of samples to be used for measurement.
enum:
- 1
- 2
- 4
- 8
- 16
default: 1
qcom,decimation:
$ref: /schemas/types.yaml#/definitions/uint32
description: This parameter is used to decrease ADC sampling rate.
Quicker measurements can be made by reducing decimation ratio.
enum:
- 256
- 512
- 1024
default: 1024
patternProperties:
"^([-a-z0-9]*)@[0-7]$":
type: object
description:
Represent one thermal sensor.
properties:
reg:
description: Specify the sensor channel. There are 8 channels in PMIC5's ADC TM
minimum: 0
maximum: 7
io-channels:
description:
From common IIO binding. Used to pipe PMIC ADC channel to thermal monitor
qcom,ratiometric:
$ref: /schemas/types.yaml#/definitions/flag
description:
Channel calibration type.
If this property is specified VADC will use the VDD reference
(1.875V) and GND for channel calibration. If property is not found,
channel will be calibrated with 0V and 1.25V reference channels,
also known as absolute calibration.
qcom,hw-settle-time-us:
description: Time between AMUX getting configured and the ADC starting conversion.
enum: [0, 100, 200, 300, 400, 500, 600, 700, 1000, 2000, 4000, 6000, 8000, 10000]
qcom,pre-scaling:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: Used for scaling the channel input signal before the
signal is fed to VADC. The configuration for this node is to know the
pre-determined ratio and use it for post scaling. It is a pair of
integers, denoting the numerator and denominator of the fraction by
which input signal is multiplied. For example, <1 3> indicates the
signal is scaled down to 1/3 of its value before ADC measurement. If
property is not found default value depending on chip will be used.
items:
- const: 1
- enum: [ 1, 3, 4, 6, 20, 8, 10 ]
required:
- reg
- io-channels
additionalProperties:
false
required:
- compatible
- reg
- interrupts
- "#address-cells"
- "#size-cells"
- "#thermal-sensor-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/iio/qcom,spmi-vadc.h>
#include <dt-bindings/interrupt-controller/irq.h>
spmi_bus {
#address-cells = <1>;
#size-cells = <0>;
pm8998_adc: adc@3100 {
reg = <0x3100>;
compatible = "qcom,spmi-adc-rev2";
#address-cells = <1>;
#size-cells = <0>;
#io-channel-cells = <1>;
/* Other propreties are omitted */
adc-chan@4c {
reg = <ADC5_XO_THERM_100K_PU>;
};
};
pm8998_adc_tm: adc-tm@3400 {
compatible = "qcom,spmi-adc-tm-hc";
reg = <0x3400>;
interrupts = <0x2 0x34 0x0 IRQ_TYPE_EDGE_RISING>;
#thermal-sensor-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
thermistor@1 {
reg = <1>;
io-channels = <&pm8998_adc ADC5_XO_THERM_100K_PU>;
qcom,ratiometric;
qcom,hw-settle-time-us = <200>;
};
};
};
...

Просмотреть файл

@ -12,14 +12,14 @@ maintainers:
properties:
compatible:
enum:
- rockchip,px30-tsadc # PX30 SoCs
- rockchip,rv1108-tsadc # RV1108 SoCs
- rockchip,rk3228-tsadc # RK3228 SoCs
- rockchip,rk3288-tsadc # RK3288 SoCs
- rockchip,rk3328-tsadc # RK3328 SoCs
- rockchip,rk3368-tsadc # RK3368 SoCs
- rockchip,rk3399-tsadc # RK3399 SoCs
- rockchip,rk3568-tsadc # RK3568 SoCs
- rockchip,px30-tsadc
- rockchip,rk3228-tsadc
- rockchip,rk3288-tsadc
- rockchip,rk3328-tsadc
- rockchip,rk3368-tsadc
- rockchip,rk3399-tsadc
- rockchip,rk3568-tsadc
- rockchip,rv1108-tsadc
reg:
maxItems: 1
@ -37,11 +37,15 @@ properties:
- const: apb_pclk
resets:
maxItems: 1
minItems: 1
maxItems: 3
reset-names:
minItems: 1
items:
- const: tsadc-apb
- const: tsadc
- const: tsadc-phy
"#thermal-sensor-cells":
const: 1
@ -71,7 +75,6 @@ required:
- clocks
- clock-names
- resets
- reset-names
- "#thermal-sensor-cells"
additionalProperties: false

Просмотреть файл

@ -20,6 +20,7 @@ properties:
- socionext,uniphier-pxs2-thermal
- socionext,uniphier-ld20-thermal
- socionext,uniphier-pxs3-thermal
- socionext,uniphier-nx1-thermal
interrupts:
maxItems: 1

Просмотреть файл

@ -428,6 +428,9 @@ of thermal zone device. E.g. the generic thermal driver registers one hwmon
class device and build the associated hwmon sysfs I/F for all the registered
ACPI thermal zones.
Please read Documentation/ABI/testing/sysfs-class-thermal for thermal
zone and cooling device attribute details.
::
/sys/class/hwmon/hwmon[0-*]:
@ -437,228 +440,6 @@ ACPI thermal zones.
Please read Documentation/hwmon/sysfs-interface.rst for additional information.
Thermal zone attributes
-----------------------
type
Strings which represent the thermal zone type.
This is given by thermal zone driver as part of registration.
E.g: "acpitz" indicates it's an ACPI thermal device.
In order to keep it consistent with hwmon sys attribute; this should
be a short, lowercase string, not containing spaces nor dashes.
RO, Required
temp
Current temperature as reported by thermal zone (sensor).
Unit: millidegree Celsius
RO, Required
mode
One of the predefined values in [enabled, disabled].
This file gives information about the algorithm that is currently
managing the thermal zone. It can be either default kernel based
algorithm or user space application.
enabled
enable Kernel Thermal management.
disabled
Preventing kernel thermal zone driver actions upon
trip points so that user application can take full
charge of the thermal management.
RW, Optional
policy
One of the various thermal governors used for a particular zone.
RW, Required
available_policies
Available thermal governors which can be used for a particular zone.
RO, Required
`trip_point_[0-*]_temp`
The temperature above which trip point will be fired.
Unit: millidegree Celsius
RO, Optional
`trip_point_[0-*]_type`
Strings which indicate the type of the trip point.
E.g. it can be one of critical, hot, passive, `active[0-*]` for ACPI
thermal zone.
RO, Optional
`trip_point_[0-*]_hyst`
The hysteresis value for a trip point, represented as an integer
Unit: Celsius
RW, Optional
`cdev[0-*]`
Sysfs link to the thermal cooling device node where the sys I/F
for cooling device throttling control represents.
RO, Optional
`cdev[0-*]_trip_point`
The trip point in this thermal zone which `cdev[0-*]` is associated
with; -1 means the cooling device is not associated with any trip
point.
RO, Optional
`cdev[0-*]_weight`
The influence of `cdev[0-*]` in this thermal zone. This value
is relative to the rest of cooling devices in the thermal
zone. For example, if a cooling device has a weight double
than that of other, it's twice as effective in cooling the
thermal zone.
RW, Optional
emul_temp
Interface to set the emulated temperature method in thermal zone
(sensor). After setting this temperature, the thermal zone may pass
this temperature to platform emulation function if registered or
cache it locally. This is useful in debugging different temperature
threshold and its associated cooling action. This is write only node
and writing 0 on this node should disable emulation.
Unit: millidegree Celsius
WO, Optional
WARNING:
Be careful while enabling this option on production systems,
because userland can easily disable the thermal policy by simply
flooding this sysfs node with low temperature values.
sustainable_power
An estimate of the sustained power that can be dissipated by
the thermal zone. Used by the power allocator governor. For
more information see Documentation/driver-api/thermal/power_allocator.rst
Unit: milliwatts
RW, Optional
k_po
The proportional term of the power allocator governor's PID
controller during temperature overshoot. Temperature overshoot
is when the current temperature is above the "desired
temperature" trip point. For more information see
Documentation/driver-api/thermal/power_allocator.rst
RW, Optional
k_pu
The proportional term of the power allocator governor's PID
controller during temperature undershoot. Temperature undershoot
is when the current temperature is below the "desired
temperature" trip point. For more information see
Documentation/driver-api/thermal/power_allocator.rst
RW, Optional
k_i
The integral term of the power allocator governor's PID
controller. This term allows the PID controller to compensate
for long term drift. For more information see
Documentation/driver-api/thermal/power_allocator.rst
RW, Optional
k_d
The derivative term of the power allocator governor's PID
controller. For more information see
Documentation/driver-api/thermal/power_allocator.rst
RW, Optional
integral_cutoff
Temperature offset from the desired temperature trip point
above which the integral term of the power allocator
governor's PID controller starts accumulating errors. For
example, if integral_cutoff is 0, then the integral term only
accumulates error when temperature is above the desired
temperature trip point. For more information see
Documentation/driver-api/thermal/power_allocator.rst
Unit: millidegree Celsius
RW, Optional
slope
The slope constant used in a linear extrapolation model
to determine a hotspot temperature based off the sensor's
raw readings. It is up to the device driver to determine
the usage of these values.
RW, Optional
offset
The offset constant used in a linear extrapolation model
to determine a hotspot temperature based off the sensor's
raw readings. It is up to the device driver to determine
the usage of these values.
RW, Optional
Cooling device attributes
-------------------------
type
String which represents the type of device, e.g:
- for generic ACPI: should be "Fan", "Processor" or "LCD"
- for memory controller device on intel_menlow platform:
should be "Memory controller".
RO, Required
max_state
The maximum permissible cooling state of this cooling device.
RO, Required
cur_state
The current cooling state of this cooling device.
The value can any integer numbers between 0 and max_state:
- cur_state == 0 means no cooling
- cur_state == max_state means the maximum cooling.
RW, Required
stats/reset
Writing any value resets the cooling device's statistics.
WO, Required
stats/time_in_state_ms:
The amount of time spent by the cooling device in various cooling
states. The output will have "<state> <time>" pair in each line, which
will mean this cooling device spent <time> msec of time at <state>.
Output will have one line for each of the supported states.
RO, Required
stats/total_trans:
A single positive value showing the total number of times the state of a
cooling device is changed.
RO, Required
stats/trans_table:
This gives fine grained information about all the cooling state
transitions. The cat output here is a two dimensional matrix, where an
entry <i,j> (row i, column j) represents the number of transitions from
State_i to State_j. If the transition table is bigger than PAGE_SIZE,
reading this will return an -EFBIG error.
RO, Required
3. A simple implementation
==========================

Просмотреть файл

@ -18649,7 +18649,9 @@ L: linux-pm@vger.kernel.org
S: Supported
Q: https://patchwork.kernel.org/project/linux-pm/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git thermal
F: Documentation/ABI/testing/sysfs-class-thermal
F: Documentation/devicetree/bindings/thermal/
F: Documentation/driver-api/thermal/
F: drivers/thermal/
F: include/linux/cpu_cooling.h
F: include/linux/thermal.h

Просмотреть файл

@ -15,6 +15,14 @@
#include "thermal_core.h"
static int user_space_bind(struct thermal_zone_device *tz)
{
pr_warn("Userspace governor deprecated: use thermal netlink " \
"notification instead\n");
return 0;
}
/**
* notify_user_space - Notifies user space about thermal events
* @tz: thermal_zone_device
@ -43,5 +51,6 @@ static int notify_user_space(struct thermal_zone_device *tz, int trip)
static struct thermal_governor thermal_gov_user_space = {
.name = "user_space",
.throttle = notify_user_space,
.bind_to_tz = user_space_bind,
};
THERMAL_GOVERNOR_DECLARE(thermal_gov_user_space);

Просмотреть файл

@ -129,11 +129,10 @@ static ssize_t available_uuids_show(struct device *dev,
for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) {
if (priv->uuid_bitmap & (1 << i))
if (PAGE_SIZE - length > 0)
length += scnprintf(&buf[length],
PAGE_SIZE - length,
"%s\n",
int3400_thermal_uuids[i]);
length += scnprintf(&buf[length],
PAGE_SIZE - length,
"%s\n",
int3400_thermal_uuids[i]);
}
return length;

Просмотреть файл

@ -44,15 +44,21 @@ static int int3401_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM_SLEEP
static int int3401_thermal_suspend(struct device *dev)
{
return proc_thermal_suspend(dev);
}
static int int3401_thermal_resume(struct device *dev)
{
return proc_thermal_resume(dev);
}
#else
#define int3401_thermal_suspend NULL
#define int3401_thermal_resume NULL
#endif
static SIMPLE_DEV_PM_OPS(int3401_proc_thermal_pm, NULL, int3401_thermal_resume);
static SIMPLE_DEV_PM_OPS(int3401_proc_thermal_pm, int3401_thermal_suspend,
int3401_thermal_resume);
static struct platform_driver int3401_driver = {
.probe = int3401_add,

Просмотреть файл

@ -68,8 +68,7 @@ static const struct attribute_group power_limit_attribute_group = {
.name = "power_limits"
};
static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
struct device_attribute *attr, char *buf)
static int tcc_get_offset(void)
{
u64 val;
int err;
@ -78,8 +77,20 @@ static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
if (err)
return err;
val = (val >> 24) & 0x3f;
return sprintf(buf, "%d\n", (int)val);
return (val >> 24) & 0x3f;
}
static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int tcc;
tcc = tcc_get_offset();
if (tcc < 0)
return tcc;
return sprintf(buf, "%d\n", tcc);
}
static int tcc_offset_update(unsigned int tcc)
@ -107,8 +118,6 @@ static int tcc_offset_update(unsigned int tcc)
return 0;
}
static int tcc_offset_save = -1;
static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
@ -131,8 +140,6 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
if (err)
return err;
tcc_offset_save = tcc;
return count;
}
@ -345,6 +352,18 @@ void proc_thermal_remove(struct proc_thermal_device *proc_priv)
}
EXPORT_SYMBOL_GPL(proc_thermal_remove);
static int tcc_offset_save = -1;
int proc_thermal_suspend(struct device *dev)
{
tcc_offset_save = tcc_get_offset();
if (tcc_offset_save < 0)
dev_warn(dev, "failed to save offset (%d)\n", tcc_offset_save);
return 0;
}
EXPORT_SYMBOL_GPL(proc_thermal_suspend);
int proc_thermal_resume(struct device *dev)
{
struct proc_thermal_device *proc_dev;
@ -352,6 +371,7 @@ int proc_thermal_resume(struct device *dev)
proc_dev = dev_get_drvdata(dev);
proc_thermal_read_ppcc(proc_dev);
/* Do not update if saving failed */
if (tcc_offset_save >= 0)
tcc_offset_update(tcc_offset_save);

Просмотреть файл

@ -83,6 +83,7 @@ void proc_thermal_mbox_remove(struct pci_dev *pdev);
int processor_thermal_send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp);
int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv);
void proc_thermal_remove(struct proc_thermal_device *proc_priv);
int proc_thermal_suspend(struct device *dev);
int proc_thermal_resume(struct device *dev);
int proc_thermal_mmio_add(struct pci_dev *pdev,
struct proc_thermal_device *proc_priv,

Просмотреть файл

@ -314,6 +314,20 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev)
}
#ifdef CONFIG_PM_SLEEP
static int proc_thermal_pci_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct proc_thermal_device *proc_priv;
struct proc_thermal_pci *pci_info;
proc_priv = pci_get_drvdata(pdev);
pci_info = proc_priv->priv_data;
if (!pci_info->no_legacy)
return proc_thermal_suspend(dev);
return 0;
}
static int proc_thermal_pci_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
@ -335,10 +349,12 @@ static int proc_thermal_pci_resume(struct device *dev)
return 0;
}
#else
#define proc_thermal_pci_suspend NULL
#define proc_thermal_pci_resume NULL
#endif
static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume);
static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
proc_thermal_pci_resume);
static const struct pci_device_id proc_thermal_pci_ids[] = {
{ PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) },

Просмотреть файл

@ -107,15 +107,21 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev)
}
#ifdef CONFIG_PM_SLEEP
static int proc_thermal_pci_suspend(struct device *dev)
{
return proc_thermal_suspend(dev);
}
static int proc_thermal_pci_resume(struct device *dev)
{
return proc_thermal_resume(dev);
}
#else
#define proc_thermal_pci_suspend NULL
#define proc_thermal_pci_resume NULL
#endif
static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume);
static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
proc_thermal_pci_resume);
static const struct pci_device_id proc_thermal_pci_ids[] = {
{ PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) },

Просмотреть файл

@ -705,10 +705,8 @@ static enum cpuhp_state hp_state;
static int __init powerclamp_init(void)
{
int retval;
int bitmap_size;
bitmap_size = BITS_TO_LONGS(num_possible_cpus()) * sizeof(long);
cpu_clamping_mask = kzalloc(bitmap_size, GFP_KERNEL);
cpu_clamping_mask = bitmap_zalloc(num_possible_cpus(), GFP_KERNEL);
if (!cpu_clamping_mask)
return -ENOMEM;
@ -753,7 +751,7 @@ exit_free_thread:
exit_unregister:
cpuhp_remove_state_nocalls(hp_state);
exit_free:
kfree(cpu_clamping_mask);
bitmap_free(cpu_clamping_mask);
return retval;
}
module_init(powerclamp_init);
@ -764,7 +762,7 @@ static void __exit powerclamp_exit(void)
cpuhp_remove_state_nocalls(hp_state);
free_percpu(worker_data);
thermal_cooling_device_unregister(cooling_dev);
kfree(cpu_clamping_mask);
bitmap_free(cpu_clamping_mask);
cancel_delayed_work_sync(&poll_pkg_cstate_work);
debugfs_remove_recursive(debug_dir);

Просмотреть файл

@ -34,7 +34,7 @@ config QCOM_SPMI_TEMP_ALARM
config QCOM_LMH
tristate "Qualcomm Limits Management Hardware"
depends on ARCH_QCOM
depends on ARCH_QCOM && QCOM_SCM
help
This enables initialization of Qualcomm limits management
hardware(LMh). LMh allows for hardware-enforced mitigation for cpus based on

Просмотреть файл

@ -82,6 +82,7 @@ struct adc_tm5_data {
const u32 full_scale_code_volt;
unsigned int *decimation;
unsigned int *hw_settle;
bool is_hc;
};
enum adc_tm5_cal_method {
@ -146,6 +147,14 @@ static const struct adc_tm5_data adc_tm5_data_pmic = {
64000, 128000 },
};
static const struct adc_tm5_data adc_tm_hc_data_pmic = {
.full_scale_code_volt = 0x70e4,
.decimation = (unsigned int []) { 256, 512, 1024 },
.hw_settle = (unsigned int []) { 0, 100, 200, 300, 400, 500, 600, 700,
1000, 2000, 4000, 6000, 8000, 10000 },
.is_hc = true,
};
static int adc_tm5_read(struct adc_tm5_chip *adc_tm, u16 offset, u8 *data, int len)
{
return regmap_bulk_read(adc_tm->regmap, adc_tm->base + offset, data, len);
@ -375,6 +384,29 @@ static int adc_tm5_register_tzd(struct adc_tm5_chip *adc_tm)
return 0;
}
static int adc_tm_hc_init(struct adc_tm5_chip *chip)
{
unsigned int i;
u8 buf[2];
int ret;
for (i = 0; i < chip->nchannels; i++) {
if (chip->channels[i].channel >= ADC_TM5_NUM_CHANNELS) {
dev_err(chip->dev, "Invalid channel %d\n", chip->channels[i].channel);
return -EINVAL;
}
}
buf[0] = chip->decimation;
buf[1] = chip->avg_samples | ADC_TM5_FAST_AVG_EN;
ret = adc_tm5_write(chip, ADC_TM5_ADC_DIG_PARAM, buf, sizeof(buf));
if (ret)
dev_err(chip->dev, "block write failed: %d\n", ret);
return ret;
}
static int adc_tm5_init(struct adc_tm5_chip *chip)
{
u8 buf[4], channels_available;
@ -591,7 +623,10 @@ static int adc_tm5_probe(struct platform_device *pdev)
return ret;
}
ret = adc_tm5_init(adc_tm);
if (adc_tm->data->is_hc)
ret = adc_tm_hc_init(adc_tm);
else
ret = adc_tm5_init(adc_tm);
if (ret) {
dev_err(dev, "adc-tm init failed\n");
return ret;
@ -612,6 +647,10 @@ static const struct of_device_id adc_tm5_match_table[] = {
.compatible = "qcom,spmi-adc-tm5",
.data = &adc_tm5_data_pmic,
},
{
.compatible = "qcom,spmi-adc-tm-hc",
.data = &adc_tm_hc_data_pmic,
},
{ }
};
MODULE_DEVICE_TABLE(of, adc_tm5_match_table);

Просмотреть файл

@ -603,22 +603,21 @@ int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp)
int ret;
/* VER_0 doesn't have VALID bit */
if (tsens_version(priv) >= VER_0_1) {
ret = regmap_field_read(priv->rf[valid_idx], &valid);
if (ret)
return ret;
while (!valid) {
/* Valid bit is 0 for 6 AHB clock cycles.
* At 19.2MHz, 1 AHB clock is ~60ns.
* We should enter this loop very, very rarely.
*/
ndelay(400);
ret = regmap_field_read(priv->rf[valid_idx], &valid);
if (ret)
return ret;
}
}
if (tsens_version(priv) == VER_0)
goto get_temp;
/* Valid bit is 0 for 6 AHB clock cycles.
* At 19.2MHz, 1 AHB clock is ~60ns.
* We should enter this loop very, very rarely.
* Wait 1 us since it's the min of poll_timeout macro.
* Old value was 400 ns.
*/
ret = regmap_field_read_poll_timeout(priv->rf[valid_idx], valid,
valid, 1, 20 * USEC_PER_MSEC);
if (ret)
return ret;
get_temp:
/* Valid bit is set, OK to read the temperature */
*temp = tsens_hw_to_mC(s, temp_idx);

Просмотреть файл

@ -34,6 +34,10 @@
#define REG_GEN3_THCODE1 0x50
#define REG_GEN3_THCODE2 0x54
#define REG_GEN3_THCODE3 0x58
#define REG_GEN3_PTAT1 0x5c
#define REG_GEN3_PTAT2 0x60
#define REG_GEN3_PTAT3 0x64
#define REG_GEN3_THSCP 0x68
/* IRQ{STR,MSK,EN} bits */
#define IRQ_TEMP1 BIT(0)
@ -55,6 +59,9 @@
#define THCTR_PONM BIT(6)
#define THCTR_THSST BIT(0)
/* THSCP bits */
#define THSCP_COR_PARA_VLD (BIT(15) | BIT(14))
#define CTEMP_MASK 0xFFF
#define MCELSIUS(temp) ((temp) * 1000)
@ -62,15 +69,6 @@
#define TSC_MAX_NUM 5
/* default THCODE values if FUSEs are missing */
static const int thcodes[TSC_MAX_NUM][3] = {
{ 3397, 2800, 2221 },
{ 3393, 2795, 2216 },
{ 3389, 2805, 2237 },
{ 3415, 2694, 2195 },
{ 3356, 2724, 2244 },
};
/* Structure for thermal temperature calculation */
struct equation_coefs {
int a1;
@ -84,13 +82,14 @@ struct rcar_gen3_thermal_tsc {
struct thermal_zone_device *zone;
struct equation_coefs coef;
int tj_t;
unsigned int id; /* thermal channel id */
int thcode[3];
};
struct rcar_gen3_thermal_priv {
struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM];
unsigned int num_tscs;
void (*thermal_init)(struct rcar_gen3_thermal_tsc *tsc);
int ptat[3];
};
static inline u32 rcar_gen3_thermal_read(struct rcar_gen3_thermal_tsc *tsc,
@ -133,8 +132,8 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
/* no idea where these constants come from */
#define TJ_3 -41
static void rcar_gen3_thermal_calc_coefs(struct rcar_gen3_thermal_tsc *tsc,
int *ptat, const int *thcode,
static void rcar_gen3_thermal_calc_coefs(struct rcar_gen3_thermal_priv *priv,
struct rcar_gen3_thermal_tsc *tsc,
int ths_tj_1)
{
/* TODO: Find documentation and document constant calculation formula */
@ -143,16 +142,16 @@ static void rcar_gen3_thermal_calc_coefs(struct rcar_gen3_thermal_tsc *tsc,
* Division is not scaled in BSP and if scaled it might overflow
* the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled
*/
tsc->tj_t = (FIXPT_INT((ptat[1] - ptat[2]) * (ths_tj_1 - TJ_3))
/ (ptat[0] - ptat[2])) + FIXPT_INT(TJ_3);
tsc->tj_t = (FIXPT_INT((priv->ptat[1] - priv->ptat[2]) * (ths_tj_1 - TJ_3))
/ (priv->ptat[0] - priv->ptat[2])) + FIXPT_INT(TJ_3);
tsc->coef.a1 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[2]),
tsc->coef.a1 = FIXPT_DIV(FIXPT_INT(tsc->thcode[1] - tsc->thcode[2]),
tsc->tj_t - FIXPT_INT(TJ_3));
tsc->coef.b1 = FIXPT_INT(thcode[2]) - tsc->coef.a1 * TJ_3;
tsc->coef.b1 = FIXPT_INT(tsc->thcode[2]) - tsc->coef.a1 * TJ_3;
tsc->coef.a2 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[0]),
tsc->coef.a2 = FIXPT_DIV(FIXPT_INT(tsc->thcode[1] - tsc->thcode[0]),
tsc->tj_t - FIXPT_INT(ths_tj_1));
tsc->coef.b2 = FIXPT_INT(thcode[0]) - tsc->coef.a2 * ths_tj_1;
tsc->coef.b2 = FIXPT_INT(tsc->thcode[0]) - tsc->coef.a2 * ths_tj_1;
}
static int rcar_gen3_thermal_round(int temp)
@ -174,7 +173,7 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
/* Read register and convert to mili Celsius */
reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK;
if (reg <= thcodes[tsc->id][1])
if (reg <= tsc->thcode[1])
val = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1,
tsc->coef.a1);
else
@ -253,6 +252,64 @@ static const struct soc_device_attribute r8a7795es1[] = {
{ /* sentinel */ }
};
static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
{
unsigned int i;
u32 thscp;
/* If fuses are not set, fallback to pseudo values. */
thscp = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_THSCP);
if ((thscp & THSCP_COR_PARA_VLD) != THSCP_COR_PARA_VLD) {
/* Default THCODE values in case FUSEs are not set. */
static const int thcodes[TSC_MAX_NUM][3] = {
{ 3397, 2800, 2221 },
{ 3393, 2795, 2216 },
{ 3389, 2805, 2237 },
{ 3415, 2694, 2195 },
{ 3356, 2724, 2244 },
};
priv->ptat[0] = 2631;
priv->ptat[1] = 1509;
priv->ptat[2] = 435;
for (i = 0; i < priv->num_tscs; i++) {
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
tsc->thcode[0] = thcodes[i][0];
tsc->thcode[1] = thcodes[i][1];
tsc->thcode[2] = thcodes[i][2];
}
return false;
}
/*
* Set the pseudo calibration points with fused values.
* PTAT is shared between all TSCs but only fused for the first
* TSC while THCODEs are fused for each TSC.
*/
priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT1) &
GEN3_FUSE_MASK;
priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT2) &
GEN3_FUSE_MASK;
priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT3) &
GEN3_FUSE_MASK;
for (i = 0; i < priv->num_tscs; i++) {
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE1) &
GEN3_FUSE_MASK;
tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE2) &
GEN3_FUSE_MASK;
tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE3) &
GEN3_FUSE_MASK;
}
return true;
}
static void rcar_gen3_thermal_init_r8a7795es1(struct rcar_gen3_thermal_tsc *tsc)
{
rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR);
@ -401,10 +458,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
unsigned int i;
int ret;
/* default values if FUSEs are missing */
/* TODO: Read values from hardware on supported platforms */
int ptat[3] = { 2631, 1509, 435 };
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@ -439,9 +492,17 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
ret = PTR_ERR(tsc->base);
goto error_unregister;
}
tsc->id = i;
priv->tscs[i] = tsc;
}
priv->num_tscs = i;
if (!rcar_gen3_thermal_read_fuses(priv))
dev_info(dev, "No calibration values fused, fallback to driver values\n");
for (i = 0; i < priv->num_tscs; i++) {
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,
&rcar_gen3_tz_of_ops);
@ -453,7 +514,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
tsc->zone = zone;
priv->thermal_init(tsc);
rcar_gen3_thermal_calc_coefs(tsc, ptat, thcodes[i], *ths_tj_1);
rcar_gen3_thermal_calc_coefs(priv, tsc, *ths_tj_1);
tsc->zone->tzp->no_hwmon = false;
ret = thermal_add_hwmon_sysfs(tsc->zone);
@ -471,8 +532,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
dev_info(dev, "TSC%u: Loaded %d trip points\n", i, ret);
}
priv->num_tscs = i;
if (!priv->num_tscs) {
ret = -ENODEV;
goto error_unregister;

Просмотреть файл

@ -1383,7 +1383,7 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
if (IS_ERR(thermal->regs))
return PTR_ERR(thermal->regs);
thermal->reset = devm_reset_control_get(&pdev->dev, "tsadc-apb");
thermal->reset = devm_reset_control_array_get(&pdev->dev, false, false);
if (IS_ERR(thermal->reset)) {
error = PTR_ERR(thermal->reset);
dev_err(&pdev->dev, "failed to get tsadc reset: %d\n", error);

Просмотреть файл

@ -375,10 +375,12 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
if (tz->last_temperature != THERMAL_TEMP_INVALID) {
if (tz->last_temperature < trip_temp &&
tz->temperature >= trip_temp)
thermal_notify_tz_trip_up(tz->id, trip);
thermal_notify_tz_trip_up(tz->id, trip,
tz->temperature);
if (tz->last_temperature >= trip_temp &&
tz->temperature < (trip_temp - hyst))
thermal_notify_tz_trip_down(tz->id, trip);
thermal_notify_tz_trip_down(tz->id, trip,
tz->temperature);
}
if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
@ -887,7 +889,7 @@ __thermal_cooling_device_register(struct device_node *np,
{
struct thermal_cooling_device *cdev;
struct thermal_zone_device *pos = NULL;
int ret;
int id, ret;
if (!ops || !ops->get_max_state || !ops->get_cur_state ||
!ops->set_cur_state)
@ -901,6 +903,11 @@ __thermal_cooling_device_register(struct device_node *np,
if (ret < 0)
goto out_kfree_cdev;
cdev->id = ret;
id = ret;
ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
if (ret)
goto out_ida_remove;
cdev->type = kstrdup(type ? type : "", GFP_KERNEL);
if (!cdev->type) {
@ -916,7 +923,6 @@ __thermal_cooling_device_register(struct device_node *np,
cdev->device.class = &thermal_class;
cdev->devdata = devdata;
thermal_cooling_device_setup_sysfs(cdev);
dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
ret = device_register(&cdev->device);
if (ret)
goto out_kfree_type;
@ -941,8 +947,9 @@ __thermal_cooling_device_register(struct device_node *np,
out_kfree_type:
kfree(cdev->type);
put_device(&cdev->device);
cdev = NULL;
out_ida_remove:
ida_simple_remove(&thermal_cdev_ida, cdev->id);
ida_simple_remove(&thermal_cdev_ida, id);
out_kfree_cdev:
kfree(cdev);
return ERR_PTR(ret);
@ -1227,6 +1234,10 @@ thermal_zone_device_register(const char *type, int trips, int mask,
tz->id = id;
strlcpy(tz->type, type, sizeof(tz->type));
result = dev_set_name(&tz->device, "thermal_zone%d", tz->id);
if (result)
goto remove_id;
if (!ops->critical)
ops->critical = thermal_zone_device_critical;
@ -1248,7 +1259,6 @@ thermal_zone_device_register(const char *type, int trips, int mask,
/* A new thermal zone needs to be updated anyway. */
atomic_set(&tz->need_update, 1);
dev_set_name(&tz->device, "thermal_zone%d", tz->id);
result = device_register(&tz->device);
if (result)
goto release_device;

Просмотреть файл

@ -34,7 +34,7 @@ static int thermal_mmio_get_temperature(void *private, int *temp)
return 0;
}
static struct thermal_zone_of_device_ops thermal_mmio_ops = {
static const struct thermal_zone_of_device_ops thermal_mmio_ops = {
.get_temp = thermal_mmio_get_temperature,
};

Просмотреть файл

@ -121,7 +121,8 @@ static int thermal_genl_event_tz(struct param *p)
static int thermal_genl_event_tz_trip_up(struct param *p)
{
if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) ||
nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id))
nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id) ||
nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TEMP, p->temp))
return -EMSGSIZE;
return 0;
@ -285,16 +286,16 @@ int thermal_notify_tz_disable(int tz_id)
return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_DISABLE, &p);
}
int thermal_notify_tz_trip_down(int tz_id, int trip_id)
int thermal_notify_tz_trip_down(int tz_id, int trip_id, int temp)
{
struct param p = { .tz_id = tz_id, .trip_id = trip_id };
struct param p = { .tz_id = tz_id, .trip_id = trip_id, .temp = temp };
return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_DOWN, &p);
}
int thermal_notify_tz_trip_up(int tz_id, int trip_id)
int thermal_notify_tz_trip_up(int tz_id, int trip_id, int temp)
{
struct param p = { .tz_id = tz_id, .trip_id = trip_id };
struct param p = { .tz_id = tz_id, .trip_id = trip_id, .temp = temp };
return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_UP, &p);
}

Просмотреть файл

@ -11,8 +11,8 @@ int thermal_notify_tz_create(int tz_id, const char *name);
int thermal_notify_tz_delete(int tz_id);
int thermal_notify_tz_enable(int tz_id);
int thermal_notify_tz_disable(int tz_id);
int thermal_notify_tz_trip_down(int tz_id, int id);
int thermal_notify_tz_trip_up(int tz_id, int id);
int thermal_notify_tz_trip_down(int tz_id, int id, int temp);
int thermal_notify_tz_trip_up(int tz_id, int id, int temp);
int thermal_notify_tz_trip_delete(int tz_id, int id);
int thermal_notify_tz_trip_add(int tz_id, int id, int type,
int temp, int hyst);
@ -49,12 +49,12 @@ static inline int thermal_notify_tz_disable(int tz_id)
return 0;
}
static inline int thermal_notify_tz_trip_down(int tz_id, int id)
static inline int thermal_notify_tz_trip_down(int tz_id, int id, int temp)
{
return 0;
}
static inline int thermal_notify_tz_trip_up(int tz_id, int id)
static inline int thermal_notify_tz_trip_up(int tz_id, int id, int temp)
{
return 0;
}

Просмотреть файл

@ -610,6 +610,9 @@ cur_state_store(struct device *dev, struct device_attribute *attr,
unsigned long state;
int result;
dev_warn_once(&cdev->device,
"Setting cooling device state is deprecated\n");
if (sscanf(buf, "%ld\n", &state) != 1)
return -EINVAL;

Просмотреть файл

@ -358,6 +358,10 @@ static const struct of_device_id uniphier_tm_dt_ids[] = {
.compatible = "socionext,uniphier-pxs3-thermal",
.data = &uniphier_ld20_tm_data,
},
{
.compatible = "socionext,uniphier-nx1-thermal",
.data = &uniphier_ld20_tm_data,
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, uniphier_tm_dt_ids);