diff options
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/imx_tmu.c | 95 |
1 files changed, 93 insertions, 2 deletions
diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c index 8d638797eb..eb5605590f 100644 --- a/drivers/thermal/imx_tmu.c +++ b/drivers/thermal/imx_tmu.c @@ -244,8 +244,99 @@ static int imx_tmu_calibration(struct udevice *dev) return 0; } -void __weak imx_tmu_arch_init(void *reg_base) +#if defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN) +static void imx_tmu_mx8mm_mx8mn_init(struct udevice *dev) { + /* Load TCALIV and TASR from fuses */ + struct ocotp_regs *ocotp = + (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[3]; + struct fuse_bank3_regs *fuse = + (struct fuse_bank3_regs *)bank->fuse_regs; + struct imx_tmu_plat *pdata = dev_get_plat(dev); + void *reg_base = (void *)pdata->regs; + + u32 tca_rt, tca_hr, tca_en; + u32 buf_vref, buf_slope; + + tca_rt = fuse->ana0 & 0xFF; + tca_hr = (fuse->ana0 & 0xFF00) >> 8; + tca_en = (fuse->ana0 & 0x2000000) >> 25; + + buf_vref = (fuse->ana0 & 0x1F00000) >> 20; + buf_slope = (fuse->ana0 & 0xF0000) >> 16; + + writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28); + writel((tca_en << 31) | (tca_hr << 16) | tca_rt, + (ulong)reg_base + 0x30); +} +#else +static inline void imx_tmu_mx8mm_mx8mn_init(struct udevice *dev) { } +#endif + +#if defined(CONFIG_IMX8MP) +static void imx_tmu_mx8mp_init(struct udevice *dev) +{ + /* Load TCALIV0/1/m40 and TRIM from fuses */ + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[38]; + struct fuse_bank38_regs *fuse = + (struct fuse_bank38_regs *)bank->fuse_regs; + struct fuse_bank *bank2 = &ocotp->bank[39]; + struct fuse_bank39_regs *fuse2 = + (struct fuse_bank39_regs *)bank2->fuse_regs; + struct imx_tmu_plat *pdata = dev_get_plat(dev); + void *reg_base = (void *)pdata->regs; + u32 buf_vref, buf_slope, bjt_cur, vlsb, bgr; + u32 reg; + u32 tca40[2], tca25[2], tca105[2]; + + /* For blank sample */ + if (!fuse->ana_trim2 && !fuse->ana_trim3 && + !fuse->ana_trim4 && !fuse2->ana_trim5) { + /* Use a default 25C binary codes */ + tca25[0] = 1596; + tca25[1] = 1596; + writel(tca25[0], (ulong)reg_base + 0x30); + writel(tca25[1], (ulong)reg_base + 0x34); + return; + } + + buf_vref = (fuse->ana_trim2 & 0xc0) >> 6; + buf_slope = (fuse->ana_trim2 & 0xF00) >> 8; + bjt_cur = (fuse->ana_trim2 & 0xF000) >> 12; + bgr = (fuse->ana_trim2 & 0xF0000) >> 16; + vlsb = (fuse->ana_trim2 & 0xF00000) >> 20; + writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28); + + reg = (bgr << 28) | (bjt_cur << 20) | (vlsb << 12) | (1 << 7); + writel(reg, (ulong)reg_base + 0x3c); + + tca40[0] = (fuse->ana_trim3 & 0xFFF0000) >> 16; + tca25[0] = (fuse->ana_trim3 & 0xF0000000) >> 28; + tca25[0] |= ((fuse->ana_trim4 & 0xFF) << 4); + tca105[0] = (fuse->ana_trim4 & 0xFFF00) >> 8; + tca40[1] = (fuse->ana_trim4 & 0xFFF00000) >> 20; + tca25[1] = fuse2->ana_trim5 & 0xFFF; + tca105[1] = (fuse2->ana_trim5 & 0xFFF000) >> 12; + + /* use 25c for 1p calibration */ + writel(tca25[0] | (tca105[0] << 16), (ulong)reg_base + 0x30); + writel(tca25[1] | (tca105[1] << 16), (ulong)reg_base + 0x34); + writel(tca40[0] | (tca40[1] << 16), (ulong)reg_base + 0x38); +} +#else +static inline void imx_tmu_mx8mp_init(struct udevice *dev) { } +#endif + +static void imx_tmu_arch_init(struct udevice *dev) +{ + if (is_imx8mm() || is_imx8mn()) + imx_tmu_mx8mm_mx8mn_init(dev); + else if (is_imx8mp()) + imx_tmu_mx8mp_init(dev); + else + dev_err(dev, "Unsupported SoC, TMU calibration not loaded!\n"); } static void imx_tmu_init(struct udevice *dev) @@ -279,7 +370,7 @@ static void imx_tmu_init(struct udevice *dev) writel(TMTMIR_DEFAULT, &pdata->regs->regs_v1.tmtmir); } - imx_tmu_arch_init((void *)pdata->regs); + imx_tmu_arch_init(dev); } static int imx_tmu_enable_msite(struct udevice *dev) |