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:
Коммит
e4cb5bb286
|
@ -3,15 +3,39 @@ Binding for Thermal Sensor driver for BCM2835 SoCs.
|
|||
Required parameters:
|
||||
-------------------
|
||||
|
||||
compatible: should be one of: "brcm,bcm2835-thermal",
|
||||
"brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
|
||||
reg: Address range of the thermal registers.
|
||||
clocks: Phandle of the clock used by the thermal sensor.
|
||||
compatible: should be one of: "brcm,bcm2835-thermal",
|
||||
"brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
|
||||
reg: Address range of the thermal registers.
|
||||
clocks: Phandle of the clock used by the thermal sensor.
|
||||
#thermal-sensor-cells: should be 0 (see thermal.txt)
|
||||
|
||||
Example:
|
||||
|
||||
thermal-zones {
|
||||
cpu_thermal: cpu-thermal {
|
||||
polling-delay-passive = <0>;
|
||||
polling-delay = <1000>;
|
||||
|
||||
thermal-sensors = <&thermal>;
|
||||
|
||||
trips {
|
||||
cpu-crit {
|
||||
temperature = <80000>;
|
||||
hysteresis = <0>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
|
||||
coefficients = <(-538) 407000>;
|
||||
|
||||
cooling-maps {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
thermal: thermal@7e212000 {
|
||||
compatible = "brcm,bcm2835-thermal";
|
||||
reg = <0x7e212000 0x8>;
|
||||
clocks = <&clocks BCM2835_CLOCK_TSENS>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
* Broadcom Northstar Thermal
|
||||
|
||||
This binding describes thermal sensor that is part of Northstar's DMU (Device
|
||||
Management Unit).
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be "brcm,ns-thermal"
|
||||
- reg : iomem address range of PVTMON registers
|
||||
- #thermal-sensor-cells : Should be <0>
|
||||
|
||||
Example:
|
||||
|
||||
thermal: thermal@1800c2c0 {
|
||||
compatible = "brcm,ns-thermal";
|
||||
reg = <0x1800c2c0 0x10>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
cpu_thermal: cpu-thermal {
|
||||
polling-delay-passive = <0>;
|
||||
polling-delay = <1000>;
|
||||
coefficients = <(-556) 418000>;
|
||||
thermal-sensors = <&thermal>;
|
||||
|
||||
trips {
|
||||
cpu-crit {
|
||||
temperature = <125000>;
|
||||
hysteresis = <0>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
* Dialog DA9062/61 TJUNC Thermal Module
|
||||
|
||||
This module is part of the DA9061/DA9062. For more details about entire
|
||||
DA9062 and DA9061 chips see Documentation/devicetree/bindings/mfd/da9062.txt
|
||||
|
||||
Junction temperature thermal module uses an interrupt signal to identify
|
||||
high THERMAL_TRIP_HOT temperatures for the PMIC device.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should be one of the following valid compatible string lines:
|
||||
"dlg,da9061-thermal", "dlg,da9062-thermal"
|
||||
"dlg,da9062-thermal"
|
||||
|
||||
Optional properties:
|
||||
|
||||
- polling-delay-passive : Specify the polling period, measured in
|
||||
milliseconds, between thermal zone device update checks.
|
||||
|
||||
Example: DA9062
|
||||
|
||||
pmic0: da9062@58 {
|
||||
thermal {
|
||||
compatible = "dlg,da9062-thermal";
|
||||
polling-delay-passive = <3000>;
|
||||
};
|
||||
};
|
||||
|
||||
Example: DA9061 using a fall-back compatible for the DA9062 onkey driver
|
||||
|
||||
pmic0: da9061@58 {
|
||||
thermal {
|
||||
compatible = "dlg,da9061-thermal", "dlg,da9062-thermal";
|
||||
polling-delay-passive = <3000>;
|
||||
};
|
||||
};
|
|
@ -303,6 +303,16 @@ config DB8500_CPUFREQ_COOLING
|
|||
bound cpufreq cooling device turns active to set CPU frequency low to
|
||||
cool down the CPU.
|
||||
|
||||
config DA9062_THERMAL
|
||||
tristate "DA9062/DA9061 Dialog Semiconductor thermal driver"
|
||||
depends on MFD_DA9062 || COMPILE_TEST
|
||||
depends on OF
|
||||
help
|
||||
Enable this for the Dialog Semiconductor thermal sensor driver.
|
||||
This will report PMIC junction over-temperature for one thermal trip
|
||||
zone.
|
||||
Compatible with the DA9062 and DA9061 PMICs.
|
||||
|
||||
config INTEL_POWERCLAMP
|
||||
tristate "Intel PowerClamp idle injection driver"
|
||||
depends on THERMAL
|
||||
|
@ -392,6 +402,11 @@ config MTK_THERMAL
|
|||
Enable this option if you want to have support for thermal management
|
||||
controller present in Mediatek SoCs
|
||||
|
||||
menu "Broadcom thermal drivers"
|
||||
depends on ARCH_BCM || COMPILE_TEST
|
||||
source "drivers/thermal/broadcom/Kconfig"
|
||||
endmenu
|
||||
|
||||
menu "Texas Instruments thermal drivers"
|
||||
depends on ARCH_HAS_BANDGAP || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
|
|
|
@ -27,6 +27,7 @@ thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o
|
|||
thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
|
||||
|
||||
# platform thermal drivers
|
||||
obj-y += broadcom/
|
||||
obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
|
||||
obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
|
||||
obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
|
||||
|
@ -42,6 +43,7 @@ obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
|
|||
obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o
|
||||
obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
|
||||
obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
|
||||
obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o
|
||||
obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
|
||||
obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
|
||||
obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE) += intel_soc_dts_iosf.o
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
config BCM2835_THERMAL
|
||||
tristate "Thermal sensors on bcm2835 SoC"
|
||||
depends on ARCH_BCM2835 || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
depends on THERMAL_OF
|
||||
help
|
||||
Support for thermal sensors on Broadcom bcm2835 SoCs.
|
||||
|
||||
config BCM_NS_THERMAL
|
||||
tristate "Northstar thermal driver"
|
||||
depends on ARCH_BCM_IPROC || COMPILE_TEST
|
||||
help
|
||||
Northstar is a family of SoCs that includes e.g. BCM4708, BCM47081,
|
||||
BCM4709 and BCM47094. It contains DMU (Device Management Unit) block
|
||||
with a thermal sensor that allows checking CPU temperature. This
|
||||
driver provides support for it.
|
|
@ -0,0 +1,2 @@
|
|||
obj-$(CONFIG_BCM2835_THERMAL) += bcm2835_thermal.o
|
||||
obj-$(CONFIG_BCM_NS_THERMAL) += ns-thermal.o
|
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
* Driver for Broadcom BCM2835 SoC temperature sensor
|
||||
*
|
||||
* Copyright (C) 2016 Martin Sperl
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/thermal.h>
|
||||
|
||||
#define BCM2835_TS_TSENSCTL 0x00
|
||||
#define BCM2835_TS_TSENSSTAT 0x04
|
||||
|
||||
#define BCM2835_TS_TSENSCTL_PRWDW BIT(0)
|
||||
#define BCM2835_TS_TSENSCTL_RSTB BIT(1)
|
||||
|
||||
/*
|
||||
* bandgap reference voltage in 6 mV increments
|
||||
* 000b = 1178 mV, 001b = 1184 mV, ... 111b = 1220 mV
|
||||
*/
|
||||
#define BCM2835_TS_TSENSCTL_CTRL_BITS 3
|
||||
#define BCM2835_TS_TSENSCTL_CTRL_SHIFT 2
|
||||
#define BCM2835_TS_TSENSCTL_CTRL_MASK \
|
||||
GENMASK(BCM2835_TS_TSENSCTL_CTRL_BITS + \
|
||||
BCM2835_TS_TSENSCTL_CTRL_SHIFT - 1, \
|
||||
BCM2835_TS_TSENSCTL_CTRL_SHIFT)
|
||||
#define BCM2835_TS_TSENSCTL_CTRL_DEFAULT 1
|
||||
#define BCM2835_TS_TSENSCTL_EN_INT BIT(5)
|
||||
#define BCM2835_TS_TSENSCTL_DIRECT BIT(6)
|
||||
#define BCM2835_TS_TSENSCTL_CLR_INT BIT(7)
|
||||
#define BCM2835_TS_TSENSCTL_THOLD_SHIFT 8
|
||||
#define BCM2835_TS_TSENSCTL_THOLD_BITS 10
|
||||
#define BCM2835_TS_TSENSCTL_THOLD_MASK \
|
||||
GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS + \
|
||||
BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \
|
||||
BCM2835_TS_TSENSCTL_THOLD_SHIFT)
|
||||
/*
|
||||
* time how long the block to be asserted in reset
|
||||
* which based on a clock counter (TSENS clock assumed)
|
||||
*/
|
||||
#define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT 18
|
||||
#define BCM2835_TS_TSENSCTL_RSTDELAY_BITS 8
|
||||
#define BCM2835_TS_TSENSCTL_REGULEN BIT(26)
|
||||
|
||||
#define BCM2835_TS_TSENSSTAT_DATA_BITS 10
|
||||
#define BCM2835_TS_TSENSSTAT_DATA_SHIFT 0
|
||||
#define BCM2835_TS_TSENSSTAT_DATA_MASK \
|
||||
GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS + \
|
||||
BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \
|
||||
BCM2835_TS_TSENSSTAT_DATA_SHIFT)
|
||||
#define BCM2835_TS_TSENSSTAT_VALID BIT(10)
|
||||
#define BCM2835_TS_TSENSSTAT_INTERRUPT BIT(11)
|
||||
|
||||
struct bcm2835_thermal_data {
|
||||
struct thermal_zone_device *tz;
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
struct dentry *debugfsdir;
|
||||
};
|
||||
|
||||
static int bcm2835_thermal_adc2temp(u32 adc, int offset, int slope)
|
||||
{
|
||||
return offset + slope * adc;
|
||||
}
|
||||
|
||||
static int bcm2835_thermal_temp2adc(int temp, int offset, int slope)
|
||||
{
|
||||
temp -= offset;
|
||||
temp /= slope;
|
||||
|
||||
if (temp < 0)
|
||||
temp = 0;
|
||||
if (temp >= BIT(BCM2835_TS_TSENSSTAT_DATA_BITS))
|
||||
temp = BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static int bcm2835_thermal_get_temp(void *d, int *temp)
|
||||
{
|
||||
struct bcm2835_thermal_data *data = d;
|
||||
u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT);
|
||||
|
||||
if (!(val & BCM2835_TS_TSENSSTAT_VALID))
|
||||
return -EIO;
|
||||
|
||||
val &= BCM2835_TS_TSENSSTAT_DATA_MASK;
|
||||
|
||||
*temp = bcm2835_thermal_adc2temp(
|
||||
val,
|
||||
thermal_zone_get_offset(data->tz),
|
||||
thermal_zone_get_slope(data->tz));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct debugfs_reg32 bcm2835_thermal_regs[] = {
|
||||
{
|
||||
.name = "ctl",
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
.name = "stat",
|
||||
.offset = 4
|
||||
}
|
||||
};
|
||||
|
||||
static void bcm2835_thermal_debugfs(struct platform_device *pdev)
|
||||
{
|
||||
struct thermal_zone_device *tz = platform_get_drvdata(pdev);
|
||||
struct bcm2835_thermal_data *data = tz->devdata;
|
||||
struct debugfs_regset32 *regset;
|
||||
|
||||
data->debugfsdir = debugfs_create_dir("bcm2835_thermal", NULL);
|
||||
if (!data->debugfsdir)
|
||||
return;
|
||||
|
||||
regset = devm_kzalloc(&pdev->dev, sizeof(*regset), GFP_KERNEL);
|
||||
if (!regset)
|
||||
return;
|
||||
|
||||
regset->regs = bcm2835_thermal_regs;
|
||||
regset->nregs = ARRAY_SIZE(bcm2835_thermal_regs);
|
||||
regset->base = data->regs;
|
||||
|
||||
debugfs_create_regset32("regset", 0444, data->debugfsdir, regset);
|
||||
}
|
||||
|
||||
static struct thermal_zone_of_device_ops bcm2835_thermal_ops = {
|
||||
.get_temp = bcm2835_thermal_get_temp,
|
||||
};
|
||||
|
||||
/*
|
||||
* Note: as per Raspberry Foundation FAQ
|
||||
* (https://www.raspberrypi.org/help/faqs/#performanceOperatingTemperature)
|
||||
* the recommended temperature range for the SoC -40C to +85C
|
||||
* so the trip limit is set to 80C.
|
||||
* this applies to all the BCM283X SoC
|
||||
*/
|
||||
|
||||
static const struct of_device_id bcm2835_thermal_of_match_table[] = {
|
||||
{
|
||||
.compatible = "brcm,bcm2835-thermal",
|
||||
},
|
||||
{
|
||||
.compatible = "brcm,bcm2836-thermal",
|
||||
},
|
||||
{
|
||||
.compatible = "brcm,bcm2837-thermal",
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);
|
||||
|
||||
static int bcm2835_thermal_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
struct thermal_zone_device *tz;
|
||||
struct bcm2835_thermal_data *data;
|
||||
struct resource *res;
|
||||
int err = 0;
|
||||
u32 val;
|
||||
unsigned long rate;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
match = of_match_device(bcm2835_thermal_of_match_table,
|
||||
&pdev->dev);
|
||||
if (!match)
|
||||
return -EINVAL;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
data->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(data->regs)) {
|
||||
err = PTR_ERR(data->regs);
|
||||
dev_err(&pdev->dev, "Could not get registers: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
data->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(data->clk)) {
|
||||
err = PTR_ERR(data->clk);
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "Could not get clk: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = clk_prepare_enable(data->clk);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
rate = clk_get_rate(data->clk);
|
||||
if ((rate < 1920000) || (rate > 5000000))
|
||||
dev_warn(&pdev->dev,
|
||||
"Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz\n",
|
||||
data->clk, data->clk);
|
||||
|
||||
/* register of thermal sensor and get info from DT */
|
||||
tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
|
||||
&bcm2835_thermal_ops);
|
||||
if (IS_ERR(tz)) {
|
||||
err = PTR_ERR(tz);
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to register the thermal device: %d\n",
|
||||
err);
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* right now the FW does set up the HW-block, so we are not
|
||||
* touching the configuration registers.
|
||||
* But if the HW is not enabled, then set it up
|
||||
* using "sane" values used by the firmware right now.
|
||||
*/
|
||||
val = readl(data->regs + BCM2835_TS_TSENSCTL);
|
||||
if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {
|
||||
int trip_temp, offset, slope;
|
||||
|
||||
slope = thermal_zone_get_slope(tz);
|
||||
offset = thermal_zone_get_offset(tz);
|
||||
/*
|
||||
* For now we deal only with critical, otherwise
|
||||
* would need to iterate
|
||||
*/
|
||||
err = tz->ops->get_trip_temp(tz, 0, &trip_temp);
|
||||
if (err < 0) {
|
||||
err = PTR_ERR(tz);
|
||||
dev_err(&pdev->dev,
|
||||
"Not able to read trip_temp: %d\n",
|
||||
err);
|
||||
goto err_tz;
|
||||
}
|
||||
|
||||
/* set bandgap reference voltage and enable voltage regulator */
|
||||
val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT <<
|
||||
BCM2835_TS_TSENSCTL_CTRL_SHIFT) |
|
||||
BCM2835_TS_TSENSCTL_REGULEN;
|
||||
|
||||
/* use the recommended reset duration */
|
||||
val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);
|
||||
|
||||
/* trip_adc value from info */
|
||||
val |= bcm2835_thermal_temp2adc(trip_temp,
|
||||
offset,
|
||||
slope)
|
||||
<< BCM2835_TS_TSENSCTL_THOLD_SHIFT;
|
||||
|
||||
/* write the value back to the register as 2 steps */
|
||||
writel(val, data->regs + BCM2835_TS_TSENSCTL);
|
||||
val |= BCM2835_TS_TSENSCTL_RSTB;
|
||||
writel(val, data->regs + BCM2835_TS_TSENSCTL);
|
||||
}
|
||||
|
||||
data->tz = tz;
|
||||
|
||||
platform_set_drvdata(pdev, tz);
|
||||
|
||||
bcm2835_thermal_debugfs(pdev);
|
||||
|
||||
return 0;
|
||||
err_tz:
|
||||
thermal_zone_of_sensor_unregister(&pdev->dev, tz);
|
||||
err_clk:
|
||||
clk_disable_unprepare(data->clk);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bcm2835_thermal_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct thermal_zone_device *tz = platform_get_drvdata(pdev);
|
||||
struct bcm2835_thermal_data *data = tz->devdata;
|
||||
|
||||
debugfs_remove_recursive(data->debugfsdir);
|
||||
thermal_zone_of_sensor_unregister(&pdev->dev, tz);
|
||||
clk_disable_unprepare(data->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver bcm2835_thermal_driver = {
|
||||
.probe = bcm2835_thermal_probe,
|
||||
.remove = bcm2835_thermal_remove,
|
||||
.driver = {
|
||||
.name = "bcm2835_thermal",
|
||||
.of_match_table = bcm2835_thermal_of_match_table,
|
||||
},
|
||||
};
|
||||
module_platform_driver(bcm2835_thermal_driver);
|
||||
|
||||
MODULE_AUTHOR("Martin Sperl");
|
||||
MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/thermal.h>
|
||||
|
||||
#define PVTMON_CONTROL0 0x00
|
||||
#define PVTMON_CONTROL0_SEL_MASK 0x0000000e
|
||||
#define PVTMON_CONTROL0_SEL_TEMP_MONITOR 0x00000000
|
||||
#define PVTMON_CONTROL0_SEL_TEST_MODE 0x0000000e
|
||||
#define PVTMON_STATUS 0x08
|
||||
|
||||
struct ns_thermal {
|
||||
struct thermal_zone_device *tz;
|
||||
void __iomem *pvtmon;
|
||||
};
|
||||
|
||||
static int ns_thermal_get_temp(void *data, int *temp)
|
||||
{
|
||||
struct ns_thermal *ns_thermal = data;
|
||||
int offset = thermal_zone_get_offset(ns_thermal->tz);
|
||||
int slope = thermal_zone_get_slope(ns_thermal->tz);
|
||||
u32 val;
|
||||
|
||||
val = readl(ns_thermal->pvtmon + PVTMON_CONTROL0);
|
||||
if ((val & PVTMON_CONTROL0_SEL_MASK) != PVTMON_CONTROL0_SEL_TEMP_MONITOR) {
|
||||
/* Clear current mode selection */
|
||||
val &= ~PVTMON_CONTROL0_SEL_MASK;
|
||||
|
||||
/* Set temp monitor mode (it's the default actually) */
|
||||
val |= PVTMON_CONTROL0_SEL_TEMP_MONITOR;
|
||||
|
||||
writel(val, ns_thermal->pvtmon + PVTMON_CONTROL0);
|
||||
}
|
||||
|
||||
val = readl(ns_thermal->pvtmon + PVTMON_STATUS);
|
||||
*temp = slope * val + offset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct thermal_zone_of_device_ops ns_thermal_ops = {
|
||||
.get_temp = ns_thermal_get_temp,
|
||||
};
|
||||
|
||||
static int ns_thermal_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ns_thermal *ns_thermal;
|
||||
|
||||
ns_thermal = devm_kzalloc(dev, sizeof(*ns_thermal), GFP_KERNEL);
|
||||
if (!ns_thermal)
|
||||
return -ENOMEM;
|
||||
|
||||
ns_thermal->pvtmon = of_iomap(dev_of_node(dev), 0);
|
||||
if (WARN_ON(!ns_thermal->pvtmon))
|
||||
return -ENOENT;
|
||||
|
||||
ns_thermal->tz = devm_thermal_zone_of_sensor_register(dev, 0,
|
||||
ns_thermal,
|
||||
&ns_thermal_ops);
|
||||
if (IS_ERR(ns_thermal->tz)) {
|
||||
iounmap(ns_thermal->pvtmon);
|
||||
return PTR_ERR(ns_thermal->tz);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, ns_thermal);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ns_thermal_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ns_thermal *ns_thermal = platform_get_drvdata(pdev);
|
||||
|
||||
iounmap(ns_thermal->pvtmon);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ns_thermal_of_match[] = {
|
||||
{ .compatible = "brcm,ns-thermal", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ns_thermal_of_match);
|
||||
|
||||
static struct platform_driver ns_thermal_driver = {
|
||||
.probe = ns_thermal_probe,
|
||||
.remove = ns_thermal_remove,
|
||||
.driver = {
|
||||
.name = "ns-thermal",
|
||||
.of_match_table = ns_thermal_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(ns_thermal_driver);
|
||||
|
||||
MODULE_AUTHOR("Rafał Miłecki <rafal@milecki.pl>");
|
||||
MODULE_DESCRIPTION("Northstar thermal driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
* Thermal device driver for DA9062 and DA9061
|
||||
* Copyright (C) 2017 Dialog Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* When over-temperature is reached, an interrupt from the device will be
|
||||
* triggered. Following this event the interrupt will be disabled and
|
||||
* periodic transmission of uevents (HOT trip point) should define the
|
||||
* first level of temperature supervision. It is expected that any final
|
||||
* implementation of the thermal driver will include a .notify() function
|
||||
* to implement these uevents to userspace.
|
||||
*
|
||||
* These uevents are intended to indicate non-invasive temperature control
|
||||
* of the system, where the necessary measures for cooling are the
|
||||
* responsibility of the host software. Once the temperature falls again,
|
||||
* the IRQ is re-enabled so the start of a new over-temperature event can
|
||||
* be detected without constant software monitoring.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <linux/mfd/da9062/core.h>
|
||||
#include <linux/mfd/da9062/registers.h>
|
||||
|
||||
/* Minimum, maximum and default polling millisecond periods are provided
|
||||
* here as an example. It is expected that any final implementation to also
|
||||
* include a modification of these settings to match the required
|
||||
* application.
|
||||
*/
|
||||
#define DA9062_DEFAULT_POLLING_MS_PERIOD 3000
|
||||
#define DA9062_MAX_POLLING_MS_PERIOD 10000
|
||||
#define DA9062_MIN_POLLING_MS_PERIOD 1000
|
||||
|
||||
#define DA9062_MILLI_CELSIUS(t) ((t) * 1000)
|
||||
|
||||
struct da9062_thermal_config {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct da9062_thermal {
|
||||
struct da9062 *hw;
|
||||
struct delayed_work work;
|
||||
struct thermal_zone_device *zone;
|
||||
enum thermal_device_mode mode;
|
||||
struct mutex lock; /* protection for da9062_thermal temperature */
|
||||
int temperature;
|
||||
int irq;
|
||||
const struct da9062_thermal_config *config;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
static void da9062_thermal_poll_on(struct work_struct *work)
|
||||
{
|
||||
struct da9062_thermal *thermal = container_of(work,
|
||||
struct da9062_thermal,
|
||||
work.work);
|
||||
unsigned long delay;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
/* clear E_TEMP */
|
||||
ret = regmap_write(thermal->hw->regmap,
|
||||
DA9062AA_EVENT_B,
|
||||
DA9062AA_E_TEMP_MASK);
|
||||
if (ret < 0) {
|
||||
dev_err(thermal->dev,
|
||||
"Cannot clear the TJUNC temperature status\n");
|
||||
goto err_enable_irq;
|
||||
}
|
||||
|
||||
/* Now read E_TEMP again: it is acting like a status bit.
|
||||
* If over-temperature, then this status will be true.
|
||||
* If not over-temperature, this status will be false.
|
||||
*/
|
||||
ret = regmap_read(thermal->hw->regmap,
|
||||
DA9062AA_EVENT_B,
|
||||
&val);
|
||||
if (ret < 0) {
|
||||
dev_err(thermal->dev,
|
||||
"Cannot check the TJUNC temperature status\n");
|
||||
goto err_enable_irq;
|
||||
}
|
||||
|
||||
if (val & DA9062AA_E_TEMP_MASK) {
|
||||
mutex_lock(&thermal->lock);
|
||||
thermal->temperature = DA9062_MILLI_CELSIUS(125);
|
||||
mutex_unlock(&thermal->lock);
|
||||
thermal_zone_device_update(thermal->zone,
|
||||
THERMAL_EVENT_UNSPECIFIED);
|
||||
|
||||
delay = msecs_to_jiffies(thermal->zone->passive_delay);
|
||||
schedule_delayed_work(&thermal->work, delay);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&thermal->lock);
|
||||
thermal->temperature = DA9062_MILLI_CELSIUS(0);
|
||||
mutex_unlock(&thermal->lock);
|
||||
thermal_zone_device_update(thermal->zone,
|
||||
THERMAL_EVENT_UNSPECIFIED);
|
||||
|
||||
err_enable_irq:
|
||||
enable_irq(thermal->irq);
|
||||
}
|
||||
|
||||
static irqreturn_t da9062_thermal_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct da9062_thermal *thermal = data;
|
||||
|
||||
disable_irq_nosync(thermal->irq);
|
||||
schedule_delayed_work(&thermal->work, 0);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int da9062_thermal_get_mode(struct thermal_zone_device *z,
|
||||
enum thermal_device_mode *mode)
|
||||
{
|
||||
struct da9062_thermal *thermal = z->devdata;
|
||||
*mode = thermal->mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int da9062_thermal_get_trip_type(struct thermal_zone_device *z,
|
||||
int trip,
|
||||
enum thermal_trip_type *type)
|
||||
{
|
||||
struct da9062_thermal *thermal = z->devdata;
|
||||
|
||||
switch (trip) {
|
||||
case 0:
|
||||
*type = THERMAL_TRIP_HOT;
|
||||
break;
|
||||
default:
|
||||
dev_err(thermal->dev,
|
||||
"Driver does not support more than 1 trip-wire\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int da9062_thermal_get_trip_temp(struct thermal_zone_device *z,
|
||||
int trip,
|
||||
int *temp)
|
||||
{
|
||||
struct da9062_thermal *thermal = z->devdata;
|
||||
|
||||
switch (trip) {
|
||||
case 0:
|
||||
*temp = DA9062_MILLI_CELSIUS(125);
|
||||
break;
|
||||
default:
|
||||
dev_err(thermal->dev,
|
||||
"Driver does not support more than 1 trip-wire\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int da9062_thermal_get_temp(struct thermal_zone_device *z,
|
||||
int *temp)
|
||||
{
|
||||
struct da9062_thermal *thermal = z->devdata;
|
||||
|
||||
mutex_lock(&thermal->lock);
|
||||
*temp = thermal->temperature;
|
||||
mutex_unlock(&thermal->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct thermal_zone_device_ops da9062_thermal_ops = {
|
||||
.get_temp = da9062_thermal_get_temp,
|
||||
.get_mode = da9062_thermal_get_mode,
|
||||
.get_trip_type = da9062_thermal_get_trip_type,
|
||||
.get_trip_temp = da9062_thermal_get_trip_temp,
|
||||
};
|
||||
|
||||
static const struct da9062_thermal_config da9062_config = {
|
||||
.name = "da9062-thermal",
|
||||
};
|
||||
|
||||
static const struct of_device_id da9062_compatible_reg_id_table[] = {
|
||||
{ .compatible = "dlg,da9062-thermal", .data = &da9062_config },
|
||||
{ },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, da9062_compatible_reg_id_table);
|
||||
|
||||
static int da9062_thermal_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct da9062 *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct da9062_thermal *thermal;
|
||||
unsigned int pp_tmp = DA9062_DEFAULT_POLLING_MS_PERIOD;
|
||||
const struct of_device_id *match;
|
||||
int ret = 0;
|
||||
|
||||
match = of_match_node(da9062_compatible_reg_id_table,
|
||||
pdev->dev.of_node);
|
||||
if (!match)
|
||||
return -ENXIO;
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
if (!of_property_read_u32(pdev->dev.of_node,
|
||||
"polling-delay-passive",
|
||||
&pp_tmp)) {
|
||||
if (pp_tmp < DA9062_MIN_POLLING_MS_PERIOD ||
|
||||
pp_tmp > DA9062_MAX_POLLING_MS_PERIOD) {
|
||||
dev_warn(&pdev->dev,
|
||||
"Out-of-range polling period %d ms\n",
|
||||
pp_tmp);
|
||||
pp_tmp = DA9062_DEFAULT_POLLING_MS_PERIOD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thermal = devm_kzalloc(&pdev->dev, sizeof(struct da9062_thermal),
|
||||
GFP_KERNEL);
|
||||
if (!thermal) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
thermal->config = match->data;
|
||||
thermal->hw = chip;
|
||||
thermal->mode = THERMAL_DEVICE_ENABLED;
|
||||
thermal->dev = &pdev->dev;
|
||||
|
||||
INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on);
|
||||
mutex_init(&thermal->lock);
|
||||
|
||||
thermal->zone = thermal_zone_device_register(thermal->config->name,
|
||||
1, 0, thermal,
|
||||
&da9062_thermal_ops, NULL, pp_tmp,
|
||||
0);
|
||||
if (IS_ERR(thermal->zone)) {
|
||||
dev_err(&pdev->dev, "Cannot register thermal zone device\n");
|
||||
ret = PTR_ERR(thermal->zone);
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev_dbg(&pdev->dev,
|
||||
"TJUNC temperature polling period set at %d ms\n",
|
||||
thermal->zone->passive_delay);
|
||||
|
||||
ret = platform_get_irq_byname(pdev, "THERMAL");
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to get platform IRQ.\n");
|
||||
goto err_zone;
|
||||
}
|
||||
thermal->irq = ret;
|
||||
|
||||
ret = request_threaded_irq(thermal->irq, NULL,
|
||||
da9062_thermal_irq_handler,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
"THERMAL", thermal);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to request thermal device IRQ.\n");
|
||||
goto err_zone;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, thermal);
|
||||
return 0;
|
||||
|
||||
err_zone:
|
||||
thermal_zone_device_unregister(thermal->zone);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int da9062_thermal_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct da9062_thermal *thermal = platform_get_drvdata(pdev);
|
||||
|
||||
free_irq(thermal->irq, thermal);
|
||||
cancel_delayed_work_sync(&thermal->work);
|
||||
thermal_zone_device_unregister(thermal->zone);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver da9062_thermal_driver = {
|
||||
.probe = da9062_thermal_probe,
|
||||
.remove = da9062_thermal_remove,
|
||||
.driver = {
|
||||
.name = "da9062-thermal",
|
||||
.of_match_table = da9062_compatible_reg_id_table,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(da9062_thermal_driver);
|
||||
|
||||
MODULE_AUTHOR("Steve Twiss");
|
||||
MODULE_DESCRIPTION("Thermal TJUNC device driver for Dialog DA9062 and DA9061");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:da9062-thermal");
|
|
@ -191,7 +191,7 @@ static const int mt8173_bank_data[MT8173_NUM_ZONES][3] = {
|
|||
};
|
||||
|
||||
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_MSR3
|
||||
};
|
||||
|
||||
static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = {
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
#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/spinlock.h>
|
||||
#include <linux/thermal.h>
|
||||
|
||||
#include "thermal_core.h"
|
||||
|
||||
/* Register offsets */
|
||||
#define REG_GEN3_IRQSTR 0x04
|
||||
#define REG_GEN3_IRQMSK 0x08
|
||||
|
@ -41,6 +43,14 @@
|
|||
#define REG_GEN3_THCODE2 0x54
|
||||
#define REG_GEN3_THCODE3 0x58
|
||||
|
||||
/* IRQ{STR,MSK,EN} bits */
|
||||
#define IRQ_TEMP1 BIT(0)
|
||||
#define IRQ_TEMP2 BIT(1)
|
||||
#define IRQ_TEMP3 BIT(2)
|
||||
#define IRQ_TEMPD1 BIT(3)
|
||||
#define IRQ_TEMPD2 BIT(4)
|
||||
#define IRQ_TEMPD3 BIT(5)
|
||||
|
||||
/* CTSR bits */
|
||||
#define CTSR_PONM BIT(8)
|
||||
#define CTSR_AOUT BIT(7)
|
||||
|
@ -72,11 +82,15 @@ struct rcar_gen3_thermal_tsc {
|
|||
void __iomem *base;
|
||||
struct thermal_zone_device *zone;
|
||||
struct equation_coefs coef;
|
||||
struct mutex lock;
|
||||
int low;
|
||||
int high;
|
||||
};
|
||||
|
||||
struct rcar_gen3_thermal_priv {
|
||||
struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM];
|
||||
unsigned int num_tscs;
|
||||
spinlock_t lock; /* Protect interrupts on and off */
|
||||
const struct rcar_gen3_thermal_data *data;
|
||||
};
|
||||
|
||||
struct rcar_gen3_thermal_data {
|
||||
|
@ -114,6 +128,7 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
|
|||
|
||||
#define FIXPT_SHIFT 7
|
||||
#define FIXPT_INT(_x) ((_x) << FIXPT_SHIFT)
|
||||
#define INT_FIXPT(_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)
|
||||
|
||||
|
@ -163,16 +178,12 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
|
|||
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;
|
||||
|
@ -183,10 +194,90 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rcar_gen3_thermal_mcelsius_to_temp(struct rcar_gen3_thermal_tsc *tsc,
|
||||
int mcelsius)
|
||||
{
|
||||
int celsius, val1, val2;
|
||||
|
||||
celsius = DIV_ROUND_CLOSEST(mcelsius, 1000);
|
||||
val1 = celsius * tsc->coef.a1 + tsc->coef.b1;
|
||||
val2 = celsius * tsc->coef.a2 + tsc->coef.b2;
|
||||
|
||||
return INT_FIXPT((val1 + val2) / 2);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP1,
|
||||
rcar_gen3_thermal_mcelsius_to_temp(tsc, low));
|
||||
|
||||
rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP2,
|
||||
rcar_gen3_thermal_mcelsius_to_temp(tsc, high));
|
||||
|
||||
tsc->low = low;
|
||||
tsc->high = high;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = {
|
||||
.get_temp = rcar_gen3_thermal_get_temp,
|
||||
.set_trips = rcar_gen3_thermal_set_trips,
|
||||
};
|
||||
|
||||
static void rcar_thermal_irq_set(struct rcar_gen3_thermal_priv *priv, bool on)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 val = on ? IRQ_TEMPD1 | IRQ_TEMP2 : 0;
|
||||
|
||||
for (i = 0; i < priv->num_tscs; i++)
|
||||
rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQMSK, val);
|
||||
}
|
||||
|
||||
static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data)
|
||||
{
|
||||
struct rcar_gen3_thermal_priv *priv = data;
|
||||
u32 status;
|
||||
int i, ret = IRQ_HANDLED;
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
for (i = 0; i < priv->num_tscs; i++) {
|
||||
status = rcar_gen3_thermal_read(priv->tscs[i], REG_GEN3_IRQSTR);
|
||||
rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQSTR, 0);
|
||||
if (status)
|
||||
ret = IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
if (ret == IRQ_WAKE_THREAD)
|
||||
rcar_thermal_irq_set(priv, false);
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t rcar_gen3_thermal_irq_thread(int irq, void *data)
|
||||
{
|
||||
struct rcar_gen3_thermal_priv *priv = data;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->num_tscs; i++)
|
||||
thermal_zone_device_update(priv->tscs[i]->zone,
|
||||
THERMAL_EVENT_UNSPECIFIED);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
rcar_thermal_irq_set(priv, true);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
|
||||
{
|
||||
rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR);
|
||||
|
@ -195,7 +286,11 @@ static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
|
|||
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_IRQMSK, 0);
|
||||
rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2);
|
||||
|
||||
rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR,
|
||||
CTSR_PONM | CTSR_AOUT | CTSR_THBGR | CTSR_VMEN);
|
||||
|
||||
|
@ -219,9 +314,14 @@ static void r8a7796_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
|
|||
usleep_range(1000, 2000);
|
||||
|
||||
rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F);
|
||||
rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0);
|
||||
rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2);
|
||||
|
||||
reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR);
|
||||
reg_val |= THCTR_THSST;
|
||||
rcar_gen3_thermal_write(tsc, REG_GEN3_THCTR, reg_val);
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
|
||||
static const struct rcar_gen3_thermal_data r8a7795_data = {
|
||||
|
@ -255,9 +355,8 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
|||
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);
|
||||
int ret, irq, i;
|
||||
char *irqname;
|
||||
|
||||
/* default values if FUSEs are missing */
|
||||
/* TODO: Read values from hardware on supported platforms */
|
||||
|
@ -272,24 +371,50 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
|||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->data = of_device_get_match_data(dev);
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
/*
|
||||
* Request 2 (of the 3 possible) IRQs, the driver only needs to
|
||||
* to trigger on the low and high trip points of the current
|
||||
* temp window at this point.
|
||||
*/
|
||||
for (i = 0; i < 2; i++) {
|
||||
irq = platform_get_irq(pdev, i);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
irqname = devm_kasprintf(dev, GFP_KERNEL, "%s:ch%d",
|
||||
dev_name(dev), i);
|
||||
if (!irqname)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, rcar_gen3_thermal_irq,
|
||||
rcar_gen3_thermal_irq_thread,
|
||||
IRQF_SHARED, irqname, priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
for (i = 0; i < TSC_MAX_NUM; i++) {
|
||||
struct rcar_gen3_thermal_tsc *tsc;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
|
||||
if (!res)
|
||||
break;
|
||||
|
||||
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);
|
||||
|
@ -297,9 +422,8 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
priv->tscs[i] = tsc;
|
||||
mutex_init(&tsc->lock);
|
||||
|
||||
match_data->thermal_init(tsc);
|
||||
priv->data->thermal_init(tsc);
|
||||
rcar_gen3_thermal_calc_coefs(&tsc->coef, ptat, thcode[i]);
|
||||
|
||||
zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,
|
||||
|
@ -310,8 +434,23 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
|||
goto error_unregister;
|
||||
}
|
||||
tsc->zone = zone;
|
||||
|
||||
ret = of_thermal_get_ntrips(tsc->zone);
|
||||
if (ret < 0)
|
||||
goto error_unregister;
|
||||
|
||||
dev_info(dev, "TSC%d: Loaded %d trip points\n", i, ret);
|
||||
}
|
||||
|
||||
priv->num_tscs = i;
|
||||
|
||||
if (!priv->num_tscs) {
|
||||
ret = -ENODEV;
|
||||
goto error_unregister;
|
||||
}
|
||||
|
||||
rcar_thermal_irq_set(priv, true);
|
||||
|
||||
return 0;
|
||||
|
||||
error_unregister:
|
||||
|
@ -320,9 +459,39 @@ error_unregister:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused rcar_gen3_thermal_suspend(struct device *dev)
|
||||
{
|
||||
struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev);
|
||||
|
||||
rcar_thermal_irq_set(priv, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev)
|
||||
{
|
||||
struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < priv->num_tscs; i++) {
|
||||
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
|
||||
|
||||
priv->data->thermal_init(tsc);
|
||||
rcar_gen3_thermal_set_trips(tsc, tsc->low, tsc->high);
|
||||
}
|
||||
|
||||
rcar_thermal_irq_set(priv, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, rcar_gen3_thermal_suspend,
|
||||
rcar_gen3_thermal_resume);
|
||||
|
||||
static struct platform_driver rcar_gen3_thermal_driver = {
|
||||
.driver = {
|
||||
.name = "rcar_gen3_thermal",
|
||||
.pm = &rcar_gen3_thermal_pm_ops,
|
||||
.of_match_table = rcar_gen3_thermal_dt_ids,
|
||||
},
|
||||
.probe = rcar_gen3_thermal_probe,
|
||||
|
|
|
@ -410,8 +410,6 @@ const struct ti_bandgap_data dra752_data = {
|
|||
.domain = "cpu",
|
||||
.register_cooling = ti_thermal_register_cpu_cooling,
|
||||
.unregister_cooling = ti_thermal_unregister_cpu_cooling,
|
||||
.slope = DRA752_GRADIENT_SLOPE,
|
||||
.constant = DRA752_GRADIENT_CONST,
|
||||
.slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
|
||||
.constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
|
||||
},
|
||||
|
@ -419,8 +417,6 @@ const struct ti_bandgap_data dra752_data = {
|
|||
.registers = &dra752_gpu_temp_sensor_registers,
|
||||
.ts_data = &dra752_gpu_temp_sensor_data,
|
||||
.domain = "gpu",
|
||||
.slope = DRA752_GRADIENT_SLOPE,
|
||||
.constant = DRA752_GRADIENT_CONST,
|
||||
.slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
|
||||
.constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
|
||||
},
|
||||
|
@ -428,8 +424,6 @@ const struct ti_bandgap_data dra752_data = {
|
|||
.registers = &dra752_core_temp_sensor_registers,
|
||||
.ts_data = &dra752_core_temp_sensor_data,
|
||||
.domain = "core",
|
||||
.slope = DRA752_GRADIENT_SLOPE,
|
||||
.constant = DRA752_GRADIENT_CONST,
|
||||
.slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
|
||||
.constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
|
||||
},
|
||||
|
@ -437,8 +431,6 @@ const struct ti_bandgap_data dra752_data = {
|
|||
.registers = &dra752_dspeve_temp_sensor_registers,
|
||||
.ts_data = &dra752_dspeve_temp_sensor_data,
|
||||
.domain = "dspeve",
|
||||
.slope = DRA752_GRADIENT_SLOPE,
|
||||
.constant = DRA752_GRADIENT_CONST,
|
||||
.slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
|
||||
.constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
|
||||
},
|
||||
|
@ -446,8 +438,6 @@ const struct ti_bandgap_data dra752_data = {
|
|||
.registers = &dra752_iva_temp_sensor_registers,
|
||||
.ts_data = &dra752_iva_temp_sensor_data,
|
||||
.domain = "iva",
|
||||
.slope = DRA752_GRADIENT_SLOPE,
|
||||
.constant = DRA752_GRADIENT_CONST,
|
||||
.slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
|
||||
.constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
|
||||
},
|
||||
|
|
|
@ -91,8 +91,6 @@ const struct ti_bandgap_data omap34xx_data = {
|
|||
.registers = &omap34xx_mpu_temp_sensor_registers,
|
||||
.ts_data = &omap34xx_mpu_temp_sensor_data,
|
||||
.domain = "cpu",
|
||||
.slope = 0,
|
||||
.constant = 20000,
|
||||
.slope_pcb = 0,
|
||||
.constant_pcb = 20000,
|
||||
.register_cooling = NULL,
|
||||
|
@ -164,8 +162,6 @@ const struct ti_bandgap_data omap36xx_data = {
|
|||
.registers = &omap36xx_mpu_temp_sensor_registers,
|
||||
.ts_data = &omap36xx_mpu_temp_sensor_data,
|
||||
.domain = "cpu",
|
||||
.slope = 0,
|
||||
.constant = 20000,
|
||||
.slope_pcb = 0,
|
||||
.constant_pcb = 20000,
|
||||
.register_cooling = NULL,
|
||||
|
|
|
@ -82,8 +82,6 @@ const struct ti_bandgap_data omap4430_data = {
|
|||
.registers = &omap4430_mpu_temp_sensor_registers,
|
||||
.ts_data = &omap4430_mpu_temp_sensor_data,
|
||||
.domain = "cpu",
|
||||
.slope = OMAP_GRADIENT_SLOPE_4430,
|
||||
.constant = OMAP_GRADIENT_CONST_4430,
|
||||
.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4430,
|
||||
.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4430,
|
||||
.register_cooling = ti_thermal_register_cpu_cooling,
|
||||
|
@ -222,8 +220,6 @@ const struct ti_bandgap_data omap4460_data = {
|
|||
.registers = &omap4460_mpu_temp_sensor_registers,
|
||||
.ts_data = &omap4460_mpu_temp_sensor_data,
|
||||
.domain = "cpu",
|
||||
.slope = OMAP_GRADIENT_SLOPE_4460,
|
||||
.constant = OMAP_GRADIENT_CONST_4460,
|
||||
.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4460,
|
||||
.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4460,
|
||||
.register_cooling = ti_thermal_register_cpu_cooling,
|
||||
|
@ -255,8 +251,6 @@ const struct ti_bandgap_data omap4470_data = {
|
|||
.registers = &omap4460_mpu_temp_sensor_registers,
|
||||
.ts_data = &omap4460_mpu_temp_sensor_data,
|
||||
.domain = "cpu",
|
||||
.slope = OMAP_GRADIENT_SLOPE_4470,
|
||||
.constant = OMAP_GRADIENT_CONST_4470,
|
||||
.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4470,
|
||||
.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4470,
|
||||
.register_cooling = ti_thermal_register_cpu_cooling,
|
||||
|
|
|
@ -336,8 +336,6 @@ const struct ti_bandgap_data omap5430_data = {
|
|||
.domain = "cpu",
|
||||
.register_cooling = ti_thermal_register_cpu_cooling,
|
||||
.unregister_cooling = ti_thermal_unregister_cpu_cooling,
|
||||
.slope = OMAP_GRADIENT_SLOPE_5430_CPU,
|
||||
.constant = OMAP_GRADIENT_CONST_5430_CPU,
|
||||
.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU,
|
||||
.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_CPU,
|
||||
},
|
||||
|
@ -345,8 +343,6 @@ const struct ti_bandgap_data omap5430_data = {
|
|||
.registers = &omap5430_gpu_temp_sensor_registers,
|
||||
.ts_data = &omap5430_gpu_temp_sensor_data,
|
||||
.domain = "gpu",
|
||||
.slope = OMAP_GRADIENT_SLOPE_5430_GPU,
|
||||
.constant = OMAP_GRADIENT_CONST_5430_GPU,
|
||||
.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU,
|
||||
.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_GPU,
|
||||
},
|
||||
|
|
|
@ -254,8 +254,6 @@ struct ti_bandgap {
|
|||
* @ts_data: pointer to struct with thresholds, limits of temperature sensor
|
||||
* @registers: pointer to the list of register offsets and bitfields
|
||||
* @domain: the name of the domain where the sensor is located
|
||||
* @slope: sensor gradient slope info for hotspot extrapolation equation
|
||||
* @constant: sensor gradient const info for hotspot extrapolation equation
|
||||
* @slope_pcb: sensor gradient slope info for hotspot extrapolation equation
|
||||
* with no external influence
|
||||
* @constant_pcb: sensor gradient const info for hotspot extrapolation equation
|
||||
|
@ -274,8 +272,6 @@ struct ti_temp_sensor {
|
|||
struct temp_sensor_registers *registers;
|
||||
char *domain;
|
||||
/* for hotspot extrapolation */
|
||||
const int slope;
|
||||
const int constant;
|
||||
const int slope_pcb;
|
||||
const int constant_pcb;
|
||||
int (*register_cooling)(struct ti_bandgap *bgp, int id);
|
||||
|
|
|
@ -96,8 +96,8 @@ static inline int __ti_thermal_get_temp(void *devdata, int *temp)
|
|||
return ret;
|
||||
|
||||
/* Default constants */
|
||||
slope = s->slope;
|
||||
constant = s->constant;
|
||||
slope = thermal_zone_get_slope(data->ti_thermal);
|
||||
constant = thermal_zone_get_offset(data->ti_thermal);
|
||||
|
||||
pcb_tz = data->pcb_tz;
|
||||
/* In case pcb zone is available, use the extrapolation rule with it */
|
||||
|
@ -126,119 +126,6 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
|
|||
return __ti_thermal_get_temp(data, temp);
|
||||
}
|
||||
|
||||
/* Bind callback functions for thermal zone */
|
||||
static int ti_thermal_bind(struct thermal_zone_device *thermal,
|
||||
struct thermal_cooling_device *cdev)
|
||||
{
|
||||
struct ti_thermal_data *data = thermal->devdata;
|
||||
int id;
|
||||
|
||||
if (!data || IS_ERR(data))
|
||||
return -ENODEV;
|
||||
|
||||
/* check if this is the cooling device we registered */
|
||||
if (data->cool_dev != cdev)
|
||||
return 0;
|
||||
|
||||
id = data->sensor_id;
|
||||
|
||||
/* Simple thing, two trips, one passive another critical */
|
||||
return thermal_zone_bind_cooling_device(thermal, 0, cdev,
|
||||
/* bind with min and max states defined by cpu_cooling */
|
||||
THERMAL_NO_LIMIT,
|
||||
THERMAL_NO_LIMIT,
|
||||
THERMAL_WEIGHT_DEFAULT);
|
||||
}
|
||||
|
||||
/* Unbind callback functions for thermal zone */
|
||||
static int ti_thermal_unbind(struct thermal_zone_device *thermal,
|
||||
struct thermal_cooling_device *cdev)
|
||||
{
|
||||
struct ti_thermal_data *data = thermal->devdata;
|
||||
|
||||
if (!data || IS_ERR(data))
|
||||
return -ENODEV;
|
||||
|
||||
/* check if this is the cooling device we registered */
|
||||
if (data->cool_dev != cdev)
|
||||
return 0;
|
||||
|
||||
/* Simple thing, two trips, one passive another critical */
|
||||
return thermal_zone_unbind_cooling_device(thermal, 0, cdev);
|
||||
}
|
||||
|
||||
/* Get mode callback functions for thermal zone */
|
||||
static int ti_thermal_get_mode(struct thermal_zone_device *thermal,
|
||||
enum thermal_device_mode *mode)
|
||||
{
|
||||
struct ti_thermal_data *data = thermal->devdata;
|
||||
|
||||
if (data)
|
||||
*mode = data->mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set mode callback functions for thermal zone */
|
||||
static int ti_thermal_set_mode(struct thermal_zone_device *thermal,
|
||||
enum thermal_device_mode mode)
|
||||
{
|
||||
struct ti_thermal_data *data = thermal->devdata;
|
||||
struct ti_bandgap *bgp;
|
||||
|
||||
bgp = data->bgp;
|
||||
|
||||
if (!data->ti_thermal) {
|
||||
dev_notice(&thermal->device, "thermal zone not registered\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&data->ti_thermal->lock);
|
||||
|
||||
if (mode == THERMAL_DEVICE_ENABLED)
|
||||
data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
|
||||
else
|
||||
data->ti_thermal->polling_delay = 0;
|
||||
|
||||
mutex_unlock(&data->ti_thermal->lock);
|
||||
|
||||
data->mode = mode;
|
||||
ti_bandgap_write_update_interval(bgp, data->sensor_id,
|
||||
data->ti_thermal->polling_delay);
|
||||
thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED);
|
||||
dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n",
|
||||
data->ti_thermal->polling_delay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get trip type callback functions for thermal zone */
|
||||
static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal,
|
||||
int trip, enum thermal_trip_type *type)
|
||||
{
|
||||
if (!ti_thermal_is_valid_trip(trip))
|
||||
return -EINVAL;
|
||||
|
||||
if (trip + 1 == OMAP_TRIP_NUMBER)
|
||||
*type = THERMAL_TRIP_CRITICAL;
|
||||
else
|
||||
*type = THERMAL_TRIP_PASSIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get trip temperature callback functions for thermal zone */
|
||||
static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
||||
int trip, int *temp)
|
||||
{
|
||||
if (!ti_thermal_is_valid_trip(trip))
|
||||
return -EINVAL;
|
||||
|
||||
*temp = ti_thermal_get_trip_value(trip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
|
||||
{
|
||||
struct ti_thermal_data *data = p;
|
||||
|
@ -262,38 +149,11 @@ static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Get the temperature trend callback functions for thermal zone */
|
||||
static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
|
||||
int trip, enum thermal_trend *trend)
|
||||
{
|
||||
return __ti_thermal_get_trend(thermal->devdata, trip, trend);
|
||||
}
|
||||
|
||||
/* Get critical temperature callback functions for thermal zone */
|
||||
static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
|
||||
int *temp)
|
||||
{
|
||||
/* shutdown zone */
|
||||
return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
|
||||
}
|
||||
|
||||
static const struct thermal_zone_of_device_ops ti_of_thermal_ops = {
|
||||
.get_temp = __ti_thermal_get_temp,
|
||||
.get_trend = __ti_thermal_get_trend,
|
||||
};
|
||||
|
||||
static struct thermal_zone_device_ops ti_thermal_ops = {
|
||||
.get_temp = ti_thermal_get_temp,
|
||||
.get_trend = ti_thermal_get_trend,
|
||||
.bind = ti_thermal_bind,
|
||||
.unbind = ti_thermal_unbind,
|
||||
.get_mode = ti_thermal_get_mode,
|
||||
.set_mode = ti_thermal_set_mode,
|
||||
.get_trip_type = ti_thermal_get_trip_type,
|
||||
.get_trip_temp = ti_thermal_get_trip_temp,
|
||||
.get_crit_temp = ti_thermal_get_crit_temp,
|
||||
};
|
||||
|
||||
static struct ti_thermal_data
|
||||
*ti_thermal_build_data(struct ti_bandgap *bgp, int id)
|
||||
{
|
||||
|
@ -331,18 +191,10 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
|
|||
data->ti_thermal = devm_thermal_zone_of_sensor_register(bgp->dev, id,
|
||||
data, &ti_of_thermal_ops);
|
||||
if (IS_ERR(data->ti_thermal)) {
|
||||
/* Create thermal zone */
|
||||
data->ti_thermal = thermal_zone_device_register(domain,
|
||||
OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
|
||||
NULL, FAST_TEMP_MONITORING_RATE,
|
||||
FAST_TEMP_MONITORING_RATE);
|
||||
if (IS_ERR(data->ti_thermal)) {
|
||||
dev_err(bgp->dev, "thermal zone device is NULL\n");
|
||||
return PTR_ERR(data->ti_thermal);
|
||||
}
|
||||
data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
|
||||
data->our_zone = true;
|
||||
dev_err(bgp->dev, "thermal zone device is NULL\n");
|
||||
return PTR_ERR(data->ti_thermal);
|
||||
}
|
||||
|
||||
ti_bandgap_set_sensor_data(bgp, id, data);
|
||||
ti_bandgap_write_update_interval(bgp, data->sensor_id,
|
||||
data->ti_thermal->polling_delay);
|
||||
|
|
|
@ -25,22 +25,6 @@
|
|||
|
||||
#include "ti-bandgap.h"
|
||||
|
||||
/* sensors gradient and offsets */
|
||||
#define OMAP_GRADIENT_SLOPE_4430 0
|
||||
#define OMAP_GRADIENT_CONST_4430 20000
|
||||
#define OMAP_GRADIENT_SLOPE_4460 348
|
||||
#define OMAP_GRADIENT_CONST_4460 -9301
|
||||
#define OMAP_GRADIENT_SLOPE_4470 308
|
||||
#define OMAP_GRADIENT_CONST_4470 -7896
|
||||
|
||||
#define OMAP_GRADIENT_SLOPE_5430_CPU 65
|
||||
#define OMAP_GRADIENT_CONST_5430_CPU -1791
|
||||
#define OMAP_GRADIENT_SLOPE_5430_GPU 117
|
||||
#define OMAP_GRADIENT_CONST_5430_GPU -2992
|
||||
|
||||
#define DRA752_GRADIENT_SLOPE 0
|
||||
#define DRA752_GRADIENT_CONST 2000
|
||||
|
||||
/* PCB sensor calculation constants */
|
||||
#define OMAP_GRADIENT_SLOPE_W_PCB_4430 0
|
||||
#define OMAP_GRADIENT_CONST_W_PCB_4430 20000
|
||||
|
|
Загрузка…
Ссылка в новой задаче