thermal: imx_tmu: support i.MX8MP
Support i.MX8MP thermal which has two probes and supports
temperature range from -40 to 125. Still uses default 1p HW
calibration at 25C and loads calibration parameters from fuse.
Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c
index c577b0b..4ca2208 100644
--- a/drivers/thermal/imx_tmu.c
+++ b/drivers/thermal/imx_tmu.c
@@ -21,6 +21,7 @@
#define SITES_MAX 16
#define FLAGS_VER2 0x1
+#define FLAGS_VER3 0x2
#define TMR_DISABLE 0x0
#define TMR_ME 0x80000000
@@ -30,6 +31,8 @@
#define TER_EN 0x80000000
#define TER_ADC_PD 0x40000000
+#define TER_ALPF 0x3
+
/*
* i.MX TMU Registers
*/
@@ -86,9 +89,29 @@
u32 tcaliv;
};
+struct imx_tmu_regs_v3 {
+ u32 ter; /* TMU enable Register */
+ u32 tps; /* Status Register */
+ u32 tier; /* Interrupt enable register */
+ u32 tidr; /* Interrupt detect register */
+ u32 tmhtitr; /* Monitor high temperature immediate threshold register */
+ u32 tmhtatr; /* Monitor high temperature average threshold register */
+ u32 tmhtactr; /* TMU monitor high temperature average critical threshold register */
+ u32 tscr; /* Sensor value capture register */
+ u32 tritsr; /* Report immediate temperature site register 0 */
+ u32 tratsr; /* Report average temperature site register 0 */
+ u32 tasr; /* Amplifier setting register */
+ u32 ttmc; /* Test MUX control */
+ u32 tcaliv0;
+ u32 tcaliv1;
+ u32 tcaliv_m40;
+ u32 trim;
+};
+
union tmu_regs {
struct imx_tmu_regs regs_v1;
struct imx_tmu_regs_v2 regs_v2;
+ struct imx_tmu_regs_v3 regs_v3;
};
struct imx_tmu_plat {
@@ -112,7 +135,10 @@
mdelay(100);
retry--;
- if (drv_data & FLAGS_VER2) {
+ if (drv_data & FLAGS_VER3) {
+ val = readl(&pdata->regs->regs_v3.tritsr);
+ valid = val & (1 << (30 + pdata->id));
+ } else if (drv_data & FLAGS_VER2) {
val = readl(&pdata->regs->regs_v2.tritsr);
/*
* Check if TEMP is in valid range, the V bit in TRITSR
@@ -125,10 +151,23 @@
}
} while (!valid && retry > 0);
- if (retry > 0)
- *temp = (val & 0xff) * 1000;
- else
+ if (retry > 0) {
+ if (drv_data & FLAGS_VER3) {
+ val = (val >> (pdata->id * 16)) & 0xff;
+ if (val & 0x80) /* Negative */
+ val = (~(val & 0x7f) + 1);
+
+ *temp = val;
+ if (*temp < -40 || *temp > 125) /* Check the range */
+ return -EINVAL;
+
+ *temp *= 1000;
+ } else {
+ *temp = (val & 0xff) * 1000;
+ }
+ } else {
return -EINVAL;
+ }
return 0;
}
@@ -171,7 +210,7 @@
debug("%s\n", __func__);
- if (drv_data & FLAGS_VER2)
+ if (drv_data & (FLAGS_VER2 | FLAGS_VER3))
return 0;
ret = dev_read_u32_array(dev, "fsl,tmu-range", range, 4);
@@ -213,7 +252,14 @@
debug("%s\n", __func__);
- if (drv_data & FLAGS_VER2) {
+ if (drv_data & FLAGS_VER3) {
+ /* Disable monitoring */
+ writel(0x0, &pdata->regs->regs_v3.ter);
+
+ /* Disable interrupt, using polling instead */
+ writel(0x0, &pdata->regs->regs_v3.tier);
+
+ } else if (drv_data & FLAGS_VER2) {
/* Disable monitoring */
writel(0x0, &pdata->regs->regs_v2.ter);
@@ -244,7 +290,22 @@
if (!pdata->regs)
return -EIO;
- if (drv_data & FLAGS_VER2) {
+ if (drv_data & FLAGS_VER3) {
+ reg = readl(&pdata->regs->regs_v3.ter);
+ reg &= ~TER_EN;
+ writel(reg, &pdata->regs->regs_v3.ter);
+
+ writel(pdata->id << 30, &pdata->regs->regs_v3.tps);
+
+ reg &= ~TER_ALPF;
+ reg |= 0x1;
+ reg &= ~TER_ADC_PD;
+ writel(reg, &pdata->regs->regs_v3.ter);
+
+ /* Enable monitor */
+ reg |= TER_EN;
+ writel(reg, &pdata->regs->regs_v3.ter);
+ } else if (drv_data & FLAGS_VER2) {
reg = readl(&pdata->regs->regs_v2.ter);
reg &= ~TER_EN;
writel(reg, &pdata->regs->regs_v2.ter);
@@ -390,6 +451,7 @@
static const struct udevice_id imx_tmu_ids[] = {
{ .compatible = "fsl,imx8mq-tmu", },
{ .compatible = "fsl,imx8mm-tmu", .data = FLAGS_VER2, },
+ { .compatible = "fsl,imx8mp-tmu", .data = FLAGS_VER3, },
{ }
};