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".
|
||||
For Tegra132, must contain "nvidia,tegra132-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
|
||||
- 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
|
||||
- clocks : Must contain an entry for each entry in clock-names.
|
||||
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
|
||||
of this property. See <dt-bindings/thermal/tegra124-soctherm.h> for a
|
||||
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:
|
||||
- the "critical" type trip points will be set to SOC_THERM hardware as the
|
||||
shut down temperature. Once the temperature of this thermal zone is higher
|
||||
than it, the system will be shutdown or reset by hardware.
|
||||
- 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 :
|
||||
|
||||
soctherm@700e2000 {
|
||||
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>;
|
||||
clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
|
||||
<&tegra_car TEGRA124_CLK_SOC_THERM>;
|
||||
@ -44,6 +78,76 @@ Example :
|
||||
reset-names = "soctherm";
|
||||
|
||||
#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 :
|
||||
@ -62,6 +166,19 @@ Example: referring to thermal sensors :
|
||||
hysteresis = <1000>;
|
||||
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 @@
|
||||
thermal-zones {
|
||||
cpu {
|
||||
trips {
|
||||
trip {
|
||||
cpu-shutdown-trip {
|
||||
temperature = <101000>;
|
||||
hysteresis = <0>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
/* There are currently no cooling maps because there are no cooling devices */
|
||||
};
|
||||
};
|
||||
|
||||
mem {
|
||||
trips {
|
||||
trip {
|
||||
mem-shutdown-trip {
|
||||
temperature = <101000>;
|
||||
hysteresis = <0>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
/* There are currently no cooling maps because there are no cooling devices */
|
||||
};
|
||||
};
|
||||
|
||||
gpu {
|
||||
trips {
|
||||
trip {
|
||||
gpu-shutdown-trip {
|
||||
temperature = <101000>;
|
||||
hysteresis = <0>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
/* There are currently no cooling maps because there are no cooling devices */
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -851,7 +851,9 @@
|
||||
|
||||
soctherm: thermal-sensor@700e2000 {
|
||||
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>;
|
||||
clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
|
||||
<&tegra_car TEGRA124_CLK_SOC_THERM>;
|
||||
@ -859,6 +861,15 @@
|
||||
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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dfll: clock@70110000 {
|
||||
@ -1154,6 +1165,26 @@
|
||||
|
||||
thermal-sensors =
|
||||
<&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 {
|
||||
@ -1162,6 +1193,21 @@
|
||||
|
||||
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 {
|
||||
@ -1170,6 +1216,26 @@
|
||||
|
||||
thermal-sensors =
|
||||
<&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 {
|
||||
@ -1178,6 +1244,21 @@
|
||||
|
||||
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.
|
||||
*/
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
|
||||
#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/thermal/tegra124-soctherm.h>
|
||||
|
||||
/ {
|
||||
compatible = "nvidia,tegra132", "nvidia,tegra124";
|
||||
@ -727,8 +728,10 @@
|
||||
};
|
||||
|
||||
soctherm: thermal-sensor@700e2000 {
|
||||
compatible = "nvidia,tegra124-soctherm";
|
||||
reg = <0x0 0x700e2000 0x0 0x1000>;
|
||||
compatible = "nvidia,tegra132-soctherm";
|
||||
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>;
|
||||
clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
|
||||
<&tegra_car TEGRA124_CLK_SOC_THERM>;
|
||||
@ -736,6 +739,118 @@
|
||||
resets = <&tegra_car 78>;
|
||||
reset-names = "soctherm";
|
||||
#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 {
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <dt-bindings/memory/tegra210-mc.h>
|
||||
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/thermal/tegra124-soctherm.h>
|
||||
|
||||
/ {
|
||||
compatible = "nvidia,tegra210";
|
||||
@ -1094,4 +1095,130 @@
|
||||
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
|
||||
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
|
||||
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
|
||||
tristate "Intel PCH Thermal Reporting Driver"
|
||||
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_TI_SOC_THERMAL) += ti-soc-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_ST_THERMAL) += st/
|
||||
obj-$(CONFIG_QCOM_TSENS) += qcom/
|
||||
|
@ -74,7 +74,7 @@ struct power_table {
|
||||
* cpufreq frequencies.
|
||||
* @allowed_cpus: all the cpus involved for this cpufreq_cooling_device.
|
||||
* @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_timestamp: wall time of the last invocation of
|
||||
* 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 "../thermal_core.h"
|
||||
#include "soctherm.h"
|
||||
|
||||
#define SENSOR_CONFIG0 0
|
||||
@ -67,35 +68,228 @@
|
||||
#define READBACK_ADD_HALF BIT(7)
|
||||
#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) */
|
||||
#define REG_GET_MASK(r, m) (((r) & (m)) >> (ffs(m) - 1))
|
||||
/* set val(v) to mask bits(m) of register(r) */
|
||||
#define REG_SET_MASK(r, m, v) (((r) & ~(m)) | \
|
||||
(((v) & (m >> (ffs(m) - 1))) << (ffs(m) - 1)))
|
||||
|
||||
/* 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 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 {
|
||||
void __iomem *reg;
|
||||
struct device *dev;
|
||||
struct tegra_soctherm *ts;
|
||||
struct thermal_zone_device *tz;
|
||||
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 reset_control *reset;
|
||||
struct clk *clock_tsensor;
|
||||
struct clk *clock_soctherm;
|
||||
void __iomem *regs;
|
||||
struct thermal_zone_device **thermctl_tzs;
|
||||
void __iomem *clk_regs;
|
||||
void __iomem *ccroc_regs;
|
||||
|
||||
u32 *calib;
|
||||
struct thermal_zone_device **thermctl_tzs;
|
||||
struct tegra_soctherm_soc *soc;
|
||||
|
||||
struct soctherm_throt_cfg throt_cfgs[THROTTLE_SIZE];
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
thermtrip_program(struct device *dev, const struct tegra_tsensor_group *sg,
|
||||
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)
|
||||
{
|
||||
struct tegra_thermctl_zone *zone = data;
|
||||
struct thermal_zone_device *tz = zone->tz;
|
||||
struct tegra_soctherm *ts = zone->ts;
|
||||
const struct tegra_tsensor_group *sg = zone->sg;
|
||||
struct device *dev = zone->dev;
|
||||
enum thermal_trip_type type;
|
||||
@ -167,10 +367,29 @@ static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (type != THERMAL_TRIP_CRITICAL)
|
||||
return 0;
|
||||
if (type == THERMAL_TRIP_CRITICAL) {
|
||||
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 = {
|
||||
@ -237,15 +456,111 @@ static int thermtrip_program(struct device *dev,
|
||||
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
|
||||
* @dev: struct device * of the SOC_THERM instance
|
||||
*
|
||||
* Configure the SOC_THERM HW trip points, setting "THERMTRIP"
|
||||
* trip points , using "critical" type trip_temp from thermal
|
||||
* zone.
|
||||
* After they have been configured, THERMTRIP will take action
|
||||
* when the configured SoC thermal sensor group reaches a
|
||||
* "THROTTLE" trip points , using "critical" or "hot" type trip_temp
|
||||
* from thermal zone.
|
||||
* After they have been configured, THERMTRIP or THROTTLE will take
|
||||
* action when the configured SoC thermal sensor group reaches a
|
||||
* certain temperature.
|
||||
*
|
||||
* Return: 0 upon success, or a negative error code on failure.
|
||||
@ -254,19 +569,24 @@ static int thermtrip_program(struct device *dev,
|
||||
* THERMTRIP has been enabled successfully when a message similar to
|
||||
* this one appears on the serial console:
|
||||
* "thermtrip: will shut down when sensor group XXX reaches YYYYYY mC"
|
||||
* 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,
|
||||
const struct tegra_tsensor_group *sg,
|
||||
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;
|
||||
|
||||
ret = tz->ops->get_crit_temp(tz, &temperature);
|
||||
if (ret) {
|
||||
dev_warn(dev, "thermtrip: %s: missing critical temperature\n",
|
||||
sg->name);
|
||||
return ret;
|
||||
goto set_throttle;
|
||||
}
|
||||
|
||||
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",
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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_group **ttgs = ts->soc->ttgs;
|
||||
u32 r, state;
|
||||
int i;
|
||||
int i, level;
|
||||
|
||||
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);
|
||||
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);
|
||||
state = REG_GET_MASK(r, ttgs[0]->thermtrip_any_en_mask);
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -449,6 +907,326 @@ static int soctherm_clk_enable(struct platform_device *pdev, bool enable)
|
||||
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)
|
||||
{
|
||||
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(hotspot, tegra->regs + SENSOR_HOTSPOT_OFF);
|
||||
|
||||
/* Configure hw throttle */
|
||||
tegra_soctherm_throttle(&pdev->dev);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
if (IS_ERR(tegra->regs))
|
||||
if (IS_ERR(tegra->regs)) {
|
||||
dev_err(&pdev->dev, "can't get soctherm registers");
|
||||
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");
|
||||
if (IS_ERR(tegra->reset)) {
|
||||
@ -580,6 +1382,8 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
soctherm_init_hw_throt_cdev(pdev);
|
||||
|
||||
soctherm_init(pdev);
|
||||
|
||||
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->dev = &pdev->dev;
|
||||
zone->sg = soc->ttgs[i];
|
||||
zone->ts = tegra;
|
||||
|
||||
z = devm_thermal_zone_of_sensor_register(&pdev->dev,
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
@ -661,7 +1468,12 @@ static int __maybe_unused soctherm_resume(struct device *dev)
|
||||
struct thermal_zone_device *tz;
|
||||
|
||||
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;
|
||||
|
@ -15,6 +15,11 @@
|
||||
#ifndef __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_THERMA_MASK (0xffff << 16)
|
||||
#define SENSOR_CONFIG2_THERMA_SHIFT 16
|
||||
@ -65,6 +70,9 @@ struct tegra_tsensor_group {
|
||||
u32 thermtrip_enable_mask;
|
||||
u32 thermtrip_any_en_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 {
|
||||
@ -103,6 +111,8 @@ struct tegra_soctherm_soc {
|
||||
const unsigned int num_ttgs;
|
||||
const struct tegra_soctherm_fuse *tfuse;
|
||||
const int thresh_grain;
|
||||
const unsigned int bptt;
|
||||
const bool use_ccroc;
|
||||
};
|
||||
|
||||
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_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_BPTT 8
|
||||
|
||||
static const struct tegra_tsensor_configuration tegra124_tsensor_config = {
|
||||
.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_enable_mask = TEGRA124_THERMTRIP_CPU_EN_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 = {
|
||||
@ -66,6 +73,9 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_gpu = {
|
||||
.thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
|
||||
.thermtrip_enable_mask = TEGRA124_THERMTRIP_GPU_EN_MASK,
|
||||
.thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
|
||||
.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 = {
|
||||
@ -79,6 +89,9 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_pll = {
|
||||
.thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
|
||||
.thermtrip_enable_mask = TEGRA124_THERMTRIP_TSENSE_EN_MASK,
|
||||
.thermtrip_threshold_mask = TEGRA124_THERMTRIP_TSENSE_THRESH_MASK,
|
||||
.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 = {
|
||||
@ -94,6 +107,9 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_mem = {
|
||||
.thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
|
||||
.thermtrip_enable_mask = TEGRA124_THERMTRIP_MEM_EN_MASK,
|
||||
.thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
|
||||
.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[] = {
|
||||
@ -193,4 +209,6 @@ const struct tegra_soctherm_soc tegra124_soctherm = {
|
||||
.num_ttgs = ARRAY_SIZE(tegra124_tsensor_groups),
|
||||
.tfuse = &tegra124_soctherm_fuse,
|
||||
.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_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_BPTT 8
|
||||
|
||||
static const struct tegra_tsensor_configuration tegra132_tsensor_config = {
|
||||
.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_enable_mask = TEGRA132_THERMTRIP_CPU_EN_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 = {
|
||||
@ -66,6 +73,9 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_gpu = {
|
||||
.thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
|
||||
.thermtrip_enable_mask = TEGRA132_THERMTRIP_GPU_EN_MASK,
|
||||
.thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
|
||||
.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 = {
|
||||
@ -79,6 +89,9 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_pll = {
|
||||
.thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
|
||||
.thermtrip_enable_mask = TEGRA132_THERMTRIP_TSENSE_EN_MASK,
|
||||
.thermtrip_threshold_mask = TEGRA132_THERMTRIP_TSENSE_THRESH_MASK,
|
||||
.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 = {
|
||||
@ -94,6 +107,9 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_mem = {
|
||||
.thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
|
||||
.thermtrip_enable_mask = TEGRA132_THERMTRIP_MEM_EN_MASK,
|
||||
.thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
|
||||
.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[] = {
|
||||
@ -193,4 +209,6 @@ const struct tegra_soctherm_soc tegra132_soctherm = {
|
||||
.num_ttgs = ARRAY_SIZE(tegra132_tsensor_groups),
|
||||
.tfuse = &tegra132_soctherm_fuse,
|
||||
.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_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_BPTT 9
|
||||
|
||||
static const struct tegra_tsensor_configuration tegra210_tsensor_config = {
|
||||
.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_enable_mask = TEGRA210_THERMTRIP_CPU_EN_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 = {
|
||||
@ -67,6 +74,9 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_gpu = {
|
||||
.thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
|
||||
.thermtrip_enable_mask = TEGRA210_THERMTRIP_GPU_EN_MASK,
|
||||
.thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
|
||||
.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 = {
|
||||
@ -80,6 +90,9 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_pll = {
|
||||
.thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
|
||||
.thermtrip_enable_mask = TEGRA210_THERMTRIP_TSENSE_EN_MASK,
|
||||
.thermtrip_threshold_mask = TEGRA210_THERMTRIP_TSENSE_THRESH_MASK,
|
||||
.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 = {
|
||||
@ -95,6 +108,9 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_mem = {
|
||||
.thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
|
||||
.thermtrip_enable_mask = TEGRA210_THERMTRIP_MEM_EN_MASK,
|
||||
.thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
|
||||
.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[] = {
|
||||
@ -194,4 +210,6 @@ const struct tegra_soctherm_soc tegra210_soctherm = {
|
||||
.num_ttgs = ARRAY_SIZE(tegra210_tsensor_groups),
|
||||
.tfuse = &tegra210_soctherm_fuse,
|
||||
.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_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
|
||||
|
Loading…
Reference in New Issue
Block a user