mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-08 14:13:53 +00:00
Merge branches 'thermal-soc', 'thermal-core', 'thermal-intel' and 'thermal-tegra-hw-throttle' into next
This commit is contained in:
commit
040a3eadf0
@ -10,8 +10,14 @@ Required properties :
|
|||||||
- compatible : For Tegra124, must contain "nvidia,tegra124-soctherm".
|
- compatible : For Tegra124, must contain "nvidia,tegra124-soctherm".
|
||||||
For Tegra132, must contain "nvidia,tegra132-soctherm".
|
For Tegra132, must contain "nvidia,tegra132-soctherm".
|
||||||
For Tegra210, must contain "nvidia,tegra210-soctherm".
|
For Tegra210, must contain "nvidia,tegra210-soctherm".
|
||||||
- reg : Should contain 1 entry:
|
- reg : Should contain at least 2 entries for each entry in reg-names:
|
||||||
- SOCTHERM register set
|
- SOCTHERM register set
|
||||||
|
- Tegra CAR register set: Required for Tegra124 and Tegra210.
|
||||||
|
- CCROC register set: Required for Tegra132.
|
||||||
|
- reg-names : Should contain at least 2 entries:
|
||||||
|
- soctherm-reg
|
||||||
|
- car-reg
|
||||||
|
- ccroc-reg
|
||||||
- interrupts : Defines the interrupt used by SOCTHERM
|
- interrupts : Defines the interrupt used by SOCTHERM
|
||||||
- clocks : Must contain an entry for each entry in clock-names.
|
- clocks : Must contain an entry for each entry in clock-names.
|
||||||
See ../clocks/clock-bindings.txt for details.
|
See ../clocks/clock-bindings.txt for details.
|
||||||
@ -25,17 +31,45 @@ Required properties :
|
|||||||
- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description
|
- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description
|
||||||
of this property. See <dt-bindings/thermal/tegra124-soctherm.h> for a
|
of this property. See <dt-bindings/thermal/tegra124-soctherm.h> for a
|
||||||
list of valid values when referring to thermal sensors.
|
list of valid values when referring to thermal sensors.
|
||||||
|
- throttle-cfgs: A sub-node which is a container of configuration for each
|
||||||
|
hardware throttle events. These events can be set as cooling devices.
|
||||||
|
* throttle events: Sub-nodes must be named as "light" or "heavy".
|
||||||
|
Properties:
|
||||||
|
- nvidia,priority: Each throttles has its own throttle settings, so the
|
||||||
|
SW need to set priorities for various throttle, the HW arbiter can select
|
||||||
|
the final throttle settings.
|
||||||
|
Bigger value indicates higher priority, In general, higher priority
|
||||||
|
translates to lower target frequency. SW needs to ensure that critical
|
||||||
|
thermal alarms are given higher priority, and ensure that there is
|
||||||
|
no race if priority of two vectors is set to the same value.
|
||||||
|
The range of this value is 1~100.
|
||||||
|
- nvidia,cpu-throt-percent: This property is for Tegra124 and Tegra210.
|
||||||
|
It is the throttling depth of pulse skippers, it's the percentage
|
||||||
|
throttling.
|
||||||
|
- nvidia,cpu-throt-level: This property is only for Tegra132, it is the
|
||||||
|
level of pulse skippers, which used to throttle clock frequencies. It
|
||||||
|
indicates cpu clock throttling depth, and the depth can be programmed.
|
||||||
|
Must set as following values:
|
||||||
|
TEGRA_SOCTHERM_THROT_LEVEL_LOW, TEGRA_SOCTHERM_THROT_LEVEL_MED
|
||||||
|
TEGRA_SOCTHERM_THROT_LEVEL_HIGH, TEGRA_SOCTHERM_THROT_LEVEL_NONE
|
||||||
|
- #cooling-cells: Should be 1. This cooling device only support on/off state.
|
||||||
|
See ./thermal.txt for a description of this property.
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
- the "critical" type trip points will be set to SOC_THERM hardware as the
|
- 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
|
shut down temperature. Once the temperature of this thermal zone is higher
|
||||||
than it, the system will be shutdown or reset by hardware.
|
than it, the system will be shutdown or reset by hardware.
|
||||||
|
- the "hot" type trip points will be set to SOC_THERM hardware as the throttle
|
||||||
|
temperature. Once the the temperature of this thermal zone is higher
|
||||||
|
than it, it will trigger the HW throttle event.
|
||||||
|
|
||||||
Example :
|
Example :
|
||||||
|
|
||||||
soctherm@700e2000 {
|
soctherm@700e2000 {
|
||||||
compatible = "nvidia,tegra124-soctherm";
|
compatible = "nvidia,tegra124-soctherm";
|
||||||
reg = <0x0 0x700e2000 0x0 0x1000>;
|
reg = <0x0 0x700e2000 0x0 0x600 /* SOC_THERM reg_base */
|
||||||
|
0x0 0x60006000 0x0 0x400 /* CAR reg_base */
|
||||||
|
reg-names = "soctherm-reg", "car-reg";
|
||||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
|
clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
|
||||||
<&tegra_car TEGRA124_CLK_SOC_THERM>;
|
<&tegra_car TEGRA124_CLK_SOC_THERM>;
|
||||||
@ -44,6 +78,76 @@ Example :
|
|||||||
reset-names = "soctherm";
|
reset-names = "soctherm";
|
||||||
|
|
||||||
#thermal-sensor-cells = <1>;
|
#thermal-sensor-cells = <1>;
|
||||||
|
|
||||||
|
throttle-cfgs {
|
||||||
|
/*
|
||||||
|
* When the "heavy" cooling device triggered,
|
||||||
|
* the HW will skip cpu clock's pulse in 85% depth
|
||||||
|
*/
|
||||||
|
throttle_heavy: heavy {
|
||||||
|
nvidia,priority = <100>;
|
||||||
|
nvidia,cpu-throt-percent = <85>;
|
||||||
|
|
||||||
|
#cooling-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the "light" cooling device triggered,
|
||||||
|
* the HW will skip cpu clock's pulse in 50% depth
|
||||||
|
*/
|
||||||
|
throttle_light: light {
|
||||||
|
nvidia,priority = <80>;
|
||||||
|
nvidia,cpu-throt-percent = <50>;
|
||||||
|
|
||||||
|
#cooling-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If these two devices are triggered in same time, the HW throttle
|
||||||
|
* arbiter will select the highest priority as the final throttle
|
||||||
|
* settings to skip cpu pulse.
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Example: referring to Tegra132's "reg", "reg-names" and "throttle-cfgs" :
|
||||||
|
|
||||||
|
soctherm@700e2000 {
|
||||||
|
compatible = "nvidia,tegra132-soctherm";
|
||||||
|
reg = <0x0 0x700e2000 0x0 0x600 /* SOC_THERM reg_base */
|
||||||
|
0x0 0x70040000 0x0 0x200>; /* CCROC reg_base */;
|
||||||
|
reg-names = "soctherm-reg", "ccroc-reg";
|
||||||
|
|
||||||
|
throttle-cfgs {
|
||||||
|
/*
|
||||||
|
* When the "heavy" cooling device triggered,
|
||||||
|
* the HW will skip cpu clock's pulse in HIGH level
|
||||||
|
*/
|
||||||
|
throttle_heavy: heavy {
|
||||||
|
nvidia,priority = <100>;
|
||||||
|
nvidia,cpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_HIGH>;
|
||||||
|
|
||||||
|
#cooling-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the "light" cooling device triggered,
|
||||||
|
* the HW will skip cpu clock's pulse in MED level
|
||||||
|
*/
|
||||||
|
throttle_light: light {
|
||||||
|
nvidia,priority = <80>;
|
||||||
|
nvidia,cpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_MED>;
|
||||||
|
|
||||||
|
#cooling-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If these two devices are triggered in same time, the HW throttle
|
||||||
|
* arbiter will select the highest priority as the final throttle
|
||||||
|
* settings to skip cpu pulse.
|
||||||
|
*/
|
||||||
|
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Example: referring to thermal sensors :
|
Example: referring to thermal sensors :
|
||||||
@ -62,6 +166,19 @@ Example: referring to thermal sensors :
|
|||||||
hysteresis = <1000>;
|
hysteresis = <1000>;
|
||||||
type = "critical";
|
type = "critical";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
cpu_throttle_trip: throttle-trip {
|
||||||
|
temperature = <100000>;
|
||||||
|
hysteresis = <1000>;
|
||||||
|
type = "hot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
map0 {
|
||||||
|
trip = <&cpu_throttle_trip>;
|
||||||
|
cooling-device = <&throttle_heavy 1 1>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -2045,44 +2045,32 @@ sound {
|
|||||||
thermal-zones {
|
thermal-zones {
|
||||||
cpu {
|
cpu {
|
||||||
trips {
|
trips {
|
||||||
trip {
|
cpu-shutdown-trip {
|
||||||
temperature = <101000>;
|
temperature = <101000>;
|
||||||
hysteresis = <0>;
|
hysteresis = <0>;
|
||||||
type = "critical";
|
type = "critical";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
cooling-maps {
|
|
||||||
/* There are currently no cooling maps because there are no cooling devices */
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mem {
|
mem {
|
||||||
trips {
|
trips {
|
||||||
trip {
|
mem-shutdown-trip {
|
||||||
temperature = <101000>;
|
temperature = <101000>;
|
||||||
hysteresis = <0>;
|
hysteresis = <0>;
|
||||||
type = "critical";
|
type = "critical";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
cooling-maps {
|
|
||||||
/* There are currently no cooling maps because there are no cooling devices */
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
gpu {
|
gpu {
|
||||||
trips {
|
trips {
|
||||||
trip {
|
gpu-shutdown-trip {
|
||||||
temperature = <101000>;
|
temperature = <101000>;
|
||||||
hysteresis = <0>;
|
hysteresis = <0>;
|
||||||
type = "critical";
|
type = "critical";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
cooling-maps {
|
|
||||||
/* There are currently no cooling maps because there are no cooling devices */
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -851,7 +851,9 @@ sdhci@700b0600 {
|
|||||||
|
|
||||||
soctherm: thermal-sensor@700e2000 {
|
soctherm: thermal-sensor@700e2000 {
|
||||||
compatible = "nvidia,tegra124-soctherm";
|
compatible = "nvidia,tegra124-soctherm";
|
||||||
reg = <0x0 0x700e2000 0x0 0x1000>;
|
reg = <0x0 0x700e2000 0x0 0x600 /* SOC_THERM reg_base */
|
||||||
|
0x0 0x60006000 0x0 0x400>; /* CAR reg_base */
|
||||||
|
reg-names = "soctherm-reg", "car-reg";
|
||||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
|
clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
|
||||||
<&tegra_car TEGRA124_CLK_SOC_THERM>;
|
<&tegra_car TEGRA124_CLK_SOC_THERM>;
|
||||||
@ -859,6 +861,15 @@ soctherm: thermal-sensor@700e2000 {
|
|||||||
resets = <&tegra_car 78>;
|
resets = <&tegra_car 78>;
|
||||||
reset-names = "soctherm";
|
reset-names = "soctherm";
|
||||||
#thermal-sensor-cells = <1>;
|
#thermal-sensor-cells = <1>;
|
||||||
|
|
||||||
|
throttle-cfgs {
|
||||||
|
throttle_heavy: heavy {
|
||||||
|
nvidia,priority = <100>;
|
||||||
|
nvidia,cpu-throt-percent = <85>;
|
||||||
|
|
||||||
|
#cooling-cells = <2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
dfll: clock@70110000 {
|
dfll: clock@70110000 {
|
||||||
@ -1154,6 +1165,26 @@ cpu {
|
|||||||
|
|
||||||
thermal-sensors =
|
thermal-sensors =
|
||||||
<&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>;
|
<&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
cpu-shutdown-trip {
|
||||||
|
temperature = <103000>;
|
||||||
|
hysteresis = <0>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
cpu_throttle_trip: throttle-trip {
|
||||||
|
temperature = <100000>;
|
||||||
|
hysteresis = <1000>;
|
||||||
|
type = "hot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
map0 {
|
||||||
|
trip = <&cpu_throttle_trip>;
|
||||||
|
cooling-device = <&throttle_heavy 1 1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
mem {
|
mem {
|
||||||
@ -1162,6 +1193,21 @@ mem {
|
|||||||
|
|
||||||
thermal-sensors =
|
thermal-sensors =
|
||||||
<&soctherm TEGRA124_SOCTHERM_SENSOR_MEM>;
|
<&soctherm TEGRA124_SOCTHERM_SENSOR_MEM>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
mem-shutdown-trip {
|
||||||
|
temperature = <103000>;
|
||||||
|
hysteresis = <0>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
/*
|
||||||
|
* There are currently no cooling maps,
|
||||||
|
* because there are no cooling devices.
|
||||||
|
*/
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
gpu {
|
gpu {
|
||||||
@ -1170,6 +1216,26 @@ gpu {
|
|||||||
|
|
||||||
thermal-sensors =
|
thermal-sensors =
|
||||||
<&soctherm TEGRA124_SOCTHERM_SENSOR_GPU>;
|
<&soctherm TEGRA124_SOCTHERM_SENSOR_GPU>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
gpu-shutdown-trip {
|
||||||
|
temperature = <101000>;
|
||||||
|
hysteresis = <0>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
gpu_throttle_trip: throttle-trip {
|
||||||
|
temperature = <99000>;
|
||||||
|
hysteresis = <1000>;
|
||||||
|
type = "hot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
map0 {
|
||||||
|
trip = <&gpu_throttle_trip>;
|
||||||
|
cooling-device = <&throttle_heavy 1 1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
pllx {
|
pllx {
|
||||||
@ -1178,6 +1244,21 @@ pllx {
|
|||||||
|
|
||||||
thermal-sensors =
|
thermal-sensors =
|
||||||
<&soctherm TEGRA124_SOCTHERM_SENSOR_PLLX>;
|
<&soctherm TEGRA124_SOCTHERM_SENSOR_PLLX>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
pllx-shutdown-trip {
|
||||||
|
temperature = <103000>;
|
||||||
|
hysteresis = <0>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
/*
|
||||||
|
* There are currently no cooling maps,
|
||||||
|
* because there are no cooling devices.
|
||||||
|
*/
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
|
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
|
||||||
#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
|
#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
|
||||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
#include <dt-bindings/thermal/tegra124-soctherm.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
compatible = "nvidia,tegra132", "nvidia,tegra124";
|
compatible = "nvidia,tegra132", "nvidia,tegra124";
|
||||||
@ -727,8 +728,10 @@ sdhci@700b0600 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
soctherm: thermal-sensor@700e2000 {
|
soctherm: thermal-sensor@700e2000 {
|
||||||
compatible = "nvidia,tegra124-soctherm";
|
compatible = "nvidia,tegra132-soctherm";
|
||||||
reg = <0x0 0x700e2000 0x0 0x1000>;
|
reg = <0x0 0x700e2000 0x0 0x600 /* 0: SOC_THERM reg_base */
|
||||||
|
0x0 0x70040000 0x0 0x200>; /* 2: CCROC reg_base */
|
||||||
|
reg-names = "soctherm-reg", "ccroc-reg";
|
||||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
|
clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
|
||||||
<&tegra_car TEGRA124_CLK_SOC_THERM>;
|
<&tegra_car TEGRA124_CLK_SOC_THERM>;
|
||||||
@ -736,6 +739,118 @@ soctherm: thermal-sensor@700e2000 {
|
|||||||
resets = <&tegra_car 78>;
|
resets = <&tegra_car 78>;
|
||||||
reset-names = "soctherm";
|
reset-names = "soctherm";
|
||||||
#thermal-sensor-cells = <1>;
|
#thermal-sensor-cells = <1>;
|
||||||
|
|
||||||
|
throttle-cfgs {
|
||||||
|
throttle_heavy: heavy {
|
||||||
|
nvidia,priority = <100>;
|
||||||
|
nvidia,cpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_HIGH>;
|
||||||
|
|
||||||
|
#cooling-cells = <2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
thermal-zones {
|
||||||
|
cpu {
|
||||||
|
polling-delay-passive = <1000>;
|
||||||
|
polling-delay = <0>;
|
||||||
|
|
||||||
|
thermal-sensors =
|
||||||
|
<&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
cpu_shutdown_trip {
|
||||||
|
temperature = <105000>;
|
||||||
|
hysteresis = <1000>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu_throttle_trip: throttle-trip {
|
||||||
|
temperature = <102000>;
|
||||||
|
hysteresis = <1000>;
|
||||||
|
type = "hot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
map0 {
|
||||||
|
trip = <&cpu_throttle_trip>;
|
||||||
|
cooling-device = <&throttle_heavy 1 1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
mem {
|
||||||
|
polling-delay-passive = <0>;
|
||||||
|
polling-delay = <0>;
|
||||||
|
|
||||||
|
thermal-sensors =
|
||||||
|
<&soctherm TEGRA124_SOCTHERM_SENSOR_MEM>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
mem_shutdown_trip {
|
||||||
|
temperature = <101000>;
|
||||||
|
hysteresis = <1000>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
/*
|
||||||
|
* There are currently no cooling maps,
|
||||||
|
* because there are no cooling devices.
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
};
|
||||||
|
gpu {
|
||||||
|
polling-delay-passive = <1000>;
|
||||||
|
polling-delay = <0>;
|
||||||
|
|
||||||
|
thermal-sensors =
|
||||||
|
<&soctherm TEGRA124_SOCTHERM_SENSOR_GPU>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
gpu_shutdown_trip {
|
||||||
|
temperature = <101000>;
|
||||||
|
hysteresis = <1000>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
|
||||||
|
gpu_throttle_trip: throttle-trip {
|
||||||
|
temperature = <99000>;
|
||||||
|
hysteresis = <1000>;
|
||||||
|
type = "hot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
map0 {
|
||||||
|
trip = <&gpu_throttle_trip>;
|
||||||
|
cooling-device = <&throttle_heavy 1 1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
pllx {
|
||||||
|
polling-delay-passive = <0>;
|
||||||
|
polling-delay = <0>;
|
||||||
|
|
||||||
|
thermal-sensors =
|
||||||
|
<&soctherm TEGRA124_SOCTHERM_SENSOR_PLLX>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
pllx_shutdown_trip {
|
||||||
|
temperature = <105000>;
|
||||||
|
hysteresis = <1000>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
/*
|
||||||
|
* There are currently no cooling maps,
|
||||||
|
* because there are no cooling devices.
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
ahub@70300000 {
|
ahub@70300000 {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <dt-bindings/memory/tegra210-mc.h>
|
#include <dt-bindings/memory/tegra210-mc.h>
|
||||||
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
|
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
|
||||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
#include <dt-bindings/thermal/tegra124-soctherm.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
compatible = "nvidia,tegra210";
|
compatible = "nvidia,tegra210";
|
||||||
@ -1094,4 +1095,130 @@ timer {
|
|||||||
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
|
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
|
||||||
interrupt-parent = <&gic>;
|
interrupt-parent = <&gic>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
soctherm: thermal-sensor@700e2000 {
|
||||||
|
compatible = "nvidia,tegra210-soctherm";
|
||||||
|
reg = <0x0 0x700e2000 0x0 0x600 /* SOC_THERM reg_base */
|
||||||
|
0x0 0x60006000 0x0 0x400>; /* CAR reg_base */
|
||||||
|
reg-names = "soctherm-reg", "car-reg";
|
||||||
|
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
clocks = <&tegra_car TEGRA210_CLK_TSENSOR>,
|
||||||
|
<&tegra_car TEGRA210_CLK_SOC_THERM>;
|
||||||
|
clock-names = "tsensor", "soctherm";
|
||||||
|
resets = <&tegra_car 78>;
|
||||||
|
reset-names = "soctherm";
|
||||||
|
#thermal-sensor-cells = <1>;
|
||||||
|
|
||||||
|
throttle-cfgs {
|
||||||
|
throttle_heavy: heavy {
|
||||||
|
nvidia,priority = <100>;
|
||||||
|
nvidia,cpu-throt-percent = <85>;
|
||||||
|
|
||||||
|
#cooling-cells = <2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
thermal-zones {
|
||||||
|
cpu {
|
||||||
|
polling-delay-passive = <1000>;
|
||||||
|
polling-delay = <0>;
|
||||||
|
|
||||||
|
thermal-sensors =
|
||||||
|
<&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
cpu-shutdown-trip {
|
||||||
|
temperature = <102500>;
|
||||||
|
hysteresis = <0>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu_throttle_trip: throttle-trip {
|
||||||
|
temperature = <98500>;
|
||||||
|
hysteresis = <1000>;
|
||||||
|
type = "hot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
map0 {
|
||||||
|
trip = <&cpu_throttle_trip>;
|
||||||
|
cooling-device = <&throttle_heavy 1 1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
mem {
|
||||||
|
polling-delay-passive = <0>;
|
||||||
|
polling-delay = <0>;
|
||||||
|
|
||||||
|
thermal-sensors =
|
||||||
|
<&soctherm TEGRA124_SOCTHERM_SENSOR_MEM>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
mem-shutdown-trip {
|
||||||
|
temperature = <103000>;
|
||||||
|
hysteresis = <0>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
/*
|
||||||
|
* There are currently no cooling maps,
|
||||||
|
* because there are no cooling devices.
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
};
|
||||||
|
gpu {
|
||||||
|
polling-delay-passive = <1000>;
|
||||||
|
polling-delay = <0>;
|
||||||
|
|
||||||
|
thermal-sensors =
|
||||||
|
<&soctherm TEGRA124_SOCTHERM_SENSOR_GPU>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
gpu-shutdown-trip {
|
||||||
|
temperature = <103000>;
|
||||||
|
hysteresis = <0>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
|
||||||
|
gpu_throttle_trip: throttle-trip {
|
||||||
|
temperature = <100000>;
|
||||||
|
hysteresis = <1000>;
|
||||||
|
type = "hot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
map0 {
|
||||||
|
trip = <&gpu_throttle_trip>;
|
||||||
|
cooling-device = <&throttle_heavy 1 1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
pllx {
|
||||||
|
polling-delay-passive = <0>;
|
||||||
|
polling-delay = <0>;
|
||||||
|
|
||||||
|
thermal-sensors =
|
||||||
|
<&soctherm TEGRA124_SOCTHERM_SENSOR_PLLX>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
pllx-shutdown-trip {
|
||||||
|
temperature = <103000>;
|
||||||
|
hysteresis = <0>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
/*
|
||||||
|
* There are currently no cooling maps,
|
||||||
|
* because there are no cooling devices.
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
@ -352,6 +352,16 @@ menu "ACPI INT340X thermal drivers"
|
|||||||
source drivers/thermal/int340x_thermal/Kconfig
|
source drivers/thermal/int340x_thermal/Kconfig
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
config INTEL_BXT_PMIC_THERMAL
|
||||||
|
tristate "Intel Broxton PMIC thermal driver"
|
||||||
|
depends on X86 && INTEL_SOC_PMIC && REGMAP
|
||||||
|
help
|
||||||
|
Select this driver for Intel Broxton PMIC with ADC channels monitoring
|
||||||
|
system temperature measurements and alerts.
|
||||||
|
This driver is used for monitoring the ADC channels of PMIC and handles
|
||||||
|
the alert trip point interrupts and notifies the thermal framework with
|
||||||
|
the trip point and temperature details of the zone.
|
||||||
|
|
||||||
config INTEL_PCH_THERMAL
|
config INTEL_PCH_THERMAL
|
||||||
tristate "Intel PCH Thermal Reporting Driver"
|
tristate "Intel PCH Thermal Reporting Driver"
|
||||||
depends on X86 && PCI
|
depends on X86 && PCI
|
||||||
|
@ -47,6 +47,7 @@ obj-$(CONFIG_INTEL_SOC_DTS_THERMAL) += intel_soc_dts_thermal.o
|
|||||||
obj-$(CONFIG_INTEL_QUARK_DTS_THERMAL) += intel_quark_dts_thermal.o
|
obj-$(CONFIG_INTEL_QUARK_DTS_THERMAL) += intel_quark_dts_thermal.o
|
||||||
obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
|
obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
|
||||||
obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/
|
obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/
|
||||||
|
obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o
|
||||||
obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
|
obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
|
||||||
obj-$(CONFIG_ST_THERMAL) += st/
|
obj-$(CONFIG_ST_THERMAL) += st/
|
||||||
obj-$(CONFIG_QCOM_TSENS) += qcom/
|
obj-$(CONFIG_QCOM_TSENS) += qcom/
|
||||||
|
@ -74,7 +74,7 @@ struct power_table {
|
|||||||
* cpufreq frequencies.
|
* cpufreq frequencies.
|
||||||
* @allowed_cpus: all the cpus involved for this cpufreq_cooling_device.
|
* @allowed_cpus: all the cpus involved for this cpufreq_cooling_device.
|
||||||
* @node: list_head to link all cpufreq_cooling_device together.
|
* @node: list_head to link all cpufreq_cooling_device together.
|
||||||
* @last_load: load measured by the latest call to cpufreq_get_actual_power()
|
* @last_load: load measured by the latest call to cpufreq_get_requested_power()
|
||||||
* @time_in_idle: previous reading of the absolute time that this cpu was idle
|
* @time_in_idle: previous reading of the absolute time that this cpu was idle
|
||||||
* @time_in_idle_timestamp: wall time of the last invocation of
|
* @time_in_idle_timestamp: wall time of the last invocation of
|
||||||
* get_cpu_idle_time_us()
|
* get_cpu_idle_time_us()
|
||||||
|
299
drivers/thermal/intel_bxt_pmic_thermal.c
Normal file
299
drivers/thermal/intel_bxt_pmic_thermal.c
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
/*
|
||||||
|
* Intel Broxton PMIC thermal driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Intel Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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/kernel.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/thermal.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/mfd/intel_soc_pmic.h>
|
||||||
|
|
||||||
|
#define BXTWC_THRM0IRQ 0x4E04
|
||||||
|
#define BXTWC_THRM1IRQ 0x4E05
|
||||||
|
#define BXTWC_THRM2IRQ 0x4E06
|
||||||
|
#define BXTWC_MTHRM0IRQ 0x4E12
|
||||||
|
#define BXTWC_MTHRM1IRQ 0x4E13
|
||||||
|
#define BXTWC_MTHRM2IRQ 0x4E14
|
||||||
|
#define BXTWC_STHRM0IRQ 0x4F19
|
||||||
|
#define BXTWC_STHRM1IRQ 0x4F1A
|
||||||
|
#define BXTWC_STHRM2IRQ 0x4F1B
|
||||||
|
|
||||||
|
struct trip_config_map {
|
||||||
|
u16 irq_reg;
|
||||||
|
u16 irq_en;
|
||||||
|
u16 evt_stat;
|
||||||
|
u8 irq_mask;
|
||||||
|
u8 irq_en_mask;
|
||||||
|
u8 evt_mask;
|
||||||
|
u8 trip_num;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct thermal_irq_map {
|
||||||
|
char handle[20];
|
||||||
|
int num_trips;
|
||||||
|
const struct trip_config_map *trip_config;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pmic_thermal_data {
|
||||||
|
const struct thermal_irq_map *maps;
|
||||||
|
int num_maps;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct trip_config_map bxtwc_str0_trip_config[] = {
|
||||||
|
{
|
||||||
|
.irq_reg = BXTWC_THRM0IRQ,
|
||||||
|
.irq_mask = 0x01,
|
||||||
|
.irq_en = BXTWC_MTHRM0IRQ,
|
||||||
|
.irq_en_mask = 0x01,
|
||||||
|
.evt_stat = BXTWC_STHRM0IRQ,
|
||||||
|
.evt_mask = 0x01,
|
||||||
|
.trip_num = 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.irq_reg = BXTWC_THRM0IRQ,
|
||||||
|
.irq_mask = 0x10,
|
||||||
|
.irq_en = BXTWC_MTHRM0IRQ,
|
||||||
|
.irq_en_mask = 0x10,
|
||||||
|
.evt_stat = BXTWC_STHRM0IRQ,
|
||||||
|
.evt_mask = 0x10,
|
||||||
|
.trip_num = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct trip_config_map bxtwc_str1_trip_config[] = {
|
||||||
|
{
|
||||||
|
.irq_reg = BXTWC_THRM0IRQ,
|
||||||
|
.irq_mask = 0x02,
|
||||||
|
.irq_en = BXTWC_MTHRM0IRQ,
|
||||||
|
.irq_en_mask = 0x02,
|
||||||
|
.evt_stat = BXTWC_STHRM0IRQ,
|
||||||
|
.evt_mask = 0x02,
|
||||||
|
.trip_num = 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.irq_reg = BXTWC_THRM0IRQ,
|
||||||
|
.irq_mask = 0x20,
|
||||||
|
.irq_en = BXTWC_MTHRM0IRQ,
|
||||||
|
.irq_en_mask = 0x20,
|
||||||
|
.evt_stat = BXTWC_STHRM0IRQ,
|
||||||
|
.evt_mask = 0x20,
|
||||||
|
.trip_num = 1
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct trip_config_map bxtwc_str2_trip_config[] = {
|
||||||
|
{
|
||||||
|
.irq_reg = BXTWC_THRM0IRQ,
|
||||||
|
.irq_mask = 0x04,
|
||||||
|
.irq_en = BXTWC_MTHRM0IRQ,
|
||||||
|
.irq_en_mask = 0x04,
|
||||||
|
.evt_stat = BXTWC_STHRM0IRQ,
|
||||||
|
.evt_mask = 0x04,
|
||||||
|
.trip_num = 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.irq_reg = BXTWC_THRM0IRQ,
|
||||||
|
.irq_mask = 0x40,
|
||||||
|
.irq_en = BXTWC_MTHRM0IRQ,
|
||||||
|
.irq_en_mask = 0x40,
|
||||||
|
.evt_stat = BXTWC_STHRM0IRQ,
|
||||||
|
.evt_mask = 0x40,
|
||||||
|
.trip_num = 1
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct trip_config_map bxtwc_str3_trip_config[] = {
|
||||||
|
{
|
||||||
|
.irq_reg = BXTWC_THRM2IRQ,
|
||||||
|
.irq_mask = 0x10,
|
||||||
|
.irq_en = BXTWC_MTHRM2IRQ,
|
||||||
|
.irq_en_mask = 0x10,
|
||||||
|
.evt_stat = BXTWC_STHRM2IRQ,
|
||||||
|
.evt_mask = 0x10,
|
||||||
|
.trip_num = 0
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct thermal_irq_map bxtwc_thermal_irq_map[] = {
|
||||||
|
{
|
||||||
|
.handle = "STR0",
|
||||||
|
.trip_config = bxtwc_str0_trip_config,
|
||||||
|
.num_trips = ARRAY_SIZE(bxtwc_str0_trip_config),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.handle = "STR1",
|
||||||
|
.trip_config = bxtwc_str1_trip_config,
|
||||||
|
.num_trips = ARRAY_SIZE(bxtwc_str1_trip_config),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.handle = "STR2",
|
||||||
|
.trip_config = bxtwc_str2_trip_config,
|
||||||
|
.num_trips = ARRAY_SIZE(bxtwc_str2_trip_config),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.handle = "STR3",
|
||||||
|
.trip_config = bxtwc_str3_trip_config,
|
||||||
|
.num_trips = ARRAY_SIZE(bxtwc_str3_trip_config),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pmic_thermal_data bxtwc_thermal_data = {
|
||||||
|
.maps = bxtwc_thermal_irq_map,
|
||||||
|
.num_maps = ARRAY_SIZE(bxtwc_thermal_irq_map),
|
||||||
|
};
|
||||||
|
|
||||||
|
static irqreturn_t pmic_thermal_irq_handler(int irq, void *data)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = data;
|
||||||
|
struct thermal_zone_device *tzd;
|
||||||
|
struct pmic_thermal_data *td;
|
||||||
|
struct intel_soc_pmic *pmic;
|
||||||
|
struct regmap *regmap;
|
||||||
|
u8 reg_val, mask, irq_stat, trip;
|
||||||
|
u16 reg, evt_stat_reg;
|
||||||
|
int i, j, ret;
|
||||||
|
|
||||||
|
pmic = dev_get_drvdata(pdev->dev.parent);
|
||||||
|
regmap = pmic->regmap;
|
||||||
|
td = (struct pmic_thermal_data *)
|
||||||
|
platform_get_device_id(pdev)->driver_data;
|
||||||
|
|
||||||
|
/* Resolve thermal irqs */
|
||||||
|
for (i = 0; i < td->num_maps; i++) {
|
||||||
|
for (j = 0; j < td->maps[i].num_trips; j++) {
|
||||||
|
reg = td->maps[i].trip_config[j].irq_reg;
|
||||||
|
mask = td->maps[i].trip_config[j].irq_mask;
|
||||||
|
/*
|
||||||
|
* Read the irq register to resolve whether the
|
||||||
|
* interrupt was triggered for this sensor
|
||||||
|
*/
|
||||||
|
if (regmap_read(regmap, reg, &ret))
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
|
||||||
|
reg_val = (u8)ret;
|
||||||
|
irq_stat = ((u8)ret & mask);
|
||||||
|
|
||||||
|
if (!irq_stat)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the status register to find out what
|
||||||
|
* event occurred i.e a high or a low
|
||||||
|
*/
|
||||||
|
evt_stat_reg = td->maps[i].trip_config[j].evt_stat;
|
||||||
|
if (regmap_read(regmap, evt_stat_reg, &ret))
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
|
||||||
|
trip = td->maps[i].trip_config[j].trip_num;
|
||||||
|
tzd = thermal_zone_get_zone_by_name(td->maps[i].handle);
|
||||||
|
if (!IS_ERR(tzd))
|
||||||
|
thermal_zone_device_update(tzd);
|
||||||
|
|
||||||
|
/* Clear the appropriate irq */
|
||||||
|
regmap_write(regmap, reg, reg_val & mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pmic_thermal_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct regmap_irq_chip_data *regmap_irq_chip;
|
||||||
|
struct pmic_thermal_data *thermal_data;
|
||||||
|
int ret, irq, virq, i, j, pmic_irq_count;
|
||||||
|
struct intel_soc_pmic *pmic;
|
||||||
|
struct regmap *regmap;
|
||||||
|
struct device *dev;
|
||||||
|
u16 reg;
|
||||||
|
u8 mask;
|
||||||
|
|
||||||
|
dev = &pdev->dev;
|
||||||
|
pmic = dev_get_drvdata(pdev->dev.parent);
|
||||||
|
if (!pmic) {
|
||||||
|
dev_err(dev, "Failed to get struct intel_soc_pmic pointer\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
thermal_data = (struct pmic_thermal_data *)
|
||||||
|
platform_get_device_id(pdev)->driver_data;
|
||||||
|
if (!thermal_data) {
|
||||||
|
dev_err(dev, "No thermal data initialized!!\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
regmap = pmic->regmap;
|
||||||
|
regmap_irq_chip = pmic->irq_chip_data_level2;
|
||||||
|
|
||||||
|
pmic_irq_count = 0;
|
||||||
|
while ((irq = platform_get_irq(pdev, pmic_irq_count)) != -ENXIO) {
|
||||||
|
virq = regmap_irq_get_virq(regmap_irq_chip, irq);
|
||||||
|
if (virq < 0) {
|
||||||
|
dev_err(dev, "failed to get virq by irq %d\n", irq);
|
||||||
|
return virq;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = devm_request_threaded_irq(&pdev->dev, virq,
|
||||||
|
NULL, pmic_thermal_irq_handler,
|
||||||
|
IRQF_ONESHOT, "pmic_thermal", pdev);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "request irq(%d) failed: %d\n", virq, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
pmic_irq_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable thermal interrupts */
|
||||||
|
for (i = 0; i < thermal_data->num_maps; i++) {
|
||||||
|
for (j = 0; j < thermal_data->maps[i].num_trips; j++) {
|
||||||
|
reg = thermal_data->maps[i].trip_config[j].irq_en;
|
||||||
|
mask = thermal_data->maps[i].trip_config[j].irq_en_mask;
|
||||||
|
ret = regmap_update_bits(regmap, reg, mask, 0x00);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct platform_device_id pmic_thermal_id_table[] = {
|
||||||
|
{
|
||||||
|
.name = "bxt_wcove_thermal",
|
||||||
|
.driver_data = (kernel_ulong_t)&bxtwc_thermal_data,
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_driver pmic_thermal_driver = {
|
||||||
|
.probe = pmic_thermal_probe,
|
||||||
|
.driver = {
|
||||||
|
.name = "pmic_thermal",
|
||||||
|
},
|
||||||
|
.id_table = pmic_thermal_id_table,
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(platform, pmic_thermal_id_table);
|
||||||
|
module_platform_driver(pmic_thermal_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Yegnesh S Iyer <yegnesh.s.iyer@intel.com>");
|
||||||
|
MODULE_DESCRIPTION("Intel Broxton PMIC Thermal Driver");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include <dt-bindings/thermal/tegra124-soctherm.h>
|
#include <dt-bindings/thermal/tegra124-soctherm.h>
|
||||||
|
|
||||||
|
#include "../thermal_core.h"
|
||||||
#include "soctherm.h"
|
#include "soctherm.h"
|
||||||
|
|
||||||
#define SENSOR_CONFIG0 0
|
#define SENSOR_CONFIG0 0
|
||||||
@ -67,35 +68,228 @@
|
|||||||
#define READBACK_ADD_HALF BIT(7)
|
#define READBACK_ADD_HALF BIT(7)
|
||||||
#define READBACK_NEGATE BIT(0)
|
#define READBACK_NEGATE BIT(0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* THERMCTL_LEVEL0_GROUP_CPU is defined in soctherm.h
|
||||||
|
* because it will be used by tegraxxx_soctherm.c
|
||||||
|
*/
|
||||||
|
#define THERMCTL_LVL0_CPU0_EN_MASK BIT(8)
|
||||||
|
#define THERMCTL_LVL0_CPU0_CPU_THROT_MASK (0x3 << 5)
|
||||||
|
#define THERMCTL_LVL0_CPU0_CPU_THROT_LIGHT 0x1
|
||||||
|
#define THERMCTL_LVL0_CPU0_CPU_THROT_HEAVY 0x2
|
||||||
|
#define THERMCTL_LVL0_CPU0_GPU_THROT_MASK (0x3 << 3)
|
||||||
|
#define THERMCTL_LVL0_CPU0_GPU_THROT_LIGHT 0x1
|
||||||
|
#define THERMCTL_LVL0_CPU0_GPU_THROT_HEAVY 0x2
|
||||||
|
#define THERMCTL_LVL0_CPU0_MEM_THROT_MASK BIT(2)
|
||||||
|
#define THERMCTL_LVL0_CPU0_STATUS_MASK 0x3
|
||||||
|
|
||||||
|
#define THERMCTL_LVL0_UP_STATS 0x10
|
||||||
|
#define THERMCTL_LVL0_DN_STATS 0x14
|
||||||
|
|
||||||
|
#define THERMCTL_STATS_CTL 0x94
|
||||||
|
#define STATS_CTL_CLR_DN 0x8
|
||||||
|
#define STATS_CTL_EN_DN 0x4
|
||||||
|
#define STATS_CTL_CLR_UP 0x2
|
||||||
|
#define STATS_CTL_EN_UP 0x1
|
||||||
|
|
||||||
|
#define THROT_GLOBAL_CFG 0x400
|
||||||
|
#define THROT_GLOBAL_ENB_MASK BIT(0)
|
||||||
|
|
||||||
|
#define CPU_PSKIP_STATUS 0x418
|
||||||
|
#define XPU_PSKIP_STATUS_M_MASK (0xff << 12)
|
||||||
|
#define XPU_PSKIP_STATUS_N_MASK (0xff << 4)
|
||||||
|
#define XPU_PSKIP_STATUS_SW_OVERRIDE_MASK BIT(1)
|
||||||
|
#define XPU_PSKIP_STATUS_ENABLED_MASK BIT(0)
|
||||||
|
|
||||||
|
#define THROT_PRIORITY_LOCK 0x424
|
||||||
|
#define THROT_PRIORITY_LOCK_PRIORITY_MASK 0xff
|
||||||
|
|
||||||
|
#define THROT_STATUS 0x428
|
||||||
|
#define THROT_STATUS_BREACH_MASK BIT(12)
|
||||||
|
#define THROT_STATUS_STATE_MASK (0xff << 4)
|
||||||
|
#define THROT_STATUS_ENABLED_MASK BIT(0)
|
||||||
|
|
||||||
|
#define THROT_PSKIP_CTRL_LITE_CPU 0x430
|
||||||
|
#define THROT_PSKIP_CTRL_ENABLE_MASK BIT(31)
|
||||||
|
#define THROT_PSKIP_CTRL_DIVIDEND_MASK (0xff << 8)
|
||||||
|
#define THROT_PSKIP_CTRL_DIVISOR_MASK 0xff
|
||||||
|
#define THROT_PSKIP_CTRL_VECT_GPU_MASK (0x7 << 16)
|
||||||
|
#define THROT_PSKIP_CTRL_VECT_CPU_MASK (0x7 << 8)
|
||||||
|
#define THROT_PSKIP_CTRL_VECT2_CPU_MASK 0x7
|
||||||
|
|
||||||
|
#define THROT_VECT_NONE 0x0 /* 3'b000 */
|
||||||
|
#define THROT_VECT_LOW 0x1 /* 3'b001 */
|
||||||
|
#define THROT_VECT_MED 0x3 /* 3'b011 */
|
||||||
|
#define THROT_VECT_HIGH 0x7 /* 3'b111 */
|
||||||
|
|
||||||
|
#define THROT_PSKIP_RAMP_LITE_CPU 0x434
|
||||||
|
#define THROT_PSKIP_RAMP_SEQ_BYPASS_MODE_MASK BIT(31)
|
||||||
|
#define THROT_PSKIP_RAMP_DURATION_MASK (0xffff << 8)
|
||||||
|
#define THROT_PSKIP_RAMP_STEP_MASK 0xff
|
||||||
|
|
||||||
|
#define THROT_PRIORITY_LITE 0x444
|
||||||
|
#define THROT_PRIORITY_LITE_PRIO_MASK 0xff
|
||||||
|
|
||||||
|
#define THROT_DELAY_LITE 0x448
|
||||||
|
#define THROT_DELAY_LITE_DELAY_MASK 0xff
|
||||||
|
|
||||||
|
/* car register offsets needed for enabling HW throttling */
|
||||||
|
#define CAR_SUPER_CCLKG_DIVIDER 0x36c
|
||||||
|
#define CDIVG_USE_THERM_CONTROLS_MASK BIT(30)
|
||||||
|
|
||||||
|
/* ccroc register offsets needed for enabling HW throttling for Tegra132 */
|
||||||
|
#define CCROC_SUPER_CCLKG_DIVIDER 0x024
|
||||||
|
|
||||||
|
#define CCROC_GLOBAL_CFG 0x148
|
||||||
|
|
||||||
|
#define CCROC_THROT_PSKIP_RAMP_CPU 0x150
|
||||||
|
#define CCROC_THROT_PSKIP_RAMP_SEQ_BYPASS_MODE_MASK BIT(31)
|
||||||
|
#define CCROC_THROT_PSKIP_RAMP_DURATION_MASK (0xffff << 8)
|
||||||
|
#define CCROC_THROT_PSKIP_RAMP_STEP_MASK 0xff
|
||||||
|
|
||||||
|
#define CCROC_THROT_PSKIP_CTRL_CPU 0x154
|
||||||
|
#define CCROC_THROT_PSKIP_CTRL_ENB_MASK BIT(31)
|
||||||
|
#define CCROC_THROT_PSKIP_CTRL_DIVIDEND_MASK (0xff << 8)
|
||||||
|
#define CCROC_THROT_PSKIP_CTRL_DIVISOR_MASK 0xff
|
||||||
|
|
||||||
/* get val from register(r) mask bits(m) */
|
/* get val from register(r) mask bits(m) */
|
||||||
#define REG_GET_MASK(r, m) (((r) & (m)) >> (ffs(m) - 1))
|
#define REG_GET_MASK(r, m) (((r) & (m)) >> (ffs(m) - 1))
|
||||||
/* set val(v) to mask bits(m) of register(r) */
|
/* set val(v) to mask bits(m) of register(r) */
|
||||||
#define REG_SET_MASK(r, m, v) (((r) & ~(m)) | \
|
#define REG_SET_MASK(r, m, v) (((r) & ~(m)) | \
|
||||||
(((v) & (m >> (ffs(m) - 1))) << (ffs(m) - 1)))
|
(((v) & (m >> (ffs(m) - 1))) << (ffs(m) - 1)))
|
||||||
|
|
||||||
|
/* get dividend from the depth */
|
||||||
|
#define THROT_DEPTH_DIVIDEND(depth) ((256 * (100 - (depth)) / 100) - 1)
|
||||||
|
|
||||||
|
/* get THROT_PSKIP_xxx offset per LIGHT/HEAVY throt and CPU/GPU dev */
|
||||||
|
#define THROT_OFFSET 0x30
|
||||||
|
#define THROT_PSKIP_CTRL(throt, dev) (THROT_PSKIP_CTRL_LITE_CPU + \
|
||||||
|
(THROT_OFFSET * throt) + (8 * dev))
|
||||||
|
#define THROT_PSKIP_RAMP(throt, dev) (THROT_PSKIP_RAMP_LITE_CPU + \
|
||||||
|
(THROT_OFFSET * throt) + (8 * dev))
|
||||||
|
|
||||||
|
/* get THROT_xxx_CTRL offset per LIGHT/HEAVY throt */
|
||||||
|
#define THROT_PRIORITY_CTRL(throt) (THROT_PRIORITY_LITE + \
|
||||||
|
(THROT_OFFSET * throt))
|
||||||
|
#define THROT_DELAY_CTRL(throt) (THROT_DELAY_LITE + \
|
||||||
|
(THROT_OFFSET * throt))
|
||||||
|
|
||||||
|
/* get CCROC_THROT_PSKIP_xxx offset per HIGH/MED/LOW vect*/
|
||||||
|
#define CCROC_THROT_OFFSET 0x0c
|
||||||
|
#define CCROC_THROT_PSKIP_CTRL_CPU_REG(vect) (CCROC_THROT_PSKIP_CTRL_CPU + \
|
||||||
|
(CCROC_THROT_OFFSET * vect))
|
||||||
|
#define CCROC_THROT_PSKIP_RAMP_CPU_REG(vect) (CCROC_THROT_PSKIP_RAMP_CPU + \
|
||||||
|
(CCROC_THROT_OFFSET * vect))
|
||||||
|
|
||||||
|
/* get THERMCTL_LEVELx offset per CPU/GPU/MEM/TSENSE rg and LEVEL0~3 lv */
|
||||||
|
#define THERMCTL_LVL_REGS_SIZE 0x20
|
||||||
|
#define THERMCTL_LVL_REG(rg, lv) ((rg) + ((lv) * THERMCTL_LVL_REGS_SIZE))
|
||||||
|
|
||||||
static const int min_low_temp = -127000;
|
static const int min_low_temp = -127000;
|
||||||
static const int max_high_temp = 127000;
|
static const int max_high_temp = 127000;
|
||||||
|
|
||||||
|
enum soctherm_throttle_id {
|
||||||
|
THROTTLE_LIGHT = 0,
|
||||||
|
THROTTLE_HEAVY,
|
||||||
|
THROTTLE_SIZE,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum soctherm_throttle_dev_id {
|
||||||
|
THROTTLE_DEV_CPU = 0,
|
||||||
|
THROTTLE_DEV_GPU,
|
||||||
|
THROTTLE_DEV_SIZE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *const throt_names[] = {
|
||||||
|
[THROTTLE_LIGHT] = "light",
|
||||||
|
[THROTTLE_HEAVY] = "heavy",
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tegra_soctherm;
|
||||||
struct tegra_thermctl_zone {
|
struct tegra_thermctl_zone {
|
||||||
void __iomem *reg;
|
void __iomem *reg;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
struct tegra_soctherm *ts;
|
||||||
struct thermal_zone_device *tz;
|
struct thermal_zone_device *tz;
|
||||||
const struct tegra_tsensor_group *sg;
|
const struct tegra_tsensor_group *sg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct soctherm_throt_cfg {
|
||||||
|
const char *name;
|
||||||
|
unsigned int id;
|
||||||
|
u8 priority;
|
||||||
|
u8 cpu_throt_level;
|
||||||
|
u32 cpu_throt_depth;
|
||||||
|
struct thermal_cooling_device *cdev;
|
||||||
|
bool init;
|
||||||
|
};
|
||||||
|
|
||||||
struct tegra_soctherm {
|
struct tegra_soctherm {
|
||||||
struct reset_control *reset;
|
struct reset_control *reset;
|
||||||
struct clk *clock_tsensor;
|
struct clk *clock_tsensor;
|
||||||
struct clk *clock_soctherm;
|
struct clk *clock_soctherm;
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
struct thermal_zone_device **thermctl_tzs;
|
void __iomem *clk_regs;
|
||||||
|
void __iomem *ccroc_regs;
|
||||||
|
|
||||||
u32 *calib;
|
u32 *calib;
|
||||||
|
struct thermal_zone_device **thermctl_tzs;
|
||||||
struct tegra_soctherm_soc *soc;
|
struct tegra_soctherm_soc *soc;
|
||||||
|
|
||||||
|
struct soctherm_throt_cfg throt_cfgs[THROTTLE_SIZE];
|
||||||
|
|
||||||
struct dentry *debugfs_dir;
|
struct dentry *debugfs_dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clk_writel() - writes a value to a CAR register
|
||||||
|
* @ts: pointer to a struct tegra_soctherm
|
||||||
|
* @v: the value to write
|
||||||
|
* @reg: the register offset
|
||||||
|
*
|
||||||
|
* Writes @v to @reg. No return value.
|
||||||
|
*/
|
||||||
|
static inline void clk_writel(struct tegra_soctherm *ts, u32 value, u32 reg)
|
||||||
|
{
|
||||||
|
writel(value, (ts->clk_regs + reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clk_readl() - reads specified register from CAR IP block
|
||||||
|
* @ts: pointer to a struct tegra_soctherm
|
||||||
|
* @reg: register address to be read
|
||||||
|
*
|
||||||
|
* Return: the value of the register
|
||||||
|
*/
|
||||||
|
static inline u32 clk_readl(struct tegra_soctherm *ts, u32 reg)
|
||||||
|
{
|
||||||
|
return readl(ts->clk_regs + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ccroc_writel() - writes a value to a CCROC register
|
||||||
|
* @ts: pointer to a struct tegra_soctherm
|
||||||
|
* @v: the value to write
|
||||||
|
* @reg: the register offset
|
||||||
|
*
|
||||||
|
* Writes @v to @reg. No return value.
|
||||||
|
*/
|
||||||
|
static inline void ccroc_writel(struct tegra_soctherm *ts, u32 value, u32 reg)
|
||||||
|
{
|
||||||
|
writel(value, (ts->ccroc_regs + reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ccroc_readl() - reads specified register from CCROC IP block
|
||||||
|
* @ts: pointer to a struct tegra_soctherm
|
||||||
|
* @reg: register address to be read
|
||||||
|
*
|
||||||
|
* Return: the value of the register
|
||||||
|
*/
|
||||||
|
static inline u32 ccroc_readl(struct tegra_soctherm *ts, u32 reg)
|
||||||
|
{
|
||||||
|
return readl(ts->ccroc_regs + reg);
|
||||||
|
}
|
||||||
|
|
||||||
static void enable_tsensor(struct tegra_soctherm *tegra, unsigned int i)
|
static void enable_tsensor(struct tegra_soctherm *tegra, unsigned int i)
|
||||||
{
|
{
|
||||||
const struct tegra_tsensor *sensor = &tegra->soc->tsensors[i];
|
const struct tegra_tsensor *sensor = &tegra->soc->tsensors[i];
|
||||||
@ -150,11 +344,17 @@ static int tegra_thermctl_get_temp(void *data, int *out_temp)
|
|||||||
static int
|
static int
|
||||||
thermtrip_program(struct device *dev, const struct tegra_tsensor_group *sg,
|
thermtrip_program(struct device *dev, const struct tegra_tsensor_group *sg,
|
||||||
int trip_temp);
|
int trip_temp);
|
||||||
|
static int
|
||||||
|
throttrip_program(struct device *dev, const struct tegra_tsensor_group *sg,
|
||||||
|
struct soctherm_throt_cfg *stc, int trip_temp);
|
||||||
|
static struct soctherm_throt_cfg *
|
||||||
|
find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name);
|
||||||
|
|
||||||
static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
|
static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
|
||||||
{
|
{
|
||||||
struct tegra_thermctl_zone *zone = data;
|
struct tegra_thermctl_zone *zone = data;
|
||||||
struct thermal_zone_device *tz = zone->tz;
|
struct thermal_zone_device *tz = zone->tz;
|
||||||
|
struct tegra_soctherm *ts = zone->ts;
|
||||||
const struct tegra_tsensor_group *sg = zone->sg;
|
const struct tegra_tsensor_group *sg = zone->sg;
|
||||||
struct device *dev = zone->dev;
|
struct device *dev = zone->dev;
|
||||||
enum thermal_trip_type type;
|
enum thermal_trip_type type;
|
||||||
@ -167,10 +367,29 @@ static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (type != THERMAL_TRIP_CRITICAL)
|
if (type == THERMAL_TRIP_CRITICAL) {
|
||||||
return 0;
|
return thermtrip_program(dev, sg, temp);
|
||||||
|
} else if (type == THERMAL_TRIP_HOT) {
|
||||||
|
int i;
|
||||||
|
|
||||||
return thermtrip_program(dev, sg, temp);
|
for (i = 0; i < THROTTLE_SIZE; i++) {
|
||||||
|
struct thermal_cooling_device *cdev;
|
||||||
|
struct soctherm_throt_cfg *stc;
|
||||||
|
|
||||||
|
if (!ts->throt_cfgs[i].init)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cdev = ts->throt_cfgs[i].cdev;
|
||||||
|
if (get_thermal_instance(tz, cdev, trip))
|
||||||
|
stc = find_throttle_cfg_by_name(ts, cdev->type);
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return throttrip_program(dev, sg, stc, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = {
|
static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = {
|
||||||
@ -237,15 +456,111 @@ static int thermtrip_program(struct device *dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* throttrip_program() - Configures the hardware to throttle the
|
||||||
|
* pulse 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
|
||||||
|
* @stc: pointer to the throttle need to be triggered
|
||||||
|
* @trip_temp: the temperature in millicelsius to trigger the thermal trip at
|
||||||
|
*
|
||||||
|
* Sets the thermal trip threshold and throttle event of the given sensor
|
||||||
|
* group. If this threshold is crossed, the hardware will trigger the
|
||||||
|
* throttle.
|
||||||
|
*
|
||||||
|
* 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 throttrip_program(struct device *dev,
|
||||||
|
const struct tegra_tsensor_group *sg,
|
||||||
|
struct soctherm_throt_cfg *stc,
|
||||||
|
int trip_temp)
|
||||||
|
{
|
||||||
|
struct tegra_soctherm *ts = dev_get_drvdata(dev);
|
||||||
|
int temp, cpu_throt, gpu_throt;
|
||||||
|
unsigned int throt;
|
||||||
|
u32 r, reg_off;
|
||||||
|
|
||||||
|
if (!dev || !sg || !stc || !stc->init)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
temp = enforce_temp_range(dev, trip_temp) / ts->soc->thresh_grain;
|
||||||
|
|
||||||
|
/* Hardcode LIGHT on LEVEL1 and HEAVY on LEVEL2 */
|
||||||
|
throt = stc->id;
|
||||||
|
reg_off = THERMCTL_LVL_REG(sg->thermctl_lvl0_offset, throt + 1);
|
||||||
|
|
||||||
|
if (throt == THROTTLE_LIGHT) {
|
||||||
|
cpu_throt = THERMCTL_LVL0_CPU0_CPU_THROT_LIGHT;
|
||||||
|
gpu_throt = THERMCTL_LVL0_CPU0_GPU_THROT_LIGHT;
|
||||||
|
} else {
|
||||||
|
cpu_throt = THERMCTL_LVL0_CPU0_CPU_THROT_HEAVY;
|
||||||
|
gpu_throt = THERMCTL_LVL0_CPU0_GPU_THROT_HEAVY;
|
||||||
|
if (throt != THROTTLE_HEAVY)
|
||||||
|
dev_warn(dev,
|
||||||
|
"invalid throt id %d - assuming HEAVY",
|
||||||
|
throt);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = readl(ts->regs + reg_off);
|
||||||
|
r = REG_SET_MASK(r, sg->thermctl_lvl0_up_thresh_mask, temp);
|
||||||
|
r = REG_SET_MASK(r, sg->thermctl_lvl0_dn_thresh_mask, temp);
|
||||||
|
r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_CPU_THROT_MASK, cpu_throt);
|
||||||
|
r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_GPU_THROT_MASK, gpu_throt);
|
||||||
|
r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 1);
|
||||||
|
writel(r, ts->regs + reg_off);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct soctherm_throt_cfg *
|
||||||
|
find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; ts->throt_cfgs[i].name; i++)
|
||||||
|
if (!strcmp(ts->throt_cfgs[i].name, name))
|
||||||
|
return &ts->throt_cfgs[i];
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp)
|
||||||
|
{
|
||||||
|
int ntrips, i, ret;
|
||||||
|
enum thermal_trip_type type;
|
||||||
|
|
||||||
|
ntrips = of_thermal_get_ntrips(tz);
|
||||||
|
if (ntrips <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (i = 0; i < ntrips; i++) {
|
||||||
|
ret = tz->ops->get_trip_type(tz, i, &type);
|
||||||
|
if (ret)
|
||||||
|
return -EINVAL;
|
||||||
|
if (type == THERMAL_TRIP_HOT) {
|
||||||
|
ret = tz->ops->get_trip_temp(tz, i, temp);
|
||||||
|
if (!ret)
|
||||||
|
*trip = i;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tegra_soctherm_set_hwtrips() - set HW trip point from DT data
|
* tegra_soctherm_set_hwtrips() - set HW trip point from DT data
|
||||||
* @dev: struct device * of the SOC_THERM instance
|
* @dev: struct device * of the SOC_THERM instance
|
||||||
*
|
*
|
||||||
* Configure the SOC_THERM HW trip points, setting "THERMTRIP"
|
* Configure the SOC_THERM HW trip points, setting "THERMTRIP"
|
||||||
* trip points , using "critical" type trip_temp from thermal
|
* "THROTTLE" trip points , using "critical" or "hot" type trip_temp
|
||||||
* zone.
|
* from thermal zone.
|
||||||
* After they have been configured, THERMTRIP will take action
|
* After they have been configured, THERMTRIP or THROTTLE will take
|
||||||
* when the configured SoC thermal sensor group reaches a
|
* action when the configured SoC thermal sensor group reaches a
|
||||||
* certain temperature.
|
* certain temperature.
|
||||||
*
|
*
|
||||||
* Return: 0 upon success, or a negative error code on failure.
|
* Return: 0 upon success, or a negative error code on failure.
|
||||||
@ -254,19 +569,24 @@ static int thermtrip_program(struct device *dev,
|
|||||||
* THERMTRIP has been enabled successfully when a message similar to
|
* THERMTRIP has been enabled successfully when a message similar to
|
||||||
* this one appears on the serial console:
|
* this one appears on the serial console:
|
||||||
* "thermtrip: will shut down when sensor group XXX reaches YYYYYY mC"
|
* "thermtrip: will shut down when sensor group XXX reaches YYYYYY mC"
|
||||||
|
* THROTTLE has been enabled successfully when a message similar to
|
||||||
|
* this one appears on the serial console:
|
||||||
|
* ""throttrip: will throttle when sensor group XXX reaches YYYYYY mC"
|
||||||
*/
|
*/
|
||||||
static int tegra_soctherm_set_hwtrips(struct device *dev,
|
static int tegra_soctherm_set_hwtrips(struct device *dev,
|
||||||
const struct tegra_tsensor_group *sg,
|
const struct tegra_tsensor_group *sg,
|
||||||
struct thermal_zone_device *tz)
|
struct thermal_zone_device *tz)
|
||||||
{
|
{
|
||||||
int temperature;
|
struct tegra_soctherm *ts = dev_get_drvdata(dev);
|
||||||
|
struct soctherm_throt_cfg *stc;
|
||||||
|
int i, trip, temperature;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = tz->ops->get_crit_temp(tz, &temperature);
|
ret = tz->ops->get_crit_temp(tz, &temperature);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_warn(dev, "thermtrip: %s: missing critical temperature\n",
|
dev_warn(dev, "thermtrip: %s: missing critical temperature\n",
|
||||||
sg->name);
|
sg->name);
|
||||||
return ret;
|
goto set_throttle;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = thermtrip_program(dev, sg, temperature);
|
ret = thermtrip_program(dev, sg, temperature);
|
||||||
@ -280,6 +600,43 @@ static int tegra_soctherm_set_hwtrips(struct device *dev,
|
|||||||
"thermtrip: will shut down when %s reaches %d mC\n",
|
"thermtrip: will shut down when %s reaches %d mC\n",
|
||||||
sg->name, temperature);
|
sg->name, temperature);
|
||||||
|
|
||||||
|
set_throttle:
|
||||||
|
ret = get_hot_temp(tz, &trip, &temperature);
|
||||||
|
if (ret) {
|
||||||
|
dev_warn(dev, "throttrip: %s: missing hot temperature\n",
|
||||||
|
sg->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < THROTTLE_SIZE; i++) {
|
||||||
|
struct thermal_cooling_device *cdev;
|
||||||
|
|
||||||
|
if (!ts->throt_cfgs[i].init)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cdev = ts->throt_cfgs[i].cdev;
|
||||||
|
if (get_thermal_instance(tz, cdev, trip))
|
||||||
|
stc = find_throttle_cfg_by_name(ts, cdev->type);
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = throttrip_program(dev, sg, stc, temperature);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "throttrip: %s: error during enable\n",
|
||||||
|
sg->name);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_info(dev,
|
||||||
|
"throttrip: will throttle when %s reaches %d mC\n",
|
||||||
|
sg->name, temperature);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == THROTTLE_SIZE)
|
||||||
|
dev_warn(dev, "throttrip: %s: missing throttle cdev\n",
|
||||||
|
sg->name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +648,7 @@ static int regs_show(struct seq_file *s, void *data)
|
|||||||
const struct tegra_tsensor *tsensors = ts->soc->tsensors;
|
const struct tegra_tsensor *tsensors = ts->soc->tsensors;
|
||||||
const struct tegra_tsensor_group **ttgs = ts->soc->ttgs;
|
const struct tegra_tsensor_group **ttgs = ts->soc->ttgs;
|
||||||
u32 r, state;
|
u32 r, state;
|
||||||
int i;
|
int i, level;
|
||||||
|
|
||||||
seq_puts(s, "-----TSENSE (convert HW)-----\n");
|
seq_puts(s, "-----TSENSE (convert HW)-----\n");
|
||||||
|
|
||||||
@ -365,6 +722,81 @@ static int regs_show(struct seq_file *s, void *data)
|
|||||||
state = REG_GET_MASK(r, SENSOR_TEMP2_MEM_TEMP_MASK);
|
state = REG_GET_MASK(r, SENSOR_TEMP2_MEM_TEMP_MASK);
|
||||||
seq_printf(s, " MEM(%d)\n", translate_temp(state));
|
seq_printf(s, " MEM(%d)\n", translate_temp(state));
|
||||||
|
|
||||||
|
for (i = 0; i < ts->soc->num_ttgs; i++) {
|
||||||
|
seq_printf(s, "%s:\n", ttgs[i]->name);
|
||||||
|
for (level = 0; level < 4; level++) {
|
||||||
|
s32 v;
|
||||||
|
u32 mask;
|
||||||
|
u16 off = ttgs[i]->thermctl_lvl0_offset;
|
||||||
|
|
||||||
|
r = readl(ts->regs + THERMCTL_LVL_REG(off, level));
|
||||||
|
|
||||||
|
mask = ttgs[i]->thermctl_lvl0_up_thresh_mask;
|
||||||
|
state = REG_GET_MASK(r, mask);
|
||||||
|
v = sign_extend32(state, ts->soc->bptt - 1);
|
||||||
|
v *= ts->soc->thresh_grain;
|
||||||
|
seq_printf(s, " %d: Up/Dn(%d /", level, v);
|
||||||
|
|
||||||
|
mask = ttgs[i]->thermctl_lvl0_dn_thresh_mask;
|
||||||
|
state = REG_GET_MASK(r, mask);
|
||||||
|
v = sign_extend32(state, ts->soc->bptt - 1);
|
||||||
|
v *= ts->soc->thresh_grain;
|
||||||
|
seq_printf(s, "%d ) ", v);
|
||||||
|
|
||||||
|
mask = THERMCTL_LVL0_CPU0_EN_MASK;
|
||||||
|
state = REG_GET_MASK(r, mask);
|
||||||
|
seq_printf(s, "En(%d) ", state);
|
||||||
|
|
||||||
|
mask = THERMCTL_LVL0_CPU0_CPU_THROT_MASK;
|
||||||
|
state = REG_GET_MASK(r, mask);
|
||||||
|
seq_puts(s, "CPU Throt");
|
||||||
|
if (!state)
|
||||||
|
seq_printf(s, "(%s) ", "none");
|
||||||
|
else if (state == THERMCTL_LVL0_CPU0_CPU_THROT_LIGHT)
|
||||||
|
seq_printf(s, "(%s) ", "L");
|
||||||
|
else if (state == THERMCTL_LVL0_CPU0_CPU_THROT_HEAVY)
|
||||||
|
seq_printf(s, "(%s) ", "H");
|
||||||
|
else
|
||||||
|
seq_printf(s, "(%s) ", "H+L");
|
||||||
|
|
||||||
|
mask = THERMCTL_LVL0_CPU0_GPU_THROT_MASK;
|
||||||
|
state = REG_GET_MASK(r, mask);
|
||||||
|
seq_puts(s, "GPU Throt");
|
||||||
|
if (!state)
|
||||||
|
seq_printf(s, "(%s) ", "none");
|
||||||
|
else if (state == THERMCTL_LVL0_CPU0_GPU_THROT_LIGHT)
|
||||||
|
seq_printf(s, "(%s) ", "L");
|
||||||
|
else if (state == THERMCTL_LVL0_CPU0_GPU_THROT_HEAVY)
|
||||||
|
seq_printf(s, "(%s) ", "H");
|
||||||
|
else
|
||||||
|
seq_printf(s, "(%s) ", "H+L");
|
||||||
|
|
||||||
|
mask = THERMCTL_LVL0_CPU0_STATUS_MASK;
|
||||||
|
state = REG_GET_MASK(r, mask);
|
||||||
|
seq_printf(s, "Status(%s)\n",
|
||||||
|
state == 0 ? "LO" :
|
||||||
|
state == 1 ? "In" :
|
||||||
|
state == 2 ? "Res" : "HI");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = readl(ts->regs + THERMCTL_STATS_CTL);
|
||||||
|
seq_printf(s, "STATS: Up(%s) Dn(%s)\n",
|
||||||
|
r & STATS_CTL_EN_UP ? "En" : "--",
|
||||||
|
r & STATS_CTL_EN_DN ? "En" : "--");
|
||||||
|
|
||||||
|
for (level = 0; level < 4; level++) {
|
||||||
|
u16 off;
|
||||||
|
|
||||||
|
off = THERMCTL_LVL0_UP_STATS;
|
||||||
|
r = readl(ts->regs + THERMCTL_LVL_REG(off, level));
|
||||||
|
seq_printf(s, " Level_%d Up(%d) ", level, r);
|
||||||
|
|
||||||
|
off = THERMCTL_LVL0_DN_STATS;
|
||||||
|
r = readl(ts->regs + THERMCTL_LVL_REG(off, level));
|
||||||
|
seq_printf(s, "Dn(%d)\n", r);
|
||||||
|
}
|
||||||
|
|
||||||
r = readl(ts->regs + THERMCTL_THERMTRIP_CTL);
|
r = readl(ts->regs + THERMCTL_THERMTRIP_CTL);
|
||||||
state = REG_GET_MASK(r, ttgs[0]->thermtrip_any_en_mask);
|
state = REG_GET_MASK(r, ttgs[0]->thermtrip_any_en_mask);
|
||||||
seq_printf(s, "Thermtrip Any En(%d)\n", state);
|
seq_printf(s, "Thermtrip Any En(%d)\n", state);
|
||||||
@ -376,6 +808,32 @@ static int regs_show(struct seq_file *s, void *data)
|
|||||||
seq_printf(s, "Thresh(%d)\n", state);
|
seq_printf(s, "Thresh(%d)\n", state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = readl(ts->regs + THROT_GLOBAL_CFG);
|
||||||
|
seq_puts(s, "\n");
|
||||||
|
seq_printf(s, "GLOBAL THROTTLE CONFIG: 0x%08x\n", r);
|
||||||
|
|
||||||
|
seq_puts(s, "---------------------------------------------------\n");
|
||||||
|
r = readl(ts->regs + THROT_STATUS);
|
||||||
|
state = REG_GET_MASK(r, THROT_STATUS_BREACH_MASK);
|
||||||
|
seq_printf(s, "THROT STATUS: breach(%d) ", state);
|
||||||
|
state = REG_GET_MASK(r, THROT_STATUS_STATE_MASK);
|
||||||
|
seq_printf(s, "state(%d) ", state);
|
||||||
|
state = REG_GET_MASK(r, THROT_STATUS_ENABLED_MASK);
|
||||||
|
seq_printf(s, "enabled(%d)\n", state);
|
||||||
|
|
||||||
|
r = readl(ts->regs + CPU_PSKIP_STATUS);
|
||||||
|
if (ts->soc->use_ccroc) {
|
||||||
|
state = REG_GET_MASK(r, XPU_PSKIP_STATUS_ENABLED_MASK);
|
||||||
|
seq_printf(s, "CPU PSKIP STATUS: enabled(%d)\n", state);
|
||||||
|
} else {
|
||||||
|
state = REG_GET_MASK(r, XPU_PSKIP_STATUS_M_MASK);
|
||||||
|
seq_printf(s, "CPU PSKIP STATUS: M(%d) ", state);
|
||||||
|
state = REG_GET_MASK(r, XPU_PSKIP_STATUS_N_MASK);
|
||||||
|
seq_printf(s, "N(%d) ", state);
|
||||||
|
state = REG_GET_MASK(r, XPU_PSKIP_STATUS_ENABLED_MASK);
|
||||||
|
seq_printf(s, "enabled(%d)\n", state);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,6 +907,326 @@ static int soctherm_clk_enable(struct platform_device *pdev, bool enable)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int throt_get_cdev_max_state(struct thermal_cooling_device *cdev,
|
||||||
|
unsigned long *max_state)
|
||||||
|
{
|
||||||
|
*max_state = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int throt_get_cdev_cur_state(struct thermal_cooling_device *cdev,
|
||||||
|
unsigned long *cur_state)
|
||||||
|
{
|
||||||
|
struct tegra_soctherm *ts = cdev->devdata;
|
||||||
|
u32 r;
|
||||||
|
|
||||||
|
r = readl(ts->regs + THROT_STATUS);
|
||||||
|
if (REG_GET_MASK(r, THROT_STATUS_STATE_MASK))
|
||||||
|
*cur_state = 1;
|
||||||
|
else
|
||||||
|
*cur_state = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int throt_set_cdev_state(struct thermal_cooling_device *cdev,
|
||||||
|
unsigned long cur_state)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct thermal_cooling_device_ops throt_cooling_ops = {
|
||||||
|
.get_max_state = throt_get_cdev_max_state,
|
||||||
|
.get_cur_state = throt_get_cdev_cur_state,
|
||||||
|
.set_cur_state = throt_set_cdev_state,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* soctherm_init_hw_throt_cdev() - Parse the HW throttle configurations
|
||||||
|
* and register them as cooling devices.
|
||||||
|
*/
|
||||||
|
static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct tegra_soctherm *ts = dev_get_drvdata(dev);
|
||||||
|
struct device_node *np_stc, *np_stcc;
|
||||||
|
const char *name;
|
||||||
|
u32 val;
|
||||||
|
int i, r;
|
||||||
|
|
||||||
|
for (i = 0; i < THROTTLE_SIZE; i++) {
|
||||||
|
ts->throt_cfgs[i].name = throt_names[i];
|
||||||
|
ts->throt_cfgs[i].id = i;
|
||||||
|
ts->throt_cfgs[i].init = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
np_stc = of_get_child_by_name(dev->of_node, "throttle-cfgs");
|
||||||
|
if (!np_stc) {
|
||||||
|
dev_info(dev,
|
||||||
|
"throttle-cfg: no throttle-cfgs - not enabling\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_child_of_node(np_stc, np_stcc) {
|
||||||
|
struct soctherm_throt_cfg *stc;
|
||||||
|
struct thermal_cooling_device *tcd;
|
||||||
|
|
||||||
|
name = np_stcc->name;
|
||||||
|
stc = find_throttle_cfg_by_name(ts, name);
|
||||||
|
if (!stc) {
|
||||||
|
dev_err(dev,
|
||||||
|
"throttle-cfg: could not find %s\n", name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = of_property_read_u32(np_stcc, "nvidia,priority", &val);
|
||||||
|
if (r) {
|
||||||
|
dev_info(dev,
|
||||||
|
"throttle-cfg: %s: missing priority\n", name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
stc->priority = val;
|
||||||
|
|
||||||
|
if (ts->soc->use_ccroc) {
|
||||||
|
r = of_property_read_u32(np_stcc,
|
||||||
|
"nvidia,cpu-throt-level",
|
||||||
|
&val);
|
||||||
|
if (r) {
|
||||||
|
dev_info(dev,
|
||||||
|
"throttle-cfg: %s: missing cpu-throt-level\n",
|
||||||
|
name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
stc->cpu_throt_level = val;
|
||||||
|
} else {
|
||||||
|
r = of_property_read_u32(np_stcc,
|
||||||
|
"nvidia,cpu-throt-percent",
|
||||||
|
&val);
|
||||||
|
if (r) {
|
||||||
|
dev_info(dev,
|
||||||
|
"throttle-cfg: %s: missing cpu-throt-percent\n",
|
||||||
|
name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
stc->cpu_throt_depth = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcd = thermal_of_cooling_device_register(np_stcc,
|
||||||
|
(char *)name, ts,
|
||||||
|
&throt_cooling_ops);
|
||||||
|
of_node_put(np_stcc);
|
||||||
|
if (IS_ERR_OR_NULL(tcd)) {
|
||||||
|
dev_err(dev,
|
||||||
|
"throttle-cfg: %s: failed to register cooling device\n",
|
||||||
|
name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
stc->cdev = tcd;
|
||||||
|
stc->init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
of_node_put(np_stc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* throttlectl_cpu_level_cfg() - programs CCROC NV_THERM level config
|
||||||
|
* @level: describing the level LOW/MED/HIGH of throttling
|
||||||
|
*
|
||||||
|
* It's necessary to set up the CPU-local CCROC NV_THERM instance with
|
||||||
|
* the M/N values desired for each level. This function does this.
|
||||||
|
*
|
||||||
|
* This function pre-programs the CCROC NV_THERM levels in terms of
|
||||||
|
* pre-configured "Low", "Medium" or "Heavy" throttle levels which are
|
||||||
|
* mapped to THROT_LEVEL_LOW, THROT_LEVEL_MED and THROT_LEVEL_HVY.
|
||||||
|
*/
|
||||||
|
static void throttlectl_cpu_level_cfg(struct tegra_soctherm *ts, int level)
|
||||||
|
{
|
||||||
|
u8 depth, dividend;
|
||||||
|
u32 r;
|
||||||
|
|
||||||
|
switch (level) {
|
||||||
|
case TEGRA_SOCTHERM_THROT_LEVEL_LOW:
|
||||||
|
depth = 50;
|
||||||
|
break;
|
||||||
|
case TEGRA_SOCTHERM_THROT_LEVEL_MED:
|
||||||
|
depth = 75;
|
||||||
|
break;
|
||||||
|
case TEGRA_SOCTHERM_THROT_LEVEL_HIGH:
|
||||||
|
depth = 80;
|
||||||
|
break;
|
||||||
|
case TEGRA_SOCTHERM_THROT_LEVEL_NONE:
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dividend = THROT_DEPTH_DIVIDEND(depth);
|
||||||
|
|
||||||
|
/* setup PSKIP in ccroc nv_therm registers */
|
||||||
|
r = ccroc_readl(ts, CCROC_THROT_PSKIP_RAMP_CPU_REG(level));
|
||||||
|
r = REG_SET_MASK(r, CCROC_THROT_PSKIP_RAMP_DURATION_MASK, 0xff);
|
||||||
|
r = REG_SET_MASK(r, CCROC_THROT_PSKIP_RAMP_STEP_MASK, 0xf);
|
||||||
|
ccroc_writel(ts, r, CCROC_THROT_PSKIP_RAMP_CPU_REG(level));
|
||||||
|
|
||||||
|
r = ccroc_readl(ts, CCROC_THROT_PSKIP_CTRL_CPU_REG(level));
|
||||||
|
r = REG_SET_MASK(r, CCROC_THROT_PSKIP_CTRL_ENB_MASK, 1);
|
||||||
|
r = REG_SET_MASK(r, CCROC_THROT_PSKIP_CTRL_DIVIDEND_MASK, dividend);
|
||||||
|
r = REG_SET_MASK(r, CCROC_THROT_PSKIP_CTRL_DIVISOR_MASK, 0xff);
|
||||||
|
ccroc_writel(ts, r, CCROC_THROT_PSKIP_CTRL_CPU_REG(level));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* throttlectl_cpu_level_select() - program CPU pulse skipper config
|
||||||
|
* @throt: the LIGHT/HEAVY of throttle event id
|
||||||
|
*
|
||||||
|
* Pulse skippers are used to throttle clock frequencies. This
|
||||||
|
* function programs the pulse skippers based on @throt and platform
|
||||||
|
* data. This function is used on SoCs which have CPU-local pulse
|
||||||
|
* skipper control, such as T13x. It programs soctherm's interface to
|
||||||
|
* Denver:CCROC NV_THERM in terms of Low, Medium and HIGH throttling
|
||||||
|
* vectors. PSKIP_BYPASS mode is set as required per HW spec.
|
||||||
|
*/
|
||||||
|
static void throttlectl_cpu_level_select(struct tegra_soctherm *ts,
|
||||||
|
enum soctherm_throttle_id throt)
|
||||||
|
{
|
||||||
|
u32 r, throt_vect;
|
||||||
|
|
||||||
|
/* Denver:CCROC NV_THERM interface N:3 Mapping */
|
||||||
|
switch (ts->throt_cfgs[throt].cpu_throt_level) {
|
||||||
|
case TEGRA_SOCTHERM_THROT_LEVEL_LOW:
|
||||||
|
throt_vect = THROT_VECT_LOW;
|
||||||
|
break;
|
||||||
|
case TEGRA_SOCTHERM_THROT_LEVEL_MED:
|
||||||
|
throt_vect = THROT_VECT_MED;
|
||||||
|
break;
|
||||||
|
case TEGRA_SOCTHERM_THROT_LEVEL_HIGH:
|
||||||
|
throt_vect = THROT_VECT_HIGH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throt_vect = THROT_VECT_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));
|
||||||
|
r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1);
|
||||||
|
r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT_CPU_MASK, throt_vect);
|
||||||
|
r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT2_CPU_MASK, throt_vect);
|
||||||
|
writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));
|
||||||
|
|
||||||
|
/* bypass sequencer in soc_therm as it is programmed in ccroc */
|
||||||
|
r = REG_SET_MASK(0, THROT_PSKIP_RAMP_SEQ_BYPASS_MODE_MASK, 1);
|
||||||
|
writel(r, ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* throttlectl_cpu_mn() - program CPU pulse skipper configuration
|
||||||
|
* @throt: the LIGHT/HEAVY of throttle event id
|
||||||
|
*
|
||||||
|
* Pulse skippers are used to throttle clock frequencies. This
|
||||||
|
* function programs the pulse skippers based on @throt and platform
|
||||||
|
* data. This function is used for CPUs that have "remote" pulse
|
||||||
|
* skipper control, e.g., the CPU pulse skipper is controlled by the
|
||||||
|
* SOC_THERM IP block. (SOC_THERM is located outside the CPU
|
||||||
|
* complex.)
|
||||||
|
*/
|
||||||
|
static void throttlectl_cpu_mn(struct tegra_soctherm *ts,
|
||||||
|
enum soctherm_throttle_id throt)
|
||||||
|
{
|
||||||
|
u32 r;
|
||||||
|
int depth;
|
||||||
|
u8 dividend;
|
||||||
|
|
||||||
|
depth = ts->throt_cfgs[throt].cpu_throt_depth;
|
||||||
|
dividend = THROT_DEPTH_DIVIDEND(depth);
|
||||||
|
|
||||||
|
r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));
|
||||||
|
r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1);
|
||||||
|
r = REG_SET_MASK(r, THROT_PSKIP_CTRL_DIVIDEND_MASK, dividend);
|
||||||
|
r = REG_SET_MASK(r, THROT_PSKIP_CTRL_DIVISOR_MASK, 0xff);
|
||||||
|
writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));
|
||||||
|
|
||||||
|
r = readl(ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));
|
||||||
|
r = REG_SET_MASK(r, THROT_PSKIP_RAMP_DURATION_MASK, 0xff);
|
||||||
|
r = REG_SET_MASK(r, THROT_PSKIP_RAMP_STEP_MASK, 0xf);
|
||||||
|
writel(r, ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* soctherm_throttle_program() - programs pulse skippers' configuration
|
||||||
|
* @throt: the LIGHT/HEAVY of the throttle event id.
|
||||||
|
*
|
||||||
|
* Pulse skippers are used to throttle clock frequencies.
|
||||||
|
* This function programs the pulse skippers.
|
||||||
|
*/
|
||||||
|
static void soctherm_throttle_program(struct tegra_soctherm *ts,
|
||||||
|
enum soctherm_throttle_id throt)
|
||||||
|
{
|
||||||
|
u32 r;
|
||||||
|
struct soctherm_throt_cfg stc = ts->throt_cfgs[throt];
|
||||||
|
|
||||||
|
if (!stc.init)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Setup PSKIP parameters */
|
||||||
|
if (ts->soc->use_ccroc)
|
||||||
|
throttlectl_cpu_level_select(ts, throt);
|
||||||
|
else
|
||||||
|
throttlectl_cpu_mn(ts, throt);
|
||||||
|
|
||||||
|
r = REG_SET_MASK(0, THROT_PRIORITY_LITE_PRIO_MASK, stc.priority);
|
||||||
|
writel(r, ts->regs + THROT_PRIORITY_CTRL(throt));
|
||||||
|
|
||||||
|
r = REG_SET_MASK(0, THROT_DELAY_LITE_DELAY_MASK, 0);
|
||||||
|
writel(r, ts->regs + THROT_DELAY_CTRL(throt));
|
||||||
|
|
||||||
|
r = readl(ts->regs + THROT_PRIORITY_LOCK);
|
||||||
|
r = REG_GET_MASK(r, THROT_PRIORITY_LOCK_PRIORITY_MASK);
|
||||||
|
if (r >= stc.priority)
|
||||||
|
return;
|
||||||
|
r = REG_SET_MASK(0, THROT_PRIORITY_LOCK_PRIORITY_MASK,
|
||||||
|
stc.priority);
|
||||||
|
writel(r, ts->regs + THROT_PRIORITY_LOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tegra_soctherm_throttle(struct device *dev)
|
||||||
|
{
|
||||||
|
struct tegra_soctherm *ts = dev_get_drvdata(dev);
|
||||||
|
u32 v;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* configure LOW, MED and HIGH levels for CCROC NV_THERM */
|
||||||
|
if (ts->soc->use_ccroc) {
|
||||||
|
throttlectl_cpu_level_cfg(ts, TEGRA_SOCTHERM_THROT_LEVEL_LOW);
|
||||||
|
throttlectl_cpu_level_cfg(ts, TEGRA_SOCTHERM_THROT_LEVEL_MED);
|
||||||
|
throttlectl_cpu_level_cfg(ts, TEGRA_SOCTHERM_THROT_LEVEL_HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Thermal HW throttle programming */
|
||||||
|
for (i = 0; i < THROTTLE_SIZE; i++)
|
||||||
|
soctherm_throttle_program(ts, i);
|
||||||
|
|
||||||
|
v = REG_SET_MASK(0, THROT_GLOBAL_ENB_MASK, 1);
|
||||||
|
if (ts->soc->use_ccroc) {
|
||||||
|
ccroc_writel(ts, v, CCROC_GLOBAL_CFG);
|
||||||
|
|
||||||
|
v = ccroc_readl(ts, CCROC_SUPER_CCLKG_DIVIDER);
|
||||||
|
v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1);
|
||||||
|
ccroc_writel(ts, v, CCROC_SUPER_CCLKG_DIVIDER);
|
||||||
|
} else {
|
||||||
|
writel(v, ts->regs + THROT_GLOBAL_CFG);
|
||||||
|
|
||||||
|
v = clk_readl(ts, CAR_SUPER_CCLKG_DIVIDER);
|
||||||
|
v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1);
|
||||||
|
clk_writel(ts, v, CAR_SUPER_CCLKG_DIVIDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize stats collection */
|
||||||
|
v = STATS_CTL_CLR_DN | STATS_CTL_EN_DN |
|
||||||
|
STATS_CTL_CLR_UP | STATS_CTL_EN_UP;
|
||||||
|
writel(v, ts->regs + THERMCTL_STATS_CTL);
|
||||||
|
}
|
||||||
|
|
||||||
static void soctherm_init(struct platform_device *pdev)
|
static void soctherm_init(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
|
struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
|
||||||
@ -475,6 +1253,9 @@ static void soctherm_init(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
writel(pdiv, tegra->regs + SENSOR_PDIV);
|
writel(pdiv, tegra->regs + SENSOR_PDIV);
|
||||||
writel(hotspot, tegra->regs + SENSOR_HOTSPOT_OFF);
|
writel(hotspot, tegra->regs + SENSOR_HOTSPOT_OFF);
|
||||||
|
|
||||||
|
/* Configure hw throttle */
|
||||||
|
tegra_soctherm_throttle(&pdev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id tegra_soctherm_of_match[] = {
|
static const struct of_device_id tegra_soctherm_of_match[] = {
|
||||||
@ -527,10 +1308,31 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
tegra->soc = soc;
|
tegra->soc = soc;
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||||
|
"soctherm-reg");
|
||||||
tegra->regs = devm_ioremap_resource(&pdev->dev, res);
|
tegra->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||||
if (IS_ERR(tegra->regs))
|
if (IS_ERR(tegra->regs)) {
|
||||||
|
dev_err(&pdev->dev, "can't get soctherm registers");
|
||||||
return PTR_ERR(tegra->regs);
|
return PTR_ERR(tegra->regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tegra->soc->use_ccroc) {
|
||||||
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||||
|
"car-reg");
|
||||||
|
tegra->clk_regs = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
if (IS_ERR(tegra->clk_regs)) {
|
||||||
|
dev_err(&pdev->dev, "can't get car clk registers");
|
||||||
|
return PTR_ERR(tegra->clk_regs);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||||
|
"ccroc-reg");
|
||||||
|
tegra->ccroc_regs = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
if (IS_ERR(tegra->ccroc_regs)) {
|
||||||
|
dev_err(&pdev->dev, "can't get ccroc registers");
|
||||||
|
return PTR_ERR(tegra->ccroc_regs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tegra->reset = devm_reset_control_get(&pdev->dev, "soctherm");
|
tegra->reset = devm_reset_control_get(&pdev->dev, "soctherm");
|
||||||
if (IS_ERR(tegra->reset)) {
|
if (IS_ERR(tegra->reset)) {
|
||||||
@ -580,6 +1382,8 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
soctherm_init_hw_throt_cdev(pdev);
|
||||||
|
|
||||||
soctherm_init(pdev);
|
soctherm_init(pdev);
|
||||||
|
|
||||||
for (i = 0; i < soc->num_ttgs; ++i) {
|
for (i = 0; i < soc->num_ttgs; ++i) {
|
||||||
@ -593,6 +1397,7 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
|
|||||||
zone->reg = tegra->regs + soc->ttgs[i]->sensor_temp_offset;
|
zone->reg = tegra->regs + soc->ttgs[i]->sensor_temp_offset;
|
||||||
zone->dev = &pdev->dev;
|
zone->dev = &pdev->dev;
|
||||||
zone->sg = soc->ttgs[i];
|
zone->sg = soc->ttgs[i];
|
||||||
|
zone->ts = tegra;
|
||||||
|
|
||||||
z = devm_thermal_zone_of_sensor_register(&pdev->dev,
|
z = devm_thermal_zone_of_sensor_register(&pdev->dev,
|
||||||
soc->ttgs[i]->id, zone,
|
soc->ttgs[i]->id, zone,
|
||||||
@ -608,7 +1413,9 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
|
|||||||
tegra->thermctl_tzs[soc->ttgs[i]->id] = z;
|
tegra->thermctl_tzs[soc->ttgs[i]->id] = z;
|
||||||
|
|
||||||
/* Configure hw trip points */
|
/* Configure hw trip points */
|
||||||
tegra_soctherm_set_hwtrips(&pdev->dev, soc->ttgs[i], z);
|
err = tegra_soctherm_set_hwtrips(&pdev->dev, soc->ttgs[i], z);
|
||||||
|
if (err)
|
||||||
|
goto disable_clocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
soctherm_debug_init(pdev);
|
soctherm_debug_init(pdev);
|
||||||
@ -661,7 +1468,12 @@ static int __maybe_unused soctherm_resume(struct device *dev)
|
|||||||
struct thermal_zone_device *tz;
|
struct thermal_zone_device *tz;
|
||||||
|
|
||||||
tz = tegra->thermctl_tzs[soc->ttgs[i]->id];
|
tz = tegra->thermctl_tzs[soc->ttgs[i]->id];
|
||||||
tegra_soctherm_set_hwtrips(dev, soc->ttgs[i], tz);
|
err = tegra_soctherm_set_hwtrips(dev, soc->ttgs[i], tz);
|
||||||
|
if (err) {
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"Resume failed: set hwtrips failed\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
#ifndef __DRIVERS_THERMAL_TEGRA_SOCTHERM_H
|
#ifndef __DRIVERS_THERMAL_TEGRA_SOCTHERM_H
|
||||||
#define __DRIVERS_THERMAL_TEGRA_SOCTHERM_H
|
#define __DRIVERS_THERMAL_TEGRA_SOCTHERM_H
|
||||||
|
|
||||||
|
#define THERMCTL_LEVEL0_GROUP_CPU 0x0
|
||||||
|
#define THERMCTL_LEVEL0_GROUP_GPU 0x4
|
||||||
|
#define THERMCTL_LEVEL0_GROUP_MEM 0x8
|
||||||
|
#define THERMCTL_LEVEL0_GROUP_TSENSE 0xc
|
||||||
|
|
||||||
#define SENSOR_CONFIG2 8
|
#define SENSOR_CONFIG2 8
|
||||||
#define SENSOR_CONFIG2_THERMA_MASK (0xffff << 16)
|
#define SENSOR_CONFIG2_THERMA_MASK (0xffff << 16)
|
||||||
#define SENSOR_CONFIG2_THERMA_SHIFT 16
|
#define SENSOR_CONFIG2_THERMA_SHIFT 16
|
||||||
@ -65,6 +70,9 @@ struct tegra_tsensor_group {
|
|||||||
u32 thermtrip_enable_mask;
|
u32 thermtrip_enable_mask;
|
||||||
u32 thermtrip_any_en_mask;
|
u32 thermtrip_any_en_mask;
|
||||||
u32 thermtrip_threshold_mask;
|
u32 thermtrip_threshold_mask;
|
||||||
|
u16 thermctl_lvl0_offset;
|
||||||
|
u32 thermctl_lvl0_up_thresh_mask;
|
||||||
|
u32 thermctl_lvl0_dn_thresh_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tegra_tsensor_configuration {
|
struct tegra_tsensor_configuration {
|
||||||
@ -103,6 +111,8 @@ struct tegra_soctherm_soc {
|
|||||||
const unsigned int num_ttgs;
|
const unsigned int num_ttgs;
|
||||||
const struct tegra_soctherm_fuse *tfuse;
|
const struct tegra_soctherm_fuse *tfuse;
|
||||||
const int thresh_grain;
|
const int thresh_grain;
|
||||||
|
const unsigned int bptt;
|
||||||
|
const bool use_ccroc;
|
||||||
};
|
};
|
||||||
|
|
||||||
int tegra_calc_shared_calib(const struct tegra_soctherm_fuse *tfuse,
|
int tegra_calc_shared_calib(const struct tegra_soctherm_fuse *tfuse,
|
||||||
|
@ -28,7 +28,11 @@
|
|||||||
#define TEGRA124_THERMTRIP_CPU_THRESH_MASK (0xff << 8)
|
#define TEGRA124_THERMTRIP_CPU_THRESH_MASK (0xff << 8)
|
||||||
#define TEGRA124_THERMTRIP_TSENSE_THRESH_MASK 0xff
|
#define TEGRA124_THERMTRIP_TSENSE_THRESH_MASK 0xff
|
||||||
|
|
||||||
|
#define TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK (0xff << 17)
|
||||||
|
#define TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK (0xff << 9)
|
||||||
|
|
||||||
#define TEGRA124_THRESH_GRAIN 1000
|
#define TEGRA124_THRESH_GRAIN 1000
|
||||||
|
#define TEGRA124_BPTT 8
|
||||||
|
|
||||||
static const struct tegra_tsensor_configuration tegra124_tsensor_config = {
|
static const struct tegra_tsensor_configuration tegra124_tsensor_config = {
|
||||||
.tall = 16300,
|
.tall = 16300,
|
||||||
@ -51,6 +55,9 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_cpu = {
|
|||||||
.thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
|
.thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
|
||||||
.thermtrip_enable_mask = TEGRA124_THERMTRIP_CPU_EN_MASK,
|
.thermtrip_enable_mask = TEGRA124_THERMTRIP_CPU_EN_MASK,
|
||||||
.thermtrip_threshold_mask = TEGRA124_THERMTRIP_CPU_THRESH_MASK,
|
.thermtrip_threshold_mask = TEGRA124_THERMTRIP_CPU_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
|
||||||
|
.thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_tsensor_group tegra124_tsensor_group_gpu = {
|
static const struct tegra_tsensor_group tegra124_tsensor_group_gpu = {
|
||||||
@ -66,6 +73,9 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_gpu = {
|
|||||||
.thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
|
.thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
|
||||||
.thermtrip_enable_mask = TEGRA124_THERMTRIP_GPU_EN_MASK,
|
.thermtrip_enable_mask = TEGRA124_THERMTRIP_GPU_EN_MASK,
|
||||||
.thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
|
.thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
|
||||||
|
.thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_tsensor_group tegra124_tsensor_group_pll = {
|
static const struct tegra_tsensor_group tegra124_tsensor_group_pll = {
|
||||||
@ -79,6 +89,9 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_pll = {
|
|||||||
.thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
|
.thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
|
||||||
.thermtrip_enable_mask = TEGRA124_THERMTRIP_TSENSE_EN_MASK,
|
.thermtrip_enable_mask = TEGRA124_THERMTRIP_TSENSE_EN_MASK,
|
||||||
.thermtrip_threshold_mask = TEGRA124_THERMTRIP_TSENSE_THRESH_MASK,
|
.thermtrip_threshold_mask = TEGRA124_THERMTRIP_TSENSE_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
|
||||||
|
.thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_tsensor_group tegra124_tsensor_group_mem = {
|
static const struct tegra_tsensor_group tegra124_tsensor_group_mem = {
|
||||||
@ -94,6 +107,9 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_mem = {
|
|||||||
.thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
|
.thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
|
||||||
.thermtrip_enable_mask = TEGRA124_THERMTRIP_MEM_EN_MASK,
|
.thermtrip_enable_mask = TEGRA124_THERMTRIP_MEM_EN_MASK,
|
||||||
.thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
|
.thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
|
||||||
|
.thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_tsensor_group *tegra124_tsensor_groups[] = {
|
static const struct tegra_tsensor_group *tegra124_tsensor_groups[] = {
|
||||||
@ -193,4 +209,6 @@ const struct tegra_soctherm_soc tegra124_soctherm = {
|
|||||||
.num_ttgs = ARRAY_SIZE(tegra124_tsensor_groups),
|
.num_ttgs = ARRAY_SIZE(tegra124_tsensor_groups),
|
||||||
.tfuse = &tegra124_soctherm_fuse,
|
.tfuse = &tegra124_soctherm_fuse,
|
||||||
.thresh_grain = TEGRA124_THRESH_GRAIN,
|
.thresh_grain = TEGRA124_THRESH_GRAIN,
|
||||||
|
.bptt = TEGRA124_BPTT,
|
||||||
|
.use_ccroc = false,
|
||||||
};
|
};
|
||||||
|
@ -28,7 +28,11 @@
|
|||||||
#define TEGRA132_THERMTRIP_CPU_THRESH_MASK (0xff << 8)
|
#define TEGRA132_THERMTRIP_CPU_THRESH_MASK (0xff << 8)
|
||||||
#define TEGRA132_THERMTRIP_TSENSE_THRESH_MASK 0xff
|
#define TEGRA132_THERMTRIP_TSENSE_THRESH_MASK 0xff
|
||||||
|
|
||||||
|
#define TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK (0xff << 17)
|
||||||
|
#define TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK (0xff << 9)
|
||||||
|
|
||||||
#define TEGRA132_THRESH_GRAIN 1000
|
#define TEGRA132_THRESH_GRAIN 1000
|
||||||
|
#define TEGRA132_BPTT 8
|
||||||
|
|
||||||
static const struct tegra_tsensor_configuration tegra132_tsensor_config = {
|
static const struct tegra_tsensor_configuration tegra132_tsensor_config = {
|
||||||
.tall = 16300,
|
.tall = 16300,
|
||||||
@ -51,6 +55,9 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_cpu = {
|
|||||||
.thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
|
.thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
|
||||||
.thermtrip_enable_mask = TEGRA132_THERMTRIP_CPU_EN_MASK,
|
.thermtrip_enable_mask = TEGRA132_THERMTRIP_CPU_EN_MASK,
|
||||||
.thermtrip_threshold_mask = TEGRA132_THERMTRIP_CPU_THRESH_MASK,
|
.thermtrip_threshold_mask = TEGRA132_THERMTRIP_CPU_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
|
||||||
|
.thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_tsensor_group tegra132_tsensor_group_gpu = {
|
static const struct tegra_tsensor_group tegra132_tsensor_group_gpu = {
|
||||||
@ -66,6 +73,9 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_gpu = {
|
|||||||
.thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
|
.thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
|
||||||
.thermtrip_enable_mask = TEGRA132_THERMTRIP_GPU_EN_MASK,
|
.thermtrip_enable_mask = TEGRA132_THERMTRIP_GPU_EN_MASK,
|
||||||
.thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
|
.thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
|
||||||
|
.thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_tsensor_group tegra132_tsensor_group_pll = {
|
static const struct tegra_tsensor_group tegra132_tsensor_group_pll = {
|
||||||
@ -79,6 +89,9 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_pll = {
|
|||||||
.thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
|
.thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
|
||||||
.thermtrip_enable_mask = TEGRA132_THERMTRIP_TSENSE_EN_MASK,
|
.thermtrip_enable_mask = TEGRA132_THERMTRIP_TSENSE_EN_MASK,
|
||||||
.thermtrip_threshold_mask = TEGRA132_THERMTRIP_TSENSE_THRESH_MASK,
|
.thermtrip_threshold_mask = TEGRA132_THERMTRIP_TSENSE_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
|
||||||
|
.thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_tsensor_group tegra132_tsensor_group_mem = {
|
static const struct tegra_tsensor_group tegra132_tsensor_group_mem = {
|
||||||
@ -94,6 +107,9 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_mem = {
|
|||||||
.thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
|
.thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
|
||||||
.thermtrip_enable_mask = TEGRA132_THERMTRIP_MEM_EN_MASK,
|
.thermtrip_enable_mask = TEGRA132_THERMTRIP_MEM_EN_MASK,
|
||||||
.thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
|
.thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
|
||||||
|
.thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_tsensor_group *tegra132_tsensor_groups[] = {
|
static const struct tegra_tsensor_group *tegra132_tsensor_groups[] = {
|
||||||
@ -193,4 +209,6 @@ const struct tegra_soctherm_soc tegra132_soctherm = {
|
|||||||
.num_ttgs = ARRAY_SIZE(tegra132_tsensor_groups),
|
.num_ttgs = ARRAY_SIZE(tegra132_tsensor_groups),
|
||||||
.tfuse = &tegra132_soctherm_fuse,
|
.tfuse = &tegra132_soctherm_fuse,
|
||||||
.thresh_grain = TEGRA132_THRESH_GRAIN,
|
.thresh_grain = TEGRA132_THRESH_GRAIN,
|
||||||
|
.bptt = TEGRA132_BPTT,
|
||||||
|
.use_ccroc = true,
|
||||||
};
|
};
|
||||||
|
@ -29,7 +29,11 @@
|
|||||||
#define TEGRA210_THERMTRIP_CPU_THRESH_MASK (0x1ff << 9)
|
#define TEGRA210_THERMTRIP_CPU_THRESH_MASK (0x1ff << 9)
|
||||||
#define TEGRA210_THERMTRIP_TSENSE_THRESH_MASK 0x1ff
|
#define TEGRA210_THERMTRIP_TSENSE_THRESH_MASK 0x1ff
|
||||||
|
|
||||||
|
#define TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK (0x1ff << 18)
|
||||||
|
#define TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK (0x1ff << 9)
|
||||||
|
|
||||||
#define TEGRA210_THRESH_GRAIN 500
|
#define TEGRA210_THRESH_GRAIN 500
|
||||||
|
#define TEGRA210_BPTT 9
|
||||||
|
|
||||||
static const struct tegra_tsensor_configuration tegra210_tsensor_config = {
|
static const struct tegra_tsensor_configuration tegra210_tsensor_config = {
|
||||||
.tall = 16300,
|
.tall = 16300,
|
||||||
@ -52,6 +56,9 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_cpu = {
|
|||||||
.thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
|
.thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
|
||||||
.thermtrip_enable_mask = TEGRA210_THERMTRIP_CPU_EN_MASK,
|
.thermtrip_enable_mask = TEGRA210_THERMTRIP_CPU_EN_MASK,
|
||||||
.thermtrip_threshold_mask = TEGRA210_THERMTRIP_CPU_THRESH_MASK,
|
.thermtrip_threshold_mask = TEGRA210_THERMTRIP_CPU_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
|
||||||
|
.thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_tsensor_group tegra210_tsensor_group_gpu = {
|
static const struct tegra_tsensor_group tegra210_tsensor_group_gpu = {
|
||||||
@ -67,6 +74,9 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_gpu = {
|
|||||||
.thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
|
.thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
|
||||||
.thermtrip_enable_mask = TEGRA210_THERMTRIP_GPU_EN_MASK,
|
.thermtrip_enable_mask = TEGRA210_THERMTRIP_GPU_EN_MASK,
|
||||||
.thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
|
.thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
|
||||||
|
.thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_tsensor_group tegra210_tsensor_group_pll = {
|
static const struct tegra_tsensor_group tegra210_tsensor_group_pll = {
|
||||||
@ -80,6 +90,9 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_pll = {
|
|||||||
.thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
|
.thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
|
||||||
.thermtrip_enable_mask = TEGRA210_THERMTRIP_TSENSE_EN_MASK,
|
.thermtrip_enable_mask = TEGRA210_THERMTRIP_TSENSE_EN_MASK,
|
||||||
.thermtrip_threshold_mask = TEGRA210_THERMTRIP_TSENSE_THRESH_MASK,
|
.thermtrip_threshold_mask = TEGRA210_THERMTRIP_TSENSE_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
|
||||||
|
.thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_tsensor_group tegra210_tsensor_group_mem = {
|
static const struct tegra_tsensor_group tegra210_tsensor_group_mem = {
|
||||||
@ -95,6 +108,9 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_mem = {
|
|||||||
.thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
|
.thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
|
||||||
.thermtrip_enable_mask = TEGRA210_THERMTRIP_MEM_EN_MASK,
|
.thermtrip_enable_mask = TEGRA210_THERMTRIP_MEM_EN_MASK,
|
||||||
.thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
|
.thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
|
||||||
|
.thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
|
||||||
|
.thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_tsensor_group *tegra210_tsensor_groups[] = {
|
static const struct tegra_tsensor_group *tegra210_tsensor_groups[] = {
|
||||||
@ -194,4 +210,6 @@ const struct tegra_soctherm_soc tegra210_soctherm = {
|
|||||||
.num_ttgs = ARRAY_SIZE(tegra210_tsensor_groups),
|
.num_ttgs = ARRAY_SIZE(tegra210_tsensor_groups),
|
||||||
.tfuse = &tegra210_soctherm_fuse,
|
.tfuse = &tegra210_soctherm_fuse,
|
||||||
.thresh_grain = TEGRA210_THRESH_GRAIN,
|
.thresh_grain = TEGRA210_THRESH_GRAIN,
|
||||||
|
.bptt = TEGRA210_BPTT,
|
||||||
|
.use_ccroc = false,
|
||||||
};
|
};
|
||||||
|
@ -11,4 +11,9 @@
|
|||||||
#define TEGRA124_SOCTHERM_SENSOR_PLLX 3
|
#define TEGRA124_SOCTHERM_SENSOR_PLLX 3
|
||||||
#define TEGRA124_SOCTHERM_SENSOR_NUM 4
|
#define TEGRA124_SOCTHERM_SENSOR_NUM 4
|
||||||
|
|
||||||
|
#define TEGRA_SOCTHERM_THROT_LEVEL_LOW 0
|
||||||
|
#define TEGRA_SOCTHERM_THROT_LEVEL_MED 1
|
||||||
|
#define TEGRA_SOCTHERM_THROT_LEVEL_HIGH 2
|
||||||
|
#define TEGRA_SOCTHERM_THROT_LEVEL_NONE -1
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user