Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal
Pull thermal SoC updates from Zhang Rui: "Thermal SoC management updates: - imx thermal driver now supports i.MX7 thermal sensor (Anson Huang) - exynos thermal driver dropped support for exynos 5440 (Krzysztof Kozlowski) - rcar_thermal now supports r8a77995 (Yoshihiro Kaneko) - rcar_gen3_thermal now supports r8a77965 (Niklas Söderlund) - qcom-spmi-temp-alarm now supports GEN2 PMIC peripherals (David Collins) - uniphier thermal now supports UniPhier PXs3 (Kunihiko Hayashi) - mediatek thermal now supports MT7622 SoC (Sean Wang) - considerable refactoring of exynos driver (Bartlomiej Zolnierkiewicz) - small fixes all over the place on different drivers" * 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal: (50 commits) thermal: qcom: tsens: Allow number of sensors to come from DT thermal: tegra: soctherm: add const to struct thermal_cooling_device_ops thermal: exynos: Reduce severity of too early temperature read thermal: imx: Switch to SPDX identifier thermal: qcom-spmi-temp-alarm: add support for GEN2 PMIC peripherals thermal: ti-soc-thermal: fix incorrect entry in omap5430_adc_to_temp[] thermal: rcar_thermal: add r8a77995 support dt-bindings: thermal: rcar-thermal: add R8A77995 support thermal: mediatek: use of_device_get_match_data() thermal: exynos: remove trip reporting to user-space thermal: exynos: remove unused defines for Exynos5433 thermal: exynos: cleanup code for enabling threshold interrupts thermal: exynos: check return values of ->get_trip_[temp, hyst] methods thermal: exynos: move trips setting to exynos_tmu_initialize() thermal: exynos: set trips in ascending order in exynos7_tmu_initialize() thermal: exynos: do not use trips structure directly in ->tmu_initialize thermal: exynos: add exynos*_tmu_set_[trip,hyst]() helpers thermal: exynos: move IRQs clearing to exynos_tmu_initialize() thermal: exynos: clear IRQs later in exynos4412_tmu_initialize() thermal: exynos: make ->tmu_initialize method void ...
This commit is contained in:
commit
19785cf93b
@ -12,7 +12,6 @@
|
||||
"samsung,exynos5420-tmu-ext-triminfo" for TMU channels 2, 3 and 4
|
||||
Exynos5420 (Must pass triminfo base and triminfo clock)
|
||||
"samsung,exynos5433-tmu"
|
||||
"samsung,exynos5440-tmu"
|
||||
"samsung,exynos7-tmu"
|
||||
- interrupt-parent : The phandle for the interrupt controller
|
||||
- reg : Address range of the thermal registers. For soc's which has multiple
|
||||
@ -68,18 +67,7 @@ Example 1):
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
|
||||
Example 2):
|
||||
|
||||
tmuctrl_0: tmuctrl@160118 {
|
||||
compatible = "samsung,exynos5440-tmu";
|
||||
reg = <0x160118 0x230>, <0x160368 0x10>;
|
||||
interrupts = <0 58 0>;
|
||||
clocks = <&clock 21>;
|
||||
clock-names = "tmu_apbif";
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
|
||||
Example 3): (In case of Exynos5420 "with misplaced TRIMINFO register")
|
||||
Example 2): (In case of Exynos5420 "with misplaced TRIMINFO register")
|
||||
tmu_cpu2: tmu@10068000 {
|
||||
compatible = "samsung,exynos5420-tmu-ext-triminfo";
|
||||
reg = <0x10068000 0x100>, <0x1006c000 0x4>;
|
||||
|
@ -1,8 +1,13 @@
|
||||
* Temperature Monitor (TEMPMON) on Freescale i.MX SoCs
|
||||
|
||||
Required properties:
|
||||
- compatible : "fsl,imx6q-tempmon" for i.MX6Q, "fsl,imx6sx-tempmon" for i.MX6SX.
|
||||
i.MX6SX has two more IRQs than i.MX6Q, one is IRQ_LOW and the other is IRQ_PANIC,
|
||||
- compatible : must be one of following:
|
||||
- "fsl,imx6q-tempmon" for i.MX6Q,
|
||||
- "fsl,imx6sx-tempmon" for i.MX6SX,
|
||||
- "fsl,imx7d-tempmon" for i.MX7S/D.
|
||||
- interrupts : the interrupt output of the controller:
|
||||
i.MX6Q has one IRQ which will be triggered when temperature is higher than high threshold,
|
||||
i.MX6SX and i.MX7S/D have two more IRQs than i.MX6Q, one is IRQ_LOW and the other is IRQ_PANIC,
|
||||
when temperature is below than low threshold, IRQ_LOW will be triggered, when temperature
|
||||
is higher than panic threshold, system will auto reboot by SRC module.
|
||||
- fsl,tempmon : phandle pointer to system controller that contains TEMPMON
|
||||
|
@ -12,6 +12,7 @@ Required properties:
|
||||
- "mediatek,mt8173-thermal" : For MT8173 family of SoCs
|
||||
- "mediatek,mt2701-thermal" : For MT2701 family of SoCs
|
||||
- "mediatek,mt2712-thermal" : For MT2712 family of SoCs
|
||||
- "mediatek,mt7622-thermal" : For MT7622 SoC
|
||||
- reg: Address range of the thermal controller
|
||||
- interrupts: IRQ for the thermal controller
|
||||
- clocks, clock-names: Clocks needed for the thermal controller. required
|
||||
|
@ -8,6 +8,7 @@ Required properties:
|
||||
|
||||
- reg: Address range of the thermal registers
|
||||
- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
|
||||
- #qcom,sensors: Number of sensors in tsens block
|
||||
- Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify
|
||||
nvmem cells
|
||||
|
||||
|
@ -9,6 +9,7 @@ Required properties:
|
||||
Examples with soctypes are:
|
||||
- "renesas,r8a7795-thermal" (R-Car H3)
|
||||
- "renesas,r8a7796-thermal" (R-Car M3-W)
|
||||
- "renesas,r8a77965-thermal" (R-Car M3-N)
|
||||
- reg : Address ranges of the thermal registers. Each sensor
|
||||
needs one address range. Sorting must be done in
|
||||
increasing order according to datasheet, i.e.
|
||||
@ -18,7 +19,7 @@ Required properties:
|
||||
|
||||
Optional properties:
|
||||
|
||||
- interrupts : interrupts routed to the TSC (3 for H3 and M3-W)
|
||||
- interrupts : interrupts routed to the TSC (3 for H3, M3-W and M3-N)
|
||||
- power-domain : Must contain a reference to the power domain. This
|
||||
property is mandatory if the thermal sensor instance
|
||||
is part of a controllable power domain.
|
||||
|
@ -3,7 +3,8 @@
|
||||
Required properties:
|
||||
- compatible : "renesas,thermal-<soctype>",
|
||||
"renesas,rcar-gen2-thermal" (with thermal-zone) or
|
||||
"renesas,rcar-thermal" (without thermal-zone) as fallback.
|
||||
"renesas,rcar-thermal" (without thermal-zone) as
|
||||
fallback except R-Car D3.
|
||||
Examples with soctypes are:
|
||||
- "renesas,thermal-r8a73a4" (R-Mobile APE6)
|
||||
- "renesas,thermal-r8a7743" (RZ/G1M)
|
||||
@ -12,13 +13,15 @@ Required properties:
|
||||
- "renesas,thermal-r8a7791" (R-Car M2-W)
|
||||
- "renesas,thermal-r8a7792" (R-Car V2H)
|
||||
- "renesas,thermal-r8a7793" (R-Car M2-N)
|
||||
- "renesas,thermal-r8a77995" (R-Car D3)
|
||||
- reg : Address range of the thermal registers.
|
||||
The 1st reg will be recognized as common register
|
||||
if it has "interrupts".
|
||||
|
||||
Option properties:
|
||||
|
||||
- interrupts : use interrupt
|
||||
- interrupts : If present should contain 3 interrupts for
|
||||
R-Car D3 or 1 interrupt otherwise.
|
||||
|
||||
Example (non interrupt support):
|
||||
|
||||
|
@ -8,6 +8,7 @@ Required properties:
|
||||
- compatible :
|
||||
- "socionext,uniphier-pxs2-thermal" : For UniPhier PXs2 SoC
|
||||
- "socionext,uniphier-ld20-thermal" : For UniPhier LD20 SoC
|
||||
- "socionext,uniphier-pxs3-thermal" : For UniPhier PXs3 SoC
|
||||
- interrupts : IRQ for the temperature alarm
|
||||
- #thermal-sensor-cells : Should be 0. See ./thermal.txt for details.
|
||||
|
||||
|
@ -1,11 +1,6 @@
|
||||
/*
|
||||
* Copyright 2013 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Copyright 2013 Freescale Semiconductor, Inc.
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/cpufreq.h>
|
||||
@ -31,35 +26,57 @@
|
||||
#define REG_CLR 0x8
|
||||
#define REG_TOG 0xc
|
||||
|
||||
#define MISC0 0x0150
|
||||
#define MISC0_REFTOP_SELBIASOFF (1 << 3)
|
||||
#define MISC1 0x0160
|
||||
#define MISC1_IRQ_TEMPHIGH (1 << 29)
|
||||
/* i.MX6 specific */
|
||||
#define IMX6_MISC0 0x0150
|
||||
#define IMX6_MISC0_REFTOP_SELBIASOFF (1 << 3)
|
||||
#define IMX6_MISC1 0x0160
|
||||
#define IMX6_MISC1_IRQ_TEMPHIGH (1 << 29)
|
||||
/* Below LOW and PANIC bits are only for TEMPMON_IMX6SX */
|
||||
#define MISC1_IRQ_TEMPLOW (1 << 28)
|
||||
#define MISC1_IRQ_TEMPPANIC (1 << 27)
|
||||
#define IMX6_MISC1_IRQ_TEMPLOW (1 << 28)
|
||||
#define IMX6_MISC1_IRQ_TEMPPANIC (1 << 27)
|
||||
|
||||
#define TEMPSENSE0 0x0180
|
||||
#define TEMPSENSE0_ALARM_VALUE_SHIFT 20
|
||||
#define TEMPSENSE0_ALARM_VALUE_MASK (0xfff << TEMPSENSE0_ALARM_VALUE_SHIFT)
|
||||
#define TEMPSENSE0_TEMP_CNT_SHIFT 8
|
||||
#define TEMPSENSE0_TEMP_CNT_MASK (0xfff << TEMPSENSE0_TEMP_CNT_SHIFT)
|
||||
#define TEMPSENSE0_FINISHED (1 << 2)
|
||||
#define TEMPSENSE0_MEASURE_TEMP (1 << 1)
|
||||
#define TEMPSENSE0_POWER_DOWN (1 << 0)
|
||||
#define IMX6_TEMPSENSE0 0x0180
|
||||
#define IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT 20
|
||||
#define IMX6_TEMPSENSE0_ALARM_VALUE_MASK (0xfff << 20)
|
||||
#define IMX6_TEMPSENSE0_TEMP_CNT_SHIFT 8
|
||||
#define IMX6_TEMPSENSE0_TEMP_CNT_MASK (0xfff << 8)
|
||||
#define IMX6_TEMPSENSE0_FINISHED (1 << 2)
|
||||
#define IMX6_TEMPSENSE0_MEASURE_TEMP (1 << 1)
|
||||
#define IMX6_TEMPSENSE0_POWER_DOWN (1 << 0)
|
||||
|
||||
#define TEMPSENSE1 0x0190
|
||||
#define TEMPSENSE1_MEASURE_FREQ 0xffff
|
||||
/* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */
|
||||
#define TEMPSENSE2 0x0290
|
||||
#define TEMPSENSE2_LOW_VALUE_SHIFT 0
|
||||
#define TEMPSENSE2_LOW_VALUE_MASK 0xfff
|
||||
#define TEMPSENSE2_PANIC_VALUE_SHIFT 16
|
||||
#define TEMPSENSE2_PANIC_VALUE_MASK 0xfff0000
|
||||
#define IMX6_TEMPSENSE1 0x0190
|
||||
#define IMX6_TEMPSENSE1_MEASURE_FREQ 0xffff
|
||||
#define IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT 0
|
||||
|
||||
#define OCOTP_MEM0 0x0480
|
||||
#define OCOTP_ANA1 0x04e0
|
||||
|
||||
/* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */
|
||||
#define IMX6_TEMPSENSE2 0x0290
|
||||
#define IMX6_TEMPSENSE2_LOW_VALUE_SHIFT 0
|
||||
#define IMX6_TEMPSENSE2_LOW_VALUE_MASK 0xfff
|
||||
#define IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT 16
|
||||
#define IMX6_TEMPSENSE2_PANIC_VALUE_MASK 0xfff0000
|
||||
|
||||
/* i.MX7 specific */
|
||||
#define IMX7_ANADIG_DIGPROG 0x800
|
||||
#define IMX7_TEMPSENSE0 0x300
|
||||
#define IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT 18
|
||||
#define IMX7_TEMPSENSE0_PANIC_ALARM_MASK (0x1ff << 18)
|
||||
#define IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT 9
|
||||
#define IMX7_TEMPSENSE0_HIGH_ALARM_MASK (0x1ff << 9)
|
||||
#define IMX7_TEMPSENSE0_LOW_ALARM_SHIFT 0
|
||||
#define IMX7_TEMPSENSE0_LOW_ALARM_MASK 0x1ff
|
||||
|
||||
#define IMX7_TEMPSENSE1 0x310
|
||||
#define IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT 16
|
||||
#define IMX7_TEMPSENSE1_MEASURE_FREQ_MASK (0xffff << 16)
|
||||
#define IMX7_TEMPSENSE1_FINISHED (1 << 11)
|
||||
#define IMX7_TEMPSENSE1_MEASURE_TEMP (1 << 10)
|
||||
#define IMX7_TEMPSENSE1_POWER_DOWN (1 << 9)
|
||||
#define IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT 0
|
||||
#define IMX7_TEMPSENSE1_TEMP_VALUE_MASK 0x1ff
|
||||
|
||||
/* The driver supports 1 passive trip point and 1 critical trip point */
|
||||
enum imx_thermal_trip {
|
||||
IMX_TRIP_PASSIVE,
|
||||
@ -72,17 +89,114 @@ enum imx_thermal_trip {
|
||||
|
||||
#define TEMPMON_IMX6Q 1
|
||||
#define TEMPMON_IMX6SX 2
|
||||
#define TEMPMON_IMX7D 3
|
||||
|
||||
struct thermal_soc_data {
|
||||
u32 version;
|
||||
|
||||
u32 sensor_ctrl;
|
||||
u32 power_down_mask;
|
||||
u32 measure_temp_mask;
|
||||
|
||||
u32 measure_freq_ctrl;
|
||||
u32 measure_freq_mask;
|
||||
u32 measure_freq_shift;
|
||||
|
||||
u32 temp_data;
|
||||
u32 temp_value_mask;
|
||||
u32 temp_value_shift;
|
||||
u32 temp_valid_mask;
|
||||
|
||||
u32 panic_alarm_ctrl;
|
||||
u32 panic_alarm_mask;
|
||||
u32 panic_alarm_shift;
|
||||
|
||||
u32 high_alarm_ctrl;
|
||||
u32 high_alarm_mask;
|
||||
u32 high_alarm_shift;
|
||||
|
||||
u32 low_alarm_ctrl;
|
||||
u32 low_alarm_mask;
|
||||
u32 low_alarm_shift;
|
||||
};
|
||||
|
||||
static struct thermal_soc_data thermal_imx6q_data = {
|
||||
.version = TEMPMON_IMX6Q,
|
||||
|
||||
.sensor_ctrl = IMX6_TEMPSENSE0,
|
||||
.power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,
|
||||
.measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,
|
||||
|
||||
.measure_freq_ctrl = IMX6_TEMPSENSE1,
|
||||
.measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,
|
||||
.measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,
|
||||
|
||||
.temp_data = IMX6_TEMPSENSE0,
|
||||
.temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,
|
||||
.temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,
|
||||
.temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,
|
||||
|
||||
.high_alarm_ctrl = IMX6_TEMPSENSE0,
|
||||
.high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,
|
||||
.high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,
|
||||
};
|
||||
|
||||
static struct thermal_soc_data thermal_imx6sx_data = {
|
||||
.version = TEMPMON_IMX6SX,
|
||||
|
||||
.sensor_ctrl = IMX6_TEMPSENSE0,
|
||||
.power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,
|
||||
.measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,
|
||||
|
||||
.measure_freq_ctrl = IMX6_TEMPSENSE1,
|
||||
.measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,
|
||||
.measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,
|
||||
|
||||
.temp_data = IMX6_TEMPSENSE0,
|
||||
.temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,
|
||||
.temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,
|
||||
.temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,
|
||||
|
||||
.high_alarm_ctrl = IMX6_TEMPSENSE0,
|
||||
.high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,
|
||||
.high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,
|
||||
|
||||
.panic_alarm_ctrl = IMX6_TEMPSENSE2,
|
||||
.panic_alarm_mask = IMX6_TEMPSENSE2_PANIC_VALUE_MASK,
|
||||
.panic_alarm_shift = IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT,
|
||||
|
||||
.low_alarm_ctrl = IMX6_TEMPSENSE2,
|
||||
.low_alarm_mask = IMX6_TEMPSENSE2_LOW_VALUE_MASK,
|
||||
.low_alarm_shift = IMX6_TEMPSENSE2_LOW_VALUE_SHIFT,
|
||||
};
|
||||
|
||||
static struct thermal_soc_data thermal_imx7d_data = {
|
||||
.version = TEMPMON_IMX7D,
|
||||
|
||||
.sensor_ctrl = IMX7_TEMPSENSE1,
|
||||
.power_down_mask = IMX7_TEMPSENSE1_POWER_DOWN,
|
||||
.measure_temp_mask = IMX7_TEMPSENSE1_MEASURE_TEMP,
|
||||
|
||||
.measure_freq_ctrl = IMX7_TEMPSENSE1,
|
||||
.measure_freq_shift = IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT,
|
||||
.measure_freq_mask = IMX7_TEMPSENSE1_MEASURE_FREQ_MASK,
|
||||
|
||||
.temp_data = IMX7_TEMPSENSE1,
|
||||
.temp_value_mask = IMX7_TEMPSENSE1_TEMP_VALUE_MASK,
|
||||
.temp_value_shift = IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT,
|
||||
.temp_valid_mask = IMX7_TEMPSENSE1_FINISHED,
|
||||
|
||||
.panic_alarm_ctrl = IMX7_TEMPSENSE1,
|
||||
.panic_alarm_mask = IMX7_TEMPSENSE0_PANIC_ALARM_MASK,
|
||||
.panic_alarm_shift = IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT,
|
||||
|
||||
.high_alarm_ctrl = IMX7_TEMPSENSE0,
|
||||
.high_alarm_mask = IMX7_TEMPSENSE0_HIGH_ALARM_MASK,
|
||||
.high_alarm_shift = IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT,
|
||||
|
||||
.low_alarm_ctrl = IMX7_TEMPSENSE0,
|
||||
.low_alarm_mask = IMX7_TEMPSENSE0_LOW_ALARM_MASK,
|
||||
.low_alarm_shift = IMX7_TEMPSENSE0_LOW_ALARM_SHIFT,
|
||||
};
|
||||
|
||||
struct imx_thermal_data {
|
||||
@ -107,31 +221,42 @@ struct imx_thermal_data {
|
||||
static void imx_set_panic_temp(struct imx_thermal_data *data,
|
||||
int panic_temp)
|
||||
{
|
||||
const struct thermal_soc_data *soc_data = data->socdata;
|
||||
struct regmap *map = data->tempmon;
|
||||
int critical_value;
|
||||
|
||||
critical_value = (data->c2 - panic_temp) / data->c1;
|
||||
regmap_write(map, TEMPSENSE2 + REG_CLR, TEMPSENSE2_PANIC_VALUE_MASK);
|
||||
regmap_write(map, TEMPSENSE2 + REG_SET, critical_value <<
|
||||
TEMPSENSE2_PANIC_VALUE_SHIFT);
|
||||
|
||||
regmap_write(map, soc_data->panic_alarm_ctrl + REG_CLR,
|
||||
soc_data->panic_alarm_mask);
|
||||
regmap_write(map, soc_data->panic_alarm_ctrl + REG_SET,
|
||||
critical_value << soc_data->panic_alarm_shift);
|
||||
}
|
||||
|
||||
static void imx_set_alarm_temp(struct imx_thermal_data *data,
|
||||
int alarm_temp)
|
||||
{
|
||||
struct regmap *map = data->tempmon;
|
||||
const struct thermal_soc_data *soc_data = data->socdata;
|
||||
int alarm_value;
|
||||
|
||||
data->alarm_temp = alarm_temp;
|
||||
alarm_value = (data->c2 - alarm_temp) / data->c1;
|
||||
regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK);
|
||||
regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value <<
|
||||
TEMPSENSE0_ALARM_VALUE_SHIFT);
|
||||
|
||||
if (data->socdata->version == TEMPMON_IMX7D)
|
||||
alarm_value = alarm_temp / 1000 + data->c1 - 25;
|
||||
else
|
||||
alarm_value = (data->c2 - alarm_temp) / data->c1;
|
||||
|
||||
regmap_write(map, soc_data->high_alarm_ctrl + REG_CLR,
|
||||
soc_data->high_alarm_mask);
|
||||
regmap_write(map, soc_data->high_alarm_ctrl + REG_SET,
|
||||
alarm_value << soc_data->high_alarm_shift);
|
||||
}
|
||||
|
||||
static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
|
||||
{
|
||||
struct imx_thermal_data *data = tz->devdata;
|
||||
const struct thermal_soc_data *soc_data = data->socdata;
|
||||
struct regmap *map = data->tempmon;
|
||||
unsigned int n_meas;
|
||||
bool wait;
|
||||
@ -139,16 +264,18 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
|
||||
|
||||
if (data->mode == THERMAL_DEVICE_ENABLED) {
|
||||
/* Check if a measurement is currently in progress */
|
||||
regmap_read(map, TEMPSENSE0, &val);
|
||||
wait = !(val & TEMPSENSE0_FINISHED);
|
||||
regmap_read(map, soc_data->temp_data, &val);
|
||||
wait = !(val & soc_data->temp_valid_mask);
|
||||
} else {
|
||||
/*
|
||||
* Every time we measure the temperature, we will power on the
|
||||
* temperature sensor, enable measurements, take a reading,
|
||||
* disable measurements, power off the temperature sensor.
|
||||
*/
|
||||
regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
|
||||
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
|
||||
soc_data->power_down_mask);
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
|
||||
soc_data->measure_temp_mask);
|
||||
|
||||
wait = true;
|
||||
}
|
||||
@ -160,22 +287,28 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
|
||||
if (wait)
|
||||
usleep_range(20, 50);
|
||||
|
||||
regmap_read(map, TEMPSENSE0, &val);
|
||||
regmap_read(map, soc_data->temp_data, &val);
|
||||
|
||||
if (data->mode != THERMAL_DEVICE_ENABLED) {
|
||||
regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
|
||||
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
|
||||
soc_data->measure_temp_mask);
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
|
||||
soc_data->power_down_mask);
|
||||
}
|
||||
|
||||
if ((val & TEMPSENSE0_FINISHED) == 0) {
|
||||
if ((val & soc_data->temp_valid_mask) == 0) {
|
||||
dev_dbg(&tz->device, "temp measurement never finished\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT;
|
||||
n_meas = (val & soc_data->temp_value_mask)
|
||||
>> soc_data->temp_value_shift;
|
||||
|
||||
/* See imx_init_calib() for formula derivation */
|
||||
*temp = data->c2 - n_meas * data->c1;
|
||||
if (data->socdata->version == TEMPMON_IMX7D)
|
||||
*temp = (n_meas - data->c1 + 25) * 1000;
|
||||
else
|
||||
*temp = data->c2 - n_meas * data->c1;
|
||||
|
||||
/* Update alarm value to next higher trip point for TEMPMON_IMX6Q */
|
||||
if (data->socdata->version == TEMPMON_IMX6Q) {
|
||||
@ -219,21 +352,26 @@ static int imx_set_mode(struct thermal_zone_device *tz,
|
||||
{
|
||||
struct imx_thermal_data *data = tz->devdata;
|
||||
struct regmap *map = data->tempmon;
|
||||
const struct thermal_soc_data *soc_data = data->socdata;
|
||||
|
||||
if (mode == THERMAL_DEVICE_ENABLED) {
|
||||
tz->polling_delay = IMX_POLLING_DELAY;
|
||||
tz->passive_delay = IMX_PASSIVE_DELAY;
|
||||
|
||||
regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
|
||||
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
|
||||
soc_data->power_down_mask);
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
|
||||
soc_data->measure_temp_mask);
|
||||
|
||||
if (!data->irq_enabled) {
|
||||
data->irq_enabled = true;
|
||||
enable_irq(data->irq);
|
||||
}
|
||||
} else {
|
||||
regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
|
||||
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
|
||||
soc_data->measure_temp_mask);
|
||||
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
|
||||
soc_data->power_down_mask);
|
||||
|
||||
tz->polling_delay = 0;
|
||||
tz->passive_delay = 0;
|
||||
@ -354,6 +492,15 @@ static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* On i.MX7D, we only use the calibration data at 25C to get the temp,
|
||||
* Tmeas = ( Nmeas - n1) + 25; n1 is the fuse value for 25C.
|
||||
*/
|
||||
if (data->socdata->version == TEMPMON_IMX7D) {
|
||||
data->c1 = (ocotp_ana1 >> 9) & 0x1ff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The sensor is calibrated at 25 °C (aka T1) and the value measured
|
||||
* (aka N1) at this temperature is provided in bits [31:20] in the
|
||||
@ -492,6 +639,7 @@ static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
|
||||
static const struct of_device_id of_imx_thermal_match[] = {
|
||||
{ .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, },
|
||||
{ .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, },
|
||||
{ .compatible = "fsl,imx7d-tempmon", .data = &thermal_imx7d_data, },
|
||||
{ /* end */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
|
||||
@ -523,14 +671,15 @@ static int imx_thermal_probe(struct platform_device *pdev)
|
||||
|
||||
/* make sure the IRQ flag is clear before enabling irq on i.MX6SX */
|
||||
if (data->socdata->version == TEMPMON_IMX6SX) {
|
||||
regmap_write(map, MISC1 + REG_CLR, MISC1_IRQ_TEMPHIGH |
|
||||
MISC1_IRQ_TEMPLOW | MISC1_IRQ_TEMPPANIC);
|
||||
regmap_write(map, IMX6_MISC1 + REG_CLR,
|
||||
IMX6_MISC1_IRQ_TEMPHIGH | IMX6_MISC1_IRQ_TEMPLOW
|
||||
| IMX6_MISC1_IRQ_TEMPPANIC);
|
||||
/*
|
||||
* reset value of LOW ALARM is incorrect, set it to lowest
|
||||
* value to avoid false trigger of low alarm.
|
||||
*/
|
||||
regmap_write(map, TEMPSENSE2 + REG_SET,
|
||||
TEMPSENSE2_LOW_VALUE_MASK);
|
||||
regmap_write(map, data->socdata->low_alarm_ctrl + REG_SET,
|
||||
data->socdata->low_alarm_mask);
|
||||
}
|
||||
|
||||
data->irq = platform_get_irq(pdev, 0);
|
||||
@ -557,11 +706,17 @@ static int imx_thermal_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Make sure sensor is in known good state for measurements */
|
||||
regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
|
||||
regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
|
||||
regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
|
||||
regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF);
|
||||
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
|
||||
regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
|
||||
data->socdata->power_down_mask);
|
||||
regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
|
||||
data->socdata->measure_temp_mask);
|
||||
regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
|
||||
data->socdata->measure_freq_mask);
|
||||
if (data->socdata->version != TEMPMON_IMX7D)
|
||||
regmap_write(map, IMX6_MISC0 + REG_SET,
|
||||
IMX6_MISC0_REFTOP_SELBIASOFF);
|
||||
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
|
||||
data->socdata->power_down_mask);
|
||||
|
||||
data->policy = cpufreq_cpu_get(0);
|
||||
if (!data->policy) {
|
||||
@ -626,16 +781,20 @@ static int imx_thermal_probe(struct platform_device *pdev)
|
||||
data->temp_passive / 1000);
|
||||
|
||||
/* Enable measurements at ~ 10 Hz */
|
||||
regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
|
||||
regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
|
||||
data->socdata->measure_freq_mask);
|
||||
measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
|
||||
regmap_write(map, TEMPSENSE1 + REG_SET, measure_freq);
|
||||
regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET,
|
||||
measure_freq << data->socdata->measure_freq_shift);
|
||||
imx_set_alarm_temp(data, data->temp_passive);
|
||||
|
||||
if (data->socdata->version == TEMPMON_IMX6SX)
|
||||
imx_set_panic_temp(data, data->temp_critical);
|
||||
|
||||
regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
|
||||
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
|
||||
regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
|
||||
data->socdata->power_down_mask);
|
||||
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
|
||||
data->socdata->measure_temp_mask);
|
||||
|
||||
data->irq_enabled = true;
|
||||
data->mode = THERMAL_DEVICE_ENABLED;
|
||||
@ -661,7 +820,8 @@ static int imx_thermal_remove(struct platform_device *pdev)
|
||||
struct regmap *map = data->tempmon;
|
||||
|
||||
/* Disable measurements */
|
||||
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
|
||||
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
|
||||
data->socdata->power_down_mask);
|
||||
if (!IS_ERR(data->thermal_clk))
|
||||
clk_disable_unprepare(data->thermal_clk);
|
||||
|
||||
@ -684,8 +844,10 @@ static int imx_thermal_suspend(struct device *dev)
|
||||
* temperature will be read as the thermal sensor is powered
|
||||
* down.
|
||||
*/
|
||||
regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
|
||||
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
|
||||
regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
|
||||
data->socdata->measure_temp_mask);
|
||||
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
|
||||
data->socdata->power_down_mask);
|
||||
data->mode = THERMAL_DEVICE_DISABLED;
|
||||
clk_disable_unprepare(data->thermal_clk);
|
||||
|
||||
@ -702,8 +864,10 @@ static int imx_thermal_resume(struct device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Enabled thermal sensor after resume */
|
||||
regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
|
||||
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
|
||||
regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
|
||||
data->socdata->power_down_mask);
|
||||
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
|
||||
data->socdata->measure_temp_mask);
|
||||
data->mode = THERMAL_DEVICE_ENABLED;
|
||||
|
||||
return 0;
|
||||
|
@ -153,6 +153,12 @@
|
||||
/* The number of sensing points per bank */
|
||||
#define MT2712_NUM_SENSORS_PER_ZONE 4
|
||||
|
||||
#define MT7622_TEMP_AUXADC_CHANNEL 11
|
||||
#define MT7622_NUM_SENSORS 1
|
||||
#define MT7622_NUM_ZONES 1
|
||||
#define MT7622_NUM_SENSORS_PER_ZONE 1
|
||||
#define MT7622_TS1 0
|
||||
|
||||
struct mtk_thermal;
|
||||
|
||||
struct thermal_bank_cfg {
|
||||
@ -242,6 +248,12 @@ static const int mt2712_adcpnp[MT2712_NUM_SENSORS_PER_ZONE] = {
|
||||
|
||||
static const int mt2712_mux_values[MT2712_NUM_SENSORS] = { 0, 1, 2, 3 };
|
||||
|
||||
/* MT7622 thermal sensor data */
|
||||
static const int mt7622_bank_data[MT7622_NUM_SENSORS] = { MT7622_TS1, };
|
||||
static const int mt7622_msr[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, };
|
||||
static const int mt7622_adcpnp[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, };
|
||||
static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, };
|
||||
|
||||
/**
|
||||
* The MT8173 thermal controller has four banks. Each bank can read up to
|
||||
* four temperature sensors simultaneously. The MT8173 has a total of 5
|
||||
@ -329,6 +341,25 @@ static const struct mtk_thermal_data mt2712_thermal_data = {
|
||||
.sensor_mux_values = mt2712_mux_values,
|
||||
};
|
||||
|
||||
/*
|
||||
* MT7622 have only one sensing point which uses AUXADC Channel 11 for raw data
|
||||
* access.
|
||||
*/
|
||||
static const struct mtk_thermal_data mt7622_thermal_data = {
|
||||
.auxadc_channel = MT7622_TEMP_AUXADC_CHANNEL,
|
||||
.num_banks = MT7622_NUM_ZONES,
|
||||
.num_sensors = MT7622_NUM_SENSORS,
|
||||
.bank_data = {
|
||||
{
|
||||
.num_sensors = 1,
|
||||
.sensors = mt7622_bank_data,
|
||||
},
|
||||
},
|
||||
.msr = mt7622_msr,
|
||||
.adcpnp = mt7622_adcpnp,
|
||||
.sensor_mux_values = mt7622_mux_values,
|
||||
};
|
||||
|
||||
/**
|
||||
* raw_to_mcelsius - convert a raw ADC value to mcelsius
|
||||
* @mt: The thermal controller
|
||||
@ -631,6 +662,10 @@ static const struct of_device_id mtk_thermal_of_match[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt2712-thermal",
|
||||
.data = (void *)&mt2712_thermal_data,
|
||||
},
|
||||
{
|
||||
.compatible = "mediatek,mt7622-thermal",
|
||||
.data = (void *)&mt7622_thermal_data,
|
||||
}, {
|
||||
},
|
||||
};
|
||||
@ -642,7 +677,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
|
||||
struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
|
||||
struct mtk_thermal *mt;
|
||||
struct resource *res;
|
||||
const struct of_device_id *of_id;
|
||||
u64 auxadc_phys_base, apmixed_phys_base;
|
||||
struct thermal_zone_device *tzdev;
|
||||
|
||||
@ -650,9 +684,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
|
||||
if (!mt)
|
||||
return -ENOMEM;
|
||||
|
||||
of_id = of_match_device(mtk_thermal_of_match, &pdev->dev);
|
||||
if (of_id)
|
||||
mt->conf = (const struct mtk_thermal_data *)of_id->data;
|
||||
mt->conf = of_device_get_match_data(&pdev->dev);
|
||||
|
||||
mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm");
|
||||
if (IS_ERR(mt->clk_peri_therm))
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2011-2015, 2017, The Linux Foundation. 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 and
|
||||
@ -11,6 +11,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/iio/consumer.h>
|
||||
@ -29,13 +30,17 @@
|
||||
#define QPNP_TM_REG_ALARM_CTRL 0x46
|
||||
|
||||
#define QPNP_TM_TYPE 0x09
|
||||
#define QPNP_TM_SUBTYPE 0x08
|
||||
#define QPNP_TM_SUBTYPE_GEN1 0x08
|
||||
#define QPNP_TM_SUBTYPE_GEN2 0x09
|
||||
|
||||
#define STATUS_STAGE_MASK 0x03
|
||||
#define STATUS_GEN1_STAGE_MASK GENMASK(1, 0)
|
||||
#define STATUS_GEN2_STATE_MASK GENMASK(6, 4)
|
||||
#define STATUS_GEN2_STATE_SHIFT 4
|
||||
|
||||
#define SHUTDOWN_CTRL1_THRESHOLD_MASK 0x03
|
||||
#define SHUTDOWN_CTRL1_OVERRIDE_MASK GENMASK(7, 6)
|
||||
#define SHUTDOWN_CTRL1_THRESHOLD_MASK GENMASK(1, 0)
|
||||
|
||||
#define ALARM_CTRL_FORCE_ENABLE 0x80
|
||||
#define ALARM_CTRL_FORCE_ENABLE BIT(7)
|
||||
|
||||
/*
|
||||
* Trip point values based on threshold control
|
||||
@ -58,6 +63,7 @@
|
||||
struct qpnp_tm_chip {
|
||||
struct regmap *map;
|
||||
struct thermal_zone_device *tz_dev;
|
||||
unsigned int subtype;
|
||||
long temp;
|
||||
unsigned int thresh;
|
||||
unsigned int stage;
|
||||
@ -66,6 +72,9 @@ struct qpnp_tm_chip {
|
||||
struct iio_channel *adc;
|
||||
};
|
||||
|
||||
/* This array maps from GEN2 alarm state to GEN1 alarm stage */
|
||||
static const unsigned int alarm_state_map[8] = {0, 1, 1, 2, 2, 3, 3, 3};
|
||||
|
||||
static int qpnp_tm_read(struct qpnp_tm_chip *chip, u16 addr, u8 *data)
|
||||
{
|
||||
unsigned int val;
|
||||
@ -84,13 +93,14 @@ static int qpnp_tm_write(struct qpnp_tm_chip *chip, u16 addr, u8 data)
|
||||
return regmap_write(chip->map, chip->base + addr, data);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function updates the internal temp value based on the
|
||||
* current thermal stage and threshold as well as the previous stage
|
||||
/**
|
||||
* qpnp_tm_get_temp_stage() - return over-temperature stage
|
||||
* @chip: Pointer to the qpnp_tm chip
|
||||
*
|
||||
* Return: stage (GEN1) or state (GEN2) on success, or errno on failure.
|
||||
*/
|
||||
static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip)
|
||||
static int qpnp_tm_get_temp_stage(struct qpnp_tm_chip *chip)
|
||||
{
|
||||
unsigned int stage;
|
||||
int ret;
|
||||
u8 reg = 0;
|
||||
|
||||
@ -98,16 +108,44 @@ static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
stage = reg & STATUS_STAGE_MASK;
|
||||
if (chip->subtype == QPNP_TM_SUBTYPE_GEN1)
|
||||
ret = reg & STATUS_GEN1_STAGE_MASK;
|
||||
else
|
||||
ret = (reg & STATUS_GEN2_STATE_MASK) >> STATUS_GEN2_STATE_SHIFT;
|
||||
|
||||
if (stage > chip->stage) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function updates the internal temp value based on the
|
||||
* current thermal stage and threshold as well as the previous stage
|
||||
*/
|
||||
static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip)
|
||||
{
|
||||
unsigned int stage, stage_new, stage_old;
|
||||
int ret;
|
||||
|
||||
ret = qpnp_tm_get_temp_stage(chip);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
stage = ret;
|
||||
|
||||
if (chip->subtype == QPNP_TM_SUBTYPE_GEN1) {
|
||||
stage_new = stage;
|
||||
stage_old = chip->stage;
|
||||
} else {
|
||||
stage_new = alarm_state_map[stage];
|
||||
stage_old = alarm_state_map[chip->stage];
|
||||
}
|
||||
|
||||
if (stage_new > stage_old) {
|
||||
/* increasing stage, use lower bound */
|
||||
chip->temp = (stage - 1) * TEMP_STAGE_STEP +
|
||||
chip->temp = (stage_new - 1) * TEMP_STAGE_STEP +
|
||||
chip->thresh * TEMP_THRESH_STEP +
|
||||
TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
|
||||
} else if (stage < chip->stage) {
|
||||
} else if (stage_new < stage_old) {
|
||||
/* decreasing stage, use upper bound */
|
||||
chip->temp = stage * TEMP_STAGE_STEP +
|
||||
chip->temp = stage_new * TEMP_STAGE_STEP +
|
||||
chip->thresh * TEMP_THRESH_STEP -
|
||||
TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
|
||||
}
|
||||
@ -162,28 +200,37 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data)
|
||||
*/
|
||||
static int qpnp_tm_init(struct qpnp_tm_chip *chip)
|
||||
{
|
||||
unsigned int stage;
|
||||
int ret;
|
||||
u8 reg;
|
||||
u8 reg = 0;
|
||||
|
||||
chip->thresh = THRESH_MIN;
|
||||
chip->temp = DEFAULT_TEMP;
|
||||
|
||||
ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, ®);
|
||||
ret = qpnp_tm_read(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
chip->stage = reg & STATUS_STAGE_MASK;
|
||||
chip->thresh = reg & SHUTDOWN_CTRL1_THRESHOLD_MASK;
|
||||
chip->temp = DEFAULT_TEMP;
|
||||
|
||||
if (chip->stage)
|
||||
ret = qpnp_tm_get_temp_stage(chip);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
chip->stage = ret;
|
||||
|
||||
stage = chip->subtype == QPNP_TM_SUBTYPE_GEN1
|
||||
? chip->stage : alarm_state_map[chip->stage];
|
||||
|
||||
if (stage)
|
||||
chip->temp = chip->thresh * TEMP_THRESH_STEP +
|
||||
(chip->stage - 1) * TEMP_STAGE_STEP +
|
||||
(stage - 1) * TEMP_STAGE_STEP +
|
||||
TEMP_THRESH_MIN;
|
||||
|
||||
/*
|
||||
* Set threshold and disable software override of stage 2 and 3
|
||||
* shutdowns.
|
||||
*/
|
||||
reg = chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK;
|
||||
chip->thresh = THRESH_MIN;
|
||||
reg &= ~(SHUTDOWN_CTRL1_OVERRIDE_MASK | SHUTDOWN_CTRL1_THRESHOLD_MASK);
|
||||
reg |= chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK;
|
||||
ret = qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -246,12 +293,15 @@ static int qpnp_tm_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (type != QPNP_TM_TYPE || subtype != QPNP_TM_SUBTYPE) {
|
||||
if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1
|
||||
&& subtype != QPNP_TM_SUBTYPE_GEN2)) {
|
||||
dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n",
|
||||
type, subtype);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
chip->subtype = subtype;
|
||||
|
||||
ret = qpnp_tm_init(chip);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "init failed\n");
|
||||
|
@ -115,6 +115,7 @@ static int tsens_probe(struct platform_device *pdev)
|
||||
struct tsens_device *tmdev;
|
||||
const struct tsens_data *data;
|
||||
const struct of_device_id *id;
|
||||
u32 num_sensors;
|
||||
|
||||
if (pdev->dev.of_node)
|
||||
dev = &pdev->dev;
|
||||
@ -129,19 +130,24 @@ static int tsens_probe(struct platform_device *pdev)
|
||||
else
|
||||
data = &data_8960;
|
||||
|
||||
if (data->num_sensors <= 0) {
|
||||
num_sensors = data->num_sensors;
|
||||
|
||||
if (np)
|
||||
of_property_read_u32(np, "#qcom,sensors", &num_sensors);
|
||||
|
||||
if (num_sensors <= 0) {
|
||||
dev_err(dev, "invalid number of sensors\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tmdev = devm_kzalloc(dev,
|
||||
struct_size(tmdev, sensor, data->num_sensors),
|
||||
struct_size(tmdev, sensor, num_sensors),
|
||||
GFP_KERNEL);
|
||||
if (!tmdev)
|
||||
return -ENOMEM;
|
||||
|
||||
tmdev->dev = dev;
|
||||
tmdev->num_sensors = data->num_sensors;
|
||||
tmdev->num_sensors = num_sensors;
|
||||
tmdev->ops = data->ops;
|
||||
for (i = 0; i < tmdev->num_sensors; i++) {
|
||||
if (data->hw_ids)
|
||||
|
@ -132,7 +132,7 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
|
||||
#define RCAR3_THERMAL_GRAN 500 /* mili Celsius */
|
||||
|
||||
/* no idea where these constants come from */
|
||||
#define TJ_1 96
|
||||
#define TJ_1 116
|
||||
#define TJ_3 -41
|
||||
|
||||
static void rcar_gen3_thermal_calc_coefs(struct equation_coefs *coef,
|
||||
@ -146,7 +146,7 @@ static void rcar_gen3_thermal_calc_coefs(struct equation_coefs *coef,
|
||||
* Division is not scaled in BSP and if scaled it might overflow
|
||||
* the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled
|
||||
*/
|
||||
tj_2 = (FIXPT_INT((ptat[1] - ptat[2]) * 137)
|
||||
tj_2 = (FIXPT_INT((ptat[1] - ptat[2]) * 157)
|
||||
/ (ptat[0] - ptat[2])) - FIXPT_INT(41);
|
||||
|
||||
coef->a1 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[2]),
|
||||
@ -207,8 +207,8 @@ static int rcar_gen3_thermal_set_trips(void *devdata, int low, int high)
|
||||
{
|
||||
struct rcar_gen3_thermal_tsc *tsc = devdata;
|
||||
|
||||
low = clamp_val(low, -40000, 125000);
|
||||
high = clamp_val(high, -40000, 125000);
|
||||
low = clamp_val(low, -40000, 120000);
|
||||
high = clamp_val(high, -40000, 120000);
|
||||
|
||||
rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP1,
|
||||
rcar_gen3_thermal_mcelsius_to_temp(tsc, low));
|
||||
@ -329,6 +329,7 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
|
||||
static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
|
||||
{ .compatible = "renesas,r8a7795-thermal", },
|
||||
{ .compatible = "renesas,r8a7796-thermal", },
|
||||
{ .compatible = "renesas,r8a77965-thermal", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids);
|
||||
@ -354,11 +355,11 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
||||
|
||||
/* default values if FUSEs are missing */
|
||||
/* TODO: Read values from hardware on supported platforms */
|
||||
int ptat[3] = { 2351, 1509, 435 };
|
||||
int ptat[3] = { 2631, 1509, 435 };
|
||||
int thcode[TSC_MAX_NUM][3] = {
|
||||
{ 3248, 2800, 2221 },
|
||||
{ 3245, 2795, 2216 },
|
||||
{ 3250, 2805, 2237 },
|
||||
{ 3397, 2800, 2221 },
|
||||
{ 3393, 2795, 2216 },
|
||||
{ 3389, 2805, 2237 },
|
||||
};
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
|
@ -58,10 +58,47 @@ struct rcar_thermal_common {
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
struct rcar_thermal_chip {
|
||||
unsigned int use_of_thermal : 1;
|
||||
unsigned int has_filonoff : 1;
|
||||
unsigned int irq_per_ch : 1;
|
||||
unsigned int needs_suspend_resume : 1;
|
||||
unsigned int nirqs;
|
||||
};
|
||||
|
||||
static const struct rcar_thermal_chip rcar_thermal = {
|
||||
.use_of_thermal = 0,
|
||||
.has_filonoff = 1,
|
||||
.irq_per_ch = 0,
|
||||
.needs_suspend_resume = 0,
|
||||
.nirqs = 1,
|
||||
};
|
||||
|
||||
static const struct rcar_thermal_chip rcar_gen2_thermal = {
|
||||
.use_of_thermal = 1,
|
||||
.has_filonoff = 1,
|
||||
.irq_per_ch = 0,
|
||||
.needs_suspend_resume = 0,
|
||||
.nirqs = 1,
|
||||
};
|
||||
|
||||
static const struct rcar_thermal_chip rcar_gen3_thermal = {
|
||||
.use_of_thermal = 1,
|
||||
.has_filonoff = 0,
|
||||
.irq_per_ch = 1,
|
||||
.needs_suspend_resume = 1,
|
||||
/*
|
||||
* The Gen3 chip has 3 interrupts, but this driver uses only 2
|
||||
* interrupts to detect a temperature change, rise or fall.
|
||||
*/
|
||||
.nirqs = 2,
|
||||
};
|
||||
|
||||
struct rcar_thermal_priv {
|
||||
void __iomem *base;
|
||||
struct rcar_thermal_common *common;
|
||||
struct thermal_zone_device *zone;
|
||||
const struct rcar_thermal_chip *chip;
|
||||
struct delayed_work work;
|
||||
struct mutex lock;
|
||||
struct list_head list;
|
||||
@ -77,13 +114,20 @@ struct rcar_thermal_priv {
|
||||
#define rcar_priv_to_dev(priv) ((priv)->common->dev)
|
||||
#define rcar_has_irq_support(priv) ((priv)->common->base)
|
||||
#define rcar_id_to_shift(priv) ((priv)->id * 8)
|
||||
#define rcar_of_data(dev) ((unsigned long)of_device_get_match_data(dev))
|
||||
#define rcar_use_of_thermal(dev) (rcar_of_data(dev) == USE_OF_THERMAL)
|
||||
|
||||
#define USE_OF_THERMAL 1
|
||||
static const struct of_device_id rcar_thermal_dt_ids[] = {
|
||||
{ .compatible = "renesas,rcar-thermal", },
|
||||
{ .compatible = "renesas,rcar-gen2-thermal", .data = (void *)USE_OF_THERMAL },
|
||||
{
|
||||
.compatible = "renesas,rcar-thermal",
|
||||
.data = &rcar_thermal,
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,rcar-gen2-thermal",
|
||||
.data = &rcar_gen2_thermal,
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,thermal-r8a77995",
|
||||
.data = &rcar_gen3_thermal,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids);
|
||||
@ -190,7 +234,8 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv)
|
||||
* enable IRQ
|
||||
*/
|
||||
if (rcar_has_irq_support(priv)) {
|
||||
rcar_thermal_write(priv, FILONOFF, 0);
|
||||
if (priv->chip->has_filonoff)
|
||||
rcar_thermal_write(priv, FILONOFF, 0);
|
||||
|
||||
/* enable Rising/Falling edge interrupt */
|
||||
rcar_thermal_write(priv, POSNEG, 0x1);
|
||||
@ -420,7 +465,7 @@ static int rcar_thermal_remove(struct platform_device *pdev)
|
||||
|
||||
rcar_thermal_for_each_priv(priv, common) {
|
||||
rcar_thermal_irq_disable(priv);
|
||||
if (rcar_use_of_thermal(dev))
|
||||
if (priv->chip->use_of_thermal)
|
||||
thermal_remove_hwmon_sysfs(priv->zone);
|
||||
else
|
||||
thermal_zone_device_unregister(priv->zone);
|
||||
@ -438,6 +483,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
||||
struct rcar_thermal_priv *priv;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res, *irq;
|
||||
const struct rcar_thermal_chip *chip = of_device_get_match_data(dev);
|
||||
int mres = 0;
|
||||
int i;
|
||||
int ret = -ENODEV;
|
||||
@ -457,19 +503,35 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (irq) {
|
||||
/*
|
||||
* platform has IRQ support.
|
||||
* Then, driver uses common registers
|
||||
* rcar_has_irq_support() will be enabled
|
||||
*/
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
|
||||
common->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(common->base))
|
||||
return PTR_ERR(common->base);
|
||||
for (i = 0; i < chip->nirqs; i++) {
|
||||
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!irq)
|
||||
continue;
|
||||
if (!common->base) {
|
||||
/*
|
||||
* platform has IRQ support.
|
||||
* Then, driver uses common registers
|
||||
* rcar_has_irq_support() will be enabled
|
||||
*/
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM,
|
||||
mres++);
|
||||
common->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(common->base))
|
||||
return PTR_ERR(common->base);
|
||||
|
||||
idle = 0; /* polling delay is not needed */
|
||||
idle = 0; /* polling delay is not needed */
|
||||
}
|
||||
|
||||
ret = devm_request_irq(dev, irq->start, rcar_thermal_irq,
|
||||
IRQF_SHARED, dev_name(dev), common);
|
||||
if (ret) {
|
||||
dev_err(dev, "irq request failed\n ");
|
||||
goto error_unregister;
|
||||
}
|
||||
|
||||
/* update ENR bits */
|
||||
if (chip->irq_per_ch)
|
||||
enr_bits |= 1 << i;
|
||||
}
|
||||
|
||||
for (i = 0;; i++) {
|
||||
@ -491,6 +553,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
||||
|
||||
priv->common = common;
|
||||
priv->id = i;
|
||||
priv->chip = chip;
|
||||
mutex_init(&priv->lock);
|
||||
INIT_LIST_HEAD(&priv->list);
|
||||
INIT_DELAYED_WORK(&priv->work, rcar_thermal_work);
|
||||
@ -498,7 +561,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
||||
if (ret < 0)
|
||||
goto error_unregister;
|
||||
|
||||
if (rcar_use_of_thermal(dev))
|
||||
if (chip->use_of_thermal)
|
||||
priv->zone = devm_thermal_zone_of_sensor_register(
|
||||
dev, i, priv,
|
||||
&rcar_thermal_zone_of_ops);
|
||||
@ -515,7 +578,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
||||
goto error_unregister;
|
||||
}
|
||||
|
||||
if (rcar_use_of_thermal(dev)) {
|
||||
if (chip->use_of_thermal) {
|
||||
/*
|
||||
* thermal_zone doesn't enable hwmon as default,
|
||||
* but, enable it here to keep compatible
|
||||
@ -531,20 +594,12 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
||||
list_move_tail(&priv->list, &common->head);
|
||||
|
||||
/* update ENR bits */
|
||||
enr_bits |= 3 << (i * 8);
|
||||
if (!chip->irq_per_ch)
|
||||
enr_bits |= 3 << (i * 8);
|
||||
}
|
||||
|
||||
/* enable temperature comparation */
|
||||
if (irq) {
|
||||
ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0,
|
||||
dev_name(dev), common);
|
||||
if (ret) {
|
||||
dev_err(dev, "irq request failed\n ");
|
||||
goto error_unregister;
|
||||
}
|
||||
|
||||
if (enr_bits)
|
||||
rcar_thermal_common_write(common, ENR, enr_bits);
|
||||
}
|
||||
|
||||
dev_info(dev, "%d sensor probed\n", i);
|
||||
|
||||
@ -556,9 +611,48 @@ error_unregister:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int rcar_thermal_suspend(struct device *dev)
|
||||
{
|
||||
struct rcar_thermal_common *common = dev_get_drvdata(dev);
|
||||
struct rcar_thermal_priv *priv = list_first_entry(&common->head,
|
||||
typeof(*priv), list);
|
||||
|
||||
if (priv->chip->needs_suspend_resume) {
|
||||
rcar_thermal_common_write(common, ENR, 0);
|
||||
rcar_thermal_irq_disable(priv);
|
||||
rcar_thermal_bset(priv, THSCR, CPCTL, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rcar_thermal_resume(struct device *dev)
|
||||
{
|
||||
struct rcar_thermal_common *common = dev_get_drvdata(dev);
|
||||
struct rcar_thermal_priv *priv = list_first_entry(&common->head,
|
||||
typeof(*priv), list);
|
||||
int ret;
|
||||
|
||||
if (priv->chip->needs_suspend_resume) {
|
||||
ret = rcar_thermal_update_temp(priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
rcar_thermal_irq_enable(priv);
|
||||
rcar_thermal_common_write(common, ENR, 0x03);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend,
|
||||
rcar_thermal_resume);
|
||||
|
||||
static struct platform_driver rcar_thermal_driver = {
|
||||
.driver = {
|
||||
.name = "rcar_thermal",
|
||||
.pm = &rcar_thermal_pm_ops,
|
||||
.of_match_table = rcar_thermal_dt_ids,
|
||||
},
|
||||
.probe = rcar_thermal_probe,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* exynos_tmu.h - Samsung EXYNOS TMU (Thermal Management Unit)
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics
|
||||
* Donggeun Kim <dg77.kim@samsung.com>
|
||||
* Amit Daniel Kachhap <amit.daniel@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _EXYNOS_TMU_H
|
||||
#define _EXYNOS_TMU_H
|
||||
#include <linux/cpu_cooling.h>
|
||||
#include <dt-bindings/thermal/thermal_exynos.h>
|
||||
|
||||
enum soc_type {
|
||||
SOC_ARCH_EXYNOS3250 = 1,
|
||||
SOC_ARCH_EXYNOS4210,
|
||||
SOC_ARCH_EXYNOS4412,
|
||||
SOC_ARCH_EXYNOS5250,
|
||||
SOC_ARCH_EXYNOS5260,
|
||||
SOC_ARCH_EXYNOS5420,
|
||||
SOC_ARCH_EXYNOS5420_TRIMINFO,
|
||||
SOC_ARCH_EXYNOS5433,
|
||||
SOC_ARCH_EXYNOS5440,
|
||||
SOC_ARCH_EXYNOS7,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct exynos_tmu_platform_data
|
||||
* @gain: gain of amplifier in the positive-TC generator block
|
||||
* 0 < gain <= 15
|
||||
* @reference_voltage: reference voltage of amplifier
|
||||
* in the positive-TC generator block
|
||||
* 0 < reference_voltage <= 31
|
||||
* @noise_cancel_mode: noise cancellation mode
|
||||
* 000, 100, 101, 110 and 111 can be different modes
|
||||
* @type: determines the type of SOC
|
||||
* @efuse_value: platform defined fuse value
|
||||
* @min_efuse_value: minimum valid trimming data
|
||||
* @max_efuse_value: maximum valid trimming data
|
||||
* @default_temp_offset: default temperature offset in case of no trimming
|
||||
* @cal_type: calibration type for temperature
|
||||
*
|
||||
* This structure is required for configuration of exynos_tmu driver.
|
||||
*/
|
||||
struct exynos_tmu_platform_data {
|
||||
u8 gain;
|
||||
u8 reference_voltage;
|
||||
u8 noise_cancel_mode;
|
||||
|
||||
u32 efuse_value;
|
||||
u32 min_efuse_value;
|
||||
u32 max_efuse_value;
|
||||
u8 first_point_trim;
|
||||
u8 second_point_trim;
|
||||
u8 default_temp_offset;
|
||||
|
||||
enum soc_type type;
|
||||
u32 cal_type;
|
||||
};
|
||||
|
||||
#endif /* _EXYNOS_TMU_H */
|
@ -240,31 +240,6 @@ struct tegra_soctherm {
|
||||
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
|
||||
@ -926,7 +901,7 @@ static int throt_set_cdev_state(struct thermal_cooling_device *cdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct thermal_cooling_device_ops throt_cooling_ops = {
|
||||
static const 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,
|
||||
@ -1207,9 +1182,9 @@ static void tegra_soctherm_throttle(struct device *dev)
|
||||
} else {
|
||||
writel(v, ts->regs + THROT_GLOBAL_CFG);
|
||||
|
||||
v = clk_readl(ts, CAR_SUPER_CCLKG_DIVIDER);
|
||||
v = readl(ts->clk_regs + CAR_SUPER_CCLKG_DIVIDER);
|
||||
v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1);
|
||||
clk_writel(ts, v, CAR_SUPER_CCLKG_DIVIDER);
|
||||
writel(v, ts->clk_regs + CAR_SUPER_CCLKG_DIVIDER);
|
||||
}
|
||||
|
||||
/* initialize stats collection */
|
||||
|
@ -310,7 +310,7 @@ omap5430_adc_to_temp[
|
||||
119800, 120200, 120600, 121000, 121400, 121800, 122400, 122600, 123000,
|
||||
123400,
|
||||
/* Index 940 - 945 */
|
||||
123800, 1242000, 124600, 124900, 125000, 125000,
|
||||
123800, 124200, 124600, 124900, 125000, 125000,
|
||||
};
|
||||
|
||||
/* OMAP54xx ES2.0 data */
|
||||
|
@ -365,6 +365,10 @@ static const struct of_device_id uniphier_tm_dt_ids[] = {
|
||||
.compatible = "socionext,uniphier-ld20-thermal",
|
||||
.data = &uniphier_ld20_tm_data,
|
||||
},
|
||||
{
|
||||
.compatible = "socionext,uniphier-pxs3-thermal",
|
||||
.data = &uniphier_ld20_tm_data,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, uniphier_tm_dt_ids);
|
||||
|
Loading…
Reference in New Issue
Block a user