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: Anson Huang <Anson.Huang@nxp.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/1582947862-11073-2-git-send-email-Anson.Huang@nxp.com
This commit is contained in:
Anson Huang 2020-02-29 11:44:20 +08:00 committed by Daniel Lezcano
parent 444eb18d09
commit 5eed800a68
3 changed files with 142 additions and 0 deletions

View File

@ -262,6 +262,16 @@ config IMX_SC_THERMAL
sensor. It supports one critical trip point and one
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
tristate "Temperature sensor driver for Maxim MAX77620 PMIC"
depends on MFD_MAX77620

View File

@ -44,6 +44,7 @@ obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
obj-$(CONFIG_TANGO_THERMAL) += tango_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_MAX77620_THERMAL) += max77620_thermal.o
obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o

View File

@ -0,0 +1,131 @@
// 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");