Commit 28d626d48e8b063c692418b354367e538ce82c83
1 parent
277eaf57e5
Exists in
smarc_8mq_lf_v2020.04
and in
4 other branches
MLK-23165-22 nxp_tmu: Update TMU thermal driver to support imx8mp
Update TMU driver for imx8mp thermal which has two probes and supports temperature range from -40 to 125. The driver still uses default 1p HW calibration at 25C and loads calibration parameters from fuse. Reviewed-by: Peng Fan <peng.fan@nxp.com> Signed-off-by: Ye Li <ye.li@nxp.com> (cherry picked from commit 2deda4eb4f5bc0b749e5cef1395a0b436448d4fa)
Showing 2 changed files with 112 additions and 5 deletions Side-by-side Diff
arch/arm/mach-imx/imx8m/soc.c
... | ... | @@ -943,6 +943,53 @@ |
943 | 943 | writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28); |
944 | 944 | writel((tca_en << 31) |(tca_hr <<16) | tca_rt, (ulong)reg_base + 0x30); |
945 | 945 | } |
946 | +#ifdef CONFIG_IMX8MP | |
947 | + /* Load TCALIV0/1/m40 and TRIM from fuses */ | |
948 | + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; | |
949 | + struct fuse_bank *bank = &ocotp->bank[38]; | |
950 | + struct fuse_bank38_regs *fuse = | |
951 | + (struct fuse_bank38_regs *)bank->fuse_regs; | |
952 | + | |
953 | + struct fuse_bank *bank2 = &ocotp->bank[39]; | |
954 | + struct fuse_bank39_regs *fuse2 = | |
955 | + (struct fuse_bank39_regs *)bank2->fuse_regs; | |
956 | + | |
957 | + u32 buf_vref, buf_slope, bjt_cur, vlsb, bgr; | |
958 | + u32 reg; | |
959 | + u32 tca40[2], tca25[2], tca105[2]; | |
960 | + | |
961 | + /* For blank sample */ | |
962 | + if (!fuse->ana_trim2 && !fuse->ana_trim3 && | |
963 | + !fuse->ana_trim4 && !fuse2->ana_trim5) { | |
964 | + /* Use a default 25C binary codes */ | |
965 | + tca25[0] = 1596; | |
966 | + writel(tca25[0], (ulong)reg_base + 0x30); | |
967 | + return; | |
968 | + } | |
969 | + | |
970 | + buf_vref = (fuse->ana_trim2 & 0xc0) >> 6; | |
971 | + buf_slope = (fuse->ana_trim2 & 0xF00) >> 8; | |
972 | + bjt_cur = (fuse->ana_trim2 & 0xF000) >> 12; | |
973 | + bgr = (fuse->ana_trim2 & 0xF0000) >> 16; | |
974 | + vlsb = (fuse->ana_trim2 & 0xF00000) >> 20; | |
975 | + writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28); | |
976 | + | |
977 | + reg = (bgr << 28) | (bjt_cur << 20) | (vlsb << 12) | ( 1 << 7); | |
978 | + writel(reg, (ulong)reg_base + 0x3c); | |
979 | + | |
980 | + tca40[0] = (fuse->ana_trim3 & 0xFFF0000) >> 16; | |
981 | + tca25[0] = (fuse->ana_trim3 & 0xF0000000) >> 28; | |
982 | + tca25[0] |= ((fuse->ana_trim4 & 0xFF) << 4); | |
983 | + tca105[0] = (fuse->ana_trim4 & 0xFFF00) >> 8; | |
984 | + tca40[1] = (fuse->ana_trim4 & 0xFFF00000) >> 20; | |
985 | + tca25[1] = fuse2->ana_trim5 & 0xFFF; | |
986 | + tca105[1] = (fuse2->ana_trim5 & 0xFFF000) >> 12; | |
987 | + | |
988 | + /* use 25c for 1p calibration */ | |
989 | + writel(tca25[0] | (tca105[0] << 16), (ulong)reg_base + 0x30); | |
990 | + writel(tca25[1] | (tca105[1] << 16), (ulong)reg_base + 0x34); | |
991 | + writel(tca40[0] | (tca40[1] << 16), (ulong)reg_base + 0x38); | |
992 | +#endif | |
946 | 993 | } |
947 | 994 | |
948 | 995 | #if defined(CONFIG_SPL_BUILD) |
drivers/thermal/nxp_tmu.c
... | ... | @@ -21,6 +21,7 @@ |
21 | 21 | |
22 | 22 | #define SITES_MAX 16 |
23 | 23 | #define FLAGS_VER2 0x1 |
24 | +#define FLAGS_VER3 0x2 | |
24 | 25 | |
25 | 26 | #define TMR_DISABLE 0x0 |
26 | 27 | #define TMR_ME 0x80000000 |
... | ... | @@ -29,6 +30,7 @@ |
29 | 30 | #define TIER_DISABLE 0x0 |
30 | 31 | |
31 | 32 | #define TER_EN 0x80000000 |
33 | +#define TER_ADC_PD 0x40000000 | |
32 | 34 | #define TER_ALPF 0x3 |
33 | 35 | |
34 | 36 | /* |
35 | 37 | |
... | ... | @@ -87,9 +89,29 @@ |
87 | 89 | u32 tcaliv; |
88 | 90 | }; |
89 | 91 | |
92 | +struct nxp_tmu_regs_v3 { | |
93 | + u32 ter; /* TMU enable Register */ | |
94 | + u32 tps; /* Status Register */ | |
95 | + u32 tier; /* Interrupt enable register */ | |
96 | + u32 tidr; /* Interrupt detect register */ | |
97 | + u32 tmhtitr; /* Monitor high temperature immediate threshold register */ | |
98 | + u32 tmhtatr; /* Monitor high temperature average threshold register */ | |
99 | + u32 tmhtactr; /* TMU monitor high temperature average critical threshold register */ | |
100 | + u32 tscr; /* Sensor value capture register */ | |
101 | + u32 tritsr; /* Report immediate temperature site register 0 */ | |
102 | + u32 tratsr; /* Report average temperature site register 0 */ | |
103 | + u32 tasr; /* Amplifier setting register */ | |
104 | + u32 ttmc; /* Test MUX control */ | |
105 | + u32 tcaliv0; | |
106 | + u32 tcaliv1; | |
107 | + u32 tcaliv_m40; | |
108 | + u32 trim; | |
109 | +}; | |
110 | + | |
90 | 111 | union tmu_regs { |
91 | 112 | struct nxp_tmu_regs regs_v1; |
92 | 113 | struct nxp_tmu_regs_v2 regs_v2; |
114 | + struct nxp_tmu_regs_v3 regs_v3; | |
93 | 115 | }; |
94 | 116 | |
95 | 117 | struct nxp_tmu_plat { |
... | ... | @@ -113,7 +135,10 @@ |
113 | 135 | mdelay(100); |
114 | 136 | retry--; |
115 | 137 | |
116 | - if (drv_data & FLAGS_VER2) { | |
138 | + if (drv_data & FLAGS_VER3) { | |
139 | + val = readl(&pdata->regs->regs_v3.tritsr); | |
140 | + valid = val & (1 << (30 + pdata->id)); | |
141 | + } else if (drv_data & FLAGS_VER2) { | |
117 | 142 | val = readl(&pdata->regs->regs_v2.tritsr); |
118 | 143 | |
119 | 144 | /* Check if TEMP is in valid range, the V bit in TRITSR |
... | ... | @@ -127,7 +152,19 @@ |
127 | 152 | } while (!valid && retry > 0); |
128 | 153 | |
129 | 154 | if (retry > 0) { |
130 | - *temp = (val & 0xff) * 1000; | |
155 | + if (drv_data & FLAGS_VER3) { | |
156 | + val = (val >> (pdata->id * 16)) & 0xff; | |
157 | + if (val & 0x80) /* Negative */ | |
158 | + val = (~(val & 0x7f) + 1); | |
159 | + | |
160 | + *temp = val; | |
161 | + if (*temp < -40 || *temp > 125) /* Check the range */ | |
162 | + return -EINVAL; | |
163 | + | |
164 | + *temp *= 1000; | |
165 | + } else { | |
166 | + *temp = (val & 0xff) * 1000; | |
167 | + } | |
131 | 168 | return 0; |
132 | 169 | } else { |
133 | 170 | return -EINVAL; |
... | ... | @@ -177,7 +214,7 @@ |
177 | 214 | |
178 | 215 | debug("%s\n", __func__); |
179 | 216 | |
180 | - if (drv_data & FLAGS_VER2) | |
217 | + if (drv_data & (FLAGS_VER2 | FLAGS_VER3)) | |
181 | 218 | return 0; |
182 | 219 | |
183 | 220 | ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), |
184 | 221 | |
... | ... | @@ -222,8 +259,15 @@ |
222 | 259 | |
223 | 260 | debug("%s\n", __func__); |
224 | 261 | |
225 | - if (drv_data & FLAGS_VER2) { | |
262 | + if (drv_data & FLAGS_VER3) { | |
226 | 263 | /* Disable monitoring */ |
264 | + writel(0x0, &pdata->regs->regs_v3.ter); | |
265 | + | |
266 | + /* Disable interrupt, using polling instead */ | |
267 | + writel(0x0, &pdata->regs->regs_v3.tier); | |
268 | + | |
269 | + } else if (drv_data & FLAGS_VER2) { | |
270 | + /* Disable monitoring */ | |
227 | 271 | writel(0x0, &pdata->regs->regs_v2.ter); |
228 | 272 | |
229 | 273 | /* Disable interrupt, using polling instead */ |
... | ... | @@ -253,7 +297,22 @@ |
253 | 297 | if (!pdata->regs) |
254 | 298 | return -EIO; |
255 | 299 | |
256 | - if (drv_data & FLAGS_VER2) { | |
300 | + if (drv_data & FLAGS_VER3) { | |
301 | + reg = readl(&pdata->regs->regs_v3.ter); | |
302 | + reg &= ~TER_EN; | |
303 | + writel(reg, &pdata->regs->regs_v3.ter); | |
304 | + | |
305 | + writel(pdata->id << 30, &pdata->regs->regs_v3.tps); | |
306 | + | |
307 | + reg &= ~TER_ALPF; | |
308 | + reg |= 0x1; | |
309 | + reg &= ~TER_ADC_PD; | |
310 | + writel(reg, &pdata->regs->regs_v3.ter); | |
311 | + | |
312 | + /* Enable monitor */ | |
313 | + reg |= TER_EN; | |
314 | + writel(reg, &pdata->regs->regs_v3.ter); | |
315 | + } else if (drv_data & FLAGS_VER2) { | |
257 | 316 | reg = readl(&pdata->regs->regs_v2.ter); |
258 | 317 | reg &= ~TER_EN; |
259 | 318 | writel(reg, &pdata->regs->regs_v2.ter); |
... | ... | @@ -396,6 +455,7 @@ |
396 | 455 | static const struct udevice_id nxp_tmu_ids[] = { |
397 | 456 | { .compatible = "fsl,imx8mq-tmu", }, |
398 | 457 | { .compatible = "fsl,imx8mm-tmu", .data=FLAGS_VER2, }, |
458 | + { .compatible = "fsl,imx8mp-tmu", .data=FLAGS_VER3, }, | |
399 | 459 | { } |
400 | 460 | }; |
401 | 461 |