From patchwork Sun May 3 14:19:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peng Fan X-Patchwork-Id: 244903 List-Id: U-Boot discussion From: peng.fan at nxp.com (Peng Fan) Date: Sun, 3 May 2020 22:19:47 +0800 Subject: [PATCH 03/13] thermal: imx_tmu: Add support for thermal sensor on iMX8MM In-Reply-To: <20200503141957.14635-1-peng.fan@nxp.com> References: <20200503141957.14635-1-peng.fan@nxp.com> Message-ID: <20200503141957.14635-4-peng.fan@nxp.com> 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 --- 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, }, { } };