thermal: imx_tmu: Add support for thermal sensor on iMX8MM
authorPeng Fan <peng.fan@nxp.com>
Sun, 3 May 2020 14:19:47 +0000 (22:19 +0800)
committerStefano Babic <sbabic@denx.de>
Sun, 10 May 2020 18:55:20 +0000 (20:55 +0200)
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>
drivers/thermal/imx_tmu.c

index f496ce03b6579f7af80e614e400dba7ea9478d78..df0b35b7ba3e0f3279834ed3acdb48d766c7fefc 100644 (file)
@@ -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, },
        { }
 };