@@ -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, },
{ }
};
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(-)