Merge tag 'thermal-6.6-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more thermal control updates from Rafael Wysocki:
"These are mostly updates of thermal control drivers for ARM platforms,
new thermal control support for Loongson-2 and a couple of core
cleanups made possible by recent changes merged previously.
Specifics:
- Check if the Tegra BPMP supports the trip points in order to set
the .set_trips callback (Mikko Perttunen)
- Add new Loongson-2 thermal sensor along with the DT bindings (Yinbo
Zhu)
- Use IS_ERR_OR_NULL() helper to replace a double test on the TI
bandgap sensor (Li Zetao)
- Remove redundant platform_set_drvdata() calls, as there are no
corresponding calls to platform_get_drvdata(), from a bunch of
drivers (Andrei Coardos)
- Switch the Mediatek LVTS mode to filtered in order to enable
interrupts (Nícolas F. R. A. Prado)
- Fix Wvoid-pointer-to-enum-cast warning on the Exynos TMU (Krzysztof
Kozlowski)
- Remove redundant dev_err_probe(), because the underlying function
already called it, from the Mediatek sensor (Chen Jiahao)
- Free calibration nvmem after reading it on sun8i (Mark Brown)
- Remove useless comment from the sun8i driver (Yangtao Li)
- Make tsens_xxxx_nvmem static to fix a sparse warning on QCom tsens
(Min-Hua Chen)
- Remove error message at probe deferral on imx8mm (Ahmad Fatoum)
- Fix parameter check in lvts_debugfs_init() with IS_ERR() on
Mediatek LVTS (Minjie Du)
- Fix interrupt routine and configuratoin for Mediatek LVTS (Nícolas
F. R. A. Prado)
- Drop unused .get_trip_type(), .get_trip_temp() and .get_trip_hyst()
thermal zone callbacks from the core and rework the .get_trend()
one to take a trip point pointer as an argument (Rafael Wysocki)"
* tag 'thermal-6.6-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (29 commits)
thermal: core: Rework .get_trend() thermal zone callback
thermal: core: Drop unused .get_trip_*() callbacks
thermal/drivers/tegra-bpmp: Check if BPMP supports trip points
thermal: dt-bindings: add loongson-2 thermal
thermal/drivers/loongson-2: Add thermal management support
thermal/drivers/ti-soc-thermal: Use helper function IS_ERR_OR_NULL()
thermal/drivers/generic-adc: Removed unneeded call to platform_set_drvdata()
thermal/drivers/max77620_thermal: Removed unneeded call to platform_set_drvdata()
thermal/drivers/mediatek/auxadc_thermal: Removed call to platform_set_drvdata()
thermal/drivers/sun8i_thermal: Remove unneeded call to platform_set_drvdata()
thermal/drivers/broadcom/brcstb_thermal: Removed unneeded platform_set_drvdata()
thermal/drivers/mediatek/lvts_thermal: Make readings valid in filtered mode
thermal/drivers/k3_bandgap: Remove unneeded call to platform_set_drvdata()
thermal/drivers/k3_j72xx_bandgap: Removed unneeded call to platform_set_drvdata()
thermal/drivers/broadcom/sr-thermal: Removed call to platform_set_drvdata()
thermal/drivers/samsung: Fix Wvoid-pointer-to-enum-cast warning
thermal/drivers/db8500: Remove redundant of_match_ptr()
thermal/drivers/mediatek: Clean up redundant dev_err_probe()
thermal/drivers/sun8i: Free calibration nvmem after reading it
thermal/drivers/sun8i: Remove unneeded comments
...
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/thermal/loongson,ls2k-thermal.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Thermal sensors on Loongson-2 SoCs
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- zhanghongchen <zhanghongchen@loongson.cn>
|
||||||
|
- Yinbo Zhu <zhuyinbo@loongson.cn>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
oneOf:
|
||||||
|
- enum:
|
||||||
|
- loongson,ls2k1000-thermal
|
||||||
|
- items:
|
||||||
|
- enum:
|
||||||
|
- loongson,ls2k2000-thermal
|
||||||
|
- const: loongson,ls2k1000-thermal
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- interrupts
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
thermal: thermal-sensor@1fe01500 {
|
||||||
|
compatible = "loongson,ls2k1000-thermal";
|
||||||
|
reg = <0x1fe01500 0x30>;
|
||||||
|
interrupt-parent = <&liointc0>;
|
||||||
|
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
|
||||||
|
};
|
||||||
@@ -12390,6 +12390,14 @@ S: Maintained
|
|||||||
F: Documentation/devicetree/bindings/pinctrl/loongson,ls2k-pinctrl.yaml
|
F: Documentation/devicetree/bindings/pinctrl/loongson,ls2k-pinctrl.yaml
|
||||||
F: drivers/pinctrl/pinctrl-loongson2.c
|
F: drivers/pinctrl/pinctrl-loongson2.c
|
||||||
|
|
||||||
|
LOONGSON-2 SOC SERIES THERMAL DRIVER
|
||||||
|
M: zhanghongchen <zhanghongchen@loongson.cn>
|
||||||
|
M: Yinbo Zhu <zhuyinbo@loongson.cn>
|
||||||
|
L: linux-pm@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
F: Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml
|
||||||
|
F: drivers/thermal/loongson2_thermal.c
|
||||||
|
|
||||||
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
|
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
|
||||||
M: Sathya Prakash <sathya.prakash@broadcom.com>
|
M: Sathya Prakash <sathya.prakash@broadcom.com>
|
||||||
M: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
|
M: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
|
||||||
|
|||||||
+18
-23
@@ -492,26 +492,22 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int thermal_get_trend(struct thermal_zone_device *thermal,
|
static int thermal_get_trend(struct thermal_zone_device *thermal,
|
||||||
int trip_index, enum thermal_trend *trend)
|
struct thermal_trip *trip,
|
||||||
|
enum thermal_trend *trend)
|
||||||
{
|
{
|
||||||
struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
|
struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
|
||||||
struct acpi_thermal_trip *acpi_trip;
|
struct acpi_thermal_trip *acpi_trip;
|
||||||
int t, i;
|
int t;
|
||||||
|
|
||||||
if (!tz || trip_index < 0)
|
if (!tz || !trip)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (tz->trips.critical.valid)
|
acpi_trip = trip->priv;
|
||||||
trip_index--;
|
if (!acpi_trip || !acpi_trip->valid)
|
||||||
|
|
||||||
if (tz->trips.hot.valid)
|
|
||||||
trip_index--;
|
|
||||||
|
|
||||||
if (trip_index < 0)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
acpi_trip = &tz->trips.passive.trip;
|
switch (trip->type) {
|
||||||
if (acpi_trip->valid && !trip_index--) {
|
case THERMAL_TRIP_PASSIVE:
|
||||||
t = tz->trips.passive.tc1 * (tz->temperature -
|
t = tz->trips.passive.tc1 * (tz->temperature -
|
||||||
tz->last_temperature) +
|
tz->last_temperature) +
|
||||||
tz->trips.passive.tc2 * (tz->temperature -
|
tz->trips.passive.tc2 * (tz->temperature -
|
||||||
@@ -524,19 +520,18 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
|
|||||||
*trend = THERMAL_TREND_STABLE;
|
*trend = THERMAL_TREND_STABLE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
t = acpi_thermal_temp(tz, tz->temperature);
|
case THERMAL_TRIP_ACTIVE:
|
||||||
|
t = acpi_thermal_temp(tz, tz->temperature);
|
||||||
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
|
if (t <= trip->temperature)
|
||||||
acpi_trip = &tz->trips.active[i].trip;
|
|
||||||
if (acpi_trip->valid && !trip_index--) {
|
|
||||||
if (t > acpi_thermal_temp(tz, acpi_trip->temperature)) {
|
|
||||||
*trend = THERMAL_TREND_RAISING;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
*trend = THERMAL_TREND_RAISING;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|||||||
@@ -510,4 +510,16 @@ config KHADAS_MCU_FAN_THERMAL
|
|||||||
If you say yes here you get support for the FAN controlled
|
If you say yes here you get support for the FAN controlled
|
||||||
by the Microcontroller found on the Khadas VIM boards.
|
by the Microcontroller found on the Khadas VIM boards.
|
||||||
|
|
||||||
|
config LOONGSON2_THERMAL
|
||||||
|
tristate "Loongson-2 SoC series thermal driver"
|
||||||
|
depends on LOONGARCH || COMPILE_TEST
|
||||||
|
depends on OF
|
||||||
|
help
|
||||||
|
Support for Thermal driver found on Loongson-2 SoC series platforms.
|
||||||
|
The thermal driver realizes get_temp and set_trips function, which
|
||||||
|
are used to obtain the temperature of the current node and set the
|
||||||
|
temperature range to trigger the interrupt. When the input temperature
|
||||||
|
is higher than the high temperature threshold or lower than the low
|
||||||
|
temperature threshold, the interrupt will occur.
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -63,3 +63,4 @@ obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o
|
|||||||
obj-$(CONFIG_AMLOGIC_THERMAL) += amlogic_thermal.o
|
obj-$(CONFIG_AMLOGIC_THERMAL) += amlogic_thermal.o
|
||||||
obj-$(CONFIG_SPRD_THERMAL) += sprd_thermal.o
|
obj-$(CONFIG_SPRD_THERMAL) += sprd_thermal.o
|
||||||
obj-$(CONFIG_KHADAS_MCU_FAN_THERMAL) += khadas_mcu_fan.o
|
obj-$(CONFIG_KHADAS_MCU_FAN_THERMAL) += khadas_mcu_fan.o
|
||||||
|
obj-$(CONFIG_LOONGSON2_THERMAL) += loongson2_thermal.o
|
||||||
|
|||||||
@@ -334,7 +334,6 @@ static int brcmstb_thermal_probe(struct platform_device *pdev)
|
|||||||
return PTR_ERR(priv->tmon_base);
|
return PTR_ERR(priv->tmon_base);
|
||||||
|
|
||||||
priv->dev = &pdev->dev;
|
priv->dev = &pdev->dev;
|
||||||
platform_set_drvdata(pdev, priv);
|
|
||||||
of_ops = priv->temp_params->of_ops;
|
of_ops = priv->temp_params->of_ops;
|
||||||
|
|
||||||
thermal = devm_thermal_of_zone_register(&pdev->dev, 0, priv,
|
thermal = devm_thermal_of_zone_register(&pdev->dev, 0, priv,
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ static int sr_thermal_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
dev_dbg(dev, "thermal sensor %d registered\n", i);
|
dev_dbg(dev, "thermal sensor %d registered\n", i);
|
||||||
}
|
}
|
||||||
platform_set_drvdata(pdev, sr_thermal);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ MODULE_DEVICE_TABLE(of, db8500_thermal_match);
|
|||||||
static struct platform_driver db8500_thermal_driver = {
|
static struct platform_driver db8500_thermal_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "db8500-thermal",
|
.name = "db8500-thermal",
|
||||||
.of_match_table = of_match_ptr(db8500_thermal_match),
|
.of_match_table = db8500_thermal_match,
|
||||||
},
|
},
|
||||||
.probe = db8500_thermal_probe,
|
.probe = db8500_thermal_probe,
|
||||||
.suspend = db8500_thermal_suspend,
|
.suspend = db8500_thermal_suspend,
|
||||||
|
|||||||
@@ -178,10 +178,8 @@ static int imx8mm_tmu_probe_set_calib_v1(struct platform_device *pdev,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nvmem_cell_read_u32(&pdev->dev, "calib", &ana0);
|
ret = nvmem_cell_read_u32(&pdev->dev, "calib", &ana0);
|
||||||
if (ret) {
|
if (ret)
|
||||||
dev_warn(dev, "Failed to read OCOTP nvmem cell (%d).\n", ret);
|
return dev_err_probe(dev, ret, "Failed to read OCOTP nvmem cell\n");
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
writel(FIELD_PREP(TASR_BUF_VREF_MASK,
|
writel(FIELD_PREP(TASR_BUF_VREF_MASK,
|
||||||
FIELD_GET(ANA0_BUF_VREF_MASK, ana0)) |
|
FIELD_GET(ANA0_BUF_VREF_MASK, ana0)) |
|
||||||
|
|||||||
@@ -225,7 +225,6 @@ static int k3_bandgap_probe(struct platform_device *pdev)
|
|||||||
devm_thermal_add_hwmon_sysfs(dev, data[id].tzd);
|
devm_thermal_add_hwmon_sysfs(dev, data[id].tzd);
|
||||||
}
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, bgp);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@@ -502,8 +502,6 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
|
|||||||
writel(K3_VTM_ANYMAXT_OUTRG_ALERT_EN, data[0].bgp->cfg2_base +
|
writel(K3_VTM_ANYMAXT_OUTRG_ALERT_EN, data[0].bgp->cfg2_base +
|
||||||
K3_VTM_MISC_CTRL_OFFSET);
|
K3_VTM_MISC_CTRL_OFFSET);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, bgp);
|
|
||||||
|
|
||||||
print_look_up_table(dev, ref_table);
|
print_look_up_table(dev, ref_table);
|
||||||
/*
|
/*
|
||||||
* Now that the derived_table has the appropriate look up values
|
* Now that the derived_table has the appropriate look up values
|
||||||
|
|||||||
@@ -0,0 +1,169 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Author: zhanghongchen <zhanghongchen@loongson.cn>
|
||||||
|
* Yinbo Zhu <zhuyinbo@loongson.cn>
|
||||||
|
* Copyright (C) 2022-2023 Loongson Technology Corporation Limited
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/minmax.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/thermal.h>
|
||||||
|
#include <linux/units.h>
|
||||||
|
#include "thermal_hwmon.h"
|
||||||
|
|
||||||
|
#define LOONGSON2_MAX_SENSOR_SEL_NUM 3
|
||||||
|
|
||||||
|
#define LOONGSON2_THSENS_CTRL_HI_REG 0x0
|
||||||
|
#define LOONGSON2_THSENS_CTRL_LOW_REG 0x8
|
||||||
|
#define LOONGSON2_THSENS_STATUS_REG 0x10
|
||||||
|
#define LOONGSON2_THSENS_OUT_REG 0x14
|
||||||
|
|
||||||
|
#define LOONGSON2_THSENS_INT_LO BIT(0)
|
||||||
|
#define LOONGSON2_THSENS_INT_HIGH BIT(1)
|
||||||
|
#define LOONGSON2_THSENS_OUT_MASK 0xFF
|
||||||
|
|
||||||
|
struct loongson2_thermal_chip_data {
|
||||||
|
unsigned int thermal_sensor_sel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct loongson2_thermal_data {
|
||||||
|
void __iomem *regs;
|
||||||
|
const struct loongson2_thermal_chip_data *chip_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int loongson2_thermal_set(struct loongson2_thermal_data *data,
|
||||||
|
int low, int high, bool enable)
|
||||||
|
{
|
||||||
|
u64 reg_ctrl = 0;
|
||||||
|
int reg_off = data->chip_data->thermal_sensor_sel * 2;
|
||||||
|
|
||||||
|
low = clamp(-40, low, high);
|
||||||
|
high = clamp(125, low, high);
|
||||||
|
|
||||||
|
low += HECTO;
|
||||||
|
high += HECTO;
|
||||||
|
|
||||||
|
reg_ctrl = low;
|
||||||
|
reg_ctrl |= enable ? 0x100 : 0;
|
||||||
|
writew(reg_ctrl, data->regs + LOONGSON2_THSENS_CTRL_LOW_REG + reg_off);
|
||||||
|
|
||||||
|
reg_ctrl = high;
|
||||||
|
reg_ctrl |= enable ? 0x100 : 0;
|
||||||
|
writew(reg_ctrl, data->regs + LOONGSON2_THSENS_CTRL_HI_REG + reg_off);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int loongson2_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
|
||||||
|
{
|
||||||
|
u32 reg_val;
|
||||||
|
struct loongson2_thermal_data *data = thermal_zone_device_priv(tz);
|
||||||
|
|
||||||
|
reg_val = readl(data->regs + LOONGSON2_THSENS_OUT_REG);
|
||||||
|
*temp = ((reg_val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev)
|
||||||
|
{
|
||||||
|
struct thermal_zone_device *tzd = dev;
|
||||||
|
struct loongson2_thermal_data *data = thermal_zone_device_priv(tzd);
|
||||||
|
|
||||||
|
writeb(LOONGSON2_THSENS_INT_LO | LOONGSON2_THSENS_INT_HIGH, data->regs +
|
||||||
|
LOONGSON2_THSENS_STATUS_REG);
|
||||||
|
|
||||||
|
thermal_zone_device_update(tzd, THERMAL_EVENT_UNSPECIFIED);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int loongson2_thermal_set_trips(struct thermal_zone_device *tz, int low, int high)
|
||||||
|
{
|
||||||
|
struct loongson2_thermal_data *data = thermal_zone_device_priv(tz);
|
||||||
|
|
||||||
|
return loongson2_thermal_set(data, low/MILLI, high/MILLI, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct thermal_zone_device_ops loongson2_of_thermal_ops = {
|
||||||
|
.get_temp = loongson2_thermal_get_temp,
|
||||||
|
.set_trips = loongson2_thermal_set_trips,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int loongson2_thermal_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct loongson2_thermal_data *data;
|
||||||
|
struct thermal_zone_device *tzd;
|
||||||
|
int ret, irq, i;
|
||||||
|
|
||||||
|
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||||
|
if (!data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
data->chip_data = device_get_match_data(dev);
|
||||||
|
|
||||||
|
data->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||||
|
if (IS_ERR(data->regs))
|
||||||
|
return PTR_ERR(data->regs);
|
||||||
|
|
||||||
|
irq = platform_get_irq(pdev, 0);
|
||||||
|
if (irq < 0)
|
||||||
|
return irq;
|
||||||
|
|
||||||
|
writeb(LOONGSON2_THSENS_INT_LO | LOONGSON2_THSENS_INT_HIGH, data->regs +
|
||||||
|
LOONGSON2_THSENS_STATUS_REG);
|
||||||
|
|
||||||
|
loongson2_thermal_set(data, 0, 0, false);
|
||||||
|
|
||||||
|
for (i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) {
|
||||||
|
tzd = devm_thermal_of_zone_register(dev, i, data,
|
||||||
|
&loongson2_of_thermal_ops);
|
||||||
|
|
||||||
|
if (!IS_ERR(tzd))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (PTR_ERR(tzd) != ENODEV)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return dev_err_probe(dev, PTR_ERR(tzd), "failed to register");
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = devm_request_threaded_irq(dev, irq, NULL, loongson2_thermal_irq_thread,
|
||||||
|
IRQF_ONESHOT, "loongson2_thermal", tzd);
|
||||||
|
if (ret < 0)
|
||||||
|
return dev_err_probe(dev, ret, "failed to request alarm irq\n");
|
||||||
|
|
||||||
|
devm_thermal_add_hwmon_sysfs(dev, tzd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k1000_data = {
|
||||||
|
.thermal_sensor_sel = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id of_loongson2_thermal_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "loongson,ls2k1000-thermal",
|
||||||
|
.data = &loongson2_thermal_ls2k1000_data,
|
||||||
|
},
|
||||||
|
{ /* end */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, of_loongson2_thermal_match);
|
||||||
|
|
||||||
|
static struct platform_driver loongson2_thermal_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "loongson2_thermal",
|
||||||
|
.of_match_table = of_loongson2_thermal_match,
|
||||||
|
},
|
||||||
|
.probe = loongson2_thermal_probe,
|
||||||
|
};
|
||||||
|
module_platform_driver(loongson2_thermal_driver);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Loongson2 thermal driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
@@ -139,8 +139,6 @@ static int max77620_thermal_probe(struct platform_device *pdev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, mtherm);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1282,8 +1282,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
|
|||||||
mtk_thermal_init_bank(mt, i, apmixed_phys_base,
|
mtk_thermal_init_bank(mt, i, apmixed_phys_base,
|
||||||
auxadc_phys_base, ctrl_id);
|
auxadc_phys_base, ctrl_id);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, mt);
|
|
||||||
|
|
||||||
tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
|
tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
|
||||||
&mtk_thermal_ops);
|
&mtk_thermal_ops);
|
||||||
if (IS_ERR(tzdev))
|
if (IS_ERR(tzdev))
|
||||||
|
|||||||
@@ -58,14 +58,19 @@
|
|||||||
#define LVTS_PROTTC(__base) (__base + 0x00CC)
|
#define LVTS_PROTTC(__base) (__base + 0x00CC)
|
||||||
#define LVTS_CLKEN(__base) (__base + 0x00E4)
|
#define LVTS_CLKEN(__base) (__base + 0x00E4)
|
||||||
|
|
||||||
#define LVTS_PERIOD_UNIT ((118 * 1000) / (256 * 38))
|
#define LVTS_PERIOD_UNIT 0
|
||||||
#define LVTS_GROUP_INTERVAL 1
|
#define LVTS_GROUP_INTERVAL 0
|
||||||
#define LVTS_FILTER_INTERVAL 1
|
#define LVTS_FILTER_INTERVAL 0
|
||||||
#define LVTS_SENSOR_INTERVAL 1
|
#define LVTS_SENSOR_INTERVAL 0
|
||||||
#define LVTS_HW_FILTER 0x2
|
#define LVTS_HW_FILTER 0x0
|
||||||
#define LVTS_TSSEL_CONF 0x13121110
|
#define LVTS_TSSEL_CONF 0x13121110
|
||||||
#define LVTS_CALSCALE_CONF 0x300
|
#define LVTS_CALSCALE_CONF 0x300
|
||||||
#define LVTS_MONINT_CONF 0x9FBF7BDE
|
#define LVTS_MONINT_CONF 0x8300318C
|
||||||
|
|
||||||
|
#define LVTS_MONINT_OFFSET_SENSOR0 0xC
|
||||||
|
#define LVTS_MONINT_OFFSET_SENSOR1 0x180
|
||||||
|
#define LVTS_MONINT_OFFSET_SENSOR2 0x3000
|
||||||
|
#define LVTS_MONINT_OFFSET_SENSOR3 0x3000000
|
||||||
|
|
||||||
#define LVTS_INT_SENSOR0 0x0009001F
|
#define LVTS_INT_SENSOR0 0x0009001F
|
||||||
#define LVTS_INT_SENSOR1 0x001203E0
|
#define LVTS_INT_SENSOR1 0x001203E0
|
||||||
@@ -81,8 +86,13 @@
|
|||||||
#define LVTS_MSR_IMMEDIATE_MODE 0
|
#define LVTS_MSR_IMMEDIATE_MODE 0
|
||||||
#define LVTS_MSR_FILTERED_MODE 1
|
#define LVTS_MSR_FILTERED_MODE 1
|
||||||
|
|
||||||
|
#define LVTS_MSR_READ_TIMEOUT_US 400
|
||||||
|
#define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2)
|
||||||
|
|
||||||
#define LVTS_HW_SHUTDOWN_MT8195 105000
|
#define LVTS_HW_SHUTDOWN_MT8195 105000
|
||||||
|
|
||||||
|
#define LVTS_MINIMUM_THRESHOLD 20000
|
||||||
|
|
||||||
static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT;
|
static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT;
|
||||||
static int coeff_b = LVTS_COEFF_B;
|
static int coeff_b = LVTS_COEFF_B;
|
||||||
|
|
||||||
@@ -110,6 +120,8 @@ struct lvts_sensor {
|
|||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
int id;
|
int id;
|
||||||
int dt_id;
|
int dt_id;
|
||||||
|
int low_thresh;
|
||||||
|
int high_thresh;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lvts_ctrl {
|
struct lvts_ctrl {
|
||||||
@@ -119,6 +131,8 @@ struct lvts_ctrl {
|
|||||||
int num_lvts_sensor;
|
int num_lvts_sensor;
|
||||||
int mode;
|
int mode;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
|
int low_thresh;
|
||||||
|
int high_thresh;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lvts_domain {
|
struct lvts_domain {
|
||||||
@@ -190,7 +204,7 @@ static int lvts_debugfs_init(struct device *dev, struct lvts_domain *lvts_td)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
lvts_td->dom_dentry = debugfs_create_dir(dev_name(dev), NULL);
|
lvts_td->dom_dentry = debugfs_create_dir(dev_name(dev), NULL);
|
||||||
if (!lvts_td->dom_dentry)
|
if (IS_ERR(lvts_td->dom_dentry))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (i = 0; i < lvts_td->num_lvts_ctrl; i++) {
|
for (i = 0; i < lvts_td->num_lvts_ctrl; i++) {
|
||||||
@@ -257,6 +271,7 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp)
|
|||||||
struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
|
struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
|
||||||
void __iomem *msr = lvts_sensor->msr;
|
void __iomem *msr = lvts_sensor->msr;
|
||||||
u32 value;
|
u32 value;
|
||||||
|
int rc;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Measurement registers:
|
* Measurement registers:
|
||||||
@@ -269,7 +284,8 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp)
|
|||||||
* 16 : Valid temperature
|
* 16 : Valid temperature
|
||||||
* 15-0 : Raw temperature
|
* 15-0 : Raw temperature
|
||||||
*/
|
*/
|
||||||
value = readl(msr);
|
rc = readl_poll_timeout(msr, value, value & BIT(16),
|
||||||
|
LVTS_MSR_READ_WAIT_US, LVTS_MSR_READ_TIMEOUT_US);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* As the thermal zone temperature will read before the
|
* As the thermal zone temperature will read before the
|
||||||
@@ -282,7 +298,7 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp)
|
|||||||
* functionning temperature and directly jump to a system
|
* functionning temperature and directly jump to a system
|
||||||
* shutdown.
|
* shutdown.
|
||||||
*/
|
*/
|
||||||
if (!(value & BIT(16)))
|
if (rc)
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
*temp = lvts_raw_to_temp(value & 0xFFFF);
|
*temp = lvts_raw_to_temp(value & 0xFFFF);
|
||||||
@@ -290,32 +306,84 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lvts_update_irq_mask(struct lvts_ctrl *lvts_ctrl)
|
||||||
|
{
|
||||||
|
u32 masks[] = {
|
||||||
|
LVTS_MONINT_OFFSET_SENSOR0,
|
||||||
|
LVTS_MONINT_OFFSET_SENSOR1,
|
||||||
|
LVTS_MONINT_OFFSET_SENSOR2,
|
||||||
|
LVTS_MONINT_OFFSET_SENSOR3,
|
||||||
|
};
|
||||||
|
u32 value = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
value = readl(LVTS_MONINT(lvts_ctrl->base));
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(masks); i++) {
|
||||||
|
if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh
|
||||||
|
&& lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh)
|
||||||
|
value |= masks[i];
|
||||||
|
else
|
||||||
|
value &= ~masks[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
writel(value, LVTS_MONINT(lvts_ctrl->base));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool lvts_should_update_thresh(struct lvts_ctrl *lvts_ctrl, int high)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (high > lvts_ctrl->high_thresh)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++)
|
||||||
|
if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh
|
||||||
|
&& lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
|
static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
|
||||||
{
|
{
|
||||||
struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
|
struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
|
||||||
|
struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]);
|
||||||
void __iomem *base = lvts_sensor->base;
|
void __iomem *base = lvts_sensor->base;
|
||||||
u32 raw_low = lvts_temp_to_raw(low);
|
u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD);
|
||||||
u32 raw_high = lvts_temp_to_raw(high);
|
u32 raw_high = lvts_temp_to_raw(high);
|
||||||
|
bool should_update_thresh;
|
||||||
|
|
||||||
|
lvts_sensor->low_thresh = low;
|
||||||
|
lvts_sensor->high_thresh = high;
|
||||||
|
|
||||||
|
should_update_thresh = lvts_should_update_thresh(lvts_ctrl, high);
|
||||||
|
if (should_update_thresh) {
|
||||||
|
lvts_ctrl->high_thresh = high;
|
||||||
|
lvts_ctrl->low_thresh = low;
|
||||||
|
}
|
||||||
|
lvts_update_irq_mask(lvts_ctrl);
|
||||||
|
|
||||||
|
if (!should_update_thresh)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hot to normal temperature threshold
|
* Low offset temperature threshold
|
||||||
*
|
*
|
||||||
* LVTS_H2NTHRE
|
* LVTS_OFFSETL
|
||||||
*
|
*
|
||||||
* Bits:
|
* Bits:
|
||||||
*
|
*
|
||||||
* 14-0 : Raw temperature for threshold
|
* 14-0 : Raw temperature for threshold
|
||||||
*/
|
*/
|
||||||
if (low != -INT_MAX) {
|
pr_debug("%s: Setting low limit temperature interrupt: %d\n",
|
||||||
pr_debug("%s: Setting low limit temperature interrupt: %d\n",
|
thermal_zone_device_type(tz), low);
|
||||||
thermal_zone_device_type(tz), low);
|
writel(raw_low, LVTS_OFFSETL(base));
|
||||||
writel(raw_low, LVTS_H2NTHRE(base));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hot temperature threshold
|
* High offset temperature threshold
|
||||||
*
|
*
|
||||||
* LVTS_HTHRE
|
* LVTS_OFFSETH
|
||||||
*
|
*
|
||||||
* Bits:
|
* Bits:
|
||||||
*
|
*
|
||||||
@@ -323,7 +391,7 @@ static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
|
|||||||
*/
|
*/
|
||||||
pr_debug("%s: Setting high limit temperature interrupt: %d\n",
|
pr_debug("%s: Setting high limit temperature interrupt: %d\n",
|
||||||
thermal_zone_device_type(tz), high);
|
thermal_zone_device_type(tz), high);
|
||||||
writel(raw_high, LVTS_HTHRE(base));
|
writel(raw_high, LVTS_OFFSETH(base));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -451,7 +519,7 @@ static irqreturn_t lvts_irq_handler(int irq, void *data)
|
|||||||
|
|
||||||
for (i = 0; i < lvts_td->num_lvts_ctrl; i++) {
|
for (i = 0; i < lvts_td->num_lvts_ctrl; i++) {
|
||||||
|
|
||||||
aux = lvts_ctrl_irq_handler(lvts_td->lvts_ctrl);
|
aux = lvts_ctrl_irq_handler(&lvts_td->lvts_ctrl[i]);
|
||||||
if (aux != IRQ_HANDLED)
|
if (aux != IRQ_HANDLED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -521,6 +589,9 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl,
|
|||||||
*/
|
*/
|
||||||
lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ?
|
lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ?
|
||||||
imm_regs[i] : msr_regs[i];
|
imm_regs[i] : msr_regs[i];
|
||||||
|
|
||||||
|
lvts_sensor[i].low_thresh = INT_MIN;
|
||||||
|
lvts_sensor[i].high_thresh = INT_MIN;
|
||||||
};
|
};
|
||||||
|
|
||||||
lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor;
|
lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor;
|
||||||
@@ -688,6 +759,9 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td,
|
|||||||
*/
|
*/
|
||||||
lvts_ctrl[i].hw_tshut_raw_temp =
|
lvts_ctrl[i].hw_tshut_raw_temp =
|
||||||
lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp);
|
lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp);
|
||||||
|
|
||||||
|
lvts_ctrl[i].low_thresh = INT_MIN;
|
||||||
|
lvts_ctrl[i].high_thresh = INT_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -896,24 +970,6 @@ static int lvts_ctrl_configure(struct device *dev, struct lvts_ctrl *lvts_ctrl)
|
|||||||
LVTS_HW_FILTER << 3 | LVTS_HW_FILTER;
|
LVTS_HW_FILTER << 3 | LVTS_HW_FILTER;
|
||||||
writel(value, LVTS_MSRCTL0(lvts_ctrl->base));
|
writel(value, LVTS_MSRCTL0(lvts_ctrl->base));
|
||||||
|
|
||||||
/*
|
|
||||||
* LVTS_MSRCTL1 : Measurement control
|
|
||||||
*
|
|
||||||
* Bits:
|
|
||||||
*
|
|
||||||
* 9: Ignore MSRCTL0 config and do immediate measurement on sensor3
|
|
||||||
* 6: Ignore MSRCTL0 config and do immediate measurement on sensor2
|
|
||||||
* 5: Ignore MSRCTL0 config and do immediate measurement on sensor1
|
|
||||||
* 4: Ignore MSRCTL0 config and do immediate measurement on sensor0
|
|
||||||
*
|
|
||||||
* That configuration will ignore the filtering and the delays
|
|
||||||
* introduced below in MONCTL1 and MONCTL2
|
|
||||||
*/
|
|
||||||
if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) {
|
|
||||||
value = BIT(9) | BIT(6) | BIT(5) | BIT(4);
|
|
||||||
writel(value, LVTS_MSRCTL1(lvts_ctrl->base));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LVTS_MONCTL1 : Period unit and group interval configuration
|
* LVTS_MONCTL1 : Period unit and group interval configuration
|
||||||
*
|
*
|
||||||
@@ -979,6 +1035,15 @@ static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl)
|
|||||||
struct thermal_zone_device *tz;
|
struct thermal_zone_device *tz;
|
||||||
u32 sensor_map = 0;
|
u32 sensor_map = 0;
|
||||||
int i;
|
int i;
|
||||||
|
/*
|
||||||
|
* Bitmaps to enable each sensor on immediate and filtered modes, as
|
||||||
|
* described in MSRCTL1 and MONCTL0 registers below, respectively.
|
||||||
|
*/
|
||||||
|
u32 sensor_imm_bitmap[] = { BIT(4), BIT(5), BIT(6), BIT(9) };
|
||||||
|
u32 sensor_filt_bitmap[] = { BIT(0), BIT(1), BIT(2), BIT(3) };
|
||||||
|
|
||||||
|
u32 *sensor_bitmap = lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE ?
|
||||||
|
sensor_imm_bitmap : sensor_filt_bitmap;
|
||||||
|
|
||||||
for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) {
|
for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) {
|
||||||
|
|
||||||
@@ -1016,20 +1081,38 @@ static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl)
|
|||||||
* map, so we can enable the temperature monitoring in
|
* map, so we can enable the temperature monitoring in
|
||||||
* the hardware thermal controller.
|
* the hardware thermal controller.
|
||||||
*/
|
*/
|
||||||
sensor_map |= BIT(i);
|
sensor_map |= sensor_bitmap[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bits:
|
|
||||||
* 9: Single point access flow
|
|
||||||
* 0-3: Enable sensing point 0-3
|
|
||||||
*
|
|
||||||
* The initialization of the thermal zones give us
|
* The initialization of the thermal zones give us
|
||||||
* which sensor point to enable. If any thermal zone
|
* which sensor point to enable. If any thermal zone
|
||||||
* was not described in the device tree, it won't be
|
* was not described in the device tree, it won't be
|
||||||
* enabled here in the sensor map.
|
* enabled here in the sensor map.
|
||||||
*/
|
*/
|
||||||
writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base));
|
if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) {
|
||||||
|
/*
|
||||||
|
* LVTS_MSRCTL1 : Measurement control
|
||||||
|
*
|
||||||
|
* Bits:
|
||||||
|
*
|
||||||
|
* 9: Ignore MSRCTL0 config and do immediate measurement on sensor3
|
||||||
|
* 6: Ignore MSRCTL0 config and do immediate measurement on sensor2
|
||||||
|
* 5: Ignore MSRCTL0 config and do immediate measurement on sensor1
|
||||||
|
* 4: Ignore MSRCTL0 config and do immediate measurement on sensor0
|
||||||
|
*
|
||||||
|
* That configuration will ignore the filtering and the delays
|
||||||
|
* introduced in MONCTL1 and MONCTL2
|
||||||
|
*/
|
||||||
|
writel(sensor_map, LVTS_MSRCTL1(lvts_ctrl->base));
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Bits:
|
||||||
|
* 9: Single point access flow
|
||||||
|
* 0-3: Enable sensing point 0-3
|
||||||
|
*/
|
||||||
|
writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base));
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1138,7 +1221,7 @@ static int lvts_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
return dev_err_probe(dev, irq, "No irq resource\n");
|
return irq;
|
||||||
|
|
||||||
ret = lvts_domain_init(dev, lvts_td, lvts_data);
|
ret = lvts_domain_init(dev, lvts_td, lvts_data);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#define BIT_APPEND 0x3
|
#define BIT_APPEND 0x3
|
||||||
|
|
||||||
struct tsens_legacy_calibration_format tsens_8916_nvmem = {
|
static struct tsens_legacy_calibration_format tsens_8916_nvmem = {
|
||||||
.base_len = 7,
|
.base_len = 7,
|
||||||
.base_shift = 3,
|
.base_shift = 3,
|
||||||
.sp_len = 5,
|
.sp_len = 5,
|
||||||
@@ -39,7 +39,7 @@ struct tsens_legacy_calibration_format tsens_8916_nvmem = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tsens_legacy_calibration_format tsens_8974_nvmem = {
|
static struct tsens_legacy_calibration_format tsens_8974_nvmem = {
|
||||||
.base_len = 8,
|
.base_len = 8,
|
||||||
.base_shift = 2,
|
.base_shift = 2,
|
||||||
.sp_len = 6,
|
.sp_len = 6,
|
||||||
@@ -61,7 +61,7 @@ struct tsens_legacy_calibration_format tsens_8974_nvmem = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tsens_legacy_calibration_format tsens_8974_backup_nvmem = {
|
static struct tsens_legacy_calibration_format tsens_8974_backup_nvmem = {
|
||||||
.base_len = 8,
|
.base_len = 8,
|
||||||
.base_shift = 2,
|
.base_shift = 2,
|
||||||
.sp_len = 6,
|
.sp_len = 6,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#define TM_HIGH_LOW_INT_STATUS_OFF 0x0088
|
#define TM_HIGH_LOW_INT_STATUS_OFF 0x0088
|
||||||
#define TM_HIGH_LOW_Sn_INT_THRESHOLD_OFF 0x0090
|
#define TM_HIGH_LOW_Sn_INT_THRESHOLD_OFF 0x0090
|
||||||
|
|
||||||
struct tsens_legacy_calibration_format tsens_qcs404_nvmem = {
|
static struct tsens_legacy_calibration_format tsens_qcs404_nvmem = {
|
||||||
.base_len = 8,
|
.base_len = 8,
|
||||||
.base_shift = 2,
|
.base_shift = 2,
|
||||||
.sp_len = 6,
|
.sp_len = 6,
|
||||||
|
|||||||
@@ -887,7 +887,7 @@ static int exynos_map_dt_data(struct platform_device *pdev)
|
|||||||
return -EADDRNOTAVAIL;
|
return -EADDRNOTAVAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->soc = (enum soc_type)of_device_get_match_data(&pdev->dev);
|
data->soc = (uintptr_t)of_device_get_match_data(&pdev->dev);
|
||||||
|
|
||||||
switch (data->soc) {
|
switch (data->soc) {
|
||||||
case SOC_ARCH_EXYNOS4210:
|
case SOC_ARCH_EXYNOS4210:
|
||||||
|
|||||||
@@ -56,8 +56,6 @@
|
|||||||
#define SUN50I_H6_THS_PC_TEMP_PERIOD(x) ((GENMASK(19, 0) & (x)) << 12)
|
#define SUN50I_H6_THS_PC_TEMP_PERIOD(x) ((GENMASK(19, 0) & (x)) << 12)
|
||||||
#define SUN50I_H6_THS_DATA_IRQ_STS(x) BIT(x)
|
#define SUN50I_H6_THS_DATA_IRQ_STS(x) BIT(x)
|
||||||
|
|
||||||
/* millidegree celsius */
|
|
||||||
|
|
||||||
struct tsensor {
|
struct tsensor {
|
||||||
struct ths_device *tmdev;
|
struct ths_device *tmdev;
|
||||||
struct thermal_zone_device *tzd;
|
struct thermal_zone_device *tzd;
|
||||||
@@ -286,7 +284,7 @@ static int sun8i_ths_calibrate(struct ths_device *tmdev)
|
|||||||
size_t callen;
|
size_t callen;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
calcell = devm_nvmem_cell_get(dev, "calibration");
|
calcell = nvmem_cell_get(dev, "calibration");
|
||||||
if (IS_ERR(calcell)) {
|
if (IS_ERR(calcell)) {
|
||||||
if (PTR_ERR(calcell) == -EPROBE_DEFER)
|
if (PTR_ERR(calcell) == -EPROBE_DEFER)
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
@@ -316,6 +314,8 @@ static int sun8i_ths_calibrate(struct ths_device *tmdev)
|
|||||||
|
|
||||||
kfree(caldata);
|
kfree(caldata);
|
||||||
out:
|
out:
|
||||||
|
if (!IS_ERR(calcell))
|
||||||
|
nvmem_cell_put(calcell);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,8 +489,6 @@ static int sun8i_ths_probe(struct platform_device *pdev)
|
|||||||
if (!tmdev->chip)
|
if (!tmdev->chip)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
platform_set_drvdata(pdev, tmdev);
|
|
||||||
|
|
||||||
ret = sun8i_ths_resource_init(tmdev);
|
ret = sun8i_ths_resource_init(tmdev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -167,19 +167,69 @@ static int tegra_bpmp_thermal_get_num_zones(struct tegra_bpmp *bpmp,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tegra_bpmp_thermal_trips_supported(struct tegra_bpmp *bpmp, bool *supported)
|
||||||
|
{
|
||||||
|
struct mrq_thermal_host_to_bpmp_request req;
|
||||||
|
union mrq_thermal_bpmp_to_host_response reply;
|
||||||
|
struct tegra_bpmp_message msg;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
req.type = CMD_THERMAL_QUERY_ABI;
|
||||||
|
req.query_abi.type = CMD_THERMAL_SET_TRIP;
|
||||||
|
|
||||||
|
memset(&msg, 0, sizeof(msg));
|
||||||
|
msg.mrq = MRQ_THERMAL;
|
||||||
|
msg.tx.data = &req;
|
||||||
|
msg.tx.size = sizeof(req);
|
||||||
|
msg.rx.data = &reply;
|
||||||
|
msg.rx.size = sizeof(reply);
|
||||||
|
|
||||||
|
err = tegra_bpmp_transfer(bpmp, &msg);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (msg.rx.ret == 0) {
|
||||||
|
*supported = true;
|
||||||
|
return 0;
|
||||||
|
} else if (msg.rx.ret == -BPMP_ENODEV) {
|
||||||
|
*supported = false;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct thermal_zone_device_ops tegra_bpmp_of_thermal_ops = {
|
static const struct thermal_zone_device_ops tegra_bpmp_of_thermal_ops = {
|
||||||
.get_temp = tegra_bpmp_thermal_get_temp,
|
.get_temp = tegra_bpmp_thermal_get_temp,
|
||||||
.set_trips = tegra_bpmp_thermal_set_trips,
|
.set_trips = tegra_bpmp_thermal_set_trips,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct thermal_zone_device_ops tegra_bpmp_of_thermal_ops_notrips = {
|
||||||
|
.get_temp = tegra_bpmp_thermal_get_temp,
|
||||||
|
};
|
||||||
|
|
||||||
static int tegra_bpmp_thermal_probe(struct platform_device *pdev)
|
static int tegra_bpmp_thermal_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct tegra_bpmp *bpmp = dev_get_drvdata(pdev->dev.parent);
|
struct tegra_bpmp *bpmp = dev_get_drvdata(pdev->dev.parent);
|
||||||
|
const struct thermal_zone_device_ops *thermal_ops;
|
||||||
struct tegra_bpmp_thermal *tegra;
|
struct tegra_bpmp_thermal *tegra;
|
||||||
struct thermal_zone_device *tzd;
|
struct thermal_zone_device *tzd;
|
||||||
unsigned int i, max_num_zones;
|
unsigned int i, max_num_zones;
|
||||||
|
bool supported;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
err = tegra_bpmp_thermal_trips_supported(bpmp, &supported);
|
||||||
|
if (err) {
|
||||||
|
dev_err(&pdev->dev, "failed to determine if trip points are supported\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supported)
|
||||||
|
thermal_ops = &tegra_bpmp_of_thermal_ops;
|
||||||
|
else
|
||||||
|
thermal_ops = &tegra_bpmp_of_thermal_ops_notrips;
|
||||||
|
|
||||||
tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
|
tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
|
||||||
if (!tegra)
|
if (!tegra)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -222,7 +272,7 @@ static int tegra_bpmp_thermal_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tzd = devm_thermal_of_zone_register(
|
tzd = devm_thermal_of_zone_register(
|
||||||
&pdev->dev, i, zone, &tegra_bpmp_of_thermal_ops);
|
&pdev->dev, i, zone, thermal_ops);
|
||||||
if (IS_ERR(tzd)) {
|
if (IS_ERR(tzd)) {
|
||||||
if (PTR_ERR(tzd) == -EPROBE_DEFER)
|
if (PTR_ERR(tzd) == -EPROBE_DEFER)
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
|
|||||||
@@ -142,7 +142,6 @@ static int gadc_thermal_probe(struct platform_device *pdev)
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
gti->dev = &pdev->dev;
|
gti->dev = &pdev->dev;
|
||||||
platform_set_drvdata(pdev, gti);
|
|
||||||
|
|
||||||
gti->tz_dev = devm_thermal_of_zone_register(&pdev->dev, 0, gti,
|
gti->tz_dev = devm_thermal_of_zone_register(&pdev->dev, 0, gti,
|
||||||
&gadc_thermal_ops);
|
&gadc_thermal_ops);
|
||||||
|
|||||||
@@ -1266,7 +1266,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
|
|||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp) && !trips)
|
if (num_trips > 0 && !trips)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
if (!thermal_class)
|
if (!thermal_class)
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev)
|
|||||||
void thermal_cdev_update(struct thermal_cooling_device *);
|
void thermal_cdev_update(struct thermal_cooling_device *);
|
||||||
void __thermal_cdev_update(struct thermal_cooling_device *cdev);
|
void __thermal_cdev_update(struct thermal_cooling_device *cdev);
|
||||||
|
|
||||||
int get_tz_trend(struct thermal_zone_device *tz, int trip);
|
int get_tz_trend(struct thermal_zone_device *tz, int trip_index);
|
||||||
|
|
||||||
struct thermal_instance *
|
struct thermal_instance *
|
||||||
get_thermal_instance(struct thermal_zone_device *tz,
|
get_thermal_instance(struct thermal_zone_device *tz,
|
||||||
|
|||||||
@@ -22,8 +22,9 @@
|
|||||||
#include "thermal_core.h"
|
#include "thermal_core.h"
|
||||||
#include "thermal_trace.h"
|
#include "thermal_trace.h"
|
||||||
|
|
||||||
int get_tz_trend(struct thermal_zone_device *tz, int trip)
|
int get_tz_trend(struct thermal_zone_device *tz, int trip_index)
|
||||||
{
|
{
|
||||||
|
struct thermal_trip *trip = tz->trips ? &tz->trips[trip_index] : NULL;
|
||||||
enum thermal_trend trend;
|
enum thermal_trend trend;
|
||||||
|
|
||||||
if (tz->emul_temperature || !tz->ops->get_trend ||
|
if (tz->emul_temperature || !tz->ops->get_trend ||
|
||||||
|
|||||||
@@ -101,29 +101,11 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz)
|
|||||||
int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
|
int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
|
||||||
struct thermal_trip *trip)
|
struct thermal_trip *trip)
|
||||||
{
|
{
|
||||||
int ret;
|
if (!tz || !tz->trips || trip_id < 0 || trip_id >= tz->num_trips || !trip)
|
||||||
|
|
||||||
if (!tz || trip_id < 0 || trip_id >= tz->num_trips || !trip)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (tz->trips) {
|
*trip = tz->trips[trip_id];
|
||||||
*trip = tz->trips[trip_id];
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tz->ops->get_trip_hyst) {
|
|
||||||
ret = tz->ops->get_trip_hyst(tz, trip_id, &trip->hysteresis);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
} else {
|
|
||||||
trip->hysteresis = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = tz->ops->get_trip_temp(tz, trip_id, &trip->temperature);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return tz->ops->get_trip_type(tz, trip_id, &trip->type);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__thermal_zone_get_trip);
|
EXPORT_SYMBOL_GPL(__thermal_zone_get_trip);
|
||||||
|
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ int ti_bandgap_adc_to_mcelsius(struct ti_bandgap *bgp, int adc_val, int *t)
|
|||||||
*/
|
*/
|
||||||
static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id)
|
static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id)
|
||||||
{
|
{
|
||||||
if (!bgp || IS_ERR(bgp)) {
|
if (IS_ERR_OR_NULL(bgp)) {
|
||||||
pr_err("%s: invalid bandgap pointer\n", __func__);
|
pr_err("%s: invalid bandgap pointer\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,7 +109,8 @@ static inline int __ti_thermal_get_temp(struct thermal_zone_device *tz, int *tem
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __ti_thermal_get_trend(struct thermal_zone_device *tz, int trip, enum thermal_trend *trend)
|
static int __ti_thermal_get_trend(struct thermal_zone_device *tz,
|
||||||
|
struct thermal_trip *trip, enum thermal_trend *trend)
|
||||||
{
|
{
|
||||||
struct ti_thermal_data *data = thermal_zone_device_priv(tz);
|
struct ti_thermal_data *data = thermal_zone_device_priv(tz);
|
||||||
struct ti_bandgap *bgp;
|
struct ti_bandgap *bgp;
|
||||||
|
|||||||
+19
-23
@@ -53,29 +53,6 @@ enum thermal_notify_event {
|
|||||||
THERMAL_EVENT_KEEP_ALIVE, /* Request for user space handler to respond */
|
THERMAL_EVENT_KEEP_ALIVE, /* Request for user space handler to respond */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct thermal_zone_device_ops {
|
|
||||||
int (*bind) (struct thermal_zone_device *,
|
|
||||||
struct thermal_cooling_device *);
|
|
||||||
int (*unbind) (struct thermal_zone_device *,
|
|
||||||
struct thermal_cooling_device *);
|
|
||||||
int (*get_temp) (struct thermal_zone_device *, int *);
|
|
||||||
int (*set_trips) (struct thermal_zone_device *, int, int);
|
|
||||||
int (*change_mode) (struct thermal_zone_device *,
|
|
||||||
enum thermal_device_mode);
|
|
||||||
int (*get_trip_type) (struct thermal_zone_device *, int,
|
|
||||||
enum thermal_trip_type *);
|
|
||||||
int (*get_trip_temp) (struct thermal_zone_device *, int, int *);
|
|
||||||
int (*set_trip_temp) (struct thermal_zone_device *, int, int);
|
|
||||||
int (*get_trip_hyst) (struct thermal_zone_device *, int, int *);
|
|
||||||
int (*set_trip_hyst) (struct thermal_zone_device *, int, int);
|
|
||||||
int (*get_crit_temp) (struct thermal_zone_device *, int *);
|
|
||||||
int (*set_emul_temp) (struct thermal_zone_device *, int);
|
|
||||||
int (*get_trend) (struct thermal_zone_device *, int,
|
|
||||||
enum thermal_trend *);
|
|
||||||
void (*hot)(struct thermal_zone_device *);
|
|
||||||
void (*critical)(struct thermal_zone_device *);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct thermal_trip - representation of a point in temperature domain
|
* struct thermal_trip - representation of a point in temperature domain
|
||||||
* @temperature: temperature value in miliCelsius
|
* @temperature: temperature value in miliCelsius
|
||||||
@@ -90,6 +67,25 @@ struct thermal_trip {
|
|||||||
void *priv;
|
void *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct thermal_zone_device_ops {
|
||||||
|
int (*bind) (struct thermal_zone_device *,
|
||||||
|
struct thermal_cooling_device *);
|
||||||
|
int (*unbind) (struct thermal_zone_device *,
|
||||||
|
struct thermal_cooling_device *);
|
||||||
|
int (*get_temp) (struct thermal_zone_device *, int *);
|
||||||
|
int (*set_trips) (struct thermal_zone_device *, int, int);
|
||||||
|
int (*change_mode) (struct thermal_zone_device *,
|
||||||
|
enum thermal_device_mode);
|
||||||
|
int (*set_trip_temp) (struct thermal_zone_device *, int, int);
|
||||||
|
int (*set_trip_hyst) (struct thermal_zone_device *, int, int);
|
||||||
|
int (*get_crit_temp) (struct thermal_zone_device *, int *);
|
||||||
|
int (*set_emul_temp) (struct thermal_zone_device *, int);
|
||||||
|
int (*get_trend) (struct thermal_zone_device *, struct thermal_trip *,
|
||||||
|
enum thermal_trend *);
|
||||||
|
void (*hot)(struct thermal_zone_device *);
|
||||||
|
void (*critical)(struct thermal_zone_device *);
|
||||||
|
};
|
||||||
|
|
||||||
struct thermal_cooling_device_ops {
|
struct thermal_cooling_device_ops {
|
||||||
int (*get_max_state) (struct thermal_cooling_device *, unsigned long *);
|
int (*get_max_state) (struct thermal_cooling_device *, unsigned long *);
|
||||||
int (*get_cur_state) (struct thermal_cooling_device *, unsigned long *);
|
int (*get_cur_state) (struct thermal_cooling_device *, unsigned long *);
|
||||||
|
|||||||
Reference in New Issue
Block a user