mirror of https://github.com/torvalds/linux.git
- Document the RZ/V2H TSU DT bindings (Ovidiu Panait)
- Document the Kaanapali Temperature Sensor (Manaf Meethalavalappu Pallikunhi) - Document R-Car Gen4 and RZ/G2 support in driver comment (Marek Vasut) - Convert to DEFINE_SIMPLE_DEV_PM_OPS in the R-Car [Gen3] (Geert Uytterhoeven) - Fix format string bug in thermal-engine (Malaya Kumar Rout) - Make ipq5018 tsens standalone compatible (George Moussalem) - Add the QCS8300 compatible for the QCom Tsens (Gaurav Kohli) - Add the support for the NXP i.MX91 thermal module, including the DT bindings (Pengfei Li) -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEGn3N4YVz0WNVyHskqDIjiipP6E8FAmkocvMACgkQqDIjiipP 6E/vOQgAncWodGutUfBwvXePKEiR6vgGJK1MExTpgwhPmbJRttEtQhXcG6/Rk76e hA4q+/Cags5rU/ydK5Qor8PcAmC/Y98Xs9fepWoygKB1fClWejVftTBSANgHDLnD Txz12/F9FXxy957mm0NEKgVUkMYt/cipzj0c0y5c4xPVyVFYenVG0YTitCNlmTsI ouBZgKXCZ1lYnGsRwebNcODnkvMKzjOeN5PetcI5ThSGF7SWcgJb9bKRTKS+kJ+r 1j68xJrjh/viYv7qrpaOCMaYbQcb38yPncPOWHLMAx2AIWVceOcmKWEypA2dT63z agHB9jkhf/8kUuymB6tWSA4zjACLsw== =fLGN -----END PGP SIGNATURE----- Merge tag 'thermal-v6.19-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux Pull thermal control changes for 6.19-rc1 from Daniel Lezcano: "- Document the RZ/V2H TSU DT bindings (Ovidiu Panait) - Document the Kaanapali Temperature Sensor (Manaf Meethalavalappu Pallikunhi) - Document R-Car Gen4 and RZ/G2 support in driver comment (Marek Vasut) - Convert to DEFINE_SIMPLE_DEV_PM_OPS in the R-Car [Gen3] (Geert Uytterhoeven) - Fix format string bug in thermal-engine (Malaya Kumar Rout) - Make ipq5018 tsens standalone compatible (George Moussalem) - Add the QCS8300 compatible for the QCom Tsens (Gaurav Kohli) - Add the support for the NXP i.MX91 thermal module, including the DT bindings (Pengfei Li) * tag 'thermal-v6.19-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux: thermal/drivers/imx91: Add support for i.MX91 thermal monitoring unit dt-bindings: thermal: fsl,imx91-tmu: add bindings for NXP i.MX91 thermal module dt-bindings: thermal: tsens: Add QCS8300 compatible dt-bindings: thermal: qcom-tsens: make ipq5018 tsens standalone compatible tools/thermal/thermal-engine: Fix format string bug in thermal-engine thermal/drivers/rcar_gen3: Convert to DEFINE_SIMPLE_DEV_PM_OPS() thermal/drivers/rcar: Convert to DEFINE_SIMPLE_DEV_PM_OPS() thermal/drivers/rcar_gen3: Document R-Car Gen4 and RZ/G2 support in driver comment dt-bindings: thermal: qcom-tsens: document the Kaanapali Temperature Sensor dt-bindings: thermal: r9a09g047-tsu: Document RZ/V2H TSU
This commit is contained in:
commit
63d26c3811
|
|
@ -0,0 +1,87 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/thermal/fsl,imx91-tmu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP i.MX91 Thermal
|
||||
|
||||
maintainers:
|
||||
- Pengfei Li <pengfei.li_1@nxp.com>
|
||||
|
||||
description:
|
||||
i.MX91 features a new temperature sensor. It includes programmable
|
||||
temperature threshold comparators for both normal and privileged
|
||||
accesses and allows a programmable measurement frequency for the
|
||||
Periodic One-Shot Measurement mode. Additionally, it provides
|
||||
status registers for indicating the end of measurement and threshold
|
||||
violation events.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: fsl,imx91-tmu
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: Comparator 1 irq
|
||||
- description: Comparator 2 irq
|
||||
- description: Data ready irq
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: thr1
|
||||
- const: thr2
|
||||
- const: ready
|
||||
|
||||
nvmem-cells:
|
||||
items:
|
||||
- description: Phandle to the trim control 1 provided by ocotp
|
||||
- description: Phandle to the trim control 2 provided by ocotp
|
||||
|
||||
nvmem-cell-names:
|
||||
items:
|
||||
- const: trim1
|
||||
- const: trim2
|
||||
|
||||
"#thermal-sensor-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
allOf:
|
||||
- $ref: thermal-sensor.yaml
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/imx93-clock.h>
|
||||
|
||||
thermal-sensor@44482000 {
|
||||
compatible = "fsl,imx91-tmu";
|
||||
reg = <0x44482000 0x1000>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
clocks = <&clk IMX93_CLK_TMC_GATE>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "thr1", "thr2", "ready";
|
||||
nvmem-cells = <&tmu_trim1>, <&tmu_trim2>;
|
||||
nvmem-cell-names = "trim1", "trim2";
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -36,10 +36,15 @@ properties:
|
|||
- qcom,msm8974-tsens
|
||||
- const: qcom,tsens-v0_1
|
||||
|
||||
- description:
|
||||
v1 of TSENS without RPM which requires to be explicitly reset
|
||||
and enabled in the driver.
|
||||
enum:
|
||||
- qcom,ipq5018-tsens
|
||||
|
||||
- description: v1 of TSENS
|
||||
items:
|
||||
- enum:
|
||||
- qcom,ipq5018-tsens
|
||||
- qcom,msm8937-tsens
|
||||
- qcom,msm8956-tsens
|
||||
- qcom,msm8976-tsens
|
||||
|
|
@ -50,11 +55,13 @@ properties:
|
|||
items:
|
||||
- enum:
|
||||
- qcom,glymur-tsens
|
||||
- qcom,kaanapali-tsens
|
||||
- qcom,milos-tsens
|
||||
- qcom,msm8953-tsens
|
||||
- qcom,msm8996-tsens
|
||||
- qcom,msm8998-tsens
|
||||
- qcom,qcm2290-tsens
|
||||
- qcom,qcs8300-tsens
|
||||
- qcom,qcs615-tsens
|
||||
- qcom,sa8255p-tsens
|
||||
- qcom,sa8775p-tsens
|
||||
|
|
|
|||
|
|
@ -16,7 +16,11 @@ description:
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
const: renesas,r9a09g047-tsu
|
||||
oneOf:
|
||||
- const: renesas,r9a09g047-tsu # RZ/G3E
|
||||
- items:
|
||||
- const: renesas,r9a09g057-tsu # RZ/V2H
|
||||
- const: renesas,r9a09g047-tsu # RZ/G3E
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
|||
|
|
@ -296,6 +296,16 @@ config IMX8MM_THERMAL
|
|||
cpufreq is used as the cooling device to throttle CPUs when the passive
|
||||
trip is crossed.
|
||||
|
||||
config IMX91_THERMAL
|
||||
tristate "Temperature sensor driver for NXP i.MX91 SoC"
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
depends on OF
|
||||
help
|
||||
Include one sensor and six comparators. Each of them compares the
|
||||
temperature value (from the sensor) against the programmable
|
||||
threshold values. The direction of the comparison is configurable
|
||||
(greater / lesser than).
|
||||
|
||||
config K3_THERMAL
|
||||
tristate "Texas Instruments K3 thermal support"
|
||||
depends on ARCH_K3 || COMPILE_TEST
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
|
|||
obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
|
||||
obj-$(CONFIG_IMX_SC_THERMAL) += imx_sc_thermal.o
|
||||
obj-$(CONFIG_IMX8MM_THERMAL) += imx8mm_thermal.o
|
||||
obj-$(CONFIG_IMX91_THERMAL) += imx91_thermal.o
|
||||
obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o
|
||||
obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
|
||||
obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o
|
||||
|
|
|
|||
|
|
@ -0,0 +1,384 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright 2025 NXP.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#define REG_SET 0x4
|
||||
#define REG_CLR 0x8
|
||||
#define REG_TOG 0xc
|
||||
|
||||
#define IMX91_TMU_CTRL0 0x0
|
||||
#define IMX91_TMU_CTRL0_THR1_IE BIT(9)
|
||||
#define IMX91_TMU_CTRL0_THR1_MASK GENMASK(3, 2)
|
||||
#define IMX91_TMU_CTRL0_CLR_FLT1 BIT(21)
|
||||
|
||||
#define IMX91_TMU_THR_MODE_LE 0
|
||||
#define IMX91_TMU_THR_MODE_GE 1
|
||||
|
||||
#define IMX91_TMU_STAT0 0x10
|
||||
#define IMX91_TMU_STAT0_THR1_IF BIT(9)
|
||||
#define IMX91_TMU_STAT0_THR1_STAT BIT(13)
|
||||
#define IMX91_TMU_STAT0_DRDY0_IF_MASK BIT(16)
|
||||
|
||||
#define IMX91_TMU_DATA0 0x20
|
||||
|
||||
#define IMX91_TMU_CTRL1 0x200
|
||||
#define IMX91_TMU_CTRL1_EN BIT(31)
|
||||
#define IMX91_TMU_CTRL1_START BIT(30)
|
||||
#define IMX91_TMU_CTRL1_STOP BIT(29)
|
||||
#define IMX91_TMU_CTRL1_RES_MASK GENMASK(19, 18)
|
||||
#define IMX91_TMU_CTRL1_MEAS_MODE_MASK GENMASK(25, 24)
|
||||
#define IMX91_TMU_CTRL1_MEAS_MODE_SINGLE 0
|
||||
#define IMX91_TMU_CTRL1_MEAS_MODE_CONTINUES 1
|
||||
#define IMX91_TMU_CTRL1_MEAS_MODE_PERIODIC 2
|
||||
|
||||
#define IMX91_TMU_THR_CTRL01 0x30
|
||||
#define IMX91_TMU_THR_CTRL01_THR1_MASK GENMASK(31, 16)
|
||||
|
||||
#define IMX91_TMU_REF_DIV 0x280
|
||||
#define IMX91_TMU_DIV_EN BIT(31)
|
||||
#define IMX91_TMU_DIV_MASK GENMASK(23, 16)
|
||||
#define IMX91_TMU_DIV_MAX 255
|
||||
|
||||
#define IMX91_TMU_PUD_ST_CTRL 0x2b0
|
||||
#define IMX91_TMU_PUDL_MASK GENMASK(23, 16)
|
||||
|
||||
#define IMX91_TMU_TRIM1 0x2e0
|
||||
#define IMX91_TMU_TRIM2 0x2f0
|
||||
|
||||
#define IMX91_TMU_TEMP_LOW_LIMIT -40000
|
||||
#define IMX91_TMU_TEMP_HIGH_LIMIT 125000
|
||||
|
||||
#define IMX91_TMU_DEFAULT_TRIM1_CONFIG 0xb561bc2d
|
||||
#define IMX91_TMU_DEFAULT_TRIM2_CONFIG 0x65d4
|
||||
|
||||
#define IMX91_TMU_PERIOD_CTRL 0x270
|
||||
#define IMX91_TMU_PERIOD_CTRL_MEAS_MASK GENMASK(23, 0)
|
||||
|
||||
#define IMX91_TMP_FRAC 64
|
||||
|
||||
struct imx91_tmu {
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
struct device *dev;
|
||||
struct thermal_zone_device *tzd;
|
||||
};
|
||||
|
||||
static void imx91_tmu_start(struct imx91_tmu *tmu, bool start)
|
||||
{
|
||||
u32 val = start ? IMX91_TMU_CTRL1_START : IMX91_TMU_CTRL1_STOP;
|
||||
|
||||
writel_relaxed(val, tmu->base + IMX91_TMU_CTRL1 + REG_SET);
|
||||
}
|
||||
|
||||
static void imx91_tmu_enable(struct imx91_tmu *tmu, bool enable)
|
||||
{
|
||||
u32 reg = IMX91_TMU_CTRL1;
|
||||
|
||||
reg += enable ? REG_SET : REG_CLR;
|
||||
|
||||
writel_relaxed(IMX91_TMU_CTRL1_EN, tmu->base + reg);
|
||||
}
|
||||
|
||||
static int imx91_tmu_to_mcelsius(int x)
|
||||
{
|
||||
return x * MILLIDEGREE_PER_DEGREE / IMX91_TMP_FRAC;
|
||||
}
|
||||
|
||||
static int imx91_tmu_from_mcelsius(int x)
|
||||
{
|
||||
return x * IMX91_TMP_FRAC / MILLIDEGREE_PER_DEGREE;
|
||||
}
|
||||
|
||||
static int imx91_tmu_get_temp(struct thermal_zone_device *tz, int *temp)
|
||||
{
|
||||
struct imx91_tmu *tmu = thermal_zone_device_priv(tz);
|
||||
s16 data;
|
||||
|
||||
/* DATA0 is 16bit signed number */
|
||||
data = readw_relaxed(tmu->base + IMX91_TMU_DATA0);
|
||||
*temp = imx91_tmu_to_mcelsius(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx91_tmu_set_trips(struct thermal_zone_device *tz, int low, int high)
|
||||
{
|
||||
struct imx91_tmu *tmu = thermal_zone_device_priv(tz);
|
||||
int val;
|
||||
|
||||
if (high >= IMX91_TMU_TEMP_HIGH_LIMIT)
|
||||
return -EINVAL;
|
||||
|
||||
writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_CLR);
|
||||
|
||||
/* Comparator1 for temperature threshold */
|
||||
writel_relaxed(IMX91_TMU_THR_CTRL01_THR1_MASK, tmu->base + IMX91_TMU_THR_CTRL01 + REG_CLR);
|
||||
val = FIELD_PREP(IMX91_TMU_THR_CTRL01_THR1_MASK, imx91_tmu_from_mcelsius(high));
|
||||
|
||||
writel_relaxed(val, tmu->base + IMX91_TMU_THR_CTRL01 + REG_SET);
|
||||
|
||||
writel_relaxed(IMX91_TMU_STAT0_THR1_IF, tmu->base + IMX91_TMU_STAT0 + REG_CLR);
|
||||
|
||||
writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx91_init_from_nvmem_cells(struct imx91_tmu *tmu)
|
||||
{
|
||||
struct device *dev = tmu->dev;
|
||||
u32 trim1, trim2;
|
||||
int ret;
|
||||
|
||||
ret = nvmem_cell_read_u32(dev, "trim1", &trim1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nvmem_cell_read_u32(dev, "trim2", &trim2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (trim1 == 0 || trim2 == 0)
|
||||
return -EINVAL;
|
||||
|
||||
writel_relaxed(trim1, tmu->base + IMX91_TMU_TRIM1);
|
||||
writel_relaxed(trim2, tmu->base + IMX91_TMU_TRIM2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imx91_tmu_action_remove(void *data)
|
||||
{
|
||||
struct imx91_tmu *tmu = data;
|
||||
|
||||
/* disable tmu */
|
||||
imx91_tmu_enable(tmu, false);
|
||||
}
|
||||
|
||||
static irqreturn_t imx91_tmu_alarm_irq(int irq, void *data)
|
||||
{
|
||||
struct imx91_tmu *tmu = data;
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(tmu->base + IMX91_TMU_STAT0);
|
||||
|
||||
/* Check if comparison interrupt occurred */
|
||||
if (val & IMX91_TMU_STAT0_THR1_IF) {
|
||||
/* Clear irq flag and disable interrupt until reconfigured */
|
||||
writel(IMX91_TMU_STAT0_THR1_IF, tmu->base + IMX91_TMU_STAT0 + REG_CLR);
|
||||
writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_CLR);
|
||||
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static irqreturn_t imx91_tmu_alarm_irq_thread(int irq, void *data)
|
||||
{
|
||||
struct imx91_tmu *tmu = data;
|
||||
|
||||
thermal_zone_device_update(tmu->tzd, THERMAL_EVENT_UNSPECIFIED);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int imx91_tmu_change_mode(struct thermal_zone_device *tz, enum thermal_device_mode mode)
|
||||
{
|
||||
struct imx91_tmu *tmu = thermal_zone_device_priv(tz);
|
||||
int ret;
|
||||
|
||||
if (mode == THERMAL_DEVICE_ENABLED) {
|
||||
ret = pm_runtime_get(tmu->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
writel_relaxed(IMX91_TMU_CTRL0_THR1_IE | IMX91_TMU_CTRL0_THR1_MASK,
|
||||
tmu->base + IMX91_TMU_CTRL0 + REG_CLR);
|
||||
|
||||
writel_relaxed(FIELD_PREP(IMX91_TMU_CTRL0_THR1_MASK, IMX91_TMU_THR_MODE_GE),
|
||||
tmu->base + IMX91_TMU_CTRL0 + REG_SET);
|
||||
imx91_tmu_start(tmu, true);
|
||||
} else {
|
||||
writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_CLR);
|
||||
imx91_tmu_start(tmu, false);
|
||||
pm_runtime_put(tmu->dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct thermal_zone_device_ops tmu_tz_ops = {
|
||||
.get_temp = imx91_tmu_get_temp,
|
||||
.change_mode = imx91_tmu_change_mode,
|
||||
.set_trips = imx91_tmu_set_trips,
|
||||
};
|
||||
|
||||
static int imx91_tmu_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct imx91_tmu *tmu;
|
||||
unsigned long rate;
|
||||
int irq, ret;
|
||||
u32 div;
|
||||
|
||||
tmu = devm_kzalloc(dev, sizeof(struct imx91_tmu), GFP_KERNEL);
|
||||
if (!tmu)
|
||||
return -ENOMEM;
|
||||
|
||||
tmu->dev = dev;
|
||||
|
||||
tmu->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(tmu->base))
|
||||
return dev_err_probe(dev, PTR_ERR(tmu->base), "failed to get io resource");
|
||||
|
||||
tmu->clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(tmu->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(tmu->clk), "failed to get tmu clock\n");
|
||||
|
||||
platform_set_drvdata(pdev, tmu);
|
||||
|
||||
/* disable the monitor during initialization */
|
||||
imx91_tmu_enable(tmu, false);
|
||||
imx91_tmu_start(tmu, false);
|
||||
|
||||
ret = imx91_init_from_nvmem_cells(tmu);
|
||||
if (ret) {
|
||||
dev_warn(dev, "can't get trim value, use default settings\n");
|
||||
|
||||
writel_relaxed(IMX91_TMU_DEFAULT_TRIM1_CONFIG, tmu->base + IMX91_TMU_TRIM1);
|
||||
writel_relaxed(IMX91_TMU_DEFAULT_TRIM2_CONFIG, tmu->base + IMX91_TMU_TRIM2);
|
||||
}
|
||||
|
||||
/* The typical conv clk is 4MHz, the output freq is 'rate / (div + 1)' */
|
||||
rate = clk_get_rate(tmu->clk);
|
||||
div = (rate / (4 * HZ_PER_MHZ)) - 1;
|
||||
if (div > IMX91_TMU_DIV_MAX)
|
||||
return dev_err_probe(dev, -EINVAL, "clock divider exceed hardware limitation");
|
||||
|
||||
/* Set divider value and enable divider */
|
||||
writel_relaxed(IMX91_TMU_DIV_EN | FIELD_PREP(IMX91_TMU_DIV_MASK, div),
|
||||
tmu->base + IMX91_TMU_REF_DIV);
|
||||
|
||||
/* Set max power up delay: 'Tpud(ms) = 0xFF * 1000 / 4000000' */
|
||||
writel_relaxed(FIELD_PREP(IMX91_TMU_PUDL_MASK, 100U), tmu->base + IMX91_TMU_PUD_ST_CTRL);
|
||||
|
||||
/*
|
||||
* Set resolution mode
|
||||
* 00b - Conversion time = 0.59325 ms
|
||||
* 01b - Conversion time = 1.10525 ms
|
||||
* 10b - Conversion time = 2.12925 ms
|
||||
* 11b - Conversion time = 4.17725 ms
|
||||
*/
|
||||
writel_relaxed(FIELD_PREP(IMX91_TMU_CTRL1_RES_MASK, 0x3),
|
||||
tmu->base + IMX91_TMU_CTRL1 + REG_CLR);
|
||||
writel_relaxed(FIELD_PREP(IMX91_TMU_CTRL1_RES_MASK, 0x1),
|
||||
tmu->base + IMX91_TMU_CTRL1 + REG_SET);
|
||||
|
||||
writel_relaxed(IMX91_TMU_CTRL1_MEAS_MODE_MASK, tmu->base + IMX91_TMU_CTRL1 + REG_CLR);
|
||||
writel_relaxed(FIELD_PREP(IMX91_TMU_CTRL1_MEAS_MODE_MASK,
|
||||
IMX91_TMU_CTRL1_MEAS_MODE_PERIODIC),
|
||||
tmu->base + IMX91_TMU_CTRL1 + REG_SET);
|
||||
|
||||
/*
|
||||
* Set Periodic Measurement Frequency to 25Hz:
|
||||
* tMEAS_FREQ = tCONV_CLK * PERIOD_CTRL[MEAS_FREQ]
|
||||
*/
|
||||
writel_relaxed(FIELD_PREP(IMX91_TMU_PERIOD_CTRL_MEAS_MASK, 4 * HZ_PER_MHZ / 25),
|
||||
tmu->base + IMX91_TMU_PERIOD_CTRL);
|
||||
|
||||
imx91_tmu_enable(tmu, true);
|
||||
ret = devm_add_action(dev, imx91_tmu_action_remove, tmu);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failure to add action imx91_tmu_action_remove()\n");
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_get_noresume(dev);
|
||||
ret = devm_pm_runtime_enable(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
tmu->tzd = devm_thermal_of_zone_register(dev, 0, tmu, &tmu_tz_ops);
|
||||
if (IS_ERR(tmu->tzd))
|
||||
return dev_err_probe(dev, PTR_ERR(tmu->tzd),
|
||||
"failed to register thermal zone sensor\n");
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, imx91_tmu_alarm_irq,
|
||||
imx91_tmu_alarm_irq_thread,
|
||||
IRQF_ONESHOT, "imx91_thermal", tmu);
|
||||
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "failed to request alarm irq\n");
|
||||
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx91_tmu_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct imx91_tmu *tmu = dev_get_drvdata(dev);
|
||||
|
||||
/* disable tmu */
|
||||
imx91_tmu_enable(tmu, false);
|
||||
|
||||
clk_disable_unprepare(tmu->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx91_tmu_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct imx91_tmu *tmu = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(tmu->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
imx91_tmu_enable(tmu, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_RUNTIME_DEV_PM_OPS(imx91_tmu_pm_ops, imx91_tmu_runtime_suspend,
|
||||
imx91_tmu_runtime_resume, NULL);
|
||||
|
||||
static const struct of_device_id imx91_tmu_table[] = {
|
||||
{ .compatible = "fsl,imx91-tmu", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, imx91_tmu_table);
|
||||
|
||||
static struct platform_driver imx91_tmu = {
|
||||
.driver = {
|
||||
.name = "imx91_thermal",
|
||||
.pm = pm_ptr(&imx91_tmu_pm_ops),
|
||||
.of_match_table = imx91_tmu_table,
|
||||
},
|
||||
.probe = imx91_tmu_probe,
|
||||
};
|
||||
module_platform_driver(imx91_tmu);
|
||||
|
||||
MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
|
||||
MODULE_DESCRIPTION("i.MX91 Thermal Monitor Unit driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* R-Car Gen3 THS thermal sensor driver
|
||||
* R-Car Gen3, Gen4 and RZ/G2 THS thermal sensor driver
|
||||
* Based on rcar_thermal.c and work from Hien Dang and Khiem Nguyen.
|
||||
*
|
||||
* Copyright (C) 2016 Renesas Electronics Corporation.
|
||||
|
|
@ -601,7 +601,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev)
|
||||
static int rcar_gen3_thermal_resume(struct device *dev)
|
||||
{
|
||||
struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev);
|
||||
unsigned int i;
|
||||
|
|
@ -615,13 +615,13 @@ static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, NULL,
|
||||
rcar_gen3_thermal_resume);
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, NULL,
|
||||
rcar_gen3_thermal_resume);
|
||||
|
||||
static struct platform_driver rcar_gen3_thermal_driver = {
|
||||
.driver = {
|
||||
.name = "rcar_gen3_thermal",
|
||||
.pm = &rcar_gen3_thermal_pm_ops,
|
||||
.pm = pm_sleep_ptr(&rcar_gen3_thermal_pm_ops),
|
||||
.of_match_table = rcar_gen3_thermal_dt_ids,
|
||||
},
|
||||
.probe = rcar_gen3_thermal_probe,
|
||||
|
|
|
|||
|
|
@ -534,7 +534,6 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int rcar_thermal_suspend(struct device *dev)
|
||||
{
|
||||
struct rcar_thermal_common *common = dev_get_drvdata(dev);
|
||||
|
|
@ -567,15 +566,14 @@ static int rcar_thermal_resume(struct device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend,
|
||||
rcar_thermal_resume);
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend,
|
||||
rcar_thermal_resume);
|
||||
|
||||
static struct platform_driver rcar_thermal_driver = {
|
||||
.driver = {
|
||||
.name = "rcar_thermal",
|
||||
.pm = &rcar_thermal_pm_ops,
|
||||
.pm = pm_sleep_ptr(&rcar_thermal_pm_ops),
|
||||
.of_match_table = rcar_thermal_dt_ids,
|
||||
},
|
||||
.probe = rcar_thermal_probe,
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
if (options.daemonize && daemon(0, 0)) {
|
||||
ERROR("Failed to daemonize: %p\n");
|
||||
ERROR("Failed to daemonize: %m\n");
|
||||
return THERMAL_ENGINE_DAEMON_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue