Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal into thermal-soc
This commit is contained in:
commit
ef1d75263f
|
@ -0,0 +1,56 @@
|
||||||
|
* DT bindings for Renesas R-Car Gen3 Thermal Sensor driver
|
||||||
|
|
||||||
|
On R-Car Gen3 SoCs, the thermal sensor controllers (TSC) control the thermal
|
||||||
|
sensors (THS) which are the analog circuits for measuring temperature (Tj)
|
||||||
|
inside the LSI.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible : "renesas,<soctype>-thermal",
|
||||||
|
Examples with soctypes are:
|
||||||
|
- "renesas,r8a7795-thermal" (R-Car H3)
|
||||||
|
- "renesas,r8a7796-thermal" (R-Car M3-W)
|
||||||
|
- 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.
|
||||||
|
TSC1, TSC2, ...
|
||||||
|
- clocks : Must contain a reference to the functional clock.
|
||||||
|
- #thermal-sensor-cells : must be <1>.
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
|
||||||
|
- interrupts : interrupts routed to the TSC (3 for H3 and M3-W)
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
tsc: thermal@e6198000 {
|
||||||
|
compatible = "renesas,r8a7795-thermal";
|
||||||
|
reg = <0 0xe6198000 0 0x68>,
|
||||||
|
<0 0xe61a0000 0 0x5c>,
|
||||||
|
<0 0xe61a8000 0 0x5c>;
|
||||||
|
interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
|
||||||
|
<GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
|
||||||
|
<GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
clocks = <&cpg CPG_MOD 522>;
|
||||||
|
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
|
||||||
|
#thermal-sensor-cells = <1>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
thermal-zones {
|
||||||
|
sensor_thermal1: sensor-thermal1 {
|
||||||
|
polling-delay-passive = <250>;
|
||||||
|
polling-delay = <1000>;
|
||||||
|
thermal-sensors = <&tsc 0>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
sensor1_crit: sensor1-crit {
|
||||||
|
temperature = <90000>;
|
||||||
|
hysteresis = <2000>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,116 @@
|
||||||
|
* ZTE zx2967 family Thermal
|
||||||
|
|
||||||
|
Required Properties:
|
||||||
|
- compatible: should be one of the following.
|
||||||
|
* zte,zx296718-thermal
|
||||||
|
- reg: physical base address of the controller and length of memory mapped
|
||||||
|
region.
|
||||||
|
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
|
||||||
|
- clock-names: "topcrm" for the topcrm clock.
|
||||||
|
"apb" for the apb clock.
|
||||||
|
- #thermal-sensor-cells: must be 0.
|
||||||
|
|
||||||
|
Please note: slope coefficient defined in thermal-zones section need to be
|
||||||
|
multiplied by 1000.
|
||||||
|
|
||||||
|
Example for tempsensor:
|
||||||
|
|
||||||
|
tempsensor: tempsensor@148a000 {
|
||||||
|
compatible = "zte,zx296718-thermal";
|
||||||
|
reg = <0x0148a000 0x20>;
|
||||||
|
clocks = <&topcrm TEMPSENSOR_GATE>, <&audiocrm AUDIO_TS_PCLK>;
|
||||||
|
clock-names = "topcrm", "apb";
|
||||||
|
#thermal-sensor-cells = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
Example for cooling device:
|
||||||
|
|
||||||
|
cooling_dev: cooling_dev {
|
||||||
|
cluster0_cooling_dev: cluster0-cooling-dev {
|
||||||
|
#cooling-cells = <2>;
|
||||||
|
cpumask = <0xf>;
|
||||||
|
capacitance = <1500>;
|
||||||
|
};
|
||||||
|
|
||||||
|
cluster1_cooling_dev: cluster1-cooling-dev {
|
||||||
|
#cooling-cells = <2>;
|
||||||
|
cpumask = <0x30>;
|
||||||
|
capacitance = <2000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Example for thermal zones:
|
||||||
|
|
||||||
|
thermal-zones {
|
||||||
|
zx296718_thermal: zx296718_thermal {
|
||||||
|
polling-delay-passive = <500>;
|
||||||
|
polling-delay = <1000>;
|
||||||
|
sustainable-power = <6500>;
|
||||||
|
|
||||||
|
thermal-sensors = <&tempsensor 0>;
|
||||||
|
/*
|
||||||
|
* slope need to be multiplied by 1000.
|
||||||
|
*/
|
||||||
|
coefficients = <1951 (-922)>;
|
||||||
|
|
||||||
|
trips {
|
||||||
|
trip0: switch_on_temperature {
|
||||||
|
temperature = <90000>;
|
||||||
|
hysteresis = <2000>;
|
||||||
|
type = "passive";
|
||||||
|
};
|
||||||
|
|
||||||
|
trip1: desired_temperature {
|
||||||
|
temperature = <100000>;
|
||||||
|
hysteresis = <2000>;
|
||||||
|
type = "passive";
|
||||||
|
};
|
||||||
|
|
||||||
|
crit: critical_temperature {
|
||||||
|
temperature = <110000>;
|
||||||
|
hysteresis = <2000>;
|
||||||
|
type = "critical";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cooling-maps {
|
||||||
|
map0 {
|
||||||
|
trip = <&trip0>;
|
||||||
|
cooling-device = <&gpu 2 5>;
|
||||||
|
};
|
||||||
|
|
||||||
|
map1 {
|
||||||
|
trip = <&trip0>;
|
||||||
|
cooling-device = <&cluster0_cooling_dev 1 2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
map2 {
|
||||||
|
trip = <&trip1>;
|
||||||
|
cooling-device = <&cluster0_cooling_dev 1 2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
map3 {
|
||||||
|
trip = <&crit>;
|
||||||
|
cooling-device = <&cluster0_cooling_dev 1 2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
map4 {
|
||||||
|
trip = <&trip0>;
|
||||||
|
cooling-device = <&cluster1_cooling_dev 1 2>;
|
||||||
|
contribution = <9000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
map5 {
|
||||||
|
trip = <&trip1>;
|
||||||
|
cooling-device = <&cluster1_cooling_dev 1 2>;
|
||||||
|
contribution = <4096>;
|
||||||
|
};
|
||||||
|
|
||||||
|
map6 {
|
||||||
|
trip = <&crit>;
|
||||||
|
cooling-device = <&cluster1_cooling_dev 1 2>;
|
||||||
|
contribution = <4096>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -245,6 +245,15 @@ config RCAR_THERMAL
|
||||||
Enable this to plug the R-Car thermal sensor driver into the Linux
|
Enable this to plug the R-Car thermal sensor driver into the Linux
|
||||||
thermal framework.
|
thermal framework.
|
||||||
|
|
||||||
|
config RCAR_GEN3_THERMAL
|
||||||
|
tristate "Renesas R-Car Gen3 thermal driver"
|
||||||
|
depends on ARCH_RENESAS || COMPILE_TEST
|
||||||
|
depends on HAS_IOMEM
|
||||||
|
depends on OF
|
||||||
|
help
|
||||||
|
Enable this to plug the R-Car Gen3 thermal sensor driver into the Linux
|
||||||
|
thermal framework.
|
||||||
|
|
||||||
config KIRKWOOD_THERMAL
|
config KIRKWOOD_THERMAL
|
||||||
tristate "Temperature sensor on Marvell Kirkwood SoCs"
|
tristate "Temperature sensor on Marvell Kirkwood SoCs"
|
||||||
depends on MACH_KIRKWOOD || COMPILE_TEST
|
depends on MACH_KIRKWOOD || COMPILE_TEST
|
||||||
|
@ -436,4 +445,12 @@ depends on (ARCH_QCOM && OF) || COMPILE_TEST
|
||||||
source "drivers/thermal/qcom/Kconfig"
|
source "drivers/thermal/qcom/Kconfig"
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
config ZX2967_THERMAL
|
||||||
|
tristate "Thermal sensors on zx2967 SoC"
|
||||||
|
depends on ARCH_ZX || COMPILE_TEST
|
||||||
|
help
|
||||||
|
Enable the zx2967 thermal sensors driver, which supports
|
||||||
|
the primitive temperature sensor embedded in zx2967 SoCs.
|
||||||
|
This sensor generates the real time die temperature.
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -31,6 +31,7 @@ obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
|
||||||
obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
|
obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
|
||||||
obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
|
obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
|
||||||
obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
|
obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
|
||||||
|
obj-$(CONFIG_RCAR_GEN3_THERMAL) += rcar_gen3_thermal.o
|
||||||
obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o
|
obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o
|
||||||
obj-y += samsung/
|
obj-y += samsung/
|
||||||
obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o
|
obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o
|
||||||
|
@ -56,3 +57,4 @@ obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
|
||||||
obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
|
obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
|
||||||
obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
|
obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
|
||||||
obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
|
obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
|
||||||
|
obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
|
||||||
|
|
|
@ -489,6 +489,10 @@ static int imx_thermal_probe(struct platform_device *pdev)
|
||||||
data->tempmon = map;
|
data->tempmon = map;
|
||||||
|
|
||||||
data->socdata = of_device_get_match_data(&pdev->dev);
|
data->socdata = of_device_get_match_data(&pdev->dev);
|
||||||
|
if (!data->socdata) {
|
||||||
|
dev_err(&pdev->dev, "no device match found\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
/* make sure the IRQ flag is clear before enabling irq on i.MX6SX */
|
/* make sure the IRQ flag is clear before enabling irq on i.MX6SX */
|
||||||
if (data->socdata->version == TEMPMON_IMX6SX) {
|
if (data->socdata->version == TEMPMON_IMX6SX) {
|
||||||
|
|
|
@ -183,37 +183,37 @@ struct mtk_thermal {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* MT8173 thermal sensor data */
|
/* MT8173 thermal sensor data */
|
||||||
const int mt8173_bank_data[MT8173_NUM_ZONES][3] = {
|
static const int mt8173_bank_data[MT8173_NUM_ZONES][3] = {
|
||||||
{ MT8173_TS2, MT8173_TS3 },
|
{ MT8173_TS2, MT8173_TS3 },
|
||||||
{ MT8173_TS2, MT8173_TS4 },
|
{ MT8173_TS2, MT8173_TS4 },
|
||||||
{ MT8173_TS1, MT8173_TS2, MT8173_TSABB },
|
{ MT8173_TS1, MT8173_TS2, MT8173_TSABB },
|
||||||
{ MT8173_TS2 },
|
{ MT8173_TS2 },
|
||||||
};
|
};
|
||||||
|
|
||||||
const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = {
|
static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = {
|
||||||
TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR2
|
TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR2
|
||||||
};
|
};
|
||||||
|
|
||||||
const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = {
|
static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = {
|
||||||
TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3
|
TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3
|
||||||
};
|
};
|
||||||
|
|
||||||
const int mt8173_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 };
|
static const int mt8173_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 };
|
||||||
|
|
||||||
/* MT2701 thermal sensor data */
|
/* MT2701 thermal sensor data */
|
||||||
const int mt2701_bank_data[MT2701_NUM_SENSORS] = {
|
static const int mt2701_bank_data[MT2701_NUM_SENSORS] = {
|
||||||
MT2701_TS1, MT2701_TS2, MT2701_TSABB
|
MT2701_TS1, MT2701_TS2, MT2701_TSABB
|
||||||
};
|
};
|
||||||
|
|
||||||
const int mt2701_msr[MT2701_NUM_SENSORS_PER_ZONE] = {
|
static const int mt2701_msr[MT2701_NUM_SENSORS_PER_ZONE] = {
|
||||||
TEMP_MSR0, TEMP_MSR1, TEMP_MSR2
|
TEMP_MSR0, TEMP_MSR1, TEMP_MSR2
|
||||||
};
|
};
|
||||||
|
|
||||||
const int mt2701_adcpnp[MT2701_NUM_SENSORS_PER_ZONE] = {
|
static const int mt2701_adcpnp[MT2701_NUM_SENSORS_PER_ZONE] = {
|
||||||
TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2
|
TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2
|
||||||
};
|
};
|
||||||
|
|
||||||
const int mt2701_mux_values[MT2701_NUM_SENSORS] = { 0, 1, 16 };
|
static const int mt2701_mux_values[MT2701_NUM_SENSORS] = { 0, 1, 16 };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The MT8173 thermal controller has four banks. Each bank can read up to
|
* The MT8173 thermal controller has four banks. Each bank can read up to
|
||||||
|
|
|
@ -0,0 +1,335 @@
|
||||||
|
/*
|
||||||
|
* R-Car Gen3 THS thermal sensor driver
|
||||||
|
* Based on rcar_thermal.c and work from Hien Dang and Khiem Nguyen.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Renesas Electronics Corporation.
|
||||||
|
* Copyright (C) 2016 Sang Engineering
|
||||||
|
*
|
||||||
|
* 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; version 2 of the License.
|
||||||
|
*
|
||||||
|
* 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/delay.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/thermal.h>
|
||||||
|
|
||||||
|
/* Register offsets */
|
||||||
|
#define REG_GEN3_IRQSTR 0x04
|
||||||
|
#define REG_GEN3_IRQMSK 0x08
|
||||||
|
#define REG_GEN3_IRQCTL 0x0C
|
||||||
|
#define REG_GEN3_IRQEN 0x10
|
||||||
|
#define REG_GEN3_IRQTEMP1 0x14
|
||||||
|
#define REG_GEN3_IRQTEMP2 0x18
|
||||||
|
#define REG_GEN3_IRQTEMP3 0x1C
|
||||||
|
#define REG_GEN3_CTSR 0x20
|
||||||
|
#define REG_GEN3_THCTR 0x20
|
||||||
|
#define REG_GEN3_TEMP 0x28
|
||||||
|
#define REG_GEN3_THCODE1 0x50
|
||||||
|
#define REG_GEN3_THCODE2 0x54
|
||||||
|
#define REG_GEN3_THCODE3 0x58
|
||||||
|
|
||||||
|
/* CTSR bits */
|
||||||
|
#define CTSR_PONM BIT(8)
|
||||||
|
#define CTSR_AOUT BIT(7)
|
||||||
|
#define CTSR_THBGR BIT(5)
|
||||||
|
#define CTSR_VMEN BIT(4)
|
||||||
|
#define CTSR_VMST BIT(1)
|
||||||
|
#define CTSR_THSST BIT(0)
|
||||||
|
|
||||||
|
/* THCTR bits */
|
||||||
|
#define THCTR_PONM BIT(6)
|
||||||
|
#define THCTR_THSST BIT(0)
|
||||||
|
|
||||||
|
#define CTEMP_MASK 0xFFF
|
||||||
|
|
||||||
|
#define MCELSIUS(temp) ((temp) * 1000)
|
||||||
|
#define GEN3_FUSE_MASK 0xFFF
|
||||||
|
|
||||||
|
#define TSC_MAX_NUM 3
|
||||||
|
|
||||||
|
/* Structure for thermal temperature calculation */
|
||||||
|
struct equation_coefs {
|
||||||
|
int a1;
|
||||||
|
int b1;
|
||||||
|
int a2;
|
||||||
|
int b2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rcar_gen3_thermal_tsc {
|
||||||
|
void __iomem *base;
|
||||||
|
struct thermal_zone_device *zone;
|
||||||
|
struct equation_coefs coef;
|
||||||
|
struct mutex lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rcar_gen3_thermal_priv {
|
||||||
|
struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rcar_gen3_thermal_data {
|
||||||
|
void (*thermal_init)(struct rcar_gen3_thermal_tsc *tsc);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline u32 rcar_gen3_thermal_read(struct rcar_gen3_thermal_tsc *tsc,
|
||||||
|
u32 reg)
|
||||||
|
{
|
||||||
|
return ioread32(tsc->base + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
|
||||||
|
u32 reg, u32 data)
|
||||||
|
{
|
||||||
|
iowrite32(data, tsc->base + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Linear approximation for temperature
|
||||||
|
*
|
||||||
|
* [reg] = [temp] * a + b => [temp] = ([reg] - b) / a
|
||||||
|
*
|
||||||
|
* The constants a and b are calculated using two triplets of int values PTAT
|
||||||
|
* and THCODE. PTAT and THCODE can either be read from hardware or use hard
|
||||||
|
* coded values from driver. The formula to calculate a and b are taken from
|
||||||
|
* BSP and sparsely documented and understood.
|
||||||
|
*
|
||||||
|
* Examining the linear formula and the formula used to calculate constants a
|
||||||
|
* and b while knowing that the span for PTAT and THCODE values are between
|
||||||
|
* 0x000 and 0xfff the largest integer possible is 0xfff * 0xfff == 0xffe001.
|
||||||
|
* Integer also needs to be signed so that leaves 7 bits for binary
|
||||||
|
* fixed point scaling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FIXPT_SHIFT 7
|
||||||
|
#define FIXPT_INT(_x) ((_x) << FIXPT_SHIFT)
|
||||||
|
#define FIXPT_DIV(_a, _b) DIV_ROUND_CLOSEST(((_a) << FIXPT_SHIFT), (_b))
|
||||||
|
#define FIXPT_TO_MCELSIUS(_x) ((_x) * 1000 >> FIXPT_SHIFT)
|
||||||
|
|
||||||
|
#define RCAR3_THERMAL_GRAN 500 /* mili Celsius */
|
||||||
|
|
||||||
|
/* no idea where these constants come from */
|
||||||
|
#define TJ_1 96
|
||||||
|
#define TJ_3 -41
|
||||||
|
|
||||||
|
static void rcar_gen3_thermal_calc_coefs(struct equation_coefs *coef,
|
||||||
|
int *ptat, int *thcode)
|
||||||
|
{
|
||||||
|
int tj_2;
|
||||||
|
|
||||||
|
/* TODO: Find documentation and document constant calculation formula */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
/ (ptat[0] - ptat[2])) - FIXPT_INT(41);
|
||||||
|
|
||||||
|
coef->a1 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[2]),
|
||||||
|
tj_2 - FIXPT_INT(TJ_3));
|
||||||
|
coef->b1 = FIXPT_INT(thcode[2]) - coef->a1 * TJ_3;
|
||||||
|
|
||||||
|
coef->a2 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[0]),
|
||||||
|
tj_2 - FIXPT_INT(TJ_1));
|
||||||
|
coef->b2 = FIXPT_INT(thcode[0]) - coef->a2 * TJ_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rcar_gen3_thermal_round(int temp)
|
||||||
|
{
|
||||||
|
int result, round_offs;
|
||||||
|
|
||||||
|
round_offs = temp >= 0 ? RCAR3_THERMAL_GRAN / 2 :
|
||||||
|
-RCAR3_THERMAL_GRAN / 2;
|
||||||
|
result = (temp + round_offs) / RCAR3_THERMAL_GRAN;
|
||||||
|
return result * RCAR3_THERMAL_GRAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
|
||||||
|
{
|
||||||
|
struct rcar_gen3_thermal_tsc *tsc = devdata;
|
||||||
|
int mcelsius, val1, val2;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
/* Read register and convert to mili Celsius */
|
||||||
|
mutex_lock(&tsc->lock);
|
||||||
|
|
||||||
|
reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK;
|
||||||
|
|
||||||
|
val1 = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1, tsc->coef.a1);
|
||||||
|
val2 = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b2, tsc->coef.a2);
|
||||||
|
mcelsius = FIXPT_TO_MCELSIUS((val1 + val2) / 2);
|
||||||
|
|
||||||
|
mutex_unlock(&tsc->lock);
|
||||||
|
|
||||||
|
/* Make sure we are inside specifications */
|
||||||
|
if ((mcelsius < MCELSIUS(-40)) || (mcelsius > MCELSIUS(125)))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
/* Round value to device granularity setting */
|
||||||
|
*temp = rcar_gen3_thermal_round(mcelsius);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = {
|
||||||
|
.get_temp = rcar_gen3_thermal_get_temp,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
|
||||||
|
{
|
||||||
|
rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR);
|
||||||
|
rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, 0x0);
|
||||||
|
|
||||||
|
usleep_range(1000, 2000);
|
||||||
|
|
||||||
|
rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_PONM);
|
||||||
|
rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F);
|
||||||
|
rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR,
|
||||||
|
CTSR_PONM | CTSR_AOUT | CTSR_THBGR | CTSR_VMEN);
|
||||||
|
|
||||||
|
usleep_range(100, 200);
|
||||||
|
|
||||||
|
rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR,
|
||||||
|
CTSR_PONM | CTSR_AOUT | CTSR_THBGR | CTSR_VMEN |
|
||||||
|
CTSR_VMST | CTSR_THSST);
|
||||||
|
|
||||||
|
usleep_range(1000, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void r8a7796_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
|
||||||
|
{
|
||||||
|
u32 reg_val;
|
||||||
|
|
||||||
|
reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR);
|
||||||
|
reg_val &= ~THCTR_PONM;
|
||||||
|
rcar_gen3_thermal_write(tsc, REG_GEN3_THCTR, reg_val);
|
||||||
|
|
||||||
|
usleep_range(1000, 2000);
|
||||||
|
|
||||||
|
rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F);
|
||||||
|
reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR);
|
||||||
|
reg_val |= THCTR_THSST;
|
||||||
|
rcar_gen3_thermal_write(tsc, REG_GEN3_THCTR, reg_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rcar_gen3_thermal_data r8a7795_data = {
|
||||||
|
.thermal_init = r8a7795_thermal_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rcar_gen3_thermal_data r8a7796_data = {
|
||||||
|
.thermal_init = r8a7796_thermal_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
|
||||||
|
{ .compatible = "renesas,r8a7795-thermal", .data = &r8a7795_data},
|
||||||
|
{ .compatible = "renesas,r8a7796-thermal", .data = &r8a7796_data},
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids);
|
||||||
|
|
||||||
|
static int rcar_gen3_thermal_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
|
||||||
|
pm_runtime_put(dev);
|
||||||
|
pm_runtime_disable(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct rcar_gen3_thermal_priv *priv;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct resource *res;
|
||||||
|
struct thermal_zone_device *zone;
|
||||||
|
int ret, i;
|
||||||
|
const struct rcar_gen3_thermal_data *match_data =
|
||||||
|
of_device_get_match_data(dev);
|
||||||
|
|
||||||
|
/* default values if FUSEs are missing */
|
||||||
|
/* TODO: Read values from hardware on supported platforms */
|
||||||
|
int ptat[3] = { 2351, 1509, 435 };
|
||||||
|
int thcode[TSC_MAX_NUM][3] = {
|
||||||
|
{ 3248, 2800, 2221 },
|
||||||
|
{ 3245, 2795, 2216 },
|
||||||
|
{ 3250, 2805, 2237 },
|
||||||
|
};
|
||||||
|
|
||||||
|
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, priv);
|
||||||
|
|
||||||
|
pm_runtime_enable(dev);
|
||||||
|
pm_runtime_get_sync(dev);
|
||||||
|
|
||||||
|
for (i = 0; i < TSC_MAX_NUM; i++) {
|
||||||
|
struct rcar_gen3_thermal_tsc *tsc;
|
||||||
|
|
||||||
|
tsc = devm_kzalloc(dev, sizeof(*tsc), GFP_KERNEL);
|
||||||
|
if (!tsc) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto error_unregister;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
|
||||||
|
if (!res)
|
||||||
|
break;
|
||||||
|
|
||||||
|
tsc->base = devm_ioremap_resource(dev, res);
|
||||||
|
if (IS_ERR(tsc->base)) {
|
||||||
|
ret = PTR_ERR(tsc->base);
|
||||||
|
goto error_unregister;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->tscs[i] = tsc;
|
||||||
|
mutex_init(&tsc->lock);
|
||||||
|
|
||||||
|
match_data->thermal_init(tsc);
|
||||||
|
rcar_gen3_thermal_calc_coefs(&tsc->coef, ptat, thcode[i]);
|
||||||
|
|
||||||
|
zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,
|
||||||
|
&rcar_gen3_tz_of_ops);
|
||||||
|
if (IS_ERR(zone)) {
|
||||||
|
dev_err(dev, "Can't register thermal zone\n");
|
||||||
|
ret = PTR_ERR(zone);
|
||||||
|
goto error_unregister;
|
||||||
|
}
|
||||||
|
tsc->zone = zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error_unregister:
|
||||||
|
rcar_gen3_thermal_remove(pdev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver rcar_gen3_thermal_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "rcar_gen3_thermal",
|
||||||
|
.of_match_table = rcar_gen3_thermal_dt_ids,
|
||||||
|
},
|
||||||
|
.probe = rcar_gen3_thermal_probe,
|
||||||
|
.remove = rcar_gen3_thermal_remove,
|
||||||
|
};
|
||||||
|
module_platform_driver(rcar_gen3_thermal_driver);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
MODULE_DESCRIPTION("R-Car Gen3 THS thermal sensor driver");
|
||||||
|
MODULE_AUTHOR("Wolfram Sang <wsa+renesas@sang-engineering.com>");
|
|
@ -1168,7 +1168,6 @@ static int exynos_of_sensor_conf(struct device_node *np,
|
||||||
pdata->default_temp_offset = (u8)value;
|
pdata->default_temp_offset = (u8)value;
|
||||||
|
|
||||||
of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type);
|
of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type);
|
||||||
of_property_read_u32(np, "samsung,tmu_cal_mode", &pdata->cal_mode);
|
|
||||||
|
|
||||||
of_node_put(np);
|
of_node_put(np);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -70,7 +70,6 @@ struct exynos_tmu_platform_data {
|
||||||
|
|
||||||
enum soc_type type;
|
enum soc_type type;
|
||||||
u32 cal_type;
|
u32 cal_type;
|
||||||
u32 cal_mode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _EXYNOS_TMU_H */
|
#endif /* _EXYNOS_TMU_H */
|
||||||
|
|
|
@ -11,7 +11,6 @@ config TI_SOC_THERMAL
|
||||||
config TI_THERMAL
|
config TI_THERMAL
|
||||||
bool "Texas Instruments SoCs thermal framework support"
|
bool "Texas Instruments SoCs thermal framework support"
|
||||||
depends on TI_SOC_THERMAL
|
depends on TI_SOC_THERMAL
|
||||||
depends on CPU_THERMAL
|
|
||||||
help
|
help
|
||||||
If you say yes here you want to get support for generic thermal
|
If you say yes here you want to get support for generic thermal
|
||||||
framework for the Texas Instruments on die bandgap temperature sensor.
|
framework for the Texas Instruments on die bandgap temperature sensor.
|
||||||
|
|
|
@ -54,7 +54,6 @@
|
||||||
#define DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET 0x8
|
#define DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET 0x8
|
||||||
#define DRA752_TEMP_SENSOR_CORE_OFFSET 0x154
|
#define DRA752_TEMP_SENSOR_CORE_OFFSET 0x154
|
||||||
#define DRA752_BANDGAP_THRESHOLD_CORE_OFFSET 0x1ac
|
#define DRA752_BANDGAP_THRESHOLD_CORE_OFFSET 0x1ac
|
||||||
#define DRA752_BANDGAP_TSHUT_CORE_OFFSET 0x1b8
|
|
||||||
#define DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET 0x1c4
|
#define DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET 0x1c4
|
||||||
#define DRA752_DTEMP_CORE_0_OFFSET 0x208
|
#define DRA752_DTEMP_CORE_0_OFFSET 0x208
|
||||||
#define DRA752_DTEMP_CORE_1_OFFSET 0x20c
|
#define DRA752_DTEMP_CORE_1_OFFSET 0x20c
|
||||||
|
@ -66,7 +65,6 @@
|
||||||
#define DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET 0x388
|
#define DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET 0x388
|
||||||
#define DRA752_TEMP_SENSOR_IVA_OFFSET 0x398
|
#define DRA752_TEMP_SENSOR_IVA_OFFSET 0x398
|
||||||
#define DRA752_BANDGAP_THRESHOLD_IVA_OFFSET 0x3a4
|
#define DRA752_BANDGAP_THRESHOLD_IVA_OFFSET 0x3a4
|
||||||
#define DRA752_BANDGAP_TSHUT_IVA_OFFSET 0x3ac
|
|
||||||
#define DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET 0x3b4
|
#define DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET 0x3b4
|
||||||
#define DRA752_DTEMP_IVA_0_OFFSET 0x3d0
|
#define DRA752_DTEMP_IVA_0_OFFSET 0x3d0
|
||||||
#define DRA752_DTEMP_IVA_1_OFFSET 0x3d4
|
#define DRA752_DTEMP_IVA_1_OFFSET 0x3d4
|
||||||
|
@ -78,7 +76,6 @@
|
||||||
#define DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET 0x4
|
#define DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET 0x4
|
||||||
#define DRA752_TEMP_SENSOR_MPU_OFFSET 0x14c
|
#define DRA752_TEMP_SENSOR_MPU_OFFSET 0x14c
|
||||||
#define DRA752_BANDGAP_THRESHOLD_MPU_OFFSET 0x1a4
|
#define DRA752_BANDGAP_THRESHOLD_MPU_OFFSET 0x1a4
|
||||||
#define DRA752_BANDGAP_TSHUT_MPU_OFFSET 0x1b0
|
|
||||||
#define DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET 0x1bc
|
#define DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET 0x1bc
|
||||||
#define DRA752_DTEMP_MPU_0_OFFSET 0x1e0
|
#define DRA752_DTEMP_MPU_0_OFFSET 0x1e0
|
||||||
#define DRA752_DTEMP_MPU_1_OFFSET 0x1e4
|
#define DRA752_DTEMP_MPU_1_OFFSET 0x1e4
|
||||||
|
@ -90,7 +87,6 @@
|
||||||
#define DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET 0x384
|
#define DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET 0x384
|
||||||
#define DRA752_TEMP_SENSOR_DSPEVE_OFFSET 0x394
|
#define DRA752_TEMP_SENSOR_DSPEVE_OFFSET 0x394
|
||||||
#define DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET 0x3a0
|
#define DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET 0x3a0
|
||||||
#define DRA752_BANDGAP_TSHUT_DSPEVE_OFFSET 0x3a8
|
|
||||||
#define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET 0x3b0
|
#define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET 0x3b0
|
||||||
#define DRA752_DTEMP_DSPEVE_0_OFFSET 0x3bc
|
#define DRA752_DTEMP_DSPEVE_0_OFFSET 0x3bc
|
||||||
#define DRA752_DTEMP_DSPEVE_1_OFFSET 0x3c0
|
#define DRA752_DTEMP_DSPEVE_1_OFFSET 0x3c0
|
||||||
|
@ -102,7 +98,6 @@
|
||||||
#define DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET 0x0
|
#define DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET 0x0
|
||||||
#define DRA752_TEMP_SENSOR_GPU_OFFSET 0x150
|
#define DRA752_TEMP_SENSOR_GPU_OFFSET 0x150
|
||||||
#define DRA752_BANDGAP_THRESHOLD_GPU_OFFSET 0x1a8
|
#define DRA752_BANDGAP_THRESHOLD_GPU_OFFSET 0x1a8
|
||||||
#define DRA752_BANDGAP_TSHUT_GPU_OFFSET 0x1b4
|
|
||||||
#define DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET 0x1c0
|
#define DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET 0x1c0
|
||||||
#define DRA752_DTEMP_GPU_0_OFFSET 0x1f4
|
#define DRA752_DTEMP_GPU_0_OFFSET 0x1f4
|
||||||
#define DRA752_DTEMP_GPU_1_OFFSET 0x1f8
|
#define DRA752_DTEMP_GPU_1_OFFSET 0x1f8
|
||||||
|
@ -173,10 +168,6 @@
|
||||||
#define DRA752_BANDGAP_THRESHOLD_HOT_MASK (0x3ff << 16)
|
#define DRA752_BANDGAP_THRESHOLD_HOT_MASK (0x3ff << 16)
|
||||||
#define DRA752_BANDGAP_THRESHOLD_COLD_MASK (0x3ff << 0)
|
#define DRA752_BANDGAP_THRESHOLD_COLD_MASK (0x3ff << 0)
|
||||||
|
|
||||||
/* DRA752.TSHUT_THRESHOLD */
|
|
||||||
#define DRA752_TSHUT_THRESHOLD_MUXCTRL_MASK BIT(31)
|
|
||||||
#define DRA752_TSHUT_THRESHOLD_HOT_MASK (0x3ff << 16)
|
|
||||||
#define DRA752_TSHUT_THRESHOLD_COLD_MASK (0x3ff << 0)
|
|
||||||
|
|
||||||
/* DRA752.BANDGAP_CUMUL_DTEMP_CORE */
|
/* DRA752.BANDGAP_CUMUL_DTEMP_CORE */
|
||||||
#define DRA752_BANDGAP_CUMUL_DTEMP_CORE_MASK (0xffffffff << 0)
|
#define DRA752_BANDGAP_CUMUL_DTEMP_CORE_MASK (0xffffffff << 0)
|
||||||
|
@ -216,8 +207,6 @@
|
||||||
#define DRA752_GPU_MAX_TEMP 125000
|
#define DRA752_GPU_MAX_TEMP 125000
|
||||||
#define DRA752_GPU_HYST_VAL 5000
|
#define DRA752_GPU_HYST_VAL 5000
|
||||||
/* interrupts thresholds */
|
/* interrupts thresholds */
|
||||||
#define DRA752_GPU_TSHUT_HOT 915
|
|
||||||
#define DRA752_GPU_TSHUT_COLD 900
|
|
||||||
#define DRA752_GPU_T_HOT 800
|
#define DRA752_GPU_T_HOT 800
|
||||||
#define DRA752_GPU_T_COLD 795
|
#define DRA752_GPU_T_COLD 795
|
||||||
|
|
||||||
|
@ -230,8 +219,6 @@
|
||||||
#define DRA752_MPU_MAX_TEMP 125000
|
#define DRA752_MPU_MAX_TEMP 125000
|
||||||
#define DRA752_MPU_HYST_VAL 5000
|
#define DRA752_MPU_HYST_VAL 5000
|
||||||
/* interrupts thresholds */
|
/* interrupts thresholds */
|
||||||
#define DRA752_MPU_TSHUT_HOT 915
|
|
||||||
#define DRA752_MPU_TSHUT_COLD 900
|
|
||||||
#define DRA752_MPU_T_HOT 800
|
#define DRA752_MPU_T_HOT 800
|
||||||
#define DRA752_MPU_T_COLD 795
|
#define DRA752_MPU_T_COLD 795
|
||||||
|
|
||||||
|
@ -244,8 +231,6 @@
|
||||||
#define DRA752_CORE_MAX_TEMP 125000
|
#define DRA752_CORE_MAX_TEMP 125000
|
||||||
#define DRA752_CORE_HYST_VAL 5000
|
#define DRA752_CORE_HYST_VAL 5000
|
||||||
/* interrupts thresholds */
|
/* interrupts thresholds */
|
||||||
#define DRA752_CORE_TSHUT_HOT 915
|
|
||||||
#define DRA752_CORE_TSHUT_COLD 900
|
|
||||||
#define DRA752_CORE_T_HOT 800
|
#define DRA752_CORE_T_HOT 800
|
||||||
#define DRA752_CORE_T_COLD 795
|
#define DRA752_CORE_T_COLD 795
|
||||||
|
|
||||||
|
@ -258,8 +243,6 @@
|
||||||
#define DRA752_DSPEVE_MAX_TEMP 125000
|
#define DRA752_DSPEVE_MAX_TEMP 125000
|
||||||
#define DRA752_DSPEVE_HYST_VAL 5000
|
#define DRA752_DSPEVE_HYST_VAL 5000
|
||||||
/* interrupts thresholds */
|
/* interrupts thresholds */
|
||||||
#define DRA752_DSPEVE_TSHUT_HOT 915
|
|
||||||
#define DRA752_DSPEVE_TSHUT_COLD 900
|
|
||||||
#define DRA752_DSPEVE_T_HOT 800
|
#define DRA752_DSPEVE_T_HOT 800
|
||||||
#define DRA752_DSPEVE_T_COLD 795
|
#define DRA752_DSPEVE_T_COLD 795
|
||||||
|
|
||||||
|
@ -272,8 +255,6 @@
|
||||||
#define DRA752_IVA_MAX_TEMP 125000
|
#define DRA752_IVA_MAX_TEMP 125000
|
||||||
#define DRA752_IVA_HYST_VAL 5000
|
#define DRA752_IVA_HYST_VAL 5000
|
||||||
/* interrupts thresholds */
|
/* interrupts thresholds */
|
||||||
#define DRA752_IVA_TSHUT_HOT 915
|
|
||||||
#define DRA752_IVA_TSHUT_COLD 900
|
|
||||||
#define DRA752_IVA_T_HOT 800
|
#define DRA752_IVA_T_HOT 800
|
||||||
#define DRA752_IVA_T_COLD 795
|
#define DRA752_IVA_T_COLD 795
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,6 @@ dra752_core_temp_sensor_registers = {
|
||||||
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_CORE_OFFSET,
|
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_CORE_OFFSET,
|
||||||
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
||||||
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
||||||
.tshut_threshold = DRA752_BANDGAP_TSHUT_CORE_OFFSET,
|
|
||||||
.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
|
|
||||||
.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
|
|
||||||
.bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET,
|
.bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET,
|
||||||
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
||||||
.status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK,
|
.status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK,
|
||||||
|
@ -85,9 +82,6 @@ dra752_iva_temp_sensor_registers = {
|
||||||
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_IVA_OFFSET,
|
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_IVA_OFFSET,
|
||||||
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
||||||
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
||||||
.tshut_threshold = DRA752_BANDGAP_TSHUT_IVA_OFFSET,
|
|
||||||
.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
|
|
||||||
.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
|
|
||||||
.bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET,
|
.bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET,
|
||||||
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
||||||
.status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK,
|
.status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK,
|
||||||
|
@ -121,9 +115,6 @@ dra752_mpu_temp_sensor_registers = {
|
||||||
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_MPU_OFFSET,
|
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_MPU_OFFSET,
|
||||||
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
||||||
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
||||||
.tshut_threshold = DRA752_BANDGAP_TSHUT_MPU_OFFSET,
|
|
||||||
.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
|
|
||||||
.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
|
|
||||||
.bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET,
|
.bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET,
|
||||||
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
||||||
.status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK,
|
.status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK,
|
||||||
|
@ -157,9 +148,6 @@ dra752_dspeve_temp_sensor_registers = {
|
||||||
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET,
|
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET,
|
||||||
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
||||||
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
||||||
.tshut_threshold = DRA752_BANDGAP_TSHUT_DSPEVE_OFFSET,
|
|
||||||
.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
|
|
||||||
.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
|
|
||||||
.bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET,
|
.bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET,
|
||||||
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
||||||
.status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK,
|
.status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK,
|
||||||
|
@ -193,9 +181,6 @@ dra752_gpu_temp_sensor_registers = {
|
||||||
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_GPU_OFFSET,
|
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_GPU_OFFSET,
|
||||||
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
||||||
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
||||||
.tshut_threshold = DRA752_BANDGAP_TSHUT_GPU_OFFSET,
|
|
||||||
.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
|
|
||||||
.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
|
|
||||||
.bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET,
|
.bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET,
|
||||||
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
||||||
.status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK,
|
.status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK,
|
||||||
|
@ -211,8 +196,6 @@ dra752_gpu_temp_sensor_registers = {
|
||||||
|
|
||||||
/* Thresholds and limits for DRA752 MPU temperature sensor */
|
/* Thresholds and limits for DRA752 MPU temperature sensor */
|
||||||
static struct temp_sensor_data dra752_mpu_temp_sensor_data = {
|
static struct temp_sensor_data dra752_mpu_temp_sensor_data = {
|
||||||
.tshut_hot = DRA752_MPU_TSHUT_HOT,
|
|
||||||
.tshut_cold = DRA752_MPU_TSHUT_COLD,
|
|
||||||
.t_hot = DRA752_MPU_T_HOT,
|
.t_hot = DRA752_MPU_T_HOT,
|
||||||
.t_cold = DRA752_MPU_T_COLD,
|
.t_cold = DRA752_MPU_T_COLD,
|
||||||
.min_freq = DRA752_MPU_MIN_FREQ,
|
.min_freq = DRA752_MPU_MIN_FREQ,
|
||||||
|
@ -226,8 +209,6 @@ static struct temp_sensor_data dra752_mpu_temp_sensor_data = {
|
||||||
|
|
||||||
/* Thresholds and limits for DRA752 GPU temperature sensor */
|
/* Thresholds and limits for DRA752 GPU temperature sensor */
|
||||||
static struct temp_sensor_data dra752_gpu_temp_sensor_data = {
|
static struct temp_sensor_data dra752_gpu_temp_sensor_data = {
|
||||||
.tshut_hot = DRA752_GPU_TSHUT_HOT,
|
|
||||||
.tshut_cold = DRA752_GPU_TSHUT_COLD,
|
|
||||||
.t_hot = DRA752_GPU_T_HOT,
|
.t_hot = DRA752_GPU_T_HOT,
|
||||||
.t_cold = DRA752_GPU_T_COLD,
|
.t_cold = DRA752_GPU_T_COLD,
|
||||||
.min_freq = DRA752_GPU_MIN_FREQ,
|
.min_freq = DRA752_GPU_MIN_FREQ,
|
||||||
|
@ -241,8 +222,6 @@ static struct temp_sensor_data dra752_gpu_temp_sensor_data = {
|
||||||
|
|
||||||
/* Thresholds and limits for DRA752 CORE temperature sensor */
|
/* Thresholds and limits for DRA752 CORE temperature sensor */
|
||||||
static struct temp_sensor_data dra752_core_temp_sensor_data = {
|
static struct temp_sensor_data dra752_core_temp_sensor_data = {
|
||||||
.tshut_hot = DRA752_CORE_TSHUT_HOT,
|
|
||||||
.tshut_cold = DRA752_CORE_TSHUT_COLD,
|
|
||||||
.t_hot = DRA752_CORE_T_HOT,
|
.t_hot = DRA752_CORE_T_HOT,
|
||||||
.t_cold = DRA752_CORE_T_COLD,
|
.t_cold = DRA752_CORE_T_COLD,
|
||||||
.min_freq = DRA752_CORE_MIN_FREQ,
|
.min_freq = DRA752_CORE_MIN_FREQ,
|
||||||
|
@ -256,8 +235,6 @@ static struct temp_sensor_data dra752_core_temp_sensor_data = {
|
||||||
|
|
||||||
/* Thresholds and limits for DRA752 DSPEVE temperature sensor */
|
/* Thresholds and limits for DRA752 DSPEVE temperature sensor */
|
||||||
static struct temp_sensor_data dra752_dspeve_temp_sensor_data = {
|
static struct temp_sensor_data dra752_dspeve_temp_sensor_data = {
|
||||||
.tshut_hot = DRA752_DSPEVE_TSHUT_HOT,
|
|
||||||
.tshut_cold = DRA752_DSPEVE_TSHUT_COLD,
|
|
||||||
.t_hot = DRA752_DSPEVE_T_HOT,
|
.t_hot = DRA752_DSPEVE_T_HOT,
|
||||||
.t_cold = DRA752_DSPEVE_T_COLD,
|
.t_cold = DRA752_DSPEVE_T_COLD,
|
||||||
.min_freq = DRA752_DSPEVE_MIN_FREQ,
|
.min_freq = DRA752_DSPEVE_MIN_FREQ,
|
||||||
|
@ -271,8 +248,6 @@ static struct temp_sensor_data dra752_dspeve_temp_sensor_data = {
|
||||||
|
|
||||||
/* Thresholds and limits for DRA752 IVA temperature sensor */
|
/* Thresholds and limits for DRA752 IVA temperature sensor */
|
||||||
static struct temp_sensor_data dra752_iva_temp_sensor_data = {
|
static struct temp_sensor_data dra752_iva_temp_sensor_data = {
|
||||||
.tshut_hot = DRA752_IVA_TSHUT_HOT,
|
|
||||||
.tshut_cold = DRA752_IVA_TSHUT_COLD,
|
|
||||||
.t_hot = DRA752_IVA_T_HOT,
|
.t_hot = DRA752_IVA_T_HOT,
|
||||||
.t_cold = DRA752_IVA_T_COLD,
|
.t_cold = DRA752_IVA_T_COLD,
|
||||||
.min_freq = DRA752_IVA_MIN_FREQ,
|
.min_freq = DRA752_IVA_MIN_FREQ,
|
||||||
|
@ -416,8 +391,7 @@ int dra752_adc_to_temp[DRA752_ADC_END_VALUE - DRA752_ADC_START_VALUE + 1] = {
|
||||||
|
|
||||||
/* DRA752 data */
|
/* DRA752 data */
|
||||||
const struct ti_bandgap_data dra752_data = {
|
const struct ti_bandgap_data dra752_data = {
|
||||||
.features = TI_BANDGAP_FEATURE_TSHUT_CONFIG |
|
.features = TI_BANDGAP_FEATURE_FREEZE_BIT |
|
||||||
TI_BANDGAP_FEATURE_FREEZE_BIT |
|
|
||||||
TI_BANDGAP_FEATURE_TALERT |
|
TI_BANDGAP_FEATURE_TALERT |
|
||||||
TI_BANDGAP_FEATURE_COUNTER_DELAY |
|
TI_BANDGAP_FEATURE_COUNTER_DELAY |
|
||||||
TI_BANDGAP_FEATURE_HISTORY_BUFFER |
|
TI_BANDGAP_FEATURE_HISTORY_BUFFER |
|
||||||
|
|
|
@ -0,0 +1,258 @@
|
||||||
|
/*
|
||||||
|
* ZTE's zx2967 family thermal sensor driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 ZTE Ltd.
|
||||||
|
*
|
||||||
|
* Author: Baoyou Xie <baoyou.xie@linaro.org>
|
||||||
|
*
|
||||||
|
* License terms: GNU General Public License (GPL) version 2
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/iopoll.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/thermal.h>
|
||||||
|
|
||||||
|
/* Power Mode: 0->low 1->high */
|
||||||
|
#define ZX2967_THERMAL_POWER_MODE 0
|
||||||
|
#define ZX2967_POWER_MODE_LOW 0
|
||||||
|
#define ZX2967_POWER_MODE_HIGH 1
|
||||||
|
|
||||||
|
/* DCF Control Register */
|
||||||
|
#define ZX2967_THERMAL_DCF 0x4
|
||||||
|
#define ZX2967_DCF_EN BIT(1)
|
||||||
|
#define ZX2967_DCF_FREEZE BIT(0)
|
||||||
|
|
||||||
|
/* Selection Register */
|
||||||
|
#define ZX2967_THERMAL_SEL 0x8
|
||||||
|
|
||||||
|
/* Control Register */
|
||||||
|
#define ZX2967_THERMAL_CTRL 0x10
|
||||||
|
|
||||||
|
#define ZX2967_THERMAL_READY BIT(12)
|
||||||
|
#define ZX2967_THERMAL_TEMP_MASK GENMASK(11, 0)
|
||||||
|
#define ZX2967_THERMAL_ID_MASK 0x18
|
||||||
|
#define ZX2967_THERMAL_ID 0x10
|
||||||
|
|
||||||
|
#define ZX2967_GET_TEMP_TIMEOUT_US (100 * 1024)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct zx2967_thermal_priv - zx2967 thermal sensor private structure
|
||||||
|
* @tzd: struct thermal_zone_device where the sensor is registered
|
||||||
|
* @lock: prevents read sensor in parallel
|
||||||
|
* @clk_topcrm: topcrm clk structure
|
||||||
|
* @clk_apb: apb clk structure
|
||||||
|
* @regs: pointer to base address of the thermal sensor
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct zx2967_thermal_priv {
|
||||||
|
struct thermal_zone_device *tzd;
|
||||||
|
struct mutex lock;
|
||||||
|
struct clk *clk_topcrm;
|
||||||
|
struct clk *clk_apb;
|
||||||
|
void __iomem *regs;
|
||||||
|
struct device *dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int zx2967_thermal_get_temp(void *data, int *temp)
|
||||||
|
{
|
||||||
|
void __iomem *regs;
|
||||||
|
struct zx2967_thermal_priv *priv = data;
|
||||||
|
u32 val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!priv->tzd)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
|
regs = priv->regs;
|
||||||
|
mutex_lock(&priv->lock);
|
||||||
|
writel_relaxed(ZX2967_POWER_MODE_LOW,
|
||||||
|
regs + ZX2967_THERMAL_POWER_MODE);
|
||||||
|
writel_relaxed(ZX2967_DCF_EN, regs + ZX2967_THERMAL_DCF);
|
||||||
|
|
||||||
|
val = readl_relaxed(regs + ZX2967_THERMAL_SEL);
|
||||||
|
val &= ~ZX2967_THERMAL_ID_MASK;
|
||||||
|
val |= ZX2967_THERMAL_ID;
|
||||||
|
writel_relaxed(val, regs + ZX2967_THERMAL_SEL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must wait for a while, surely it's a bit odd.
|
||||||
|
* otherwise temperature value we got has a few deviation, even if
|
||||||
|
* the THERMAL_READY bit is set.
|
||||||
|
*/
|
||||||
|
usleep_range(100, 300);
|
||||||
|
ret = readx_poll_timeout(readl, regs + ZX2967_THERMAL_CTRL,
|
||||||
|
val, val & ZX2967_THERMAL_READY, 300,
|
||||||
|
ZX2967_GET_TEMP_TIMEOUT_US);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(priv->dev, "Thermal sensor data timeout\n");
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
writel_relaxed(ZX2967_DCF_FREEZE | ZX2967_DCF_EN,
|
||||||
|
regs + ZX2967_THERMAL_DCF);
|
||||||
|
val = readl_relaxed(regs + ZX2967_THERMAL_CTRL)
|
||||||
|
& ZX2967_THERMAL_TEMP_MASK;
|
||||||
|
writel_relaxed(ZX2967_POWER_MODE_HIGH,
|
||||||
|
regs + ZX2967_THERMAL_POWER_MODE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate temperature
|
||||||
|
* In dts, slope is multiplied by 1000.
|
||||||
|
*/
|
||||||
|
*temp = DIV_ROUND_CLOSEST(((s32)val + priv->tzd->tzp->offset) * 1000,
|
||||||
|
priv->tzd->tzp->slope);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
mutex_unlock(&priv->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct thermal_zone_of_device_ops zx2967_of_thermal_ops = {
|
||||||
|
.get_temp = zx2967_thermal_get_temp,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int zx2967_thermal_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct zx2967_thermal_priv *priv;
|
||||||
|
struct resource *res;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
priv->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
if (IS_ERR(priv->regs))
|
||||||
|
return PTR_ERR(priv->regs);
|
||||||
|
|
||||||
|
priv->clk_topcrm = devm_clk_get(&pdev->dev, "topcrm");
|
||||||
|
if (IS_ERR(priv->clk_topcrm)) {
|
||||||
|
ret = PTR_ERR(priv->clk_topcrm);
|
||||||
|
dev_err(&pdev->dev, "failed to get topcrm clock: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(priv->clk_topcrm);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "failed to enable topcrm clock: %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->clk_apb = devm_clk_get(&pdev->dev, "apb");
|
||||||
|
if (IS_ERR(priv->clk_apb)) {
|
||||||
|
ret = PTR_ERR(priv->clk_apb);
|
||||||
|
dev_err(&pdev->dev, "failed to get apb clock: %d\n", ret);
|
||||||
|
goto disable_clk_topcrm;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(priv->clk_apb);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "failed to enable apb clock: %d\n",
|
||||||
|
ret);
|
||||||
|
goto disable_clk_topcrm;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_init(&priv->lock);
|
||||||
|
priv->tzd = thermal_zone_of_sensor_register(&pdev->dev,
|
||||||
|
0, priv, &zx2967_of_thermal_ops);
|
||||||
|
|
||||||
|
if (IS_ERR(priv->tzd)) {
|
||||||
|
ret = PTR_ERR(priv->tzd);
|
||||||
|
dev_err(&pdev->dev, "failed to register sensor: %d\n", ret);
|
||||||
|
goto disable_clk_all;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->tzd->tzp->slope == 0) {
|
||||||
|
thermal_zone_of_sensor_unregister(&pdev->dev, priv->tzd);
|
||||||
|
dev_err(&pdev->dev, "coefficients of sensor is invalid\n");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto disable_clk_all;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->dev = &pdev->dev;
|
||||||
|
platform_set_drvdata(pdev, priv);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
disable_clk_all:
|
||||||
|
clk_disable_unprepare(priv->clk_apb);
|
||||||
|
disable_clk_topcrm:
|
||||||
|
clk_disable_unprepare(priv->clk_topcrm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int zx2967_thermal_exit(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
thermal_zone_of_sensor_unregister(&pdev->dev, priv->tzd);
|
||||||
|
clk_disable_unprepare(priv->clk_topcrm);
|
||||||
|
clk_disable_unprepare(priv->clk_apb);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id zx2967_thermal_id_table[] = {
|
||||||
|
{ .compatible = "zte,zx296718-thermal" },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, zx2967_thermal_id_table);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int zx2967_thermal_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
if (priv && priv->clk_topcrm)
|
||||||
|
clk_disable_unprepare(priv->clk_topcrm);
|
||||||
|
|
||||||
|
if (priv && priv->clk_apb)
|
||||||
|
clk_disable_unprepare(priv->clk_apb);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int zx2967_thermal_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = clk_prepare_enable(priv->clk_topcrm);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
error = clk_prepare_enable(priv->clk_apb);
|
||||||
|
if (error) {
|
||||||
|
clk_disable_unprepare(priv->clk_topcrm);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(zx2967_thermal_pm_ops,
|
||||||
|
zx2967_thermal_suspend, zx2967_thermal_resume);
|
||||||
|
|
||||||
|
static struct platform_driver zx2967_thermal_driver = {
|
||||||
|
.probe = zx2967_thermal_probe,
|
||||||
|
.remove = zx2967_thermal_exit,
|
||||||
|
.driver = {
|
||||||
|
.name = "zx2967_thermal",
|
||||||
|
.of_match_table = zx2967_thermal_id_table,
|
||||||
|
.pm = &zx2967_thermal_pm_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
module_platform_driver(zx2967_thermal_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
|
||||||
|
MODULE_DESCRIPTION("ZTE zx2967 thermal driver");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
Loading…
Reference in New Issue