[PATCH 03/13] thermal: imx_tmu: Add support for thermal sensor on iMX8MM

Peng Fan peng.fan at nxp.com
Sun May 3 16:19:47 CEST 2020


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 at nxp.com>
---
 drivers/thermal/imx_tmu.c | 113 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 86 insertions(+), 27 deletions(-)

diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c
index f496ce03b6..df0b35b7ba 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 @@ DECLARE_GLOBAL_DATA_PTR;
 #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 @@ struct imx_tmu_regs {
 	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 @@ static int imx_tmu_calibration(struct udevice *dev)
 	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 @@ static int imx_tmu_calibration(struct udevice *dev)
 	}
 
 	/* 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 @@ static int imx_tmu_calibration(struct udevice *dev)
 
 	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__);
 
-	/* Disable monitoring */
-	writel(TMR_DISABLE, &pdata->regs->tmr);
+	if (drv_data & FLAGS_VER2) {
+		/* Disable monitoring */
+		writel(0x0, &pdata->regs->regs_v2.ter);
+
+		/* 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 @@ static int imx_tmu_enable_msite(struct udevice *dev)
 	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 @@ static int imx_tmu_parse_fdt(struct udevice *dev)
 	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 @@ static int imx_tmu_probe(struct udevice *dev)
 	}
 
 	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 int imx_tmu_probe(struct udevice *dev)
 
 static const struct udevice_id imx_tmu_ids[] = {
 	{ .compatible = "fsl,imx8mq-tmu", },
+	{ .compatible = "fsl,imx8mm-tmu", .data = FLAGS_VER2, },
 	{ }
 };
 
-- 
2.16.4



More information about the U-Boot mailing list