thermal: imx_tmu: Add support for thermal sensor on iMX8MM

The analog sensors on iMX8MM are new, used for 14LPP process. So the
Temperature Sensor Monitoring Unit (TMU) has some change accordingly.
We use version 2 in TMU driver to represent the new TMU, so the one
driver can service for both i.MX8MQ/M.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c
index f496ce0..df0b35b 100644
--- a/drivers/thermal/imx_tmu.c
+++ b/drivers/thermal/imx_tmu.c
@@ -20,6 +20,7 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 #define SITES_MAX	16
+#define FLAGS_VER2 	0x1
 
 #define TMR_DISABLE	0x0
 #define TMR_ME		0x80000000
@@ -27,6 +28,8 @@
 #define TMTMIR_DEFAULT	0x00000002
 #define TIER_DISABLE	0x0
 
+#define TER_EN			0x80000000
+#define TER_ADC_PD		0x40000000
 /*
  * i.MX TMU Registers
  */
@@ -67,22 +70,47 @@
 	u32 ttr3cr;	/* Temperature Range 3 Control Register */
 };
 
+struct imx_tmu_regs_v2 {
+	u32 ter;	/* TMU enable Register */
+	u32 tsr;	/* 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 tcaliv;
+};
+
+union tmu_regs {
+	struct imx_tmu_regs regs_v1;
+	struct imx_tmu_regs_v2 regs_v2;
+};
+
 struct imx_tmu_plat {
 	int critical;
 	int alert;
 	int polling_delay;
 	int id;
 	bool zone_node;
-	struct imx_tmu_regs *regs;
+	union tmu_regs *regs;
 };
 
 static int read_temperature(struct udevice *dev, int *temp)
 {
 	struct imx_tmu_plat *pdata = dev_get_platdata(dev);
+	ulong drv_data = dev_get_driver_data(dev);
 	u32 val;
 
 	do {
-		val = readl(&pdata->regs->site[pdata->id].tritsr);
+		if (drv_data & FLAGS_VER2) {
+			val = readl(&pdata->regs->regs_v2.tritsr);
+		else
+			val = readl(&pdata->regs->regs_v1.site[pdata->id].tritsr);
 	} while (!(val & 0x80000000));
 
 	*temp = (val & 0xff) * 1000;
@@ -124,9 +152,13 @@
 	u32 range[4];
 	const fdt32_t *calibration;
 	struct imx_tmu_plat *pdata = dev_get_platdata(dev);
+	ulong drv_data = dev_get_driver_data(dev);
 
 	debug("%s\n", __func__);
 
+	if (drv_data & FLAGS_VER2)
+		return 0;
+
 	ret = dev_read_u32_array(dev, "fsl,tmu-range", range, 4);
 	if (ret) {
 		printf("TMU: missing calibration range, ret = %d.\n", ret);
@@ -134,10 +166,10 @@
 	}
 
 	/* Init temperature range registers */
-	writel(range[0], &pdata->regs->ttr0cr);
-	writel(range[1], &pdata->regs->ttr1cr);
-	writel(range[2], &pdata->regs->ttr2cr);
-	writel(range[3], &pdata->regs->ttr3cr);
+	writel(range[0], &pdata->regs->regs_v1.ttr0cr);
+	writel(range[1], &pdata->regs->regs_v1.ttr1cr);
+	writel(range[2], &pdata->regs->regs_v1.ttr2cr);
+	writel(range[3], &pdata->regs->regs_v1.ttr3cr);
 
 	calibration = dev_read_prop(dev, "fsl,tmu-calibration", &len);
 	if (!calibration || len % 8) {
@@ -147,31 +179,43 @@
 
 	for (i = 0; i < len; i += 8, calibration += 2) {
 		val = fdt32_to_cpu(*calibration);
-		writel(val, &pdata->regs->ttcfgr);
+		writel(val, &pdata->regs->regs_v1.ttcfgr);
 		val = fdt32_to_cpu(*(calibration + 1));
-		writel(val, &pdata->regs->tscfgr);
+		writel(val, &pdata->regs->regs_v1.tscfgr);
 	}
 
 	return 0;
 }
 
-static void imx_tmu_init(struct imx_tmu_plat *pdata)
+static void imx_tmu_init(struct udevice *dev)
 {
+	struct imx_tmu_plat *pdata = dev_get_platdata(dev);
+	ulong drv_data = dev_get_driver_data(dev);
+
 	debug("%s\n", __func__);
 
+	if (drv_data & FLAGS_VER2) {
+		/* Disable monitoring */
+		writel(0x0, &pdata->regs->regs_v2.ter);
+
-	/* Disable monitoring */
-	writel(TMR_DISABLE, &pdata->regs->tmr);
+		/* Disable interrupt, using polling instead */
+		writel(0x0, &pdata->regs->regs_v2.tier);
+	} else {
+		/* Disable monitoring */
+		writel(TMR_DISABLE, &pdata->regs->regs_v1.tmr);
 
-	/* Disable interrupt, using polling instead */
-	writel(TIER_DISABLE, &pdata->regs->tier);
+		/* Disable interrupt, using polling instead */
+		writel(TIER_DISABLE, &pdata->regs->regs_v1.tier);
 
-	/* Set update_interval */
-	writel(TMTMIR_DEFAULT, &pdata->regs->tmtmir);
+		/* Set update_interval */
+		writel(TMTMIR_DEFAULT, &pdata->regs->regs_v1.tmtmir);
+	}
 }
 
 static int imx_tmu_enable_msite(struct udevice *dev)
 {
 	struct imx_tmu_plat *pdata = dev_get_platdata(dev);
+	ulong drv_data = dev_get_driver_data(dev);
 	u32 reg;
 
 	debug("%s\n", __func__);
@@ -179,18 +223,32 @@
 	if (!pdata->regs)
 		return -EIO;
 
-	/* Clear the ME before setting MSITE and ALPF*/
-	reg = readl(&pdata->regs->tmr);
-	reg &= ~TMR_ME;
-	writel(reg, &pdata->regs->tmr);
+	if (drv_data & FLAGS_VER2) {
+		reg = readl(&pdata->regs->regs_v2.ter);
+		reg &= ~TER_EN;
+		writel(reg, &pdata->regs->regs_v2.ter);
 
-	reg |= 1 << (15 - pdata->id);
-	reg |= TMR_ALPF;
-	writel(reg, &pdata->regs->tmr);
+		reg &= ~TER_ALPF;
+		reg |= 0x1;
+		writel(reg, &pdata->regs->regs_v2.ter);
 
-	/* Enable ME */
-	reg |= TMR_ME;
-	writel(reg, &pdata->regs->tmr);
+		/* Enable monitor */
+		reg |= TER_EN;
+		writel(reg, &pdata->regs->regs_v2.ter);
+	} else {
+		/* Clear the ME before setting MSITE and ALPF*/
+		reg = readl(&pdata->regs->regs_v1.tmr);
+		reg &= ~TMR_ME;
+		writel(reg, &pdata->regs->regs_v1.tmr);
+
+		reg |= 1 << (15 - pdata->id);
+		reg |= TMR_ALPF;
+		writel(reg, &pdata->regs->regs_v1.tmr);
+
+		/* Enable ME */
+		reg |= TMR_ME;
+		writel(reg, &pdata->regs->regs_v1.tmr);
+	}
 
 	return 0;
 }
@@ -237,7 +295,7 @@
 	debug("%s dev name %s\n", __func__, dev->name);
 
 	if (pdata->zone_node) {
-		pdata->regs = (struct imx_tmu_regs *)dev_read_addr_ptr(dev);
+		pdata->regs = (union tmu_regs *)dev_read_addr_ptr(dev);
 
 		if (!pdata->regs)
 			return -EINVAL;
@@ -299,7 +357,7 @@
 	}
 
 	if (pdata->zone_node) {
-		imx_tmu_init(pdata);
+		imx_tmu_init(dev);
 		imx_tmu_calibration(dev);
 	} else {
 		imx_tmu_enable_msite(dev);
@@ -310,6 +368,7 @@
 
 static const struct udevice_id imx_tmu_ids[] = {
 	{ .compatible = "fsl,imx8mq-tmu", },
+	{ .compatible = "fsl,imx8mm-tmu", .data = FLAGS_VER2, },
 	{ }
 };