Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
88ac9906
Commit
88ac9906
authored
May 18, 2016
by
Zhang Rui
Browse files
Options
Browse Files
Download
Plain Diff
Merge branches 'thermal-core', 'thermal-intel' and 'thermal-soc' into next
parents
191b0754
5af897e4
431c30f7
Changes
37
Hide whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
2407 additions
and
762 deletions
+2407
-762
Documentation/devicetree/bindings/thermal/rcar-thermal.txt
Documentation/devicetree/bindings/thermal/rcar-thermal.txt
+0
-1
Documentation/devicetree/bindings/thermal/tango-thermal.txt
Documentation/devicetree/bindings/thermal/tango-thermal.txt
+17
-0
Documentation/devicetree/bindings/thermal/tegra-soctherm.txt
Documentation/devicetree/bindings/thermal/tegra-soctherm.txt
+12
-0
Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt
...ation/devicetree/bindings/thermal/thermal-generic-adc.txt
+89
-0
Documentation/thermal/sysfs-api.txt
Documentation/thermal/sysfs-api.txt
+22
-22
MAINTAINERS
MAINTAINERS
+1
-0
drivers/cpufreq/mt8173-cpufreq.c
drivers/cpufreq/mt8173-cpufreq.c
+9
-2
drivers/hwmon/lm75.c
drivers/hwmon/lm75.c
+3
-7
drivers/hwmon/ntc_thermistor.c
drivers/hwmon/ntc_thermistor.c
+4
-8
drivers/hwmon/scpi-hwmon.c
drivers/hwmon/scpi-hwmon.c
+9
-39
drivers/hwmon/tmp102.c
drivers/hwmon/tmp102.c
+2
-6
drivers/input/touchscreen/sun4i-ts.c
drivers/input/touchscreen/sun4i-ts.c
+1
-8
drivers/thermal/Kconfig
drivers/thermal/Kconfig
+21
-10
drivers/thermal/Makefile
drivers/thermal/Makefile
+3
-1
drivers/thermal/hisi_thermal.c
drivers/thermal/hisi_thermal.c
+26
-19
drivers/thermal/int340x_thermal/processor_thermal_device.c
drivers/thermal/int340x_thermal/processor_thermal_device.c
+77
-31
drivers/thermal/intel_powerclamp.c
drivers/thermal/intel_powerclamp.c
+9
-38
drivers/thermal/mtk_thermal.c
drivers/thermal/mtk_thermal.c
+2
-10
drivers/thermal/of-thermal.c
drivers/thermal/of-thermal.c
+9
-1
drivers/thermal/qcom-spmi-temp-alarm.c
drivers/thermal/qcom-spmi-temp-alarm.c
+1
-2
drivers/thermal/rcar_thermal.c
drivers/thermal/rcar_thermal.c
+1
-1
drivers/thermal/rockchip_thermal.c
drivers/thermal/rockchip_thermal.c
+205
-75
drivers/thermal/tango_thermal.c
drivers/thermal/tango_thermal.c
+109
-0
drivers/thermal/tegra/Kconfig
drivers/thermal/tegra/Kconfig
+13
-0
drivers/thermal/tegra/Makefile
drivers/thermal/tegra/Makefile
+6
-0
drivers/thermal/tegra/soctherm-fuse.c
drivers/thermal/tegra/soctherm-fuse.c
+169
-0
drivers/thermal/tegra/soctherm.c
drivers/thermal/tegra/soctherm.c
+685
-0
drivers/thermal/tegra/soctherm.h
drivers/thermal/tegra/soctherm.h
+127
-0
drivers/thermal/tegra/tegra124-soctherm.c
drivers/thermal/tegra/tegra124-soctherm.c
+196
-0
drivers/thermal/tegra/tegra132-soctherm.c
drivers/thermal/tegra/tegra132-soctherm.c
+196
-0
drivers/thermal/tegra/tegra210-soctherm.c
drivers/thermal/tegra/tegra210-soctherm.c
+197
-0
drivers/thermal/tegra_soctherm.c
drivers/thermal/tegra_soctherm.c
+0
-476
drivers/thermal/thermal-generic-adc.c
drivers/thermal/thermal-generic-adc.c
+182
-0
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+1
-4
drivers/thermal/x86_pkg_temp_thermal.c
drivers/thermal/x86_pkg_temp_thermal.c
+1
-1
include/dt-bindings/thermal/tegra124-soctherm.h
include/dt-bindings/thermal/tegra124-soctherm.h
+1
-0
include/linux/thermal.h
include/linux/thermal.h
+1
-0
No files found.
Documentation/devicetree/bindings/thermal/rcar-thermal.txt
View file @
88ac9906
...
...
@@ -11,7 +11,6 @@ Required properties:
- "renesas,thermal-r8a7791" (R-Car M2-W)
- "renesas,thermal-r8a7792" (R-Car V2H)
- "renesas,thermal-r8a7793" (R-Car M2-N)
- "renesas,thermal-r8a7794" (R-Car E2)
- reg : Address range of the thermal registers.
The 1st reg will be recognized as common register
if it has "interrupts".
...
...
Documentation/devicetree/bindings/thermal/tango-thermal.txt
0 → 100644
View file @
88ac9906
* Tango Thermal
The SMP8758 SoC includes 3 instances of this temperature sensor
(in the CPU, video decoder, and PCIe controller).
Required properties:
- #thermal-sensor-cells: Should be 0 (see thermal.txt)
- compatible: "sigma,smp8758-thermal"
- reg: Address range of the thermal registers
Example:
cpu_temp: thermal@920100 {
#thermal-sensor-cells = <0>;
compatible = "sigma,smp8758-thermal";
reg = <0x920100 12>;
};
Documentation/devicetree/bindings/thermal/tegra-soctherm.txt
View file @
88ac9906
...
...
@@ -26,6 +26,10 @@ Required properties :
of this property. See <dt-bindings/thermal/tegra124-soctherm.h> for a
list of valid values when referring to thermal sensors.
Note:
- the "critical" type trip points will be set to SOC_THERM hardware as the
shut down temperature. Once the temperature of this thermal zone is higher
than it, the system will be shutdown or reset by hardware.
Example :
...
...
@@ -51,5 +55,13 @@ Example: referring to thermal sensors :
thermal-sensors =
<&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>;
trips {
cpu_shutdown_trip: shutdown-trip {
temperature = <102500>;
hysteresis = <1000>;
type = "critical";
};
};
};
};
Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt
0 → 100644
View file @
88ac9906
General Purpose Analog To Digital Converter (ADC) based thermal sensor.
On some of platforms, thermal sensor like thermistors are connected to
one of ADC channel and sensor resistance is read via voltage across the
sensor resistor. The voltage read across the sensor is mapped to
temperature using voltage-temperature lookup table.
Required properties:
===================
- compatible: Must be "generic-adc-thermal".
- temperature-lookup-table: Two dimensional array of Integer; lookup table
to map the relation between ADC value and
temperature. When ADC is read, the value is
looked up on the table to get the equivalent
temperature.
The first value of the each row of array is the
temperature in milliCelsius and second value of
the each row of array is the ADC read value.
- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description
of this property.
Example :
#include <dt-bindings/thermal/thermal.h>
i2c@7000c400 {
ads1015: ads1015@4a {
reg = <0x4a>;
compatible = "ads1015";
sampling-frequency = <3300>;
#io-channel-cells = <1>;
};
};
tboard_thermistor: thermal-sensor {
compatible = "generic-adc-thermal";
#thermal-sensor-cells = <0>;
io-channels = <&ads1015 1>;
io-channel-names = "sensor-channel";
temperature-lookup-table = < (-40000) 2578
(-39000) 2577
(-38000) 2576
(-37000) 2575
(-36000) 2574
(-35000) 2573
(-34000) 2572
(-33000) 2571
(-32000) 2569
(-31000) 2568
(-30000) 2567
::::::::::
118000 254
119000 247
120000 240
121000 233
122000 226
123000 220
124000 214
125000 208>;
};
dummy_cool_dev: dummy-cool-dev {
compatible = "dummy-cooling-dev";
#cooling-cells = <2>; /* min followed by max */
};
thermal-zones {
Tboard {
polling-delay = <15000>; /* milliseconds */
polling-delay-passive = <0>; /* milliseconds */
thermal-sensors = <&tboard_thermistor>;
trips {
therm_est_trip: therm_est_trip {
temperature = <40000>;
type = "active";
hysteresis = <1000>;
};
};
cooling-maps {
map0 {
trip = <&therm_est_trip>;
cooling-device = <&dummy_cool_dev THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <100>;
};
};
};
};
Documentation/thermal/sysfs-api.txt
View file @
88ac9906
...
...
@@ -69,8 +69,8 @@ temperature) and throttle appropriate devices.
1.1.2 void thermal_zone_device_unregister(struct thermal_zone_device *tz)
This interface function removes the thermal zone device.
It deletes the corresponding entry f
or
m /sys/class/thermal folder and
unbind all the thermal cooling devices it uses.
It deletes the corresponding entry f
ro
m /sys/class/thermal folder and
unbind
s
all the thermal cooling devices it uses.
1.1.3 struct thermal_zone_device *thermal_zone_of_sensor_register(
struct device *dev, int sensor_id, void *data,
...
...
@@ -146,32 +146,32 @@ temperature) and throttle appropriate devices.
This interface function adds a new thermal cooling device (fan/processor/...)
to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself
to all the thermal zone devices register at the same time.
to all the thermal zone devices register
ed
at the same time.
name: the cooling device name.
devdata: device private data.
ops: thermal cooling devices call-backs.
.get_max_state: get the Maximum throttle state of the cooling device.
.get_cur_state: get the Current throttle state of the cooling device.
.get_cur_state: get the Current
ly requested
throttle state of the cooling device.
.set_cur_state: set the Current throttle state of the cooling device.
1.2.2 void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
This interface function remove the thermal cooling device.
It deletes the corresponding entry f
or
m /sys/class/thermal folder and
unbind itself from all the thermal zone devices using it.
This interface function remove
s
the thermal cooling device.
It deletes the corresponding entry f
ro
m /sys/class/thermal folder and
unbind
s
itself from all the thermal zone devices using it.
1.3 interface for binding a thermal zone device with a thermal cooling device
1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
int trip, struct thermal_cooling_device *cdev,
unsigned long upper, unsigned long lower, unsigned int weight);
This interface function bind
a thermal cooling device to the certain
trip
This interface function bind
s a thermal cooling device to a particular
trip
point of a thermal zone device.
This function is usually called in the thermal zone device .bind callback.
tz: the thermal zone device
cdev: thermal cooling device
trip: indicates which trip point
the cooling devices is associated with
in this thermal zone
.
trip: indicates which trip point
in this thermal zone the cooling device
is associated with
.
upper:the Maximum cooling state for this trip point.
THERMAL_NO_LIMIT means no upper limit,
and the cooling device can be in max_state.
...
...
@@ -184,13 +184,13 @@ temperature) and throttle appropriate devices.
1.3.2 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
int trip, struct thermal_cooling_device *cdev);
This interface function unbind
a thermal cooling device from the certain
This interface function unbind
s a thermal cooling device from a particular
trip point of a thermal zone device. This function is usually called in
the thermal zone device .unbind callback.
tz: the thermal zone device
cdev: thermal cooling device
trip: indicates which trip point
the cooling devices is associated with
in this thermal zone
.
trip: indicates which trip point
in this thermal zone the cooling device
is associated with
.
1.4 Thermal Zone Parameters
1.4.1 struct thermal_bind_params
...
...
@@ -210,13 +210,13 @@ temperature) and throttle appropriate devices.
this thermal zone and cdev, for a particular trip point.
If nth bit is set, then the cdev and thermal zone are bound
for trip point n.
.
limits: This is an array of cooling state limits. Must have exactly
2 * thermal_zone.number_of_trip_points. It is an array consisting
of tuples <lower-state upper-state> of state limits. Each trip
will be associated with one state limit tuple when binding.
A NULL pointer means <THERMAL_NO_LIMITS THERMAL_NO_LIMITS>
on all trips. These limits are used when binding a cdev to a
trip point.
.
binding_limits: This is an array of cooling state limits. Must have
exactly 2 * thermal_zone.number_of_trip_points. It is an
array consisting of tuples <lower-state upper-state> of
state limits. Each trip will be associated with one state
limit tuple when binding. A NULL pointer means
<THERMAL_NO_LIMITS THERMAL_NO_LIMITS> on all trips.
These limits are used when binding a cdev to a
trip point.
.match: This call back returns success(0) if the 'tz and cdev' need to
be bound, as per platform data.
1.4.2 struct thermal_zone_params
...
...
@@ -351,8 +351,8 @@ cdev[0-*]
RO, Optional
cdev[0-*]_trip_point
The trip point
with which cdev[0-*] is associated in this thermal
zone
; -1 means the cooling device is not associated with any trip
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
...
...
MAINTAINERS
View file @
88ac9906
...
...
@@ -11046,6 +11046,7 @@ F: drivers/platform/x86/thinkpad_acpi.c
TI BANDGAP AND THERMAL DRIVER
M: Eduardo Valentin <edubezval@gmail.com>
M: Keerthy <j-keerthy@ti.com>
L: linux-pm@vger.kernel.org
L: linux-omap@vger.kernel.org
S: Maintained
...
...
drivers/cpufreq/mt8173-cpufreq.c
View file @
88ac9906
...
...
@@ -310,17 +310,24 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
return
0
;
}
#define DYNAMIC_POWER "dynamic-power-coefficient"
static
void
mtk_cpufreq_ready
(
struct
cpufreq_policy
*
policy
)
{
struct
mtk_cpu_dvfs_info
*
info
=
policy
->
driver_data
;
struct
device_node
*
np
=
of_node_get
(
info
->
cpu_dev
->
of_node
);
u32
capacitance
=
0
;
if
(
WARN_ON
(
!
np
))
return
;
if
(
of_find_property
(
np
,
"#cooling-cells"
,
NULL
))
{
info
->
cdev
=
of_cpufreq_cooling_register
(
np
,
policy
->
related_cpus
);
of_property_read_u32
(
np
,
DYNAMIC_POWER
,
&
capacitance
);
info
->
cdev
=
of_cpufreq_power_cooling_register
(
np
,
policy
->
related_cpus
,
capacitance
,
NULL
);
if
(
IS_ERR
(
info
->
cdev
))
{
dev_err
(
info
->
cpu_dev
,
...
...
drivers/hwmon/lm75.c
View file @
88ac9906
...
...
@@ -77,7 +77,6 @@ static const u8 LM75_REG_TEMP[3] = {
struct
lm75_data
{
struct
i2c_client
*
client
;
struct
device
*
hwmon_dev
;
struct
thermal_zone_device
*
tz
;
struct
mutex
update_lock
;
u8
orig_conf
;
u8
resolution
;
/* In bits, between 9 and 12 */
...
...
@@ -306,11 +305,9 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
if
(
IS_ERR
(
data
->
hwmon_dev
))
return
PTR_ERR
(
data
->
hwmon_dev
);
data
->
tz
=
thermal_zone_of_sensor_register
(
data
->
hwmon_dev
,
0
,
data
->
hwmon_dev
,
&
lm75_of_thermal_ops
);
if
(
IS_ERR
(
data
->
tz
))
data
->
tz
=
NULL
;
devm_thermal_zone_of_sensor_register
(
data
->
hwmon_dev
,
0
,
data
->
hwmon_dev
,
&
lm75_of_thermal_ops
);
dev_info
(
dev
,
"%s: sensor '%s'
\n
"
,
dev_name
(
data
->
hwmon_dev
),
client
->
name
);
...
...
@@ -322,7 +319,6 @@ static int lm75_remove(struct i2c_client *client)
{
struct
lm75_data
*
data
=
i2c_get_clientdata
(
client
);
thermal_zone_of_sensor_unregister
(
data
->
hwmon_dev
,
data
->
tz
);
hwmon_device_unregister
(
data
->
hwmon_dev
);
lm75_write_value
(
client
,
LM75_REG_CONF
,
data
->
orig_conf
);
return
0
;
...
...
drivers/hwmon/ntc_thermistor.c
View file @
88ac9906
...
...
@@ -259,7 +259,6 @@ struct ntc_data {
struct
device
*
dev
;
int
n_comp
;
char
name
[
PLATFORM_NAME_SIZE
];
struct
thermal_zone_device
*
tz
;
};
#if defined(CONFIG_OF) && IS_ENABLED(CONFIG_IIO)
...
...
@@ -579,6 +578,7 @@ static const struct thermal_zone_of_device_ops ntc_of_thermal_ops = {
static
int
ntc_thermistor_probe
(
struct
platform_device
*
pdev
)
{
struct
thermal_zone_device
*
tz
;
const
struct
of_device_id
*
of_id
=
of_match_device
(
of_match_ptr
(
ntc_match
),
&
pdev
->
dev
);
const
struct
platform_device_id
*
pdev_id
;
...
...
@@ -677,12 +677,10 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
dev_info
(
&
pdev
->
dev
,
"Thermistor type: %s successfully probed.
\n
"
,
pdev_id
->
name
);
data
->
tz
=
thermal_zone_of_sensor_register
(
data
->
dev
,
0
,
data
->
dev
,
&
ntc_of_thermal_ops
);
if
(
IS_ERR
(
data
->
tz
))
{
tz
=
devm_
thermal_zone_of_sensor_register
(
data
->
dev
,
0
,
data
->
dev
,
&
ntc_of_thermal_ops
);
if
(
IS_ERR
(
tz
))
dev_dbg
(
&
pdev
->
dev
,
"Failed to register to thermal fw.
\n
"
);
data
->
tz
=
NULL
;
}
return
0
;
err_after_sysfs:
...
...
@@ -700,8 +698,6 @@ static int ntc_thermistor_remove(struct platform_device *pdev)
sysfs_remove_group
(
&
data
->
dev
->
kobj
,
&
ntc_attr_group
);
ntc_iio_channel_release
(
pdata
);
thermal_zone_of_sensor_unregister
(
data
->
dev
,
data
->
tz
);
return
0
;
}
...
...
drivers/hwmon/scpi-hwmon.c
View file @
88ac9906
...
...
@@ -31,10 +31,8 @@ struct sensor_data {
};
struct
scpi_thermal_zone
{
struct
list_head
list
;
int
sensor_id
;
struct
scpi_sensors
*
scpi_sensors
;
struct
thermal_zone_device
*
tzd
;
};
struct
scpi_sensors
{
...
...
@@ -92,20 +90,6 @@ scpi_show_label(struct device *dev, struct device_attribute *attr, char *buf)
return
sprintf
(
buf
,
"%s
\n
"
,
sensor
->
info
.
name
);
}
static
void
unregister_thermal_zones
(
struct
platform_device
*
pdev
,
struct
scpi_sensors
*
scpi_sensors
)
{
struct
list_head
*
pos
;
list_for_each
(
pos
,
&
scpi_sensors
->
thermal_zones
)
{
struct
scpi_thermal_zone
*
zone
;
zone
=
list_entry
(
pos
,
struct
scpi_thermal_zone
,
list
);
thermal_zone_of_sensor_unregister
(
&
pdev
->
dev
,
zone
->
tzd
);
}
}
static
struct
thermal_zone_of_device_ops
scpi_sensor_ops
=
{
.
get_temp
=
scpi_read_temp
,
};
...
...
@@ -118,7 +102,7 @@ static int scpi_hwmon_probe(struct platform_device *pdev)
struct
scpi_ops
*
scpi_ops
;
struct
device
*
hwdev
,
*
dev
=
&
pdev
->
dev
;
struct
scpi_sensors
*
scpi_sensors
;
int
ret
,
idx
;
int
idx
,
ret
;
scpi_ops
=
get_scpi_ops
();
if
(
!
scpi_ops
)
...
...
@@ -232,47 +216,34 @@ static int scpi_hwmon_probe(struct platform_device *pdev)
INIT_LIST_HEAD
(
&
scpi_sensors
->
thermal_zones
);
for
(
i
=
0
;
i
<
nr_sensors
;
i
++
)
{
struct
sensor_data
*
sensor
=
&
scpi_sensors
->
data
[
i
];
struct
thermal_zone_device
*
z
;
struct
scpi_thermal_zone
*
zone
;
if
(
sensor
->
info
.
class
!=
TEMPERATURE
)
continue
;
zone
=
devm_kzalloc
(
dev
,
sizeof
(
*
zone
),
GFP_KERNEL
);
if
(
!
zone
)
{
ret
=
-
ENOMEM
;
goto
unregister_tzd
;
}
if
(
!
zone
)
return
-
ENOMEM
;
zone
->
sensor_id
=
i
;
zone
->
scpi_sensors
=
scpi_sensors
;
zone
->
tzd
=
thermal_zone_of_sensor_register
(
dev
,
sensor
->
info
.
sensor_id
,
zone
,
&
scpi_sensor_ops
);
z
=
devm_thermal_zone_of_sensor_register
(
dev
,
sensor
->
info
.
sensor_id
,
zone
,
&
scpi_sensor_ops
);
/*
* The call to thermal_zone_of_sensor_register returns
* an error for sensors that are not associated with
* any thermal zones or if the thermal subsystem is
* not configured.
*/
if
(
IS_ERR
(
z
one
->
tzd
))
{
if
(
IS_ERR
(
z
))
{
devm_kfree
(
dev
,
zone
);
continue
;
}
list_add
(
&
zone
->
list
,
&
scpi_sensors
->
thermal_zones
);
}
return
0
;
unregister_tzd:
unregister_thermal_zones
(
pdev
,
scpi_sensors
);
return
ret
;
}
static
int
scpi_hwmon_remove
(
struct
platform_device
*
pdev
)
{
struct
scpi_sensors
*
scpi_sensors
=
platform_get_drvdata
(
pdev
);
unregister_thermal_zones
(
pdev
,
scpi_sensors
);
return
0
;
}
...
...
@@ -288,7 +259,6 @@ static struct platform_driver scpi_hwmon_platdrv = {
.
of_match_table
=
scpi_of_match
,
},
.
probe
=
scpi_hwmon_probe
,
.
remove
=
scpi_hwmon_remove
,
};
module_platform_driver
(
scpi_hwmon_platdrv
);
...
...
drivers/hwmon/tmp102.c
View file @
88ac9906
...
...
@@ -53,7 +53,6 @@
struct
tmp102
{
struct
i2c_client
*
client
;
struct
device
*
hwmon_dev
;
struct
thermal_zone_device
*
tz
;
struct
mutex
lock
;
u16
config_orig
;
unsigned
long
last_update
;
...
...
@@ -232,10 +231,8 @@ static int tmp102_probe(struct i2c_client *client,
goto
fail_restore_config
;
}
tmp102
->
hwmon_dev
=
hwmon_dev
;
tmp102
->
tz
=
thermal_zone_of_sensor_register
(
hwmon_dev
,
0
,
hwmon_dev
,
&
tmp102_of_thermal_ops
);
if
(
IS_ERR
(
tmp102
->
tz
))
tmp102
->
tz
=
NULL
;
devm_thermal_zone_of_sensor_register
(
hwmon_dev
,
0
,
hwmon_dev
,
&
tmp102_of_thermal_ops
);
dev_info
(
dev
,
"initialized
\n
"
);
...
...
@@ -251,7 +248,6 @@ static int tmp102_remove(struct i2c_client *client)
{
struct
tmp102
*
tmp102
=
i2c_get_clientdata
(
client
);
thermal_zone_of_sensor_unregister
(
tmp102
->
hwmon_dev
,
tmp102
->
tz
);
hwmon_device_unregister
(
tmp102
->
hwmon_dev
);
/* Stop monitoring if device was stopped originally */
...
...
drivers/input/touchscreen/sun4i-ts.c
View file @
88ac9906
...
...
@@ -115,7 +115,6 @@
struct
sun4i_ts_data
{
struct
device
*
dev
;
struct
input_dev
*
input
;
struct
thermal_zone_device
*
tz
;
void
__iomem
*
base
;
unsigned
int
irq
;
bool
ignore_fifo_data
;
...
...
@@ -366,10 +365,7 @@ static int sun4i_ts_probe(struct platform_device *pdev)
if
(
IS_ERR
(
hwmon
))
return
PTR_ERR
(
hwmon
);
ts
->
tz
=
thermal_zone_of_sensor_register
(
ts
->
dev
,
0
,
ts
,
&
sun4i_ts_tz_ops
);
if
(
IS_ERR
(
ts
->
tz
))
ts
->
tz
=
NULL
;
devm_thermal_zone_of_sensor_register
(
ts
->
dev
,
0
,
ts
,
&
sun4i_ts_tz_ops
);
writel
(
TEMP_IRQ_EN
(
1
),
ts
->
base
+
TP_INT_FIFOC
);
...
...
@@ -377,7 +373,6 @@ static int sun4i_ts_probe(struct platform_device *pdev)
error
=
input_register_device
(
ts
->
input
);
if
(
error
)
{
writel
(
0
,
ts
->
base
+
TP_INT_FIFOC
);
thermal_zone_of_sensor_unregister
(
ts
->
dev
,
ts
->
tz
);
return
error
;
}
}
...
...
@@ -394,8 +389,6 @@ static int sun4i_ts_remove(struct platform_device *pdev)
if
(
ts
->
input
)
input_unregister_device
(
ts
->
input
);
thermal_zone_of_sensor_unregister
(
ts
->
dev
,
ts
->
tz
);
/* Deactivate all IRQs */
writel
(
0
,
ts
->
base
+
TP_INT_FIFOC
);
...
...
drivers/thermal/Kconfig
View file @
88ac9906
...
...
@@ -260,16 +260,6 @@ config ARMADA_THERMAL
Enable this option if you want to have support for thermal management
controller present in Armada 370 and Armada XP SoC.
config TEGRA_SOCTHERM
tristate "Tegra SOCTHERM thermal management"
depends on ARCH_TEGRA
help
Enable this option for integrated thermal management support on NVIDIA
Tegra124 systems-on-chip. The driver supports four thermal zones
(CPU, GPU, MEM, PLLX). Cooling devices can be bound to the thermal
zones to manage temperatures. This option is also required for the
emergency thermal reset (thermtrip) feature to function.
config DB8500_CPUFREQ_COOLING
tristate "DB8500 cpufreq cooling"
depends on ARCH_U8500 || COMPILE_TEST
...
...
@@ -399,6 +389,17 @@ depends on ARCH_STI && OF
source "drivers/thermal/st/Kconfig"
endmenu
config TANGO_THERMAL
tristate "Tango thermal management"
depends on ARCH_TANGO || COMPILE_TEST
help
Enable the Tango thermal driver, which supports the primitive
temperature sensor embedded in Tango chips since the SMP8758.
This sensor only generates a 1-bit signal to indicate whether
the die temperature exceeds a programmable threshold.
source "drivers/thermal/tegra/Kconfig"
config QCOM_SPMI_TEMP_ALARM
tristate "Qualcomm SPMI PMIC Temperature Alarm"
depends on OF && SPMI && IIO
...
...
@@ -410,4 +411,14 @@ config QCOM_SPMI_TEMP_ALARM
real time die temperature if an ADC is present or an estimate of the
temperature based upon the over temperature stage value.
config GENERIC_ADC_THERMAL
tristate "Generic ADC based thermal sensor"
depends on IIO
help
This enabled a thermal sysfs driver for the temperature sensor
which is connected to the General Purpose ADC. The ADC channel
is read via IIO framework and the channel information is provided
to this driver. This driver reports the temperature by reading ADC
channel and converts it to temperature based on lookup table.
endif
drivers/thermal/Makefile
View file @
88ac9906
...
...
@@ -35,6 +35,7 @@ obj-y += samsung/
obj-$(CONFIG_DOVE_THERMAL)
+=
dove_thermal.o
obj-$(CONFIG_DB8500_THERMAL)
+=
db8500_thermal.o
obj-$(CONFIG_ARMADA_THERMAL)
+=
armada_thermal.o
obj-$(CONFIG_TANGO_THERMAL)
+=
tango_thermal.o
obj-$(CONFIG_IMX_THERMAL)
+=
imx_thermal.o
obj-$(CONFIG_DB8500_CPUFREQ_COOLING)
+=
db8500_cpufreq_cooling.o
obj-$(CONFIG_INTEL_POWERCLAMP)
+=
intel_powerclamp.o
...
...
@@ -46,6 +47,7 @@ obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
obj-$(CONFIG_INT340X_THERMAL)
+=
int340x_thermal/
obj-$(CONFIG_INTEL_PCH_THERMAL)
+=
intel_pch_thermal.o
obj-$(CONFIG_ST_THERMAL)
+=
st/
obj-$(CONFIG_TEGRA_SOCTHERM)
+=
tegra
_soctherm.o
obj-$(CONFIG_TEGRA_SOCTHERM)
+=
tegra
/
obj-$(CONFIG_HISI_THERMAL)
+=
hisi_thermal.o
obj-$(CONFIG_MTK_THERMAL)
+=
mtk_thermal.o
obj-$(CONFIG_GENERIC_ADC_THERMAL)
+=
thermal-generic-adc.o
drivers/thermal/hisi_thermal.c
View file @
88ac9906
...
...
@@ -160,7 +160,7 @@ static int hisi_thermal_get_temp(void *_sensor, int *temp)
struct
hisi_thermal_sensor
*
sensor
=
_sensor
;
struct
hisi_thermal_data
*
data
=
sensor
->
thermal
;
int
sensor_id
=
0
,
i
;
int
sensor_id
=
-
1
,
i
;
long
max_temp
=
0
;
*
temp
=
hisi_thermal_get_sensor_temp
(
data
,
sensor
);
...
...
@@ -168,12 +168,19 @@ static int hisi_thermal_get_temp(void *_sensor, int *temp)
sensor
->
sensor_temp
=
*
temp
;
for
(
i
=
0
;
i
<
HISI_MAX_SENSORS
;
i
++
)
{
if
(
!
data
->
sensors
[
i
].
tzd
)
continue
;
if
(
data
->
sensors
[
i
].
sensor_temp
>=
max_temp
)
{
max_temp
=
data
->
sensors
[
i
].
sensor_temp
;
sensor_id
=
i
;
}
}
/* If no sensor has been enabled, then skip to enable irq */
if
(
sensor_id
==
-
1
)
return
0
;
mutex_lock
(
&
data
->
thermal_lock
);
data
->
irq_bind_sensor
=
sensor_id
;
mutex_unlock
(
&
data
->
thermal_lock
);
...
...
@@ -226,8 +233,12 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev)
sensor
->
thres_temp
/
1000
);
mutex_unlock
(
&
data
->
thermal_lock
);
for
(
i
=
0
;
i
<
HISI_MAX_SENSORS
;
i
++
)
for
(
i
=
0
;
i
<
HISI_MAX_SENSORS
;
i
++
)
{
if
(
!
data
->
sensors
[
i
].
tzd
)
continue
;
thermal_zone_device_update
(
data
->
sensors
[
i
].
tzd
);
}
return
IRQ_HANDLED
;
}
...
...
@@ -243,10 +254,11 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev,
sensor
->
id
=
index
;
sensor
->
thermal
=
data
;
sensor
->
tzd
=
thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
sensor
->
id
,
sensor
,
&
hisi_of_thermal_ops
);
sensor
->
tzd
=
devm_thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
sensor
->
id
,
sensor
,
&
hisi_of_thermal_ops
);
if
(
IS_ERR
(
sensor
->
tzd
))
{
ret
=
PTR_ERR
(
sensor
->
tzd
);
sensor
->
tzd
=
NULL
;
dev_err
(
&
pdev
->
dev
,
"failed to register sensor id %d: %d
\n
"
,
sensor
->
id
,
ret
);
return
ret
;
...
...
@@ -331,28 +343,21 @@ static int hisi_thermal_probe(struct platform_device *pdev)
return
ret
;
}
hisi_thermal_enable_bind_irq_sensor
(
data
);
irq_get_irqchip_state
(
data
->
irq
,
IRQCHIP_STATE_MASKED
,
&
data
->
irq_enabled
);
for
(
i
=
0
;
i
<
HISI_MAX_SENSORS
;
++
i
)
{
ret
=
hisi_thermal_register_sensor
(
pdev
,
data
,
&
data
->
sensors
[
i
],
i
);
if
(
ret
)
{
if
(
ret
)
dev_err
(
&
pdev
->
dev
,
"failed to register thermal sensor: %d
\n
"
,
ret
);
goto
err_get_sensor_data
;
}
else
hisi_thermal_toggle_sensor
(
&
data
->
sensors
[
i
],
true
);
}
hisi_thermal_enable_bind_irq_sensor
(
data
);
data
->
irq_enabled
=
true
;
for
(
i
=
0
;
i
<
HISI_MAX_SENSORS
;
i
++
)
hisi_thermal_toggle_sensor
(
&
data
->
sensors
[
i
],
true
);
return
0
;
err_get_sensor_data:
clk_disable_unprepare
(
data
->
clk
);
return
ret
;
}
static
int
hisi_thermal_remove
(
struct
platform_device
*
pdev
)
...
...
@@ -363,8 +368,10 @@ static int hisi_thermal_remove(struct platform_device *pdev)
for
(
i
=
0
;
i
<
HISI_MAX_SENSORS
;
i
++
)
{
struct
hisi_thermal_sensor
*
sensor
=
&
data
->
sensors
[
i
];
if
(
!
sensor
->
tzd
)
continue
;
hisi_thermal_toggle_sensor
(
sensor
,
false
);
thermal_zone_of_sensor_unregister
(
&
pdev
->
dev
,
sensor
->
tzd
);
}
hisi_thermal_disable_sensor
(
data
);
...
...
drivers/thermal/int340x_thermal/processor_thermal_device.c
View file @
88ac9906
...
...
@@ -198,49 +198,33 @@ static struct thermal_zone_device_ops proc_thermal_local_ops = {
.
get_temp
=
proc_thermal_get_zone_temp
,
};
static
int
proc_thermal_add
(
struct
device
*
dev
,
struct
proc_thermal_device
**
priv
)
static
int
proc_thermal_read_ppcc
(
struct
proc_thermal_device
*
proc_priv
)
{
struct
proc_thermal_device
*
proc_priv
;
struct
acpi_device
*
adev
;
int
i
;
acpi_status
status
;
struct
acpi_buffer
buf
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
union
acpi_object
*
elements
,
*
ppcc
;
union
acpi_object
*
p
;
unsigned
long
long
tmp
;
struct
thermal_zone_device_ops
*
ops
=
NULL
;
int
i
;
int
ret
;
adev
=
ACPI_COMPANION
(
dev
);
if
(
!
adev
)
return
-
ENODEV
;
int
ret
=
0
;
status
=
acpi_evaluate_object
(
adev
->
handle
,
"PPCC"
,
NULL
,
&
buf
);
status
=
acpi_evaluate_object
(
proc_priv
->
adev
->
handle
,
"PPCC"
,
NULL
,
&
buf
);
if
(
ACPI_FAILURE
(
status
))
return
-
ENODEV
;
p
=
buf
.
pointer
;
if
(
!
p
||
(
p
->
type
!=
ACPI_TYPE_PACKAGE
))
{
dev_err
(
dev
,
"Invalid PPCC data
\n
"
);
dev_err
(
proc_priv
->
dev
,
"Invalid PPCC data
\n
"
);
ret
=
-
EFAULT
;
goto
free_buffer
;
}
if
(
!
p
->
package
.
count
)
{
dev_err
(
dev
,
"Invalid PPCC package size
\n
"
);
dev_err
(
proc_priv
->
dev
,
"Invalid PPCC package size
\n
"
);
ret
=
-
EFAULT
;
goto
free_buffer
;
}
proc_priv
=
devm_kzalloc
(
dev
,
sizeof
(
*
proc_priv
),
GFP_KERNEL
);
if
(
!
proc_priv
)
{
ret
=
-
ENOMEM
;
goto
free_buffer
;
}
proc_priv
->
dev
=
dev
;
proc_priv
->
adev
=
adev
;
for
(
i
=
0
;
i
<
min
((
int
)
p
->
package
.
count
-
1
,
2
);
++
i
)
{
elements
=
&
(
p
->
package
.
elements
[
i
+
1
]);
if
(
elements
->
type
!=
ACPI_TYPE_PACKAGE
||
...
...
@@ -257,12 +241,62 @@ static int proc_thermal_add(struct device *dev,
proc_priv
->
power_limits
[
i
].
step_uw
=
ppcc
[
5
].
integer
.
value
;
}
free_buffer:
kfree
(
buf
.
pointer
);
return
ret
;
}
#define PROC_POWER_CAPABILITY_CHANGED 0x83
static
void
proc_thermal_notify
(
acpi_handle
handle
,
u32
event
,
void
*
data
)
{
struct
proc_thermal_device
*
proc_priv
=
data
;
if
(
!
proc_priv
)
return
;
switch
(
event
)
{
case
PROC_POWER_CAPABILITY_CHANGED
:
proc_thermal_read_ppcc
(
proc_priv
);
int340x_thermal_zone_device_update
(
proc_priv
->
int340x_zone
);
break
;
default:
dev_err
(
proc_priv
->
dev
,
"Unsupported event [0x%x]
\n
"
,
event
);
break
;
}
}
static
int
proc_thermal_add
(
struct
device
*
dev
,
struct
proc_thermal_device
**
priv
)
{
struct
proc_thermal_device
*
proc_priv
;
struct
acpi_device
*
adev
;
acpi_status
status
;
unsigned
long
long
tmp
;
struct
thermal_zone_device_ops
*
ops
=
NULL
;
int
ret
;
adev
=
ACPI_COMPANION
(
dev
);
if
(
!
adev
)
return
-
ENODEV
;
proc_priv
=
devm_kzalloc
(
dev
,
sizeof
(
*
proc_priv
),
GFP_KERNEL
);
if
(
!
proc_priv
)
return
-
ENOMEM
;
proc_priv
->
dev
=
dev
;
proc_priv
->
adev
=
adev
;
*
priv
=
proc_priv
;
ret
=
sysfs_create_group
(
&
dev
->
kobj
,
&
power_limit_attribute_group
);
ret
=
proc_thermal_read_ppcc
(
proc_priv
);
if
(
!
ret
)
{
ret
=
sysfs_create_group
(
&
dev
->
kobj
,
&
power_limit_attribute_group
);
}
if
(
ret
)
goto
free_buffer
;
return
ret
;
status
=
acpi_evaluate_integer
(
adev
->
handle
,
"_TMP"
,
NULL
,
&
tmp
);
if
(
ACPI_FAILURE
(
status
))
{
...
...
@@ -274,20 +308,32 @@ static int proc_thermal_add(struct device *dev,
proc_priv
->
int340x_zone
=
int340x_thermal_zone_add
(
adev
,
ops
);
if
(
IS_ERR
(
proc_priv
->
int340x_zone
))
{
sysfs_remove_group
(
&
proc_priv
->
dev
->
kobj
,
&
power_limit_attribute_group
);
ret
=
PTR_ERR
(
proc_priv
->
int340x_zone
);
goto
remove_group
;
}
else
ret
=
0
;
free_buffer:
kfree
(
buf
.
pointer
);
ret
=
acpi_install_notify_handler
(
adev
->
handle
,
ACPI_DEVICE_NOTIFY
,
proc_thermal_notify
,
(
void
*
)
proc_priv
);
if
(
ret
)
goto
remove_zone
;
return
0
;
remove_zone:
int340x_thermal_zone_remove
(
proc_priv
->
int340x_zone
);
remove_group:
sysfs_remove_group
(
&
proc_priv
->
dev
->
kobj
,
&
power_limit_attribute_group
);
return
ret
;
}
static
void
proc_thermal_remove
(
struct
proc_thermal_device
*
proc_priv
)
{
acpi_remove_notify_handler
(
proc_priv
->
adev
->
handle
,
ACPI_DEVICE_NOTIFY
,
proc_thermal_notify
);
int340x_thermal_zone_remove
(
proc_priv
->
int340x_zone
);
sysfs_remove_group
(
&
proc_priv
->
dev
->
kobj
,
&
power_limit_attribute_group
);
...
...
drivers/thermal/intel_powerclamp.c
View file @
88ac9906
...
...
@@ -510,12 +510,6 @@ static int start_power_clamp(void)
unsigned
long
cpu
;
struct
task_struct
*
thread
;
/* check if pkg cstate counter is completely 0, abort in this case */
if
(
!
has_pkg_state_counter
())
{
pr_err
(
"pkg cstate counter not functional, abort
\n
"
);
return
-
EINVAL
;
}
set_target_ratio
=
clamp
(
set_target_ratio
,
0U
,
MAX_TARGET_RATIO
-
1
);
/* prevent cpu hotplug */
get_online_cpus
();
...
...
@@ -672,35 +666,11 @@ static struct thermal_cooling_device_ops powerclamp_cooling_ops = {
.
set_cur_state
=
powerclamp_set_cur_state
,
};
/* runs on Nehalem and later */
static
const
struct
x86_cpu_id
intel_powerclamp_ids
[]
__initconst
=
{
{
X86_VENDOR_INTEL
,
6
,
0x1a
},
{
X86_VENDOR_INTEL
,
6
,
0x1c
},
{
X86_VENDOR_INTEL
,
6
,
0x1e
},
{
X86_VENDOR_INTEL
,
6
,
0x1f
},
{
X86_VENDOR_INTEL
,
6
,
0x25
},
{
X86_VENDOR_INTEL
,
6
,
0x26
},
{
X86_VENDOR_INTEL
,
6
,
0x2a
},
{
X86_VENDOR_INTEL
,
6
,
0x2c
},
{
X86_VENDOR_INTEL
,
6
,
0x2d
},
{
X86_VENDOR_INTEL
,
6
,
0x2e
},
{
X86_VENDOR_INTEL
,
6
,
0x2f
},
{
X86_VENDOR_INTEL
,
6
,
0x37
},
{
X86_VENDOR_INTEL
,
6
,
0x3a
},
{
X86_VENDOR_INTEL
,
6
,
0x3c
},
{
X86_VENDOR_INTEL
,
6
,
0x3d
},
{
X86_VENDOR_INTEL
,
6
,
0x3e
},
{
X86_VENDOR_INTEL
,
6
,
0x3f
},
{
X86_VENDOR_INTEL
,
6
,
0x45
},
{
X86_VENDOR_INTEL
,
6
,
0x46
},
{
X86_VENDOR_INTEL
,
6
,
0x47
},
{
X86_VENDOR_INTEL
,
6
,
0x4c
},
{
X86_VENDOR_INTEL
,
6
,
0x4d
},
{
X86_VENDOR_INTEL
,
6
,
0x4e
},
{
X86_VENDOR_INTEL
,
6
,
0x4f
},
{
X86_VENDOR_INTEL
,
6
,
0x56
},
{
X86_VENDOR_INTEL
,
6
,
0x57
},
{
X86_VENDOR_INTEL
,
6
,
0x5e
},
{
X86_VENDOR_INTEL
,
X86_FAMILY_ANY
,
X86_MODEL_ANY
,
X86_FEATURE_MWAIT
},
{
X86_VENDOR_INTEL
,
X86_FAMILY_ANY
,
X86_MODEL_ANY
,
X86_FEATURE_ARAT
},
{
X86_VENDOR_INTEL
,
X86_FAMILY_ANY
,
X86_MODEL_ANY
,
X86_FEATURE_NONSTOP_TSC
},
{
X86_VENDOR_INTEL
,
X86_FAMILY_ANY
,
X86_MODEL_ANY
,
X86_FEATURE_CONSTANT_TSC
},
{}
};
MODULE_DEVICE_TABLE
(
x86cpu
,
intel_powerclamp_ids
);
...
...
@@ -712,11 +682,12 @@ static int __init powerclamp_probe(void)
boot_cpu_data
.
x86
,
boot_cpu_data
.
x86_model
);
return
-
ENODEV
;
}
if
(
!
boot_cpu_has
(
X86_FEATURE_NONSTOP_TSC
)
||
!
boot_cpu_has
(
X86_FEATURE_CONSTANT_TSC
)
||
!
boot_cpu_has
(
X86_FEATURE_MWAIT
)
||
!
boot_cpu_has
(
X86_FEATURE_ARAT
))
/* The goal for idle time alignment is to achieve package cstate. */
if
(
!
has_pkg_state_counter
())
{
pr_info
(
"No package C-state available"
);
return
-
ENODEV
;
}
/* find the deepest mwait value */
find_target_mwait
();
...
...
drivers/thermal/mtk_thermal.c
View file @
88ac9906
...
...
@@ -144,7 +144,6 @@ struct mtk_thermal {
s32
o_slope
;
s32
vts
[
MT8173_NUM_SENSORS
];
struct
thermal_zone_device
*
tzd
;
};
struct
mtk_thermal_bank_cfg
{
...
...
@@ -572,16 +571,11 @@ static int mtk_thermal_probe(struct platform_device *pdev)
platform_set_drvdata
(
pdev
,
mt
);
mt
->
tzd
=
thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
0
,
mt
,
&
mtk_thermal_ops
);
if
(
IS_ERR
(
mt
->
tzd
))
goto
err_register
;
devm_thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
0
,
mt
,
&
mtk_thermal_ops
);
return
0
;
err_register:
clk_disable_unprepare
(
mt
->
clk_peri_therm
);
err_disable_clk_auxadc:
clk_disable_unprepare
(
mt
->
clk_auxadc
);
...
...
@@ -592,8 +586,6 @@ static int mtk_thermal_remove(struct platform_device *pdev)
{
struct
mtk_thermal
*
mt
=
platform_get_drvdata
(
pdev
);
thermal_zone_of_sensor_unregister
(
&
pdev
->
dev
,
mt
->
tzd
);
clk_disable_unprepare
(
mt
->
clk_peri_therm
);
clk_disable_unprepare
(
mt
->
clk_auxadc
);
...
...
drivers/thermal/of-thermal.c
View file @
88ac9906
...
...
@@ -331,6 +331,14 @@ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
if
(
trip
>=
data
->
ntrips
||
trip
<
0
)
return
-
EDOM
;
if
(
data
->
ops
->
set_trip_temp
)
{
int
ret
;
ret
=
data
->
ops
->
set_trip_temp
(
data
->
sensor_data
,
trip
,
temp
);
if
(
ret
)
return
ret
;
}
/* thermal framework should take care of data->mask & (1 << trip) */
data
->
trips
[
trip
].
temperature
=
temp
;
...
...
@@ -906,7 +914,7 @@ __init *thermal_of_build_thermal_zone(struct device_node *np)
return
tz
;
free_tbps:
for
(
i
=
0
;
i
<
tz
->
num_tbps
;
i
++
)
for
(
i
=
i
-
1
;
i
>=
0
;
i
--
)
of_node_put
(
tz
->
tbps
[
i
].
cooling_device
);
kfree
(
tz
->
tbps
);
free_trips:
...
...
drivers/thermal/qcom-spmi-temp-alarm.c
View file @
88ac9906
...
...
@@ -260,7 +260,7 @@ static int qpnp_tm_probe(struct platform_device *pdev)
if
(
ret
<
0
)
goto
fail
;
chip
->
tz_dev
=
thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
0
,
chip
,
chip
->
tz_dev
=
devm_
thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
0
,
chip
,
&
qpnp_tm_sensor_ops
);
if
(
IS_ERR
(
chip
->
tz_dev
))
{
dev_err
(
&
pdev
->
dev
,
"failed to register sensor
\n
"
);
...
...
@@ -281,7 +281,6 @@ static int qpnp_tm_remove(struct platform_device *pdev)
{
struct
qpnp_tm_chip
*
chip
=
dev_get_drvdata
(
&
pdev
->
dev
);
thermal_zone_of_sensor_unregister
(
&
pdev
->
dev
,
chip
->
tz_dev
);
if
(
!
IS_ERR
(
chip
->
adc
))
iio_channel_release
(
chip
->
adc
);
...
...
drivers/thermal/rcar_thermal.c
View file @
88ac9906
...
...
@@ -492,7 +492,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
goto
error_unregister
;
if
(
of_data
==
USE_OF_THERMAL
)
priv
->
zone
=
thermal_zone_of_sensor_register
(
priv
->
zone
=
devm_
thermal_zone_of_sensor_register
(
dev
,
i
,
priv
,
&
rcar_thermal_zone_of_ops
);
else
...
...
drivers/thermal/rockchip_thermal.c
View file @
88ac9906
/*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
*
* Copyright (c) 2015, Fuzhou Rockchip Electronics Co., Ltd
* Copyright (c) 2014-2016, Fuzhou Rockchip Electronics Co., Ltd
* Caesar Wang <wxt@rock-chips.com>
*
* This program is free software; you can redistribute it and/or modify it
...
...
@@ -23,8 +21,10 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/thermal.h>
#include <linux/mfd/syscon.h>
#include <linux/pinctrl/consumer.h>
/**
...
...
@@ -73,7 +73,7 @@ enum adc_sort_mode {
#define SOC_MAX_SENSORS 2
/**
* struct chip_tsadc_table
:
hold information about chip-specific differences
* struct chip_tsadc_table
-
hold information about chip-specific differences
* @id: conversion table
* @length: size of conversion table
* @data_mask: mask to apply on data inputs
...
...
@@ -86,6 +86,20 @@ struct chip_tsadc_table {
enum
adc_sort_mode
mode
;
};
/**
* struct rockchip_tsadc_chip - hold the private data of tsadc chip
* @chn_id[SOC_MAX_SENSORS]: the sensor id of chip correspond to the channel
* @chn_num: the channel number of tsadc chip
* @tshut_temp: the hardware-controlled shutdown temperature value
* @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO)
* @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
* @initialize: SoC special initialize tsadc controller method
* @irq_ack: clear the interrupt
* @get_temp: get the temperature
* @set_tshut_temp: set the hardware-controlled shutdown temperature
* @set_tshut_mode: set the hardware-controlled shutdown mode
* @table: the chip-specific conversion table
*/
struct
rockchip_tsadc_chip
{
/* The sensor id of chip correspond to the ADC channel */
int
chn_id
[
SOC_MAX_SENSORS
];
...
...
@@ -97,7 +111,8 @@ struct rockchip_tsadc_chip {
enum
tshut_polarity
tshut_polarity
;
/* Chip-wide methods */
void
(
*
initialize
)(
void
__iomem
*
reg
,
enum
tshut_polarity
p
);
void
(
*
initialize
)(
struct
regmap
*
grf
,
void
__iomem
*
reg
,
enum
tshut_polarity
p
);
void
(
*
irq_ack
)(
void
__iomem
*
reg
);
void
(
*
control
)(
void
__iomem
*
reg
,
bool
on
);
...
...
@@ -112,12 +127,32 @@ struct rockchip_tsadc_chip {
struct
chip_tsadc_table
table
;
};
/**
* struct rockchip_thermal_sensor - hold the information of thermal sensor
* @thermal: pointer to the platform/configuration data
* @tzd: pointer to a thermal zone
* @id: identifier of the thermal sensor
*/
struct
rockchip_thermal_sensor
{
struct
rockchip_thermal_data
*
thermal
;
struct
thermal_zone_device
*
tzd
;
int
id
;
};
/**
* struct rockchip_thermal_data - hold the private data of thermal driver
* @chip: pointer to the platform/configuration data
* @pdev: platform device of thermal
* @reset: the reset controller of tsadc
* @sensors[SOC_MAX_SENSORS]: the thermal sensor
* @clk: the controller clock is divided by the exteral 24MHz
* @pclk: the advanced peripherals bus clock
* @grf: the general register file will be used to do static set by software
* @regs: the base address of tsadc controller
* @tshut_temp: the hardware-controlled shutdown temperature value
* @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO)
* @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
*/
struct
rockchip_thermal_data
{
const
struct
rockchip_tsadc_chip
*
chip
;
struct
platform_device
*
pdev
;
...
...
@@ -128,6 +163,7 @@ struct rockchip_thermal_data {
struct
clk
*
clk
;
struct
clk
*
pclk
;
struct
regmap
*
grf
;
void
__iomem
*
regs
;
int
tshut_temp
;
...
...
@@ -142,6 +178,7 @@ struct rockchip_thermal_data {
* TSADCV3_* are used for newer SoCs than RK3288. (e.g: RK3228, RK3399)
*
*/
#define TSADCV2_USER_CON 0x00
#define TSADCV2_AUTO_CON 0x04
#define TSADCV2_INT_EN 0x08
#define TSADCV2_INT_PD 0x0c
...
...
@@ -155,12 +192,7 @@ struct rockchip_thermal_data {
#define TSADCV2_AUTO_EN BIT(0)
#define TSADCV2_AUTO_SRC_EN(chn) BIT(4 + (chn))
#define TSADCV2_AUTO_TSHUT_POLARITY_HIGH BIT(8)
/**
* TSADCV1_AUTO_Q_SEL_EN:
* whether select (1024 - tsadc_q) as output
* 1'b0:use tsadc_q as output(temperature-code is rising sequence)
* 1'b1:use(1024 - tsadc_q) as output (temperature-code is falling sequence)
*/
#define TSADCV3_AUTO_Q_SEL_EN BIT(1)
#define TSADCV2_INT_SRC_EN(chn) BIT(chn)
...
...
@@ -177,19 +209,32 @@ struct rockchip_thermal_data {
#define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT 4
#define TSADCV2_AUTO_PERIOD_TIME 250
/* msec */
#define TSADCV2_AUTO_PERIOD_HT_TIME 50
/* msec */
#define TSADCV2_USER_INTER_PD_SOC 0x340
/* 13 clocks */
struct
tsadc_table
{
u32
code
;
int
temp
;
};
#define GRF_SARADC_TESTBIT 0x0e644
#define GRF_TSADC_TESTBIT_L 0x0e648
#define GRF_TSADC_TESTBIT_H 0x0e64c
#define GRF_TSADC_TSEN_PD_ON (0x30003 << 0)
#define GRF_TSADC_TSEN_PD_OFF (0x30000 << 0)
#define GRF_SARADC_TESTBIT_ON (0x10001 << 2)
#define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2)
/**
* struct tsadc_table - code to temperature conversion table
* @code: the value of adc channel
* @temp: the temperature
* Note:
*
Code to Temperature mapping of the T
emperature sensor is a piece wise linear
*
code to temperature mapping of the t
emperature sensor is a piece wise linear
* curve.Any temperature, code faling between to 2 give temperatures can be
* linearly interpolated.
* Code to Temperature mapping should be updated based on
sillcon
results.
* Code to Temperature mapping should be updated based on
manufacturer
results.
*/
struct
tsadc_table
{
u32
code
;
int
temp
;
};
static
const
struct
tsadc_table
rk3228_code_table
[]
=
{
{
0
,
-
40000
},
{
588
,
-
40000
},
...
...
@@ -308,40 +353,40 @@ static const struct tsadc_table rk3368_code_table[] = {
static
const
struct
tsadc_table
rk3399_code_table
[]
=
{
{
0
,
-
40000
},
{
593
,
-
40000
},
{
598
,
-
35000
},
{
603
,
-
30000
},
{
609
,
-
25000
},
{
614
,
-
20000
},
{
619
,
-
15000
},
{
625
,
-
10000
},
{
630
,
-
5000
},
{
635
,
0
},
{
641
,
5000
},
{
646
,
10000
},
{
651
,
15000
},
{
657
,
20000
},
{
662
,
25000
},
{
667
,
30000
},
{
673
,
35000
},
{
67
8
,
40000
},
{
684
,
45000
},
{
689
,
50000
},
{
69
4
,
55000
},
{
700
,
60000
},
{
705
,
65000
},
{
711
,
70000
},
{
716
,
75000
},
{
722
,
80000
},
{
727
,
85000
},
{
733
,
90000
},
{
738
,
95000
},
{
743
,
100000
},
{
749
,
105000
},
{
754
,
110000
},
{
760
,
115000
},
{
765
,
120000
},
{
771
,
125000
},
{
402
,
-
40000
},
{
410
,
-
35000
},
{
419
,
-
30000
},
{
427
,
-
25000
},
{
436
,
-
20000
},
{
444
,
-
15000
},
{
453
,
-
10000
},
{
461
,
-
5000
},
{
470
,
0
},
{
478
,
5000
},
{
487
,
10000
},
{
496
,
15000
},
{
504
,
20000
},
{
513
,
25000
},
{
521
,
30000
},
{
530
,
35000
},
{
53
8
,
40000
},
{
547
,
45000
},
{
555
,
50000
},
{
56
4
,
55000
},
{
573
,
60000
},
{
581
,
65000
},
{
590
,
70000
},
{
599
,
75000
},
{
607
,
80000
},
{
616
,
85000
},
{
624
,
90000
},
{
633
,
95000
},
{
642
,
100000
},
{
650
,
105000
},
{
659
,
110000
},
{
668
,
115000
},
{
677
,
120000
},
{
685
,
125000
},
{
TSADCV3_DATA_MASK
,
125000
},
};
...
...
@@ -405,8 +450,8 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
return
-
EAGAIN
;
/* Incorrect reading */
while
(
low
<=
high
)
{
if
(
code
>=
table
.
id
[
mid
-
1
].
code
&&
code
<
table
.
id
[
mid
].
code
)
if
(
code
<=
table
.
id
[
mid
].
code
&&
code
>
table
.
id
[
mid
-
1
].
code
)
break
;
else
if
(
code
>
table
.
id
[
mid
].
code
)
low
=
mid
+
1
;
...
...
@@ -449,7 +494,7 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
* If the temperature is higher than COMP_INT or COMP_SHUT for
* "debounce" times, TSADC controller will generate interrupt or TSHUT.
*/
static
void
rk_tsadcv2_initialize
(
void
__iomem
*
regs
,
static
void
rk_tsadcv2_initialize
(
struct
regmap
*
grf
,
void
__iomem
*
regs
,
enum
tshut_polarity
tshut_polarity
)
{
if
(
tshut_polarity
==
TSHUT_HIGH_ACTIVE
)
...
...
@@ -466,6 +511,62 @@ static void rk_tsadcv2_initialize(void __iomem *regs,
regs
+
TSADCV2_AUTO_PERIOD_HT
);
writel_relaxed
(
TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT
,
regs
+
TSADCV2_HIGHT_TSHUT_DEBOUNCE
);
if
(
IS_ERR
(
grf
))
{
pr_warn
(
"%s: Missing rockchip,grf property
\n
"
,
__func__
);
return
;
}
}
/**
* rk_tsadcv3_initialize - initialize TASDC Controller.
*
* (1) The tsadc control power sequence.
*
* (2) Set TSADC_V2_AUTO_PERIOD:
* Configure the interleave between every two accessing of
* TSADC in normal operation.
*
* (2) Set TSADCV2_AUTO_PERIOD_HT:
* Configure the interleave between every two accessing of
* TSADC after the temperature is higher than COM_SHUT or COM_INT.
*
* (3) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE:
* If the temperature is higher than COMP_INT or COMP_SHUT for
* "debounce" times, TSADC controller will generate interrupt or TSHUT.
*/
static
void
rk_tsadcv3_initialize
(
struct
regmap
*
grf
,
void
__iomem
*
regs
,
enum
tshut_polarity
tshut_polarity
)
{
/* The tsadc control power sequence */
if
(
IS_ERR
(
grf
))
{
/* Set interleave value to workround ic time sync issue */
writel_relaxed
(
TSADCV2_USER_INTER_PD_SOC
,
regs
+
TSADCV2_USER_CON
);
}
else
{
regmap_write
(
grf
,
GRF_TSADC_TESTBIT_L
,
GRF_TSADC_TSEN_PD_ON
);
mdelay
(
10
);
regmap_write
(
grf
,
GRF_TSADC_TESTBIT_L
,
GRF_TSADC_TSEN_PD_OFF
);
usleep_range
(
15
,
100
);
/* The spec note says at least 15 us */
regmap_write
(
grf
,
GRF_SARADC_TESTBIT
,
GRF_SARADC_TESTBIT_ON
);
regmap_write
(
grf
,
GRF_TSADC_TESTBIT_H
,
GRF_TSADC_TESTBIT_H_ON
);
usleep_range
(
90
,
200
);
/* The spec note says at least 90 us */
}
if
(
tshut_polarity
==
TSHUT_HIGH_ACTIVE
)
writel_relaxed
(
0U
|
TSADCV2_AUTO_TSHUT_POLARITY_HIGH
,
regs
+
TSADCV2_AUTO_CON
);
else
writel_relaxed
(
0U
&
~
TSADCV2_AUTO_TSHUT_POLARITY_HIGH
,
regs
+
TSADCV2_AUTO_CON
);
writel_relaxed
(
TSADCV2_AUTO_PERIOD_TIME
,
regs
+
TSADCV2_AUTO_PERIOD
);
writel_relaxed
(
TSADCV2_HIGHT_INT_DEBOUNCE_COUNT
,
regs
+
TSADCV2_HIGHT_INT_DEBOUNCE
);
writel_relaxed
(
TSADCV2_AUTO_PERIOD_HT_TIME
,
regs
+
TSADCV2_AUTO_PERIOD_HT
);
writel_relaxed
(
TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT
,
regs
+
TSADCV2_HIGHT_TSHUT_DEBOUNCE
);
}
static
void
rk_tsadcv2_irq_ack
(
void
__iomem
*
regs
)
...
...
@@ -498,10 +599,11 @@ static void rk_tsadcv2_control(void __iomem *regs, bool enable)
}
/**
* @rk_tsadcv3_control:
* TSADC controller works at auto mode, and some SoCs need set the tsadc_q_sel
* bit on TSADCV2_AUTO_CON[1]. The (1024 - tsadc_q) as output adc value if
* setting this bit to enable.
* rk_tsadcv3_control - the tsadc controller is enabled or disabled.
*
* NOTE: TSADC controller works at auto mode, and some SoCs need set the
* tsadc_q_sel bit on TSADCV2_AUTO_CON[1]. The (1024 - tsadc_q) as output
* adc value if setting this bit to enable.
*/
static
void
rk_tsadcv3_control
(
void
__iomem
*
regs
,
bool
enable
)
{
...
...
@@ -603,6 +705,30 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
},
};
static
const
struct
rockchip_tsadc_chip
rk3366_tsadc_data
=
{
.
chn_id
[
SENSOR_CPU
]
=
0
,
/* cpu sensor is channel 0 */
.
chn_id
[
SENSOR_GPU
]
=
1
,
/* gpu sensor is channel 1 */
.
chn_num
=
2
,
/* two channels for tsadc */
.
tshut_mode
=
TSHUT_MODE_GPIO
,
/* default TSHUT via GPIO give PMIC */
.
tshut_polarity
=
TSHUT_LOW_ACTIVE
,
/* default TSHUT LOW ACTIVE */
.
tshut_temp
=
95000
,
.
initialize
=
rk_tsadcv3_initialize
,
.
irq_ack
=
rk_tsadcv3_irq_ack
,
.
control
=
rk_tsadcv3_control
,
.
get_temp
=
rk_tsadcv2_get_temp
,
.
set_tshut_temp
=
rk_tsadcv2_tshut_temp
,
.
set_tshut_mode
=
rk_tsadcv2_tshut_mode
,
.
table
=
{
.
id
=
rk3228_code_table
,
.
length
=
ARRAY_SIZE
(
rk3228_code_table
),
.
data_mask
=
TSADCV3_DATA_MASK
,
.
mode
=
ADC_INCREMENT
,
},
};
static
const
struct
rockchip_tsadc_chip
rk3368_tsadc_data
=
{
.
chn_id
[
SENSOR_CPU
]
=
0
,
/* cpu sensor is channel 0 */
.
chn_id
[
SENSOR_GPU
]
=
1
,
/* gpu sensor is channel 1 */
...
...
@@ -636,7 +762,7 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
.
tshut_polarity
=
TSHUT_LOW_ACTIVE
,
/* default TSHUT LOW ACTIVE */
.
tshut_temp
=
95000
,
.
initialize
=
rk_tsadcv
2
_initialize
,
.
initialize
=
rk_tsadcv
3
_initialize
,
.
irq_ack
=
rk_tsadcv3_irq_ack
,
.
control
=
rk_tsadcv3_control
,
.
get_temp
=
rk_tsadcv2_get_temp
,
...
...
@@ -660,6 +786,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = {
.
compatible
=
"rockchip,rk3288-tsadc"
,
.
data
=
(
void
*
)
&
rk3288_tsadc_data
,
},
{
.
compatible
=
"rockchip,rk3366-tsadc"
,
.
data
=
(
void
*
)
&
rk3366_tsadc_data
,
},
{
.
compatible
=
"rockchip,rk3368-tsadc"
,
.
data
=
(
void
*
)
&
rk3368_tsadc_data
,
...
...
@@ -768,6 +898,11 @@ static int rockchip_configure_from_dt(struct device *dev,
return
-
EINVAL
;
}
/* The tsadc wont to handle the error in here since some SoCs didn't
* need this property.
*/
thermal
->
grf
=
syscon_regmap_lookup_by_phandle
(
np
,
"rockchip,grf"
);
return
0
;
}
...
...
@@ -786,8 +921,8 @@ rockchip_thermal_register_sensor(struct platform_device *pdev,
sensor
->
thermal
=
thermal
;
sensor
->
id
=
id
;
sensor
->
tzd
=
thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
id
,
sensor
,
&
rockchip_of_thermal_ops
);
sensor
->
tzd
=
devm_thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
id
,
sensor
,
&
rockchip_of_thermal_ops
);
if
(
IS_ERR
(
sensor
->
tzd
))
{
error
=
PTR_ERR
(
sensor
->
tzd
);
dev_err
(
&
pdev
->
dev
,
"failed to register sensor %d: %d
\n
"
,
...
...
@@ -815,7 +950,7 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
const
struct
of_device_id
*
match
;
struct
resource
*
res
;
int
irq
;
int
i
,
j
;
int
i
;
int
error
;
match
=
of_match_node
(
of_rockchip_thermal_match
,
np
);
...
...
@@ -888,7 +1023,8 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
goto
err_disable_pclk
;
}
thermal
->
chip
->
initialize
(
thermal
->
regs
,
thermal
->
tshut_polarity
);
thermal
->
chip
->
initialize
(
thermal
->
grf
,
thermal
->
regs
,
thermal
->
tshut_polarity
);
for
(
i
=
0
;
i
<
thermal
->
chip
->
chn_num
;
i
++
)
{
error
=
rockchip_thermal_register_sensor
(
pdev
,
thermal
,
...
...
@@ -898,9 +1034,6 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
dev_err
(
&
pdev
->
dev
,
"failed to register sensor[%d] : error = %d
\n
"
,
i
,
error
);
for
(
j
=
0
;
j
<
i
;
j
++
)
thermal_zone_of_sensor_unregister
(
&
pdev
->
dev
,
thermal
->
sensors
[
j
].
tzd
);
goto
err_disable_pclk
;
}
}
...
...
@@ -912,7 +1045,7 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
if
(
error
)
{
dev_err
(
&
pdev
->
dev
,
"failed to request tsadc irq: %d
\n
"
,
error
);
goto
err_
unregister_sensor
;
goto
err_
disable_pclk
;
}
thermal
->
chip
->
control
(
thermal
->
regs
,
true
);
...
...
@@ -924,11 +1057,6 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
return
0
;
err_unregister_sensor:
while
(
i
--
)
thermal_zone_of_sensor_unregister
(
&
pdev
->
dev
,
thermal
->
sensors
[
i
].
tzd
);
err_disable_pclk:
clk_disable_unprepare
(
thermal
->
pclk
);
err_disable_clk:
...
...
@@ -946,7 +1074,6 @@ static int rockchip_thermal_remove(struct platform_device *pdev)
struct
rockchip_thermal_sensor
*
sensor
=
&
thermal
->
sensors
[
i
];
rockchip_thermal_toggle_sensor
(
sensor
,
false
);
thermal_zone_of_sensor_unregister
(
&
pdev
->
dev
,
sensor
->
tzd
);
}
thermal
->
chip
->
control
(
thermal
->
regs
,
false
);
...
...
@@ -988,12 +1115,15 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev)
return
error
;
error
=
clk_enable
(
thermal
->
pclk
);
if
(
error
)
if
(
error
)
{
clk_disable
(
thermal
->
clk
);
return
error
;
}
rockchip_thermal_reset_controller
(
thermal
->
reset
);
thermal
->
chip
->
initialize
(
thermal
->
regs
,
thermal
->
tshut_polarity
);
thermal
->
chip
->
initialize
(
thermal
->
grf
,
thermal
->
regs
,
thermal
->
tshut_polarity
);
for
(
i
=
0
;
i
<
thermal
->
chip
->
chn_num
;
i
++
)
{
int
id
=
thermal
->
sensors
[
i
].
id
;
...
...
drivers/thermal/tango_thermal.c
0 → 100644
View file @
88ac9906
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/thermal.h>
#include <linux/platform_device.h>
/*
* According to a data sheet draft, "this temperature sensor uses a bandgap
* type of circuit to compare a voltage which has a negative temperature
* coefficient with a voltage that is proportional to absolute temperature.
* A resistor bank allows 41 different temperature thresholds to be selected
* and the logic output will then indicate whether the actual die temperature
* lies above or below the selected threshold."
*/
#define TEMPSI_CMD 0
#define TEMPSI_RES 4
#define TEMPSI_CFG 8
#define CMD_OFF 0
#define CMD_ON 1
#define CMD_READ 2
#define IDX_MIN 15
#define IDX_MAX 40
struct
tango_thermal_priv
{
void
__iomem
*
base
;
int
thresh_idx
;
};
static
bool
temp_above_thresh
(
void
__iomem
*
base
,
int
thresh_idx
)
{
writel
(
CMD_READ
|
thresh_idx
<<
8
,
base
+
TEMPSI_CMD
);
usleep_range
(
10
,
20
);
writel
(
CMD_READ
|
thresh_idx
<<
8
,
base
+
TEMPSI_CMD
);
return
readl
(
base
+
TEMPSI_RES
);
}
static
int
tango_get_temp
(
void
*
arg
,
int
*
res
)
{
struct
tango_thermal_priv
*
priv
=
arg
;
int
idx
=
priv
->
thresh_idx
;
if
(
temp_above_thresh
(
priv
->
base
,
idx
))
{
/* Search upward by incrementing thresh_idx */
while
(
idx
<
IDX_MAX
&&
temp_above_thresh
(
priv
->
base
,
++
idx
))
cpu_relax
();
idx
=
idx
-
1
;
/* always return lower bound */
}
else
{
/* Search downward by decrementing thresh_idx */
while
(
idx
>
IDX_MIN
&&
!
temp_above_thresh
(
priv
->
base
,
--
idx
))
cpu_relax
();
}
*
res
=
(
idx
*
9
/
2
-
38
)
*
1000
;
/* millidegrees Celsius */
priv
->
thresh_idx
=
idx
;
return
0
;
}
static
const
struct
thermal_zone_of_device_ops
ops
=
{
.
get_temp
=
tango_get_temp
,
};
static
int
tango_thermal_probe
(
struct
platform_device
*
pdev
)
{
struct
resource
*
res
;
struct
tango_thermal_priv
*
priv
;
struct
thermal_zone_device
*
tzdev
;
priv
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
priv
),
GFP_KERNEL
);
if
(
!
priv
)
return
-
ENOMEM
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
priv
->
base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
priv
->
base
))
return
PTR_ERR
(
priv
->
base
);
priv
->
thresh_idx
=
IDX_MIN
;
writel
(
0
,
priv
->
base
+
TEMPSI_CFG
);
writel
(
CMD_ON
,
priv
->
base
+
TEMPSI_CMD
);
tzdev
=
devm_thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
0
,
priv
,
&
ops
);
return
PTR_ERR_OR_ZERO
(
tzdev
);
}
static
const
struct
of_device_id
tango_sensor_ids
[]
=
{
{
.
compatible
=
"sigma,smp8758-thermal"
,
},
{
/* sentinel */
}
};
static
struct
platform_driver
tango_thermal_driver
=
{
.
probe
=
tango_thermal_probe
,
.
driver
=
{
.
name
=
"tango-thermal"
,
.
of_match_table
=
tango_sensor_ids
,
},
};
module_platform_driver
(
tango_thermal_driver
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Sigma Designs"
);
MODULE_DESCRIPTION
(
"Tango temperature sensor"
);
drivers/thermal/tegra/Kconfig
0 → 100644
View file @
88ac9906
menu "NVIDIA Tegra thermal drivers"
depends on ARCH_TEGRA
config TEGRA_SOCTHERM
tristate "Tegra SOCTHERM thermal management"
help
Enable this option for integrated thermal management support on NVIDIA
Tegra systems-on-chip. The driver supports four thermal zones
(CPU, GPU, MEM, PLLX). Cooling devices can be bound to the thermal
zones to manage temperatures. This option is also required for the
emergency thermal reset (thermtrip) feature to function.
endmenu
drivers/thermal/tegra/Makefile
0 → 100644
View file @
88ac9906
obj-$(CONFIG_TEGRA_SOCTHERM)
+=
tegra-soctherm.o
tegra-soctherm-y
:=
soctherm.o soctherm-fuse.o
tegra-soctherm-$(CONFIG_ARCH_TEGRA_124_SOC)
+=
tegra124-soctherm.o
tegra-soctherm-$(CONFIG_ARCH_TEGRA_132_SOC)
+=
tegra132-soctherm.o
tegra-soctherm-$(CONFIG_ARCH_TEGRA_210_SOC)
+=
tegra210-soctherm.o
drivers/thermal/tegra/soctherm-fuse.c
0 → 100644
View file @
88ac9906
/*
* Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <soc/tegra/fuse.h>
#include "soctherm.h"
#define NOMINAL_CALIB_FT 105
#define NOMINAL_CALIB_CP 25
#define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK 0x1fff
#define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK (0x1fff << 13)
#define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT 13
#define FUSE_TSENSOR_COMMON 0x180
/*
* Tegra210: Layout of bits in FUSE_TSENSOR_COMMON:
* 3 2 1 0
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | BASE_FT | BASE_CP | SHFT_FT | SHIFT_CP |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Tegra12x, etc:
* In chips prior to Tegra210, this fuse was incorrectly sized as 26 bits,
* and didn't hold SHIFT_CP in [31:26]. Therefore these missing six bits
* were obtained via the FUSE_SPARE_REALIGNMENT_REG register [5:0].
*
* FUSE_TSENSOR_COMMON:
* 3 2 1 0
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |-----------| SHFT_FT | BASE_FT | BASE_CP |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* FUSE_SPARE_REALIGNMENT_REG:
* 3 2 1 0
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |---------------------------------------------------| SHIFT_CP |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define CALIB_COEFFICIENT 1000000LL
/**
* div64_s64_precise() - wrapper for div64_s64()
* @a: the dividend
* @b: the divisor
*
* Implements division with fairly accurate rounding instead of truncation by
* shifting the dividend to the left by 16 so that the quotient has a
* much higher precision.
*
* Return: the quotient of a / b.
*/
static
s64
div64_s64_precise
(
s64
a
,
s32
b
)
{
s64
r
,
al
;
/* Scale up for increased precision division */
al
=
a
<<
16
;
r
=
div64_s64
(
al
*
2
+
1
,
2
*
b
);
return
r
>>
16
;
}
int
tegra_calc_shared_calib
(
const
struct
tegra_soctherm_fuse
*
tfuse
,
struct
tsensor_shared_calib
*
shared
)
{
u32
val
;
s32
shifted_cp
,
shifted_ft
;
int
err
;
err
=
tegra_fuse_readl
(
FUSE_TSENSOR_COMMON
,
&
val
);
if
(
err
)
return
err
;
shared
->
base_cp
=
(
val
&
tfuse
->
fuse_base_cp_mask
)
>>
tfuse
->
fuse_base_cp_shift
;
shared
->
base_ft
=
(
val
&
tfuse
->
fuse_base_ft_mask
)
>>
tfuse
->
fuse_base_ft_shift
;
shifted_ft
=
(
val
&
tfuse
->
fuse_shift_ft_mask
)
>>
tfuse
->
fuse_shift_ft_shift
;
shifted_ft
=
sign_extend32
(
shifted_ft
,
4
);
if
(
tfuse
->
fuse_spare_realignment
)
{
err
=
tegra_fuse_readl
(
tfuse
->
fuse_spare_realignment
,
&
val
);
if
(
err
)
return
err
;
}
shifted_cp
=
sign_extend32
(
val
,
5
);
shared
->
actual_temp_cp
=
2
*
NOMINAL_CALIB_CP
+
shifted_cp
;
shared
->
actual_temp_ft
=
2
*
NOMINAL_CALIB_FT
+
shifted_ft
;
return
0
;
}
int
tegra_calc_tsensor_calib
(
const
struct
tegra_tsensor
*
sensor
,
const
struct
tsensor_shared_calib
*
shared
,
u32
*
calibration
)
{
const
struct
tegra_tsensor_group
*
sensor_group
;
u32
val
,
calib
;
s32
actual_tsensor_ft
,
actual_tsensor_cp
;
s32
delta_sens
,
delta_temp
;
s32
mult
,
div
;
s16
therma
,
thermb
;
s64
temp
;
int
err
;
sensor_group
=
sensor
->
group
;
err
=
tegra_fuse_readl
(
sensor
->
calib_fuse_offset
,
&
val
);
if
(
err
)
return
err
;
actual_tsensor_cp
=
(
shared
->
base_cp
*
64
)
+
sign_extend32
(
val
,
12
);
val
=
(
val
&
FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK
)
>>
FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT
;
actual_tsensor_ft
=
(
shared
->
base_ft
*
32
)
+
sign_extend32
(
val
,
12
);
delta_sens
=
actual_tsensor_ft
-
actual_tsensor_cp
;
delta_temp
=
shared
->
actual_temp_ft
-
shared
->
actual_temp_cp
;
mult
=
sensor_group
->
pdiv
*
sensor
->
config
->
tsample_ate
;
div
=
sensor
->
config
->
tsample
*
sensor_group
->
pdiv_ate
;
temp
=
(
s64
)
delta_temp
*
(
1LL
<<
13
)
*
mult
;
therma
=
div64_s64_precise
(
temp
,
(
s64
)
delta_sens
*
div
);
temp
=
((
s64
)
actual_tsensor_ft
*
shared
->
actual_temp_cp
)
-
((
s64
)
actual_tsensor_cp
*
shared
->
actual_temp_ft
);
thermb
=
div64_s64_precise
(
temp
,
delta_sens
);
temp
=
(
s64
)
therma
*
sensor
->
fuse_corr_alpha
;
therma
=
div64_s64_precise
(
temp
,
CALIB_COEFFICIENT
);
temp
=
(
s64
)
thermb
*
sensor
->
fuse_corr_alpha
+
sensor
->
fuse_corr_beta
;
thermb
=
div64_s64_precise
(
temp
,
CALIB_COEFFICIENT
);
calib
=
((
u16
)
therma
<<
SENSOR_CONFIG2_THERMA_SHIFT
)
|
((
u16
)
thermb
<<
SENSOR_CONFIG2_THERMB_SHIFT
);
*
calibration
=
calib
;
return
0
;
}
MODULE_AUTHOR
(
"Wei Ni <wni@nvidia.com>"
);
MODULE_DESCRIPTION
(
"Tegra SOCTHERM fuse management"
);
MODULE_LICENSE
(
"GPL v2"
);
drivers/thermal/tegra/soctherm.c
0 → 100644
View file @
88ac9906
/*
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* Author:
* Mikko Perttunen <mperttunen@nvidia.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/debugfs.h>
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/thermal.h>
#include <dt-bindings/thermal/tegra124-soctherm.h>
#include "soctherm.h"
#define SENSOR_CONFIG0 0
#define SENSOR_CONFIG0_STOP BIT(0)
#define SENSOR_CONFIG0_CPTR_OVER BIT(2)
#define SENSOR_CONFIG0_OVER BIT(3)
#define SENSOR_CONFIG0_TCALC_OVER BIT(4)
#define SENSOR_CONFIG0_TALL_MASK (0xfffff << 8)
#define SENSOR_CONFIG0_TALL_SHIFT 8
#define SENSOR_CONFIG1 4
#define SENSOR_CONFIG1_TSAMPLE_MASK 0x3ff
#define SENSOR_CONFIG1_TSAMPLE_SHIFT 0
#define SENSOR_CONFIG1_TIDDQ_EN_MASK (0x3f << 15)
#define SENSOR_CONFIG1_TIDDQ_EN_SHIFT 15
#define SENSOR_CONFIG1_TEN_COUNT_MASK (0x3f << 24)
#define SENSOR_CONFIG1_TEN_COUNT_SHIFT 24
#define SENSOR_CONFIG1_TEMP_ENABLE BIT(31)
/*
* SENSOR_CONFIG2 is defined in soctherm.h
* because, it will be used by tegra_soctherm_fuse.c
*/
#define SENSOR_STATUS0 0xc
#define SENSOR_STATUS0_VALID_MASK BIT(31)
#define SENSOR_STATUS0_CAPTURE_MASK 0xffff
#define SENSOR_STATUS1 0x10
#define SENSOR_STATUS1_TEMP_VALID_MASK BIT(31)
#define SENSOR_STATUS1_TEMP_MASK 0xffff
#define READBACK_VALUE_MASK 0xff00
#define READBACK_VALUE_SHIFT 8
#define READBACK_ADD_HALF BIT(7)
#define READBACK_NEGATE BIT(0)
/* get val from register(r) mask bits(m) */
#define REG_GET_MASK(r, m) (((r) & (m)) >> (ffs(m) - 1))
/* set val(v) to mask bits(m) of register(r) */
#define REG_SET_MASK(r, m, v) (((r) & ~(m)) | \
(((v) & (m >> (ffs(m) - 1))) << (ffs(m) - 1)))
static
const
int
min_low_temp
=
-
127000
;
static
const
int
max_high_temp
=
127000
;
struct
tegra_thermctl_zone
{
void
__iomem
*
reg
;
struct
device
*
dev
;
struct
thermal_zone_device
*
tz
;
const
struct
tegra_tsensor_group
*
sg
;
};
struct
tegra_soctherm
{
struct
reset_control
*
reset
;
struct
clk
*
clock_tsensor
;
struct
clk
*
clock_soctherm
;
void
__iomem
*
regs
;
struct
thermal_zone_device
**
thermctl_tzs
;
u32
*
calib
;
struct
tegra_soctherm_soc
*
soc
;
struct
dentry
*
debugfs_dir
;
};
static
void
enable_tsensor
(
struct
tegra_soctherm
*
tegra
,
unsigned
int
i
)
{
const
struct
tegra_tsensor
*
sensor
=
&
tegra
->
soc
->
tsensors
[
i
];
void
__iomem
*
base
=
tegra
->
regs
+
sensor
->
base
;
unsigned
int
val
;
val
=
sensor
->
config
->
tall
<<
SENSOR_CONFIG0_TALL_SHIFT
;
writel
(
val
,
base
+
SENSOR_CONFIG0
);
val
=
(
sensor
->
config
->
tsample
-
1
)
<<
SENSOR_CONFIG1_TSAMPLE_SHIFT
;
val
|=
sensor
->
config
->
tiddq_en
<<
SENSOR_CONFIG1_TIDDQ_EN_SHIFT
;
val
|=
sensor
->
config
->
ten_count
<<
SENSOR_CONFIG1_TEN_COUNT_SHIFT
;
val
|=
SENSOR_CONFIG1_TEMP_ENABLE
;
writel
(
val
,
base
+
SENSOR_CONFIG1
);
writel
(
tegra
->
calib
[
i
],
base
+
SENSOR_CONFIG2
);
}
/*
* Translate from soctherm readback format to millicelsius.
* The soctherm readback format in bits is as follows:
* TTTTTTTT H______N
* where T's contain the temperature in Celsius,
* H denotes an addition of 0.5 Celsius and N denotes negation
* of the final value.
*/
static
int
translate_temp
(
u16
val
)
{
int
t
;
t
=
((
val
&
READBACK_VALUE_MASK
)
>>
READBACK_VALUE_SHIFT
)
*
1000
;
if
(
val
&
READBACK_ADD_HALF
)
t
+=
500
;
if
(
val
&
READBACK_NEGATE
)
t
*=
-
1
;
return
t
;
}
static
int
tegra_thermctl_get_temp
(
void
*
data
,
int
*
out_temp
)
{
struct
tegra_thermctl_zone
*
zone
=
data
;
u32
val
;
val
=
readl
(
zone
->
reg
);
val
=
REG_GET_MASK
(
val
,
zone
->
sg
->
sensor_temp_mask
);
*
out_temp
=
translate_temp
(
val
);
return
0
;
}
static
int
thermtrip_program
(
struct
device
*
dev
,
const
struct
tegra_tsensor_group
*
sg
,
int
trip_temp
);
static
int
tegra_thermctl_set_trip_temp
(
void
*
data
,
int
trip
,
int
temp
)
{
struct
tegra_thermctl_zone
*
zone
=
data
;
struct
thermal_zone_device
*
tz
=
zone
->
tz
;
const
struct
tegra_tsensor_group
*
sg
=
zone
->
sg
;
struct
device
*
dev
=
zone
->
dev
;
enum
thermal_trip_type
type
;
int
ret
;
if
(
!
tz
)
return
-
EINVAL
;
ret
=
tz
->
ops
->
get_trip_type
(
tz
,
trip
,
&
type
);
if
(
ret
)
return
ret
;
if
(
type
!=
THERMAL_TRIP_CRITICAL
)
return
0
;
return
thermtrip_program
(
dev
,
sg
,
temp
);
}
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
,
};
/**
* enforce_temp_range() - check and enforce temperature range [min, max]
* @trip_temp: the trip temperature to check
*
* Checks and enforces the permitted temperature range that SOC_THERM
* HW can support This is
* done while taking care of precision.
*
* Return: The precision adjusted capped temperature in millicelsius.
*/
static
int
enforce_temp_range
(
struct
device
*
dev
,
int
trip_temp
)
{
int
temp
;
temp
=
clamp_val
(
trip_temp
,
min_low_temp
,
max_high_temp
);
if
(
temp
!=
trip_temp
)
dev_info
(
dev
,
"soctherm: trip temperature %d forced to %d
\n
"
,
trip_temp
,
temp
);
return
temp
;
}
/**
* thermtrip_program() - Configures the hardware to shut down the
* system if a given sensor group reaches a given temperature
* @dev: ptr to the struct device for the SOC_THERM IP block
* @sg: pointer to the sensor group to set the thermtrip temperature for
* @trip_temp: the temperature in millicelsius to trigger the thermal trip at
*
* Sets the thermal trip threshold of the given sensor group to be the
* @trip_temp. If this threshold is crossed, the hardware will shut
* down.
*
* Note that, although @trip_temp is specified in millicelsius, the
* hardware is programmed in degrees Celsius.
*
* Return: 0 upon success, or %-EINVAL upon failure.
*/
static
int
thermtrip_program
(
struct
device
*
dev
,
const
struct
tegra_tsensor_group
*
sg
,
int
trip_temp
)
{
struct
tegra_soctherm
*
ts
=
dev_get_drvdata
(
dev
);
int
temp
;
u32
r
;
if
(
!
sg
||
!
sg
->
thermtrip_threshold_mask
)
return
-
EINVAL
;
temp
=
enforce_temp_range
(
dev
,
trip_temp
)
/
ts
->
soc
->
thresh_grain
;
r
=
readl
(
ts
->
regs
+
THERMCTL_THERMTRIP_CTL
);
r
=
REG_SET_MASK
(
r
,
sg
->
thermtrip_threshold_mask
,
temp
);
r
=
REG_SET_MASK
(
r
,
sg
->
thermtrip_enable_mask
,
1
);
r
=
REG_SET_MASK
(
r
,
sg
->
thermtrip_any_en_mask
,
0
);
writel
(
r
,
ts
->
regs
+
THERMCTL_THERMTRIP_CTL
);
return
0
;
}
/**
* tegra_soctherm_set_hwtrips() - set HW trip point from DT data
* @dev: struct device * of the SOC_THERM instance
*
* Configure the SOC_THERM HW trip points, setting "THERMTRIP"
* trip points , using "critical" type trip_temp from thermal
* zone.
* After they have been configured, THERMTRIP will take action
* when the configured SoC thermal sensor group reaches a
* certain temperature.
*
* Return: 0 upon success, or a negative error code on failure.
* "Success" does not mean that trips was enabled; it could also
* mean that no node was found in DT.
* THERMTRIP has been enabled successfully when a message similar to
* this one appears on the serial console:
* "thermtrip: will shut down when sensor group XXX reaches YYYYYY mC"
*/
static
int
tegra_soctherm_set_hwtrips
(
struct
device
*
dev
,
const
struct
tegra_tsensor_group
*
sg
,
struct
thermal_zone_device
*
tz
)
{
int
temperature
;
int
ret
;
ret
=
tz
->
ops
->
get_crit_temp
(
tz
,
&
temperature
);
if
(
ret
)
{
dev_warn
(
dev
,
"thermtrip: %s: missing critical temperature
\n
"
,
sg
->
name
);
return
ret
;
}
ret
=
thermtrip_program
(
dev
,
sg
,
temperature
);
if
(
ret
)
{
dev_err
(
dev
,
"thermtrip: %s: error during enable
\n
"
,
sg
->
name
);
return
ret
;
}
dev_info
(
dev
,
"thermtrip: will shut down when %s reaches %d mC
\n
"
,
sg
->
name
,
temperature
);
return
0
;
}
#ifdef CONFIG_DEBUG_FS
static
int
regs_show
(
struct
seq_file
*
s
,
void
*
data
)
{
struct
platform_device
*
pdev
=
s
->
private
;
struct
tegra_soctherm
*
ts
=
platform_get_drvdata
(
pdev
);
const
struct
tegra_tsensor
*
tsensors
=
ts
->
soc
->
tsensors
;
const
struct
tegra_tsensor_group
**
ttgs
=
ts
->
soc
->
ttgs
;
u32
r
,
state
;
int
i
;
seq_puts
(
s
,
"-----TSENSE (convert HW)-----
\n
"
);
for
(
i
=
0
;
i
<
ts
->
soc
->
num_tsensors
;
i
++
)
{
r
=
readl
(
ts
->
regs
+
tsensors
[
i
].
base
+
SENSOR_CONFIG1
);
state
=
REG_GET_MASK
(
r
,
SENSOR_CONFIG1_TEMP_ENABLE
);
seq_printf
(
s
,
"%s: "
,
tsensors
[
i
].
name
);
seq_printf
(
s
,
"En(%d) "
,
state
);
if
(
!
state
)
{
seq_puts
(
s
,
"
\n
"
);
continue
;
}
state
=
REG_GET_MASK
(
r
,
SENSOR_CONFIG1_TIDDQ_EN_MASK
);
seq_printf
(
s
,
"tiddq(%d) "
,
state
);
state
=
REG_GET_MASK
(
r
,
SENSOR_CONFIG1_TEN_COUNT_MASK
);
seq_printf
(
s
,
"ten_count(%d) "
,
state
);
state
=
REG_GET_MASK
(
r
,
SENSOR_CONFIG1_TSAMPLE_MASK
);
seq_printf
(
s
,
"tsample(%d) "
,
state
+
1
);
r
=
readl
(
ts
->
regs
+
tsensors
[
i
].
base
+
SENSOR_STATUS1
);
state
=
REG_GET_MASK
(
r
,
SENSOR_STATUS1_TEMP_VALID_MASK
);
seq_printf
(
s
,
"Temp(%d/"
,
state
);
state
=
REG_GET_MASK
(
r
,
SENSOR_STATUS1_TEMP_MASK
);
seq_printf
(
s
,
"%d) "
,
translate_temp
(
state
));
r
=
readl
(
ts
->
regs
+
tsensors
[
i
].
base
+
SENSOR_STATUS0
);
state
=
REG_GET_MASK
(
r
,
SENSOR_STATUS0_VALID_MASK
);
seq_printf
(
s
,
"Capture(%d/"
,
state
);
state
=
REG_GET_MASK
(
r
,
SENSOR_STATUS0_CAPTURE_MASK
);
seq_printf
(
s
,
"%d) "
,
state
);
r
=
readl
(
ts
->
regs
+
tsensors
[
i
].
base
+
SENSOR_CONFIG0
);
state
=
REG_GET_MASK
(
r
,
SENSOR_CONFIG0_STOP
);
seq_printf
(
s
,
"Stop(%d) "
,
state
);
state
=
REG_GET_MASK
(
r
,
SENSOR_CONFIG0_TALL_MASK
);
seq_printf
(
s
,
"Tall(%d) "
,
state
);
state
=
REG_GET_MASK
(
r
,
SENSOR_CONFIG0_TCALC_OVER
);
seq_printf
(
s
,
"Over(%d/"
,
state
);
state
=
REG_GET_MASK
(
r
,
SENSOR_CONFIG0_OVER
);
seq_printf
(
s
,
"%d/"
,
state
);
state
=
REG_GET_MASK
(
r
,
SENSOR_CONFIG0_CPTR_OVER
);
seq_printf
(
s
,
"%d) "
,
state
);
r
=
readl
(
ts
->
regs
+
tsensors
[
i
].
base
+
SENSOR_CONFIG2
);
state
=
REG_GET_MASK
(
r
,
SENSOR_CONFIG2_THERMA_MASK
);
seq_printf
(
s
,
"Therm_A/B(%d/"
,
state
);
state
=
REG_GET_MASK
(
r
,
SENSOR_CONFIG2_THERMB_MASK
);
seq_printf
(
s
,
"%d)
\n
"
,
(
s16
)
state
);
}
r
=
readl
(
ts
->
regs
+
SENSOR_PDIV
);
seq_printf
(
s
,
"PDIV: 0x%x
\n
"
,
r
);
r
=
readl
(
ts
->
regs
+
SENSOR_HOTSPOT_OFF
);
seq_printf
(
s
,
"HOTSPOT: 0x%x
\n
"
,
r
);
seq_puts
(
s
,
"
\n
"
);
seq_puts
(
s
,
"-----SOC_THERM-----
\n
"
);
r
=
readl
(
ts
->
regs
+
SENSOR_TEMP1
);
state
=
REG_GET_MASK
(
r
,
SENSOR_TEMP1_CPU_TEMP_MASK
);
seq_printf
(
s
,
"Temperatures: CPU(%d) "
,
translate_temp
(
state
));
state
=
REG_GET_MASK
(
r
,
SENSOR_TEMP1_GPU_TEMP_MASK
);
seq_printf
(
s
,
" GPU(%d) "
,
translate_temp
(
state
));
r
=
readl
(
ts
->
regs
+
SENSOR_TEMP2
);
state
=
REG_GET_MASK
(
r
,
SENSOR_TEMP2_PLLX_TEMP_MASK
);
seq_printf
(
s
,
" PLLX(%d) "
,
translate_temp
(
state
));
state
=
REG_GET_MASK
(
r
,
SENSOR_TEMP2_MEM_TEMP_MASK
);
seq_printf
(
s
,
" MEM(%d)
\n
"
,
translate_temp
(
state
));
r
=
readl
(
ts
->
regs
+
THERMCTL_THERMTRIP_CTL
);
state
=
REG_GET_MASK
(
r
,
ttgs
[
0
]
->
thermtrip_any_en_mask
);
seq_printf
(
s
,
"Thermtrip Any En(%d)
\n
"
,
state
);
for
(
i
=
0
;
i
<
ts
->
soc
->
num_ttgs
;
i
++
)
{
state
=
REG_GET_MASK
(
r
,
ttgs
[
i
]
->
thermtrip_enable_mask
);
seq_printf
(
s
,
" %s En(%d) "
,
ttgs
[
i
]
->
name
,
state
);
state
=
REG_GET_MASK
(
r
,
ttgs
[
i
]
->
thermtrip_threshold_mask
);
state
*=
ts
->
soc
->
thresh_grain
;
seq_printf
(
s
,
"Thresh(%d)
\n
"
,
state
);
}
return
0
;
}
static
int
regs_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
regs_show
,
inode
->
i_private
);
}
static
const
struct
file_operations
regs_fops
=
{
.
open
=
regs_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
};
static
void
soctherm_debug_init
(
struct
platform_device
*
pdev
)
{
struct
tegra_soctherm
*
tegra
=
platform_get_drvdata
(
pdev
);
struct
dentry
*
root
,
*
file
;
root
=
debugfs_create_dir
(
"soctherm"
,
NULL
);
if
(
!
root
)
{
dev_err
(
&
pdev
->
dev
,
"failed to create debugfs directory
\n
"
);
return
;
}
tegra
->
debugfs_dir
=
root
;
file
=
debugfs_create_file
(
"reg_contents"
,
0644
,
root
,
pdev
,
&
regs_fops
);
if
(
!
file
)
{
dev_err
(
&
pdev
->
dev
,
"failed to create debugfs file
\n
"
);
debugfs_remove_recursive
(
tegra
->
debugfs_dir
);
tegra
->
debugfs_dir
=
NULL
;
}
}
#else
static
inline
void
soctherm_debug_init
(
struct
platform_device
*
pdev
)
{}
#endif
static
int
soctherm_clk_enable
(
struct
platform_device
*
pdev
,
bool
enable
)
{
struct
tegra_soctherm
*
tegra
=
platform_get_drvdata
(
pdev
);
int
err
;
if
(
!
tegra
->
clock_soctherm
||
!
tegra
->
clock_tsensor
)
return
-
EINVAL
;
reset_control_assert
(
tegra
->
reset
);
if
(
enable
)
{
err
=
clk_prepare_enable
(
tegra
->
clock_soctherm
);
if
(
err
)
{
reset_control_deassert
(
tegra
->
reset
);
return
err
;
}
err
=
clk_prepare_enable
(
tegra
->
clock_tsensor
);
if
(
err
)
{
clk_disable_unprepare
(
tegra
->
clock_soctherm
);
reset_control_deassert
(
tegra
->
reset
);
return
err
;
}
}
else
{
clk_disable_unprepare
(
tegra
->
clock_tsensor
);
clk_disable_unprepare
(
tegra
->
clock_soctherm
);
}
reset_control_deassert
(
tegra
->
reset
);
return
0
;
}
static
void
soctherm_init
(
struct
platform_device
*
pdev
)
{
struct
tegra_soctherm
*
tegra
=
platform_get_drvdata
(
pdev
);
const
struct
tegra_tsensor_group
**
ttgs
=
tegra
->
soc
->
ttgs
;
int
i
;
u32
pdiv
,
hotspot
;
/* Initialize raw sensors */
for
(
i
=
0
;
i
<
tegra
->
soc
->
num_tsensors
;
++
i
)
enable_tsensor
(
tegra
,
i
);
/* program pdiv and hotspot offsets per THERM */
pdiv
=
readl
(
tegra
->
regs
+
SENSOR_PDIV
);
hotspot
=
readl
(
tegra
->
regs
+
SENSOR_HOTSPOT_OFF
);
for
(
i
=
0
;
i
<
tegra
->
soc
->
num_ttgs
;
++
i
)
{
pdiv
=
REG_SET_MASK
(
pdiv
,
ttgs
[
i
]
->
pdiv_mask
,
ttgs
[
i
]
->
pdiv
);
/* hotspot offset from PLLX, doesn't need to configure PLLX */
if
(
ttgs
[
i
]
->
id
==
TEGRA124_SOCTHERM_SENSOR_PLLX
)
continue
;
hotspot
=
REG_SET_MASK
(
hotspot
,
ttgs
[
i
]
->
pllx_hotspot_mask
,
ttgs
[
i
]
->
pllx_hotspot_diff
);
}
writel
(
pdiv
,
tegra
->
regs
+
SENSOR_PDIV
);
writel
(
hotspot
,
tegra
->
regs
+
SENSOR_HOTSPOT_OFF
);
}
static
const
struct
of_device_id
tegra_soctherm_of_match
[]
=
{
#ifdef CONFIG_ARCH_TEGRA_124_SOC
{
.
compatible
=
"nvidia,tegra124-soctherm"
,
.
data
=
&
tegra124_soctherm
,
},
#endif
#ifdef CONFIG_ARCH_TEGRA_132_SOC
{
.
compatible
=
"nvidia,tegra132-soctherm"
,
.
data
=
&
tegra132_soctherm
,
},
#endif
#ifdef CONFIG_ARCH_TEGRA_210_SOC
{
.
compatible
=
"nvidia,tegra210-soctherm"
,
.
data
=
&
tegra210_soctherm
,
},
#endif
{
},
};
MODULE_DEVICE_TABLE
(
of
,
tegra_soctherm_of_match
);
static
int
tegra_soctherm_probe
(
struct
platform_device
*
pdev
)
{
const
struct
of_device_id
*
match
;
struct
tegra_soctherm
*
tegra
;
struct
thermal_zone_device
*
z
;
struct
tsensor_shared_calib
shared_calib
;
struct
resource
*
res
;
struct
tegra_soctherm_soc
*
soc
;
unsigned
int
i
;
int
err
;
match
=
of_match_node
(
tegra_soctherm_of_match
,
pdev
->
dev
.
of_node
);
if
(
!
match
)
return
-
ENODEV
;
soc
=
(
struct
tegra_soctherm_soc
*
)
match
->
data
;
if
(
soc
->
num_ttgs
>
TEGRA124_SOCTHERM_SENSOR_NUM
)
return
-
EINVAL
;
tegra
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
tegra
),
GFP_KERNEL
);
if
(
!
tegra
)
return
-
ENOMEM
;
dev_set_drvdata
(
&
pdev
->
dev
,
tegra
);
tegra
->
soc
=
soc
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
tegra
->
regs
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
tegra
->
regs
))
return
PTR_ERR
(
tegra
->
regs
);
tegra
->
reset
=
devm_reset_control_get
(
&
pdev
->
dev
,
"soctherm"
);
if
(
IS_ERR
(
tegra
->
reset
))
{
dev_err
(
&
pdev
->
dev
,
"can't get soctherm reset
\n
"
);
return
PTR_ERR
(
tegra
->
reset
);
}
tegra
->
clock_tsensor
=
devm_clk_get
(
&
pdev
->
dev
,
"tsensor"
);
if
(
IS_ERR
(
tegra
->
clock_tsensor
))
{
dev_err
(
&
pdev
->
dev
,
"can't get tsensor clock
\n
"
);
return
PTR_ERR
(
tegra
->
clock_tsensor
);
}
tegra
->
clock_soctherm
=
devm_clk_get
(
&
pdev
->
dev
,
"soctherm"
);
if
(
IS_ERR
(
tegra
->
clock_soctherm
))
{
dev_err
(
&
pdev
->
dev
,
"can't get soctherm clock
\n
"
);
return
PTR_ERR
(
tegra
->
clock_soctherm
);
}
tegra
->
calib
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
u32
)
*
soc
->
num_tsensors
,
GFP_KERNEL
);
if
(
!
tegra
->
calib
)
return
-
ENOMEM
;
/* calculate shared calibration data */
err
=
tegra_calc_shared_calib
(
soc
->
tfuse
,
&
shared_calib
);
if
(
err
)
return
err
;
/* calculate tsensor calibaration data */
for
(
i
=
0
;
i
<
soc
->
num_tsensors
;
++
i
)
{
err
=
tegra_calc_tsensor_calib
(
&
soc
->
tsensors
[
i
],
&
shared_calib
,
&
tegra
->
calib
[
i
]);
if
(
err
)
return
err
;
}
tegra
->
thermctl_tzs
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
z
)
*
soc
->
num_ttgs
,
GFP_KERNEL
);
if
(
!
tegra
->
thermctl_tzs
)
return
-
ENOMEM
;
err
=
soctherm_clk_enable
(
pdev
,
true
);
if
(
err
)
return
err
;
soctherm_init
(
pdev
);
for
(
i
=
0
;
i
<
soc
->
num_ttgs
;
++
i
)
{
struct
tegra_thermctl_zone
*
zone
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
zone
),
GFP_KERNEL
);
if
(
!
zone
)
{
err
=
-
ENOMEM
;
goto
disable_clocks
;
}
zone
->
reg
=
tegra
->
regs
+
soc
->
ttgs
[
i
]
->
sensor_temp_offset
;
zone
->
dev
=
&
pdev
->
dev
;
zone
->
sg
=
soc
->
ttgs
[
i
];
z
=
devm_thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
soc
->
ttgs
[
i
]
->
id
,
zone
,
&
tegra_of_thermal_ops
);
if
(
IS_ERR
(
z
))
{
err
=
PTR_ERR
(
z
);
dev_err
(
&
pdev
->
dev
,
"failed to register sensor: %d
\n
"
,
err
);
goto
disable_clocks
;
}
zone
->
tz
=
z
;
tegra
->
thermctl_tzs
[
soc
->
ttgs
[
i
]
->
id
]
=
z
;
/* Configure hw trip points */
tegra_soctherm_set_hwtrips
(
&
pdev
->
dev
,
soc
->
ttgs
[
i
],
z
);
}
soctherm_debug_init
(
pdev
);
return
0
;
disable_clocks:
soctherm_clk_enable
(
pdev
,
false
);
return
err
;
}
static
int
tegra_soctherm_remove
(
struct
platform_device
*
pdev
)
{
struct
tegra_soctherm
*
tegra
=
platform_get_drvdata
(
pdev
);
debugfs_remove_recursive
(
tegra
->
debugfs_dir
);
soctherm_clk_enable
(
pdev
,
false
);
return
0
;
}
static
int
__maybe_unused
soctherm_suspend
(
struct
device
*
dev
)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
soctherm_clk_enable
(
pdev
,
false
);
return
0
;
}
static
int
__maybe_unused
soctherm_resume
(
struct
device
*
dev
)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
tegra_soctherm
*
tegra
=
platform_get_drvdata
(
pdev
);
struct
tegra_soctherm_soc
*
soc
=
tegra
->
soc
;
int
err
,
i
;
err
=
soctherm_clk_enable
(
pdev
,
true
);
if
(
err
)
{
dev_err
(
&
pdev
->
dev
,
"Resume failed: enable clocks failed
\n
"
);
return
err
;
}
soctherm_init
(
pdev
);
for
(
i
=
0
;
i
<
soc
->
num_ttgs
;
++
i
)
{
struct
thermal_zone_device
*
tz
;
tz
=
tegra
->
thermctl_tzs
[
soc
->
ttgs
[
i
]
->
id
];
tegra_soctherm_set_hwtrips
(
dev
,
soc
->
ttgs
[
i
],
tz
);
}
return
0
;
}
static
SIMPLE_DEV_PM_OPS
(
tegra_soctherm_pm
,
soctherm_suspend
,
soctherm_resume
);
static
struct
platform_driver
tegra_soctherm_driver
=
{
.
probe
=
tegra_soctherm_probe
,
.
remove
=
tegra_soctherm_remove
,
.
driver
=
{
.
name
=
"tegra_soctherm"
,
.
pm
=
&
tegra_soctherm_pm
,
.
of_match_table
=
tegra_soctherm_of_match
,
},
};
module_platform_driver
(
tegra_soctherm_driver
);
MODULE_AUTHOR
(
"Mikko Perttunen <mperttunen@nvidia.com>"
);
MODULE_DESCRIPTION
(
"NVIDIA Tegra SOCTHERM thermal management driver"
);
MODULE_LICENSE
(
"GPL v2"
);
drivers/thermal/tegra/soctherm.h
0 → 100644
View file @
88ac9906
/*
* Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __DRIVERS_THERMAL_TEGRA_SOCTHERM_H
#define __DRIVERS_THERMAL_TEGRA_SOCTHERM_H
#define SENSOR_CONFIG2 8
#define SENSOR_CONFIG2_THERMA_MASK (0xffff << 16)
#define SENSOR_CONFIG2_THERMA_SHIFT 16
#define SENSOR_CONFIG2_THERMB_MASK 0xffff
#define SENSOR_CONFIG2_THERMB_SHIFT 0
#define THERMCTL_THERMTRIP_CTL 0x80
/* BITs are defined in device file */
#define SENSOR_PDIV 0x1c0
#define SENSOR_PDIV_CPU_MASK (0xf << 12)
#define SENSOR_PDIV_GPU_MASK (0xf << 8)
#define SENSOR_PDIV_MEM_MASK (0xf << 4)
#define SENSOR_PDIV_PLLX_MASK (0xf << 0)
#define SENSOR_HOTSPOT_OFF 0x1c4
#define SENSOR_HOTSPOT_CPU_MASK (0xff << 16)
#define SENSOR_HOTSPOT_GPU_MASK (0xff << 8)
#define SENSOR_HOTSPOT_MEM_MASK (0xff << 0)
#define SENSOR_TEMP1 0x1c8
#define SENSOR_TEMP1_CPU_TEMP_MASK (0xffff << 16)
#define SENSOR_TEMP1_GPU_TEMP_MASK 0xffff
#define SENSOR_TEMP2 0x1cc
#define SENSOR_TEMP2_MEM_TEMP_MASK (0xffff << 16)
#define SENSOR_TEMP2_PLLX_TEMP_MASK 0xffff
/**
* struct tegra_tsensor_group - SOC_THERM sensor group data
* @name: short name of the temperature sensor group
* @id: numeric ID of the temperature sensor group
* @sensor_temp_offset: offset of the SENSOR_TEMP* register
* @sensor_temp_mask: bit mask for this sensor group in SENSOR_TEMP* register
* @pdiv: the sensor count post-divider to use during runtime
* @pdiv_ate: the sensor count post-divider used during automated test
* @pdiv_mask: register bitfield mask for the PDIV field for this sensor
* @pllx_hotspot_diff: hotspot offset from the PLLX sensor, must be 0 for
PLLX sensor group
* @pllx_hotspot_mask: register bitfield mask for the HOTSPOT field
*/
struct
tegra_tsensor_group
{
const
char
*
name
;
u8
id
;
u16
sensor_temp_offset
;
u32
sensor_temp_mask
;
u32
pdiv
,
pdiv_ate
,
pdiv_mask
;
u32
pllx_hotspot_diff
,
pllx_hotspot_mask
;
u32
thermtrip_enable_mask
;
u32
thermtrip_any_en_mask
;
u32
thermtrip_threshold_mask
;
};
struct
tegra_tsensor_configuration
{
u32
tall
,
tiddq_en
,
ten_count
,
pdiv
,
pdiv_ate
,
tsample
,
tsample_ate
;
};
struct
tegra_tsensor
{
const
char
*
name
;
const
u32
base
;
const
struct
tegra_tsensor_configuration
*
config
;
const
u32
calib_fuse_offset
;
/*
* Correction values used to modify values read from
* calibration fuses
*/
const
s32
fuse_corr_alpha
,
fuse_corr_beta
;
const
struct
tegra_tsensor_group
*
group
;
};
struct
tegra_soctherm_fuse
{
u32
fuse_base_cp_mask
,
fuse_base_cp_shift
;
u32
fuse_base_ft_mask
,
fuse_base_ft_shift
;
u32
fuse_shift_ft_mask
,
fuse_shift_ft_shift
;
u32
fuse_spare_realignment
;
};
struct
tsensor_shared_calib
{
u32
base_cp
,
base_ft
;
u32
actual_temp_cp
,
actual_temp_ft
;
};
struct
tegra_soctherm_soc
{
const
struct
tegra_tsensor
*
tsensors
;
const
unsigned
int
num_tsensors
;
const
struct
tegra_tsensor_group
**
ttgs
;
const
unsigned
int
num_ttgs
;
const
struct
tegra_soctherm_fuse
*
tfuse
;
const
int
thresh_grain
;
};
int
tegra_calc_shared_calib
(
const
struct
tegra_soctherm_fuse
*
tfuse
,
struct
tsensor_shared_calib
*
shared
);
int
tegra_calc_tsensor_calib
(
const
struct
tegra_tsensor
*
sensor
,
const
struct
tsensor_shared_calib
*
shared
,
u32
*
calib
);
#ifdef CONFIG_ARCH_TEGRA_124_SOC
extern
const
struct
tegra_soctherm_soc
tegra124_soctherm
;
#endif
#ifdef CONFIG_ARCH_TEGRA_132_SOC
extern
const
struct
tegra_soctherm_soc
tegra132_soctherm
;
#endif
#ifdef CONFIG_ARCH_TEGRA_210_SOC
extern
const
struct
tegra_soctherm_soc
tegra210_soctherm
;
#endif
#endif
drivers/thermal/tegra/tegra124-soctherm.c
0 → 100644
View file @
88ac9906
/*
* Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <dt-bindings/thermal/tegra124-soctherm.h>
#include "soctherm.h"
#define TEGRA124_THERMTRIP_ANY_EN_MASK (0x1 << 28)
#define TEGRA124_THERMTRIP_MEM_EN_MASK (0x1 << 27)
#define TEGRA124_THERMTRIP_GPU_EN_MASK (0x1 << 26)
#define TEGRA124_THERMTRIP_CPU_EN_MASK (0x1 << 25)
#define TEGRA124_THERMTRIP_TSENSE_EN_MASK (0x1 << 24)
#define TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK (0xff << 16)
#define TEGRA124_THERMTRIP_CPU_THRESH_MASK (0xff << 8)
#define TEGRA124_THERMTRIP_TSENSE_THRESH_MASK 0xff
#define TEGRA124_THRESH_GRAIN 1000
static
const
struct
tegra_tsensor_configuration
tegra124_tsensor_config
=
{
.
tall
=
16300
,
.
tiddq_en
=
1
,
.
ten_count
=
1
,
.
tsample
=
120
,
.
tsample_ate
=
480
,
};
static
const
struct
tegra_tsensor_group
tegra124_tsensor_group_cpu
=
{
.
id
=
TEGRA124_SOCTHERM_SENSOR_CPU
,
.
name
=
"cpu"
,
.
sensor_temp_offset
=
SENSOR_TEMP1
,
.
sensor_temp_mask
=
SENSOR_TEMP1_CPU_TEMP_MASK
,
.
pdiv
=
8
,
.
pdiv_ate
=
8
,
.
pdiv_mask
=
SENSOR_PDIV_CPU_MASK
,
.
pllx_hotspot_diff
=
10
,
.
pllx_hotspot_mask
=
SENSOR_HOTSPOT_CPU_MASK
,
.
thermtrip_any_en_mask
=
TEGRA124_THERMTRIP_ANY_EN_MASK
,
.
thermtrip_enable_mask
=
TEGRA124_THERMTRIP_CPU_EN_MASK
,
.
thermtrip_threshold_mask
=
TEGRA124_THERMTRIP_CPU_THRESH_MASK
,
};
static
const
struct
tegra_tsensor_group
tegra124_tsensor_group_gpu
=
{
.
id
=
TEGRA124_SOCTHERM_SENSOR_GPU
,
.
name
=
"gpu"
,
.
sensor_temp_offset
=
SENSOR_TEMP1
,
.
sensor_temp_mask
=
SENSOR_TEMP1_GPU_TEMP_MASK
,
.
pdiv
=
8
,
.
pdiv_ate
=
8
,
.
pdiv_mask
=
SENSOR_PDIV_GPU_MASK
,
.
pllx_hotspot_diff
=
5
,
.
pllx_hotspot_mask
=
SENSOR_HOTSPOT_GPU_MASK
,
.
thermtrip_any_en_mask
=
TEGRA124_THERMTRIP_ANY_EN_MASK
,
.
thermtrip_enable_mask
=
TEGRA124_THERMTRIP_GPU_EN_MASK
,
.
thermtrip_threshold_mask
=
TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK
,
};
static
const
struct
tegra_tsensor_group
tegra124_tsensor_group_pll
=
{
.
id
=
TEGRA124_SOCTHERM_SENSOR_PLLX
,
.
name
=
"pll"
,
.
sensor_temp_offset
=
SENSOR_TEMP2
,
.
sensor_temp_mask
=
SENSOR_TEMP2_PLLX_TEMP_MASK
,
.
pdiv
=
8
,
.
pdiv_ate
=
8
,
.
pdiv_mask
=
SENSOR_PDIV_PLLX_MASK
,
.
thermtrip_any_en_mask
=
TEGRA124_THERMTRIP_ANY_EN_MASK
,
.
thermtrip_enable_mask
=
TEGRA124_THERMTRIP_TSENSE_EN_MASK
,
.
thermtrip_threshold_mask
=
TEGRA124_THERMTRIP_TSENSE_THRESH_MASK
,
};
static
const
struct
tegra_tsensor_group
tegra124_tsensor_group_mem
=
{
.
id
=
TEGRA124_SOCTHERM_SENSOR_MEM
,
.
name
=
"mem"
,
.
sensor_temp_offset
=
SENSOR_TEMP2
,
.
sensor_temp_mask
=
SENSOR_TEMP2_MEM_TEMP_MASK
,
.
pdiv
=
8
,
.
pdiv_ate
=
8
,
.
pdiv_mask
=
SENSOR_PDIV_MEM_MASK
,
.
pllx_hotspot_diff
=
0
,
.
pllx_hotspot_mask
=
SENSOR_HOTSPOT_MEM_MASK
,
.
thermtrip_any_en_mask
=
TEGRA124_THERMTRIP_ANY_EN_MASK
,
.
thermtrip_enable_mask
=
TEGRA124_THERMTRIP_MEM_EN_MASK
,
.
thermtrip_threshold_mask
=
TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK
,
};
static
const
struct
tegra_tsensor_group
*
tegra124_tsensor_groups
[]
=
{
&
tegra124_tsensor_group_cpu
,
&
tegra124_tsensor_group_gpu
,
&
tegra124_tsensor_group_pll
,
&
tegra124_tsensor_group_mem
,
};
static
const
struct
tegra_tsensor
tegra124_tsensors
[]
=
{
{
.
name
=
"cpu0"
,
.
base
=
0xc0
,
.
config
=
&
tegra124_tsensor_config
,
.
calib_fuse_offset
=
0x098
,
.
fuse_corr_alpha
=
1135400
,
.
fuse_corr_beta
=
-
6266900
,
.
group
=
&
tegra124_tsensor_group_cpu
,
},
{
.
name
=
"cpu1"
,
.
base
=
0xe0
,
.
config
=
&
tegra124_tsensor_config
,
.
calib_fuse_offset
=
0x084
,
.
fuse_corr_alpha
=
1122220
,
.
fuse_corr_beta
=
-
5700700
,
.
group
=
&
tegra124_tsensor_group_cpu
,
},
{
.
name
=
"cpu2"
,
.
base
=
0x100
,
.
config
=
&
tegra124_tsensor_config
,
.
calib_fuse_offset
=
0x088
,
.
fuse_corr_alpha
=
1127000
,
.
fuse_corr_beta
=
-
6768200
,
.
group
=
&
tegra124_tsensor_group_cpu
,
},
{
.
name
=
"cpu3"
,
.
base
=
0x120
,
.
config
=
&
tegra124_tsensor_config
,
.
calib_fuse_offset
=
0x12c
,
.
fuse_corr_alpha
=
1110900
,
.
fuse_corr_beta
=
-
6232000
,
.
group
=
&
tegra124_tsensor_group_cpu
,
},
{
.
name
=
"mem0"
,
.
base
=
0x140
,
.
config
=
&
tegra124_tsensor_config
,
.
calib_fuse_offset
=
0x158
,
.
fuse_corr_alpha
=
1122300
,
.
fuse_corr_beta
=
-
5936400
,
.
group
=
&
tegra124_tsensor_group_mem
,
},
{
.
name
=
"mem1"
,
.
base
=
0x160
,
.
config
=
&
tegra124_tsensor_config
,
.
calib_fuse_offset
=
0x15c
,
.
fuse_corr_alpha
=
1145700
,
.
fuse_corr_beta
=
-
7124600
,
.
group
=
&
tegra124_tsensor_group_mem
,
},
{
.
name
=
"gpu"
,
.
base
=
0x180
,
.
config
=
&
tegra124_tsensor_config
,
.
calib_fuse_offset
=
0x154
,
.
fuse_corr_alpha
=
1120100
,
.
fuse_corr_beta
=
-
6000500
,
.
group
=
&
tegra124_tsensor_group_gpu
,
},
{
.
name
=
"pllx"
,
.
base
=
0x1a0
,
.
config
=
&
tegra124_tsensor_config
,
.
calib_fuse_offset
=
0x160
,
.
fuse_corr_alpha
=
1106500
,
.
fuse_corr_beta
=
-
6729300
,
.
group
=
&
tegra124_tsensor_group_pll
,
},
};
/*
* Mask/shift bits in FUSE_TSENSOR_COMMON and
* FUSE_TSENSOR_COMMON, which are described in
* tegra_soctherm_fuse.c
*/
static
const
struct
tegra_soctherm_fuse
tegra124_soctherm_fuse
=
{
.
fuse_base_cp_mask
=
0x3ff
,
.
fuse_base_cp_shift
=
0
,
.
fuse_base_ft_mask
=
0x7ff
<<
10
,
.
fuse_base_ft_shift
=
10
,
.
fuse_shift_ft_mask
=
0x1f
<<
21
,
.
fuse_shift_ft_shift
=
21
,
.
fuse_spare_realignment
=
0x1fc
,
};
const
struct
tegra_soctherm_soc
tegra124_soctherm
=
{
.
tsensors
=
tegra124_tsensors
,
.
num_tsensors
=
ARRAY_SIZE
(
tegra124_tsensors
),
.
ttgs
=
tegra124_tsensor_groups
,
.
num_ttgs
=
ARRAY_SIZE
(
tegra124_tsensor_groups
),
.
tfuse
=
&
tegra124_soctherm_fuse
,
.
thresh_grain
=
TEGRA124_THRESH_GRAIN
,
};
drivers/thermal/tegra/tegra132-soctherm.c
0 → 100644
View file @
88ac9906
/*
* Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <dt-bindings/thermal/tegra124-soctherm.h>
#include "soctherm.h"
#define TEGRA132_THERMTRIP_ANY_EN_MASK (0x1 << 28)
#define TEGRA132_THERMTRIP_MEM_EN_MASK (0x1 << 27)
#define TEGRA132_THERMTRIP_GPU_EN_MASK (0x1 << 26)
#define TEGRA132_THERMTRIP_CPU_EN_MASK (0x1 << 25)
#define TEGRA132_THERMTRIP_TSENSE_EN_MASK (0x1 << 24)
#define TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK (0xff << 16)
#define TEGRA132_THERMTRIP_CPU_THRESH_MASK (0xff << 8)
#define TEGRA132_THERMTRIP_TSENSE_THRESH_MASK 0xff
#define TEGRA132_THRESH_GRAIN 1000
static
const
struct
tegra_tsensor_configuration
tegra132_tsensor_config
=
{
.
tall
=
16300
,
.
tiddq_en
=
1
,
.
ten_count
=
1
,
.
tsample
=
120
,
.
tsample_ate
=
480
,
};
static
const
struct
tegra_tsensor_group
tegra132_tsensor_group_cpu
=
{
.
id
=
TEGRA124_SOCTHERM_SENSOR_CPU
,
.
name
=
"cpu"
,
.
sensor_temp_offset
=
SENSOR_TEMP1
,
.
sensor_temp_mask
=
SENSOR_TEMP1_CPU_TEMP_MASK
,
.
pdiv
=
8
,
.
pdiv_ate
=
8
,
.
pdiv_mask
=
SENSOR_PDIV_CPU_MASK
,
.
pllx_hotspot_diff
=
10
,
.
pllx_hotspot_mask
=
SENSOR_HOTSPOT_CPU_MASK
,
.
thermtrip_any_en_mask
=
TEGRA132_THERMTRIP_ANY_EN_MASK
,
.
thermtrip_enable_mask
=
TEGRA132_THERMTRIP_CPU_EN_MASK
,
.
thermtrip_threshold_mask
=
TEGRA132_THERMTRIP_CPU_THRESH_MASK
,
};
static
const
struct
tegra_tsensor_group
tegra132_tsensor_group_gpu
=
{
.
id
=
TEGRA124_SOCTHERM_SENSOR_GPU
,
.
name
=
"gpu"
,
.
sensor_temp_offset
=
SENSOR_TEMP1
,
.
sensor_temp_mask
=
SENSOR_TEMP1_GPU_TEMP_MASK
,
.
pdiv
=
8
,
.
pdiv_ate
=
8
,
.
pdiv_mask
=
SENSOR_PDIV_GPU_MASK
,
.
pllx_hotspot_diff
=
5
,
.
pllx_hotspot_mask
=
SENSOR_HOTSPOT_GPU_MASK
,
.
thermtrip_any_en_mask
=
TEGRA132_THERMTRIP_ANY_EN_MASK
,
.
thermtrip_enable_mask
=
TEGRA132_THERMTRIP_GPU_EN_MASK
,
.
thermtrip_threshold_mask
=
TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK
,
};
static
const
struct
tegra_tsensor_group
tegra132_tsensor_group_pll
=
{
.
id
=
TEGRA124_SOCTHERM_SENSOR_PLLX
,
.
name
=
"pll"
,
.
sensor_temp_offset
=
SENSOR_TEMP2
,
.
sensor_temp_mask
=
SENSOR_TEMP2_PLLX_TEMP_MASK
,
.
pdiv
=
8
,
.
pdiv_ate
=
8
,
.
pdiv_mask
=
SENSOR_PDIV_PLLX_MASK
,
.
thermtrip_any_en_mask
=
TEGRA132_THERMTRIP_ANY_EN_MASK
,
.
thermtrip_enable_mask
=
TEGRA132_THERMTRIP_TSENSE_EN_MASK
,
.
thermtrip_threshold_mask
=
TEGRA132_THERMTRIP_TSENSE_THRESH_MASK
,
};
static
const
struct
tegra_tsensor_group
tegra132_tsensor_group_mem
=
{
.
id
=
TEGRA124_SOCTHERM_SENSOR_MEM
,
.
name
=
"mem"
,
.
sensor_temp_offset
=
SENSOR_TEMP2
,
.
sensor_temp_mask
=
SENSOR_TEMP2_MEM_TEMP_MASK
,
.
pdiv
=
8
,
.
pdiv_ate
=
8
,
.
pdiv_mask
=
SENSOR_PDIV_MEM_MASK
,
.
pllx_hotspot_diff
=
0
,
.
pllx_hotspot_mask
=
SENSOR_HOTSPOT_MEM_MASK
,
.
thermtrip_any_en_mask
=
TEGRA132_THERMTRIP_ANY_EN_MASK
,
.
thermtrip_enable_mask
=
TEGRA132_THERMTRIP_MEM_EN_MASK
,
.
thermtrip_threshold_mask
=
TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK
,
};
static
const
struct
tegra_tsensor_group
*
tegra132_tsensor_groups
[]
=
{
&
tegra132_tsensor_group_cpu
,
&
tegra132_tsensor_group_gpu
,
&
tegra132_tsensor_group_pll
,
&
tegra132_tsensor_group_mem
,
};
static
struct
tegra_tsensor
tegra132_tsensors
[]
=
{
{
.
name
=
"cpu0"
,
.
base
=
0xc0
,
.
config
=
&
tegra132_tsensor_config
,
.
calib_fuse_offset
=
0x098
,
.
fuse_corr_alpha
=
1126600
,
.
fuse_corr_beta
=
-
9433500
,
.
group
=
&
tegra132_tsensor_group_cpu
,
},
{
.
name
=
"cpu1"
,
.
base
=
0xe0
,
.
config
=
&
tegra132_tsensor_config
,
.
calib_fuse_offset
=
0x084
,
.
fuse_corr_alpha
=
1110800
,
.
fuse_corr_beta
=
-
7383000
,
.
group
=
&
tegra132_tsensor_group_cpu
,
},
{
.
name
=
"cpu2"
,
.
base
=
0x100
,
.
config
=
&
tegra132_tsensor_config
,
.
calib_fuse_offset
=
0x088
,
.
fuse_corr_alpha
=
1113800
,
.
fuse_corr_beta
=
-
6215200
,
.
group
=
&
tegra132_tsensor_group_cpu
,
},
{
.
name
=
"cpu3"
,
.
base
=
0x120
,
.
config
=
&
tegra132_tsensor_config
,
.
calib_fuse_offset
=
0x12c
,
.
fuse_corr_alpha
=
1129600
,
.
fuse_corr_beta
=
-
8196100
,
.
group
=
&
tegra132_tsensor_group_cpu
,
},
{
.
name
=
"mem0"
,
.
base
=
0x140
,
.
config
=
&
tegra132_tsensor_config
,
.
calib_fuse_offset
=
0x158
,
.
fuse_corr_alpha
=
1132900
,
.
fuse_corr_beta
=
-
6755300
,
.
group
=
&
tegra132_tsensor_group_mem
,
},
{
.
name
=
"mem1"
,
.
base
=
0x160
,
.
config
=
&
tegra132_tsensor_config
,
.
calib_fuse_offset
=
0x15c
,
.
fuse_corr_alpha
=
1142300
,
.
fuse_corr_beta
=
-
7374200
,
.
group
=
&
tegra132_tsensor_group_mem
,
},
{
.
name
=
"gpu"
,
.
base
=
0x180
,
.
config
=
&
tegra132_tsensor_config
,
.
calib_fuse_offset
=
0x154
,
.
fuse_corr_alpha
=
1125100
,
.
fuse_corr_beta
=
-
6350400
,
.
group
=
&
tegra132_tsensor_group_gpu
,
},
{
.
name
=
"pllx"
,
.
base
=
0x1a0
,
.
config
=
&
tegra132_tsensor_config
,
.
calib_fuse_offset
=
0x160
,
.
fuse_corr_alpha
=
1118100
,
.
fuse_corr_beta
=
-
8208800
,
.
group
=
&
tegra132_tsensor_group_pll
,
},
};
/*
* Mask/shift bits in FUSE_TSENSOR_COMMON and
* FUSE_TSENSOR_COMMON, which are described in
* tegra_soctherm_fuse.c
*/
static
const
struct
tegra_soctherm_fuse
tegra132_soctherm_fuse
=
{
.
fuse_base_cp_mask
=
0x3ff
,
.
fuse_base_cp_shift
=
0
,
.
fuse_base_ft_mask
=
0x7ff
<<
10
,
.
fuse_base_ft_shift
=
10
,
.
fuse_shift_ft_mask
=
0x1f
<<
21
,
.
fuse_shift_ft_shift
=
21
,
.
fuse_spare_realignment
=
0x1fc
,
};
const
struct
tegra_soctherm_soc
tegra132_soctherm
=
{
.
tsensors
=
tegra132_tsensors
,
.
num_tsensors
=
ARRAY_SIZE
(
tegra132_tsensors
),
.
ttgs
=
tegra132_tsensor_groups
,
.
num_ttgs
=
ARRAY_SIZE
(
tegra132_tsensor_groups
),
.
tfuse
=
&
tegra132_soctherm_fuse
,
.
thresh_grain
=
TEGRA132_THRESH_GRAIN
,
};
drivers/thermal/tegra/tegra210-soctherm.c
0 → 100644
View file @
88ac9906
/*
* Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <soc/tegra/fuse.h>
#include <dt-bindings/thermal/tegra124-soctherm.h>
#include "soctherm.h"
#define TEGRA210_THERMTRIP_ANY_EN_MASK (0x1 << 31)
#define TEGRA210_THERMTRIP_MEM_EN_MASK (0x1 << 30)
#define TEGRA210_THERMTRIP_GPU_EN_MASK (0x1 << 29)
#define TEGRA210_THERMTRIP_CPU_EN_MASK (0x1 << 28)
#define TEGRA210_THERMTRIP_TSENSE_EN_MASK (0x1 << 27)
#define TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK (0x1ff << 18)
#define TEGRA210_THERMTRIP_CPU_THRESH_MASK (0x1ff << 9)
#define TEGRA210_THERMTRIP_TSENSE_THRESH_MASK 0x1ff
#define TEGRA210_THRESH_GRAIN 500
static
const
struct
tegra_tsensor_configuration
tegra210_tsensor_config
=
{
.
tall
=
16300
,
.
tiddq_en
=
1
,
.
ten_count
=
1
,
.
tsample
=
120
,
.
tsample_ate
=
480
,
};
static
const
struct
tegra_tsensor_group
tegra210_tsensor_group_cpu
=
{
.
id
=
TEGRA124_SOCTHERM_SENSOR_CPU
,
.
name
=
"cpu"
,
.
sensor_temp_offset
=
SENSOR_TEMP1
,
.
sensor_temp_mask
=
SENSOR_TEMP1_CPU_TEMP_MASK
,
.
pdiv
=
8
,
.
pdiv_ate
=
8
,
.
pdiv_mask
=
SENSOR_PDIV_CPU_MASK
,
.
pllx_hotspot_diff
=
10
,
.
pllx_hotspot_mask
=
SENSOR_HOTSPOT_CPU_MASK
,
.
thermtrip_any_en_mask
=
TEGRA210_THERMTRIP_ANY_EN_MASK
,
.
thermtrip_enable_mask
=
TEGRA210_THERMTRIP_CPU_EN_MASK
,
.
thermtrip_threshold_mask
=
TEGRA210_THERMTRIP_CPU_THRESH_MASK
,
};
static
const
struct
tegra_tsensor_group
tegra210_tsensor_group_gpu
=
{
.
id
=
TEGRA124_SOCTHERM_SENSOR_GPU
,
.
name
=
"gpu"
,
.
sensor_temp_offset
=
SENSOR_TEMP1
,
.
sensor_temp_mask
=
SENSOR_TEMP1_GPU_TEMP_MASK
,
.
pdiv
=
8
,
.
pdiv_ate
=
8
,
.
pdiv_mask
=
SENSOR_PDIV_GPU_MASK
,
.
pllx_hotspot_diff
=
5
,
.
pllx_hotspot_mask
=
SENSOR_HOTSPOT_GPU_MASK
,
.
thermtrip_any_en_mask
=
TEGRA210_THERMTRIP_ANY_EN_MASK
,
.
thermtrip_enable_mask
=
TEGRA210_THERMTRIP_GPU_EN_MASK
,
.
thermtrip_threshold_mask
=
TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK
,
};
static
const
struct
tegra_tsensor_group
tegra210_tsensor_group_pll
=
{
.
id
=
TEGRA124_SOCTHERM_SENSOR_PLLX
,
.
name
=
"pll"
,
.
sensor_temp_offset
=
SENSOR_TEMP2
,
.
sensor_temp_mask
=
SENSOR_TEMP2_PLLX_TEMP_MASK
,
.
pdiv
=
8
,
.
pdiv_ate
=
8
,
.
pdiv_mask
=
SENSOR_PDIV_PLLX_MASK
,
.
thermtrip_any_en_mask
=
TEGRA210_THERMTRIP_ANY_EN_MASK
,
.
thermtrip_enable_mask
=
TEGRA210_THERMTRIP_TSENSE_EN_MASK
,
.
thermtrip_threshold_mask
=
TEGRA210_THERMTRIP_TSENSE_THRESH_MASK
,
};
static
const
struct
tegra_tsensor_group
tegra210_tsensor_group_mem
=
{
.
id
=
TEGRA124_SOCTHERM_SENSOR_MEM
,
.
name
=
"mem"
,
.
sensor_temp_offset
=
SENSOR_TEMP2
,
.
sensor_temp_mask
=
SENSOR_TEMP2_MEM_TEMP_MASK
,
.
pdiv
=
8
,
.
pdiv_ate
=
8
,
.
pdiv_mask
=
SENSOR_PDIV_MEM_MASK
,
.
pllx_hotspot_diff
=
0
,
.
pllx_hotspot_mask
=
SENSOR_HOTSPOT_MEM_MASK
,
.
thermtrip_any_en_mask
=
TEGRA210_THERMTRIP_ANY_EN_MASK
,
.
thermtrip_enable_mask
=
TEGRA210_THERMTRIP_MEM_EN_MASK
,
.
thermtrip_threshold_mask
=
TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK
,
};
static
const
struct
tegra_tsensor_group
*
tegra210_tsensor_groups
[]
=
{
&
tegra210_tsensor_group_cpu
,
&
tegra210_tsensor_group_gpu
,
&
tegra210_tsensor_group_pll
,
&
tegra210_tsensor_group_mem
,
};
static
const
struct
tegra_tsensor
tegra210_tsensors
[]
=
{
{
.
name
=
"cpu0"
,
.
base
=
0xc0
,
.
config
=
&
tegra210_tsensor_config
,
.
calib_fuse_offset
=
0x098
,
.
fuse_corr_alpha
=
1085000
,
.
fuse_corr_beta
=
3244200
,
.
group
=
&
tegra210_tsensor_group_cpu
,
},
{
.
name
=
"cpu1"
,
.
base
=
0xe0
,
.
config
=
&
tegra210_tsensor_config
,
.
calib_fuse_offset
=
0x084
,
.
fuse_corr_alpha
=
1126200
,
.
fuse_corr_beta
=
-
67500
,
.
group
=
&
tegra210_tsensor_group_cpu
,
},
{
.
name
=
"cpu2"
,
.
base
=
0x100
,
.
config
=
&
tegra210_tsensor_config
,
.
calib_fuse_offset
=
0x088
,
.
fuse_corr_alpha
=
1098400
,
.
fuse_corr_beta
=
2251100
,
.
group
=
&
tegra210_tsensor_group_cpu
,
},
{
.
name
=
"cpu3"
,
.
base
=
0x120
,
.
config
=
&
tegra210_tsensor_config
,
.
calib_fuse_offset
=
0x12c
,
.
fuse_corr_alpha
=
1108000
,
.
fuse_corr_beta
=
602700
,
.
group
=
&
tegra210_tsensor_group_cpu
,
},
{
.
name
=
"mem0"
,
.
base
=
0x140
,
.
config
=
&
tegra210_tsensor_config
,
.
calib_fuse_offset
=
0x158
,
.
fuse_corr_alpha
=
1069200
,
.
fuse_corr_beta
=
3549900
,
.
group
=
&
tegra210_tsensor_group_mem
,
},
{
.
name
=
"mem1"
,
.
base
=
0x160
,
.
config
=
&
tegra210_tsensor_config
,
.
calib_fuse_offset
=
0x15c
,
.
fuse_corr_alpha
=
1173700
,
.
fuse_corr_beta
=
-
6263600
,
.
group
=
&
tegra210_tsensor_group_mem
,
},
{
.
name
=
"gpu"
,
.
base
=
0x180
,
.
config
=
&
tegra210_tsensor_config
,
.
calib_fuse_offset
=
0x154
,
.
fuse_corr_alpha
=
1074300
,
.
fuse_corr_beta
=
2734900
,
.
group
=
&
tegra210_tsensor_group_gpu
,
},
{
.
name
=
"pllx"
,
.
base
=
0x1a0
,
.
config
=
&
tegra210_tsensor_config
,
.
calib_fuse_offset
=
0x160
,
.
fuse_corr_alpha
=
1039700
,
.
fuse_corr_beta
=
6829100
,
.
group
=
&
tegra210_tsensor_group_pll
,
},
};
/*
* Mask/shift bits in FUSE_TSENSOR_COMMON and
* FUSE_TSENSOR_COMMON, which are described in
* tegra_soctherm_fuse.c
*/
static
const
struct
tegra_soctherm_fuse
tegra210_soctherm_fuse
=
{
.
fuse_base_cp_mask
=
0x3ff
<<
11
,
.
fuse_base_cp_shift
=
11
,
.
fuse_base_ft_mask
=
0x7ff
<<
21
,
.
fuse_base_ft_shift
=
21
,
.
fuse_shift_ft_mask
=
0x1f
<<
6
,
.
fuse_shift_ft_shift
=
6
,
.
fuse_spare_realignment
=
0
,
};
const
struct
tegra_soctherm_soc
tegra210_soctherm
=
{
.
tsensors
=
tegra210_tsensors
,
.
num_tsensors
=
ARRAY_SIZE
(
tegra210_tsensors
),
.
ttgs
=
tegra210_tsensor_groups
,
.
num_ttgs
=
ARRAY_SIZE
(
tegra210_tsensor_groups
),
.
tfuse
=
&
tegra210_soctherm_fuse
,
.
thresh_grain
=
TEGRA210_THRESH_GRAIN
,
};
drivers/thermal/tegra_soctherm.c
deleted
100644 → 0
View file @
191b0754
/*
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* Author:
* Mikko Perttunen <mperttunen@nvidia.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/thermal.h>
#include <soc/tegra/fuse.h>
#define SENSOR_CONFIG0 0
#define SENSOR_CONFIG0_STOP BIT(0)
#define SENSOR_CONFIG0_TALL_SHIFT 8
#define SENSOR_CONFIG0_TCALC_OVER BIT(4)
#define SENSOR_CONFIG0_OVER BIT(3)
#define SENSOR_CONFIG0_CPTR_OVER BIT(2)
#define SENSOR_CONFIG1 4
#define SENSOR_CONFIG1_TSAMPLE_SHIFT 0
#define SENSOR_CONFIG1_TIDDQ_EN_SHIFT 15
#define SENSOR_CONFIG1_TEN_COUNT_SHIFT 24
#define SENSOR_CONFIG1_TEMP_ENABLE BIT(31)
#define SENSOR_CONFIG2 8
#define SENSOR_CONFIG2_THERMA_SHIFT 16
#define SENSOR_CONFIG2_THERMB_SHIFT 0
#define SENSOR_PDIV 0x1c0
#define SENSOR_PDIV_T124 0x8888
#define SENSOR_HOTSPOT_OFF 0x1c4
#define SENSOR_HOTSPOT_OFF_T124 0x00060600
#define SENSOR_TEMP1 0x1c8
#define SENSOR_TEMP2 0x1cc
#define SENSOR_TEMP_MASK 0xffff
#define READBACK_VALUE_MASK 0xff00
#define READBACK_VALUE_SHIFT 8
#define READBACK_ADD_HALF BIT(7)
#define READBACK_NEGATE BIT(0)
#define FUSE_TSENSOR8_CALIB 0x180
#define FUSE_SPARE_REALIGNMENT_REG_0 0x1fc
#define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK 0x1fff
#define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK (0x1fff << 13)
#define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT 13
#define FUSE_TSENSOR8_CALIB_CP_TS_BASE_MASK 0x3ff
#define FUSE_TSENSOR8_CALIB_FT_TS_BASE_MASK (0x7ff << 10)
#define FUSE_TSENSOR8_CALIB_FT_TS_BASE_SHIFT 10
#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP_MASK 0x3f
#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_MASK (0x1f << 21)
#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_SHIFT 21
#define NOMINAL_CALIB_FT_T124 105
#define NOMINAL_CALIB_CP_T124 25
struct
tegra_tsensor_configuration
{
u32
tall
,
tsample
,
tiddq_en
,
ten_count
,
pdiv
,
tsample_ate
,
pdiv_ate
;
};
struct
tegra_tsensor
{
const
struct
tegra_tsensor_configuration
*
config
;
u32
base
,
calib_fuse_offset
;
/* Correction values used to modify values read from calibration fuses */
s32
fuse_corr_alpha
,
fuse_corr_beta
;
};
struct
tegra_thermctl_zone
{
void
__iomem
*
reg
;
unsigned
int
shift
;
};
static
const
struct
tegra_tsensor_configuration
t124_tsensor_config
=
{
.
tall
=
16300
,
.
tsample
=
120
,
.
tiddq_en
=
1
,
.
ten_count
=
1
,
.
pdiv
=
8
,
.
tsample_ate
=
480
,
.
pdiv_ate
=
8
};
static
const
struct
tegra_tsensor
t124_tsensors
[]
=
{
{
.
config
=
&
t124_tsensor_config
,
.
base
=
0xc0
,
.
calib_fuse_offset
=
0x098
,
.
fuse_corr_alpha
=
1135400
,
.
fuse_corr_beta
=
-
6266900
,
},
{
.
config
=
&
t124_tsensor_config
,
.
base
=
0xe0
,
.
calib_fuse_offset
=
0x084
,
.
fuse_corr_alpha
=
1122220
,
.
fuse_corr_beta
=
-
5700700
,
},
{
.
config
=
&
t124_tsensor_config
,
.
base
=
0x100
,
.
calib_fuse_offset
=
0x088
,
.
fuse_corr_alpha
=
1127000
,
.
fuse_corr_beta
=
-
6768200
,
},
{
.
config
=
&
t124_tsensor_config
,
.
base
=
0x120
,
.
calib_fuse_offset
=
0x12c
,
.
fuse_corr_alpha
=
1110900
,
.
fuse_corr_beta
=
-
6232000
,
},
{
.
config
=
&
t124_tsensor_config
,
.
base
=
0x140
,
.
calib_fuse_offset
=
0x158
,
.
fuse_corr_alpha
=
1122300
,
.
fuse_corr_beta
=
-
5936400
,
},
{
.
config
=
&
t124_tsensor_config
,
.
base
=
0x160
,
.
calib_fuse_offset
=
0x15c
,
.
fuse_corr_alpha
=
1145700
,
.
fuse_corr_beta
=
-
7124600
,
},
{
.
config
=
&
t124_tsensor_config
,
.
base
=
0x180
,
.
calib_fuse_offset
=
0x154
,
.
fuse_corr_alpha
=
1120100
,
.
fuse_corr_beta
=
-
6000500
,
},
{
.
config
=
&
t124_tsensor_config
,
.
base
=
0x1a0
,
.
calib_fuse_offset
=
0x160
,
.
fuse_corr_alpha
=
1106500
,
.
fuse_corr_beta
=
-
6729300
,
},
};
struct
tegra_soctherm
{
struct
reset_control
*
reset
;
struct
clk
*
clock_tsensor
;
struct
clk
*
clock_soctherm
;
void
__iomem
*
regs
;
struct
thermal_zone_device
*
thermctl_tzs
[
4
];
};
struct
tsensor_shared_calibration
{
u32
base_cp
,
base_ft
;
u32
actual_temp_cp
,
actual_temp_ft
;
};
static
int
calculate_shared_calibration
(
struct
tsensor_shared_calibration
*
r
)
{
u32
val
,
shifted_cp
,
shifted_ft
;
int
err
;
err
=
tegra_fuse_readl
(
FUSE_TSENSOR8_CALIB
,
&
val
);
if
(
err
)
return
err
;
r
->
base_cp
=
val
&
FUSE_TSENSOR8_CALIB_CP_TS_BASE_MASK
;
r
->
base_ft
=
(
val
&
FUSE_TSENSOR8_CALIB_FT_TS_BASE_MASK
)
>>
FUSE_TSENSOR8_CALIB_FT_TS_BASE_SHIFT
;
val
=
((
val
&
FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_MASK
)
>>
FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_SHIFT
);
shifted_ft
=
sign_extend32
(
val
,
4
);
err
=
tegra_fuse_readl
(
FUSE_SPARE_REALIGNMENT_REG_0
,
&
val
);
if
(
err
)
return
err
;
shifted_cp
=
sign_extend32
(
val
,
5
);
r
->
actual_temp_cp
=
2
*
NOMINAL_CALIB_CP_T124
+
shifted_cp
;
r
->
actual_temp_ft
=
2
*
NOMINAL_CALIB_FT_T124
+
shifted_ft
;
return
0
;
}
static
s64
div64_s64_precise
(
s64
a
,
s64
b
)
{
s64
r
,
al
;
/* Scale up for increased precision division */
al
=
a
<<
16
;
r
=
div64_s64
(
al
*
2
+
1
,
2
*
b
);
return
r
>>
16
;
}
static
int
calculate_tsensor_calibration
(
const
struct
tegra_tsensor
*
sensor
,
const
struct
tsensor_shared_calibration
*
shared
,
u32
*
calib
)
{
u32
val
;
s32
actual_tsensor_ft
,
actual_tsensor_cp
,
delta_sens
,
delta_temp
,
mult
,
div
;
s16
therma
,
thermb
;
s64
tmp
;
int
err
;
err
=
tegra_fuse_readl
(
sensor
->
calib_fuse_offset
,
&
val
);
if
(
err
)
return
err
;
actual_tsensor_cp
=
(
shared
->
base_cp
*
64
)
+
sign_extend32
(
val
,
12
);
val
=
(
val
&
FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK
)
>>
FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT
;
actual_tsensor_ft
=
(
shared
->
base_ft
*
32
)
+
sign_extend32
(
val
,
12
);
delta_sens
=
actual_tsensor_ft
-
actual_tsensor_cp
;
delta_temp
=
shared
->
actual_temp_ft
-
shared
->
actual_temp_cp
;
mult
=
sensor
->
config
->
pdiv
*
sensor
->
config
->
tsample_ate
;
div
=
sensor
->
config
->
tsample
*
sensor
->
config
->
pdiv_ate
;
therma
=
div64_s64_precise
((
s64
)
delta_temp
*
(
1LL
<<
13
)
*
mult
,
(
s64
)
delta_sens
*
div
);
tmp
=
(
s64
)
actual_tsensor_ft
*
shared
->
actual_temp_cp
-
(
s64
)
actual_tsensor_cp
*
shared
->
actual_temp_ft
;
thermb
=
div64_s64_precise
(
tmp
,
(
s64
)
delta_sens
);
therma
=
div64_s64_precise
((
s64
)
therma
*
sensor
->
fuse_corr_alpha
,
(
s64
)
1000000LL
);
thermb
=
div64_s64_precise
((
s64
)
thermb
*
sensor
->
fuse_corr_alpha
+
sensor
->
fuse_corr_beta
,
(
s64
)
1000000LL
);
*
calib
=
((
u16
)
therma
<<
SENSOR_CONFIG2_THERMA_SHIFT
)
|
((
u16
)
thermb
<<
SENSOR_CONFIG2_THERMB_SHIFT
);
return
0
;
}
static
int
enable_tsensor
(
struct
tegra_soctherm
*
tegra
,
const
struct
tegra_tsensor
*
sensor
,
const
struct
tsensor_shared_calibration
*
shared
)
{
void
__iomem
*
base
=
tegra
->
regs
+
sensor
->
base
;
unsigned
int
val
;
u32
calib
;
int
err
;
err
=
calculate_tsensor_calibration
(
sensor
,
shared
,
&
calib
);
if
(
err
)
return
err
;
val
=
sensor
->
config
->
tall
<<
SENSOR_CONFIG0_TALL_SHIFT
;
writel
(
val
,
base
+
SENSOR_CONFIG0
);
val
=
(
sensor
->
config
->
tsample
-
1
)
<<
SENSOR_CONFIG1_TSAMPLE_SHIFT
;
val
|=
sensor
->
config
->
tiddq_en
<<
SENSOR_CONFIG1_TIDDQ_EN_SHIFT
;
val
|=
sensor
->
config
->
ten_count
<<
SENSOR_CONFIG1_TEN_COUNT_SHIFT
;
val
|=
SENSOR_CONFIG1_TEMP_ENABLE
;
writel
(
val
,
base
+
SENSOR_CONFIG1
);
writel
(
calib
,
base
+
SENSOR_CONFIG2
);
return
0
;
}
/*
* Translate from soctherm readback format to millicelsius.
* The soctherm readback format in bits is as follows:
* TTTTTTTT H______N
* where T's contain the temperature in Celsius,
* H denotes an addition of 0.5 Celsius and N denotes negation
* of the final value.
*/
static
int
translate_temp
(
u16
val
)
{
long
t
;
t
=
((
val
&
READBACK_VALUE_MASK
)
>>
READBACK_VALUE_SHIFT
)
*
1000
;
if
(
val
&
READBACK_ADD_HALF
)
t
+=
500
;
if
(
val
&
READBACK_NEGATE
)
t
*=
-
1
;
return
t
;
}
static
int
tegra_thermctl_get_temp
(
void
*
data
,
int
*
out_temp
)
{
struct
tegra_thermctl_zone
*
zone
=
data
;
u32
val
;
val
=
(
readl
(
zone
->
reg
)
>>
zone
->
shift
)
&
SENSOR_TEMP_MASK
;
*
out_temp
=
translate_temp
(
val
);
return
0
;
}
static
const
struct
thermal_zone_of_device_ops
tegra_of_thermal_ops
=
{
.
get_temp
=
tegra_thermctl_get_temp
,
};
static
const
struct
of_device_id
tegra_soctherm_of_match
[]
=
{
{
.
compatible
=
"nvidia,tegra124-soctherm"
},
{
},
};
MODULE_DEVICE_TABLE
(
of
,
tegra_soctherm_of_match
);
struct
thermctl_zone_desc
{
unsigned
int
offset
;
unsigned
int
shift
;
};
static
const
struct
thermctl_zone_desc
t124_thermctl_temp_zones
[]
=
{
{
SENSOR_TEMP1
,
16
},
{
SENSOR_TEMP2
,
16
},
{
SENSOR_TEMP1
,
0
},
{
SENSOR_TEMP2
,
0
}
};
static
int
tegra_soctherm_probe
(
struct
platform_device
*
pdev
)
{
struct
tegra_soctherm
*
tegra
;
struct
thermal_zone_device
*
tz
;
struct
tsensor_shared_calibration
shared_calib
;
struct
resource
*
res
;
unsigned
int
i
;
int
err
;
const
struct
tegra_tsensor
*
tsensors
=
t124_tsensors
;
tegra
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
tegra
),
GFP_KERNEL
);
if
(
!
tegra
)
return
-
ENOMEM
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
tegra
->
regs
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
tegra
->
regs
))
return
PTR_ERR
(
tegra
->
regs
);
tegra
->
reset
=
devm_reset_control_get
(
&
pdev
->
dev
,
"soctherm"
);
if
(
IS_ERR
(
tegra
->
reset
))
{
dev_err
(
&
pdev
->
dev
,
"can't get soctherm reset
\n
"
);
return
PTR_ERR
(
tegra
->
reset
);
}
tegra
->
clock_tsensor
=
devm_clk_get
(
&
pdev
->
dev
,
"tsensor"
);
if
(
IS_ERR
(
tegra
->
clock_tsensor
))
{
dev_err
(
&
pdev
->
dev
,
"can't get tsensor clock
\n
"
);
return
PTR_ERR
(
tegra
->
clock_tsensor
);
}
tegra
->
clock_soctherm
=
devm_clk_get
(
&
pdev
->
dev
,
"soctherm"
);
if
(
IS_ERR
(
tegra
->
clock_soctherm
))
{
dev_err
(
&
pdev
->
dev
,
"can't get soctherm clock
\n
"
);
return
PTR_ERR
(
tegra
->
clock_soctherm
);
}
reset_control_assert
(
tegra
->
reset
);
err
=
clk_prepare_enable
(
tegra
->
clock_soctherm
);
if
(
err
)
return
err
;
err
=
clk_prepare_enable
(
tegra
->
clock_tsensor
);
if
(
err
)
{
clk_disable_unprepare
(
tegra
->
clock_soctherm
);
return
err
;
}
reset_control_deassert
(
tegra
->
reset
);
/* Initialize raw sensors */
err
=
calculate_shared_calibration
(
&
shared_calib
);
if
(
err
)
goto
disable_clocks
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
t124_tsensors
);
++
i
)
{
err
=
enable_tsensor
(
tegra
,
tsensors
+
i
,
&
shared_calib
);
if
(
err
)
goto
disable_clocks
;
}
writel
(
SENSOR_PDIV_T124
,
tegra
->
regs
+
SENSOR_PDIV
);
writel
(
SENSOR_HOTSPOT_OFF_T124
,
tegra
->
regs
+
SENSOR_HOTSPOT_OFF
);
/* Initialize thermctl sensors */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
tegra
->
thermctl_tzs
);
++
i
)
{
struct
tegra_thermctl_zone
*
zone
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
zone
),
GFP_KERNEL
);
if
(
!
zone
)
{
err
=
-
ENOMEM
;
goto
unregister_tzs
;
}
zone
->
reg
=
tegra
->
regs
+
t124_thermctl_temp_zones
[
i
].
offset
;
zone
->
shift
=
t124_thermctl_temp_zones
[
i
].
shift
;
tz
=
thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
i
,
zone
,
&
tegra_of_thermal_ops
);
if
(
IS_ERR
(
tz
))
{
err
=
PTR_ERR
(
tz
);
dev_err
(
&
pdev
->
dev
,
"failed to register sensor: %d
\n
"
,
err
);
goto
unregister_tzs
;
}
tegra
->
thermctl_tzs
[
i
]
=
tz
;
}
return
0
;
unregister_tzs:
while
(
i
--
)
thermal_zone_of_sensor_unregister
(
&
pdev
->
dev
,
tegra
->
thermctl_tzs
[
i
]);
disable_clocks:
clk_disable_unprepare
(
tegra
->
clock_tsensor
);
clk_disable_unprepare
(
tegra
->
clock_soctherm
);
return
err
;
}
static
int
tegra_soctherm_remove
(
struct
platform_device
*
pdev
)
{
struct
tegra_soctherm
*
tegra
=
platform_get_drvdata
(
pdev
);
unsigned
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
tegra
->
thermctl_tzs
);
++
i
)
{
thermal_zone_of_sensor_unregister
(
&
pdev
->
dev
,
tegra
->
thermctl_tzs
[
i
]);
}
clk_disable_unprepare
(
tegra
->
clock_tsensor
);
clk_disable_unprepare
(
tegra
->
clock_soctherm
);
return
0
;
}
static
struct
platform_driver
tegra_soctherm_driver
=
{
.
probe
=
tegra_soctherm_probe
,
.
remove
=
tegra_soctherm_remove
,
.
driver
=
{
.
name
=
"tegra-soctherm"
,
.
of_match_table
=
tegra_soctherm_of_match
,
},
};
module_platform_driver
(
tegra_soctherm_driver
);
MODULE_AUTHOR
(
"Mikko Perttunen <mperttunen@nvidia.com>"
);
MODULE_DESCRIPTION
(
"NVIDIA Tegra SOCTHERM thermal management driver"
);
MODULE_LICENSE
(
"GPL v2"
);
drivers/thermal/thermal-generic-adc.c
0 → 100644
View file @
88ac9906
/*
* Generic ADC thermal driver
*
* Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
*
* Author: Laxman Dewangan <ldewangan@nvidia.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/iio/consumer.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/thermal.h>
struct
gadc_thermal_info
{
struct
device
*
dev
;
struct
thermal_zone_device
*
tz_dev
;
struct
iio_channel
*
channel
;
s32
*
lookup_table
;
int
nlookup_table
;
};
static
int
gadc_thermal_adc_to_temp
(
struct
gadc_thermal_info
*
gti
,
int
val
)
{
int
temp
,
adc_hi
,
adc_lo
;
int
i
;
for
(
i
=
0
;
i
<
gti
->
nlookup_table
;
i
++
)
{
if
(
val
>=
gti
->
lookup_table
[
2
*
i
+
1
])
break
;
}
if
(
i
==
0
)
{
temp
=
gti
->
lookup_table
[
0
];
}
else
if
(
i
>=
(
gti
->
nlookup_table
-
1
))
{
temp
=
gti
->
lookup_table
[
2
*
(
gti
->
nlookup_table
-
1
)];
}
else
{
adc_hi
=
gti
->
lookup_table
[
2
*
i
-
1
];
adc_lo
=
gti
->
lookup_table
[
2
*
i
+
1
];
temp
=
gti
->
lookup_table
[
2
*
i
];
temp
-=
((
val
-
adc_lo
)
*
1000
)
/
(
adc_hi
-
adc_lo
);
}
return
temp
;
}
static
int
gadc_thermal_get_temp
(
void
*
data
,
int
*
temp
)
{
struct
gadc_thermal_info
*
gti
=
data
;
int
val
;
int
ret
;
ret
=
iio_read_channel_processed
(
gti
->
channel
,
&
val
);
if
(
ret
<
0
)
{
dev_err
(
gti
->
dev
,
"IIO channel read failed %d
\n
"
,
ret
);
return
ret
;
}
*
temp
=
gadc_thermal_adc_to_temp
(
gti
,
val
);
return
0
;
}
static
const
struct
thermal_zone_of_device_ops
gadc_thermal_ops
=
{
.
get_temp
=
gadc_thermal_get_temp
,
};
static
int
gadc_thermal_read_linear_lookup_table
(
struct
device
*
dev
,
struct
gadc_thermal_info
*
gti
)
{
struct
device_node
*
np
=
dev
->
of_node
;
int
ntable
;
int
ret
;
ntable
=
of_property_count_elems_of_size
(
np
,
"temperature-lookup-table"
,
sizeof
(
u32
));
if
(
ntable
<
0
)
{
dev_err
(
dev
,
"Lookup table is not provided
\n
"
);
return
ntable
;
}
if
(
ntable
%
2
)
{
dev_err
(
dev
,
"Pair of temperature vs ADC read value missing
\n
"
);
return
-
EINVAL
;
}
gti
->
lookup_table
=
devm_kzalloc
(
dev
,
sizeof
(
*
gti
->
lookup_table
)
*
ntable
,
GFP_KERNEL
);
if
(
!
gti
->
lookup_table
)
return
-
ENOMEM
;
ret
=
of_property_read_u32_array
(
np
,
"temperature-lookup-table"
,
(
u32
*
)
gti
->
lookup_table
,
ntable
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"Failed to read temperature lookup table: %d
\n
"
,
ret
);
return
ret
;
}
gti
->
nlookup_table
=
ntable
/
2
;
return
0
;
}
static
int
gadc_thermal_probe
(
struct
platform_device
*
pdev
)
{
struct
gadc_thermal_info
*
gti
;
int
ret
;
if
(
!
pdev
->
dev
.
of_node
)
{
dev_err
(
&
pdev
->
dev
,
"Only DT based supported
\n
"
);
return
-
ENODEV
;
}
gti
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
gti
),
GFP_KERNEL
);
if
(
!
gti
)
return
-
ENOMEM
;
ret
=
gadc_thermal_read_linear_lookup_table
(
&
pdev
->
dev
,
gti
);
if
(
ret
<
0
)
return
ret
;
gti
->
dev
=
&
pdev
->
dev
;
platform_set_drvdata
(
pdev
,
gti
);
gti
->
channel
=
iio_channel_get
(
&
pdev
->
dev
,
"sensor-channel"
);
if
(
IS_ERR
(
gti
->
channel
))
{
ret
=
PTR_ERR
(
gti
->
channel
);
dev_err
(
&
pdev
->
dev
,
"IIO channel not found: %d
\n
"
,
ret
);
return
ret
;
}
gti
->
tz_dev
=
thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
0
,
gti
,
&
gadc_thermal_ops
);
if
(
IS_ERR
(
gti
->
tz_dev
))
{
ret
=
PTR_ERR
(
gti
->
tz_dev
);
dev_err
(
&
pdev
->
dev
,
"Thermal zone sensor register failed: %d
\n
"
,
ret
);
goto
sensor_fail
;
}
return
0
;
sensor_fail:
iio_channel_release
(
gti
->
channel
);
return
ret
;
}
static
int
gadc_thermal_remove
(
struct
platform_device
*
pdev
)
{
struct
gadc_thermal_info
*
gti
=
platform_get_drvdata
(
pdev
);
thermal_zone_of_sensor_unregister
(
&
pdev
->
dev
,
gti
->
tz_dev
);
iio_channel_release
(
gti
->
channel
);
return
0
;
}
static
const
struct
of_device_id
of_adc_thermal_match
[]
=
{
{
.
compatible
=
"generic-adc-thermal"
,
},
{},
};
MODULE_DEVICE_TABLE
(
of
,
of_adc_thermal_match
);
static
struct
platform_driver
gadc_thermal_driver
=
{
.
driver
=
{
.
name
=
"generic-adc-thermal"
,
.
of_match_table
=
of_adc_thermal_match
,
},
.
probe
=
gadc_thermal_probe
,
.
remove
=
gadc_thermal_remove
,
};
module_platform_driver
(
gadc_thermal_driver
);
MODULE_AUTHOR
(
"Laxman Dewangan <ldewangan@nvidia.com>"
);
MODULE_DESCRIPTION
(
"Generic ADC thermal driver using IIO framework with DT"
);
MODULE_LICENSE
(
"GPL v2"
);
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
View file @
88ac9906
...
...
@@ -337,7 +337,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
return
-
EINVAL
;
/* in case this is specified by DT */
data
->
ti_thermal
=
thermal_zone_of_sensor_register
(
bgp
->
dev
,
id
,
data
->
ti_thermal
=
devm_
thermal_zone_of_sensor_register
(
bgp
->
dev
,
id
,
data
,
&
ti_of_thermal_ops
);
if
(
IS_ERR
(
data
->
ti_thermal
))
{
/* Create thermal zone */
...
...
@@ -368,9 +368,6 @@ int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
if
(
data
&&
data
->
ti_thermal
)
{
if
(
data
->
our_zone
)
thermal_zone_device_unregister
(
data
->
ti_thermal
);
else
thermal_zone_of_sensor_unregister
(
bgp
->
dev
,
data
->
ti_thermal
);
}
return
0
;
...
...
drivers/thermal/x86_pkg_temp_thermal.c
View file @
88ac9906
...
...
@@ -555,7 +555,7 @@ static int pkg_temp_thermal_cpu_callback(struct notifier_block *nfb,
{
unsigned
int
cpu
=
(
unsigned
long
)
hcpu
;
switch
(
action
)
{
switch
(
action
&
~
CPU_TASKS_FROZEN
)
{
case
CPU_ONLINE
:
case
CPU_DOWN_FAILED
:
get_core_online
(
cpu
);
...
...
include/dt-bindings/thermal/tegra124-soctherm.h
View file @
88ac9906
...
...
@@ -9,5 +9,6 @@
#define TEGRA124_SOCTHERM_SENSOR_MEM 1
#define TEGRA124_SOCTHERM_SENSOR_GPU 2
#define TEGRA124_SOCTHERM_SENSOR_PLLX 3
#define TEGRA124_SOCTHERM_SENSOR_NUM 4
#endif
include/linux/thermal.h
View file @
88ac9906
...
...
@@ -340,6 +340,7 @@ struct thermal_zone_of_device_ops {
int
(
*
get_temp
)(
void
*
,
int
*
);
int
(
*
get_trend
)(
void
*
,
long
*
);
int
(
*
set_emul_temp
)(
void
*
,
int
);
int
(
*
set_trip_temp
)(
void
*
,
int
,
int
);
};
/**
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment