Commit 5eed800a authored by Anson Huang's avatar Anson Huang Committed by Daniel Lezcano

thermal: imx8mm: Add support for i.MX8MM thermal monitoring unit

i.MX8MM has a thermal monitoring unit(TMU) inside, it ONLY has one
sensor for CPU, add support for reading immediate temperature of
this sensor.
Signed-off-by: default avatarAnson Huang <Anson.Huang@nxp.com>
Signed-off-by: default avatarDaniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/1582947862-11073-2-git-send-email-Anson.Huang@nxp.com
parent 444eb18d
...@@ -262,6 +262,16 @@ config IMX_SC_THERMAL ...@@ -262,6 +262,16 @@ config IMX_SC_THERMAL
sensor. It supports one critical trip point and one sensor. It supports one critical trip point and one
passive trip point for each thermal sensor. passive trip point for each thermal sensor.
config IMX8MM_THERMAL
tristate "Temperature sensor driver for Freescale i.MX8MM SoC"
depends on ARCH_MXC
depends on OF
help
Support for Thermal Monitoring Unit (TMU) found on Freescale i.MX8MM SoC.
It supports one critical trip point and one passive trip point. The
cpufreq is used as the cooling device to throttle CPUs when the passive
trip is crossed.
config MAX77620_THERMAL config MAX77620_THERMAL
tristate "Temperature sensor driver for Maxim MAX77620 PMIC" tristate "Temperature sensor driver for Maxim MAX77620 PMIC"
depends on MFD_MAX77620 depends on MFD_MAX77620
......
...@@ -44,6 +44,7 @@ obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o ...@@ -44,6 +44,7 @@ obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o
obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
obj-$(CONFIG_IMX_SC_THERMAL) += imx_sc_thermal.o obj-$(CONFIG_IMX_SC_THERMAL) += imx_sc_thermal.o
obj-$(CONFIG_IMX8MM_THERMAL) += imx8mm_thermal.o
obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o
obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2020 NXP.
*
* Author: Anson Huang <Anson.Huang@nxp.com>
*/
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/thermal.h>
#include "thermal_core.h"
#define TER 0x0 /* TMU enable */
#define TRITSR 0x20 /* TMU immediate temp */
#define TER_EN BIT(31)
#define TRITSR_VAL_MASK 0xff
#define TEMP_LOW_LIMIT 10
struct imx8mm_tmu {
struct thermal_zone_device *tzd;
void __iomem *base;
struct clk *clk;
};
static int tmu_get_temp(void *data, int *temp)
{
struct imx8mm_tmu *tmu = data;
u32 val;
val = readl_relaxed(tmu->base + TRITSR) & TRITSR_VAL_MASK;
if (val < TEMP_LOW_LIMIT)
return -EAGAIN;
*temp = val * 1000;
return 0;
}
static struct thermal_zone_of_device_ops tmu_tz_ops = {
.get_temp = tmu_get_temp,
};
static int imx8mm_tmu_probe(struct platform_device *pdev)
{
struct imx8mm_tmu *tmu;
u32 val;
int ret;
tmu = devm_kzalloc(&pdev->dev, sizeof(struct imx8mm_tmu), GFP_KERNEL);
if (!tmu)
return -ENOMEM;
tmu->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(tmu->base))
return PTR_ERR(tmu->base);
tmu->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(tmu->clk)) {
ret = PTR_ERR(tmu->clk);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"failed to get tmu clock: %d\n", ret);
return ret;
}
ret = clk_prepare_enable(tmu->clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable tmu clock: %d\n", ret);
return ret;
}
tmu->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
tmu, &tmu_tz_ops);
if (IS_ERR(tmu->tzd)) {
dev_err(&pdev->dev,
"failed to register thermal zone sensor: %d\n", ret);
return PTR_ERR(tmu->tzd);
}
platform_set_drvdata(pdev, tmu);
/* enable the monitor */
val = readl_relaxed(tmu->base + TER);
val |= TER_EN;
writel_relaxed(val, tmu->base + TER);
return 0;
}
static int imx8mm_tmu_remove(struct platform_device *pdev)
{
struct imx8mm_tmu *tmu = platform_get_drvdata(pdev);
u32 val;
/* disable TMU */
val = readl_relaxed(tmu->base + TER);
val &= ~TER_EN;
writel_relaxed(val, tmu->base + TER);
clk_disable_unprepare(tmu->clk);
platform_set_drvdata(pdev, NULL);
return 0;
}
static const struct of_device_id imx8mm_tmu_table[] = {
{ .compatible = "fsl,imx8mm-tmu", },
{ },
};
static struct platform_driver imx8mm_tmu = {
.driver = {
.name = "i.mx8mm_thermal",
.of_match_table = imx8mm_tmu_table,
},
.probe = imx8mm_tmu_probe,
.remove = imx8mm_tmu_remove,
};
module_platform_driver(imx8mm_tmu);
MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
MODULE_DESCRIPTION("i.MX8MM Thermal Monitor Unit driver");
MODULE_LICENSE("GPL v2");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment