blob: 97efc5504439873d03665eb61c6274fd4a348184 [file] [log] [blame]
Peng Fan10de5792020-05-03 22:19:46 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2017~2020 NXP
4 *
5 */
6
7#include <config.h>
8#include <common.h>
Simon Glass3ba929a2020-10-30 21:38:53 -06009#include <asm/global_data.h>
Peng Fan10de5792020-05-03 22:19:46 +080010#include <asm/io.h>
11#include <asm/arch/clock.h>
12#include <asm/arch/sys_proto.h>
13#include <dm.h>
Marek Vasut39779c62023-04-04 21:25:09 +020014#include <dm/device_compat.h>
Peng Fan10de5792020-05-03 22:19:46 +080015#include <dm/device-internal.h>
16#include <dm/device.h>
17#include <errno.h>
18#include <fuse.h>
Tim Harveya77d3092020-10-12 12:21:54 -070019#include <linux/delay.h>
Peng Fan10de5792020-05-03 22:19:46 +080020#include <malloc.h>
21#include <thermal.h>
22
23DECLARE_GLOBAL_DATA_PTR;
24
25#define SITES_MAX 16
Wolfgang Denk62fb2b42021-09-27 17:42:39 +020026#define FLAGS_VER2 0x1
27#define FLAGS_VER3 0x2
Ye Lib7662562023-04-28 12:08:07 +080028#define FLAGS_VER4 0x4
Peng Fan10de5792020-05-03 22:19:46 +080029
30#define TMR_DISABLE 0x0
31#define TMR_ME 0x80000000
32#define TMR_ALPF 0x0c000000
33#define TMTMIR_DEFAULT 0x00000002
34#define TIER_DISABLE 0x0
35
Peng Fanbef7d2a2020-05-03 22:19:47 +080036#define TER_EN 0x80000000
37#define TER_ADC_PD 0x40000000
Peng Fanfed211f2020-05-03 22:19:51 +080038#define TER_ALPF 0x3
39
Peng Fan10de5792020-05-03 22:19:46 +080040/*
41 * i.MX TMU Registers
42 */
43struct imx_tmu_site_regs {
44 u32 tritsr; /* Immediate Temperature Site Register */
45 u32 tratsr; /* Average Temperature Site Register */
46 u8 res0[0x8];
47};
48
49struct imx_tmu_regs {
50 u32 tmr; /* Mode Register */
51 u32 tsr; /* Status Register */
52 u32 tmtmir; /* Temperature measurement interval Register */
53 u8 res0[0x14];
54 u32 tier; /* Interrupt Enable Register */
55 u32 tidr; /* Interrupt Detect Register */
56 u32 tiscr; /* Interrupt Site Capture Register */
57 u32 ticscr; /* Interrupt Critical Site Capture Register */
58 u8 res1[0x10];
59 u32 tmhtcrh; /* High Temperature Capture Register */
60 u32 tmhtcrl; /* Low Temperature Capture Register */
61 u8 res2[0x8];
62 u32 tmhtitr; /* High Temperature Immediate Threshold */
63 u32 tmhtatr; /* High Temperature Average Threshold */
64 u32 tmhtactr; /* High Temperature Average Crit Threshold */
65 u8 res3[0x24];
66 u32 ttcfgr; /* Temperature Configuration Register */
67 u32 tscfgr; /* Sensor Configuration Register */
68 u8 res4[0x78];
69 struct imx_tmu_site_regs site[SITES_MAX];
70 u8 res5[0x9f8];
71 u32 ipbrr0; /* IP Block Revision Register 0 */
72 u32 ipbrr1; /* IP Block Revision Register 1 */
73 u8 res6[0x310];
74 u32 ttr0cr; /* Temperature Range 0 Control Register */
75 u32 ttr1cr; /* Temperature Range 1 Control Register */
76 u32 ttr2cr; /* Temperature Range 2 Control Register */
77 u32 ttr3cr; /* Temperature Range 3 Control Register */
78};
79
Ye Lib7662562023-04-28 12:08:07 +080080struct imx_tmu_regs_v4 {
81 u32 tmr; /* Mode Register */
82 u32 tsr; /* Status Register */
83 u32 tmsr; /* Monitor Site Register */
84 u32 tmtmir; /* Temperature measurement interval Register */
85 u8 res0[0x10];
86 u32 tier; /* Interrupt Enable Register */
87 u32 tidr; /* Interrupt Detect Register */
88 u8 res1[0x8];
89 u32 tiiscr; /* Interrupt Immediate Site Capture Register */
90 u32 tiascr; /* Interrupt Average Site Capture Register */
91 u32 ticscr; /* Interrupt Critical Site Capture Register */
92 u8 res2[0x4];
93 u32 tmhtcr; /* Monitor High Temperature Capture Register */
94 u32 tmltcr; /* MonitorLow Temperature Capture Register */
95 u32 tmrtrcr; /* Monitor Rising Temperature Rate Capture Register */
96 u32 tmftrcr; /* Monitor Falling Temperature Rate Capture Register */
97 u32 tmhtitr; /* Monitor High Temperature Immediate Threshold */
98 u32 tmhtatr; /* Monitor High Temperature Average Threshold */
99 u32 tmhtactr; /* Monitor High Temperature Average Crit Threshold */
100 u8 res3[0x4];
101 u32 tmltitr; /* Monitor Low Temperature Immediate Threshold */
102 u32 tmltatr; /* Monitor Low Temperature Average Threshold */
103 u32 tmltactr; /* Monitor Low Temperature Average Crit Threshold */
104 u8 res4[0x4];
105 u32 tmrtrctr; /* Monitor Rising Temperature Rate Critical Threshold Register */
106 u32 tmftrctr; /* Monitor Falling Temperature Rate Critical Threshold Register */
107 u8 res5[0x8];
108 u32 ttcfgr; /* Temperature Configuration Register */
109 u32 tscfgr; /* Sensor Configuration Register */
110 u8 res6[0x78];
111 u32 tritsr0; /* Immediate Temperature Site Register */
112 u32 tratsr0; /* Average Temperature Site Register */
113 u8 res7[0xdf8];
114 u32 tcmcfg; /* Central Module Configuration */
115 u8 res8[0xc];
116 u32 ttrcr[16]; /* Temperature Range Control Register */
117};
118
Peng Fanbef7d2a2020-05-03 22:19:47 +0800119struct imx_tmu_regs_v2 {
120 u32 ter; /* TMU enable Register */
121 u32 tsr; /* Status Register */
122 u32 tier; /* Interrupt enable register */
123 u32 tidr; /* Interrupt detect register */
124 u32 tmhtitr; /* Monitor high temperature immediate threshold register */
125 u32 tmhtatr; /* Monitor high temperature average threshold register */
126 u32 tmhtactr; /* TMU monitor high temperature average critical threshold register */
127 u32 tscr; /* Sensor value capture register */
128 u32 tritsr; /* Report immediate temperature site register 0 */
129 u32 tratsr; /* Report average temperature site register 0 */
130 u32 tasr; /* Amplifier setting register */
131 u32 ttmc; /* Test MUX control */
132 u32 tcaliv;
133};
134
Peng Fanfed211f2020-05-03 22:19:51 +0800135struct imx_tmu_regs_v3 {
136 u32 ter; /* TMU enable Register */
137 u32 tps; /* Status Register */
138 u32 tier; /* Interrupt enable register */
139 u32 tidr; /* Interrupt detect register */
140 u32 tmhtitr; /* Monitor high temperature immediate threshold register */
141 u32 tmhtatr; /* Monitor high temperature average threshold register */
142 u32 tmhtactr; /* TMU monitor high temperature average critical threshold register */
143 u32 tscr; /* Sensor value capture register */
144 u32 tritsr; /* Report immediate temperature site register 0 */
145 u32 tratsr; /* Report average temperature site register 0 */
146 u32 tasr; /* Amplifier setting register */
147 u32 ttmc; /* Test MUX control */
148 u32 tcaliv0;
149 u32 tcaliv1;
150 u32 tcaliv_m40;
151 u32 trim;
152};
153
Peng Fanbef7d2a2020-05-03 22:19:47 +0800154union tmu_regs {
155 struct imx_tmu_regs regs_v1;
156 struct imx_tmu_regs_v2 regs_v2;
Peng Fanfed211f2020-05-03 22:19:51 +0800157 struct imx_tmu_regs_v3 regs_v3;
Ye Lib7662562023-04-28 12:08:07 +0800158 struct imx_tmu_regs_v4 regs_v4;
Peng Fanbef7d2a2020-05-03 22:19:47 +0800159};
160
Peng Fan10de5792020-05-03 22:19:46 +0800161struct imx_tmu_plat {
162 int critical;
163 int alert;
164 int polling_delay;
165 int id;
166 bool zone_node;
Peng Fanbef7d2a2020-05-03 22:19:47 +0800167 union tmu_regs *regs;
Peng Fan10de5792020-05-03 22:19:46 +0800168};
169
170static int read_temperature(struct udevice *dev, int *temp)
171{
Simon Glassfa20e932020-12-03 16:55:20 -0700172 struct imx_tmu_plat *pdata = dev_get_plat(dev);
Peng Fanbef7d2a2020-05-03 22:19:47 +0800173 ulong drv_data = dev_get_driver_data(dev);
Peng Fan10de5792020-05-03 22:19:46 +0800174 u32 val;
Peng Fancabe2312020-05-03 22:19:49 +0800175 u32 retry = 10;
Peng Fan6eff2872020-05-03 22:19:50 +0800176 u32 valid = 0;
Peng Fan10de5792020-05-03 22:19:46 +0800177
178 do {
Peng Fancabe2312020-05-03 22:19:49 +0800179 mdelay(100);
180 retry--;
181
Peng Fanfed211f2020-05-03 22:19:51 +0800182 if (drv_data & FLAGS_VER3) {
183 val = readl(&pdata->regs->regs_v3.tritsr);
184 valid = val & (1 << (30 + pdata->id));
185 } else if (drv_data & FLAGS_VER2) {
Peng Fanbef7d2a2020-05-03 22:19:47 +0800186 val = readl(&pdata->regs->regs_v2.tritsr);
Peng Fan6eff2872020-05-03 22:19:50 +0800187 /*
188 * Check if TEMP is in valid range, the V bit in TRITSR
189 * only reflects the RAW uncalibrated data
190 */
191 valid = ((val & 0xff) < 10 || (val & 0xff) > 125) ? 0 : 1;
Ye Lib7662562023-04-28 12:08:07 +0800192 } else if (drv_data & FLAGS_VER4) {
193 val = readl(&pdata->regs->regs_v4.tritsr0);
194 valid = val & 0x80000000;
Peng Fan6eff2872020-05-03 22:19:50 +0800195 } else {
Peng Fanbef7d2a2020-05-03 22:19:47 +0800196 val = readl(&pdata->regs->regs_v1.site[pdata->id].tritsr);
Peng Fan6eff2872020-05-03 22:19:50 +0800197 valid = val & 0x80000000;
198 }
199 } while (!valid && retry > 0);
Peng Fan10de5792020-05-03 22:19:46 +0800200
Peng Fanfed211f2020-05-03 22:19:51 +0800201 if (retry > 0) {
202 if (drv_data & FLAGS_VER3) {
203 val = (val >> (pdata->id * 16)) & 0xff;
204 if (val & 0x80) /* Negative */
205 val = (~(val & 0x7f) + 1);
206
207 *temp = val;
208 if (*temp < -40 || *temp > 125) /* Check the range */
209 return -EINVAL;
210
211 *temp *= 1000;
Ye Lib7662562023-04-28 12:08:07 +0800212 } else if (drv_data & FLAGS_VER4) {
213 *temp = (val & 0x1ff) * 1000;
214 if (val & 0x200)
215 *temp += 500;
216
217 /* Convert Kelvin to Celsius */
218 *temp -= 273000;
Peng Fanfed211f2020-05-03 22:19:51 +0800219 } else {
220 *temp = (val & 0xff) * 1000;
221 }
222 } else {
Peng Fancabe2312020-05-03 22:19:49 +0800223 return -EINVAL;
Peng Fanfed211f2020-05-03 22:19:51 +0800224 }
Peng Fan10de5792020-05-03 22:19:46 +0800225
226 return 0;
227}
228
229int imx_tmu_get_temp(struct udevice *dev, int *temp)
230{
Simon Glassfa20e932020-12-03 16:55:20 -0700231 struct imx_tmu_plat *pdata = dev_get_plat(dev);
Peng Fan10de5792020-05-03 22:19:46 +0800232 int cpu_tmp = 0;
233 int ret;
234
235 ret = read_temperature(dev, &cpu_tmp);
236 if (ret)
237 return ret;
238
239 while (cpu_tmp >= pdata->alert) {
Marek Vasut39779c62023-04-04 21:25:09 +0200240 dev_info(dev, "CPU Temperature (%dC) has beyond alert (%dC), close to critical (%dC) waiting...\n",
241 cpu_tmp, pdata->alert, pdata->critical);
Peng Fan10de5792020-05-03 22:19:46 +0800242 mdelay(pdata->polling_delay);
243 ret = read_temperature(dev, &cpu_tmp);
244 if (ret)
245 return ret;
246 }
247
248 *temp = cpu_tmp / 1000;
249
250 return 0;
251}
252
253static const struct dm_thermal_ops imx_tmu_ops = {
254 .get_temp = imx_tmu_get_temp,
255};
256
257static int imx_tmu_calibration(struct udevice *dev)
258{
259 int i, val, len, ret;
Ye Lib7662562023-04-28 12:08:07 +0800260 int index;
Peng Fan10de5792020-05-03 22:19:46 +0800261 u32 range[4];
262 const fdt32_t *calibration;
Simon Glassfa20e932020-12-03 16:55:20 -0700263 struct imx_tmu_plat *pdata = dev_get_plat(dev);
Peng Fanbef7d2a2020-05-03 22:19:47 +0800264 ulong drv_data = dev_get_driver_data(dev);
Peng Fan10de5792020-05-03 22:19:46 +0800265
Marek Vasut39779c62023-04-04 21:25:09 +0200266 dev_dbg(dev, "%s\n", __func__);
Peng Fan10de5792020-05-03 22:19:46 +0800267
Peng Fanfed211f2020-05-03 22:19:51 +0800268 if (drv_data & (FLAGS_VER2 | FLAGS_VER3))
Peng Fanbef7d2a2020-05-03 22:19:47 +0800269 return 0;
270
Ye Lib7662562023-04-28 12:08:07 +0800271 if (drv_data & FLAGS_VER4) {
272 calibration = dev_read_prop(dev, "fsl,tmu-calibration", &len);
273 if (!calibration || len % 8 || len > 128) {
274 printf("TMU: invalid calibration data.\n");
275 return -ENODEV;
276 }
277
278 for (i = 0; i < len; i += 8, calibration += 2) {
279 index = i / 8;
280 writel(index, &pdata->regs->regs_v4.ttcfgr);
281 val = fdt32_to_cpu(*calibration);
282 writel(val, &pdata->regs->regs_v4.tscfgr);
283 val = fdt32_to_cpu(*(calibration + 1));
284 writel((1 << 31) | val, &pdata->regs->regs_v4.ttrcr[index]);
285 }
286
287 return 0;
288 }
289
Peng Fan10de5792020-05-03 22:19:46 +0800290 ret = dev_read_u32_array(dev, "fsl,tmu-range", range, 4);
291 if (ret) {
Marek Vasut39779c62023-04-04 21:25:09 +0200292 dev_err(dev, "TMU: missing calibration range, ret = %d.\n", ret);
Peng Fan10de5792020-05-03 22:19:46 +0800293 return ret;
294 }
295
296 /* Init temperature range registers */
Peng Fanbef7d2a2020-05-03 22:19:47 +0800297 writel(range[0], &pdata->regs->regs_v1.ttr0cr);
298 writel(range[1], &pdata->regs->regs_v1.ttr1cr);
299 writel(range[2], &pdata->regs->regs_v1.ttr2cr);
300 writel(range[3], &pdata->regs->regs_v1.ttr3cr);
Peng Fan10de5792020-05-03 22:19:46 +0800301
302 calibration = dev_read_prop(dev, "fsl,tmu-calibration", &len);
303 if (!calibration || len % 8) {
Marek Vasut39779c62023-04-04 21:25:09 +0200304 dev_err(dev, "TMU: invalid calibration data.\n");
Peng Fan10de5792020-05-03 22:19:46 +0800305 return -ENODEV;
306 }
307
308 for (i = 0; i < len; i += 8, calibration += 2) {
309 val = fdt32_to_cpu(*calibration);
Peng Fanbef7d2a2020-05-03 22:19:47 +0800310 writel(val, &pdata->regs->regs_v1.ttcfgr);
Peng Fan10de5792020-05-03 22:19:46 +0800311 val = fdt32_to_cpu(*(calibration + 1));
Peng Fanbef7d2a2020-05-03 22:19:47 +0800312 writel(val, &pdata->regs->regs_v1.tscfgr);
Peng Fan10de5792020-05-03 22:19:46 +0800313 }
314
315 return 0;
316}
317
Marek Vasut7903bcf2023-04-04 21:25:10 +0200318#if defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
319static void imx_tmu_mx8mm_mx8mn_init(struct udevice *dev)
Peng Fan4f5026c2020-05-03 22:19:48 +0800320{
Marek Vasut7903bcf2023-04-04 21:25:10 +0200321 /* Load TCALIV and TASR from fuses */
322 struct ocotp_regs *ocotp =
323 (struct ocotp_regs *)OCOTP_BASE_ADDR;
324 struct fuse_bank *bank = &ocotp->bank[3];
325 struct fuse_bank3_regs *fuse =
326 (struct fuse_bank3_regs *)bank->fuse_regs;
327 struct imx_tmu_plat *pdata = dev_get_plat(dev);
328 void *reg_base = (void *)pdata->regs;
329
330 u32 tca_rt, tca_hr, tca_en;
331 u32 buf_vref, buf_slope;
332
333 tca_rt = fuse->ana0 & 0xFF;
334 tca_hr = (fuse->ana0 & 0xFF00) >> 8;
335 tca_en = (fuse->ana0 & 0x2000000) >> 25;
336
337 buf_vref = (fuse->ana0 & 0x1F00000) >> 20;
338 buf_slope = (fuse->ana0 & 0xF0000) >> 16;
339
340 writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
341 writel((tca_en << 31) | (tca_hr << 16) | tca_rt,
342 (ulong)reg_base + 0x30);
343}
344#else
345static inline void imx_tmu_mx8mm_mx8mn_init(struct udevice *dev) { }
346#endif
347
348#if defined(CONFIG_IMX8MP)
349static void imx_tmu_mx8mp_init(struct udevice *dev)
350{
351 /* Load TCALIV0/1/m40 and TRIM from fuses */
352 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
353 struct fuse_bank *bank = &ocotp->bank[38];
354 struct fuse_bank38_regs *fuse =
355 (struct fuse_bank38_regs *)bank->fuse_regs;
356 struct fuse_bank *bank2 = &ocotp->bank[39];
357 struct fuse_bank39_regs *fuse2 =
358 (struct fuse_bank39_regs *)bank2->fuse_regs;
359 struct imx_tmu_plat *pdata = dev_get_plat(dev);
360 void *reg_base = (void *)pdata->regs;
361 u32 buf_vref, buf_slope, bjt_cur, vlsb, bgr;
362 u32 reg;
363 u32 tca40[2], tca25[2], tca105[2];
364
365 /* For blank sample */
366 if (!fuse->ana_trim2 && !fuse->ana_trim3 &&
367 !fuse->ana_trim4 && !fuse2->ana_trim5) {
368 /* Use a default 25C binary codes */
369 tca25[0] = 1596;
370 tca25[1] = 1596;
371 writel(tca25[0], (ulong)reg_base + 0x30);
372 writel(tca25[1], (ulong)reg_base + 0x34);
373 return;
374 }
375
376 buf_vref = (fuse->ana_trim2 & 0xc0) >> 6;
377 buf_slope = (fuse->ana_trim2 & 0xF00) >> 8;
378 bjt_cur = (fuse->ana_trim2 & 0xF000) >> 12;
379 bgr = (fuse->ana_trim2 & 0xF0000) >> 16;
380 vlsb = (fuse->ana_trim2 & 0xF00000) >> 20;
381 writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
382
383 reg = (bgr << 28) | (bjt_cur << 20) | (vlsb << 12) | (1 << 7);
384 writel(reg, (ulong)reg_base + 0x3c);
385
386 tca40[0] = (fuse->ana_trim3 & 0xFFF0000) >> 16;
387 tca25[0] = (fuse->ana_trim3 & 0xF0000000) >> 28;
388 tca25[0] |= ((fuse->ana_trim4 & 0xFF) << 4);
389 tca105[0] = (fuse->ana_trim4 & 0xFFF00) >> 8;
390 tca40[1] = (fuse->ana_trim4 & 0xFFF00000) >> 20;
391 tca25[1] = fuse2->ana_trim5 & 0xFFF;
392 tca105[1] = (fuse2->ana_trim5 & 0xFFF000) >> 12;
393
394 /* use 25c for 1p calibration */
395 writel(tca25[0] | (tca105[0] << 16), (ulong)reg_base + 0x30);
396 writel(tca25[1] | (tca105[1] << 16), (ulong)reg_base + 0x34);
397 writel(tca40[0] | (tca40[1] << 16), (ulong)reg_base + 0x38);
398}
399#else
400static inline void imx_tmu_mx8mp_init(struct udevice *dev) { }
401#endif
402
Ye Lib7662562023-04-28 12:08:07 +0800403static inline void imx_tmu_mx93_init(struct udevice *dev) { }
404
Marek Vasut7903bcf2023-04-04 21:25:10 +0200405static void imx_tmu_arch_init(struct udevice *dev)
406{
407 if (is_imx8mm() || is_imx8mn())
408 imx_tmu_mx8mm_mx8mn_init(dev);
409 else if (is_imx8mp())
410 imx_tmu_mx8mp_init(dev);
Ye Lib7662562023-04-28 12:08:07 +0800411 else if (is_imx93())
412 imx_tmu_mx93_init(dev);
Marek Vasut7903bcf2023-04-04 21:25:10 +0200413 else
414 dev_err(dev, "Unsupported SoC, TMU calibration not loaded!\n");
Peng Fan4f5026c2020-05-03 22:19:48 +0800415}
416
Peng Fanbef7d2a2020-05-03 22:19:47 +0800417static void imx_tmu_init(struct udevice *dev)
Peng Fan10de5792020-05-03 22:19:46 +0800418{
Simon Glassfa20e932020-12-03 16:55:20 -0700419 struct imx_tmu_plat *pdata = dev_get_plat(dev);
Peng Fanbef7d2a2020-05-03 22:19:47 +0800420 ulong drv_data = dev_get_driver_data(dev);
421
Marek Vasut39779c62023-04-04 21:25:09 +0200422 dev_dbg(dev, "%s\n", __func__);
Peng Fan10de5792020-05-03 22:19:46 +0800423
Peng Fanfed211f2020-05-03 22:19:51 +0800424 if (drv_data & FLAGS_VER3) {
425 /* Disable monitoring */
426 writel(0x0, &pdata->regs->regs_v3.ter);
427
428 /* Disable interrupt, using polling instead */
429 writel(0x0, &pdata->regs->regs_v3.tier);
430
431 } else if (drv_data & FLAGS_VER2) {
Peng Fanbef7d2a2020-05-03 22:19:47 +0800432 /* Disable monitoring */
433 writel(0x0, &pdata->regs->regs_v2.ter);
434
435 /* Disable interrupt, using polling instead */
436 writel(0x0, &pdata->regs->regs_v2.tier);
Ye Lib7662562023-04-28 12:08:07 +0800437 } else if (drv_data & FLAGS_VER4) {
438 /* Disable monitoring */
439 writel(TMR_DISABLE, &pdata->regs->regs_v4.tmr);
440
441 /* Disable interrupt, using polling instead */
442 writel(TIER_DISABLE, &pdata->regs->regs_v4.tier);
443
444 /* Set update_interval */
445 writel(TMTMIR_DEFAULT, &pdata->regs->regs_v4.tmtmir);
Peng Fanbef7d2a2020-05-03 22:19:47 +0800446 } else {
447 /* Disable monitoring */
448 writel(TMR_DISABLE, &pdata->regs->regs_v1.tmr);
Peng Fan10de5792020-05-03 22:19:46 +0800449
Peng Fanbef7d2a2020-05-03 22:19:47 +0800450 /* Disable interrupt, using polling instead */
451 writel(TIER_DISABLE, &pdata->regs->regs_v1.tier);
Peng Fan10de5792020-05-03 22:19:46 +0800452
Peng Fanbef7d2a2020-05-03 22:19:47 +0800453 /* Set update_interval */
454 writel(TMTMIR_DEFAULT, &pdata->regs->regs_v1.tmtmir);
455 }
Peng Fan4f5026c2020-05-03 22:19:48 +0800456
Marek Vasut7903bcf2023-04-04 21:25:10 +0200457 imx_tmu_arch_init(dev);
Peng Fan10de5792020-05-03 22:19:46 +0800458}
459
460static int imx_tmu_enable_msite(struct udevice *dev)
461{
Simon Glassfa20e932020-12-03 16:55:20 -0700462 struct imx_tmu_plat *pdata = dev_get_plat(dev);
Peng Fanbef7d2a2020-05-03 22:19:47 +0800463 ulong drv_data = dev_get_driver_data(dev);
Peng Fan10de5792020-05-03 22:19:46 +0800464 u32 reg;
465
Marek Vasut39779c62023-04-04 21:25:09 +0200466 dev_dbg(dev, "%s\n", __func__);
Peng Fan10de5792020-05-03 22:19:46 +0800467
468 if (!pdata->regs)
469 return -EIO;
470
Peng Fanfed211f2020-05-03 22:19:51 +0800471 if (drv_data & FLAGS_VER3) {
472 reg = readl(&pdata->regs->regs_v3.ter);
473 reg &= ~TER_EN;
474 writel(reg, &pdata->regs->regs_v3.ter);
475
476 writel(pdata->id << 30, &pdata->regs->regs_v3.tps);
477
478 reg &= ~TER_ALPF;
479 reg |= 0x1;
480 reg &= ~TER_ADC_PD;
481 writel(reg, &pdata->regs->regs_v3.ter);
482
483 /* Enable monitor */
484 reg |= TER_EN;
485 writel(reg, &pdata->regs->regs_v3.ter);
486 } else if (drv_data & FLAGS_VER2) {
Peng Fanbef7d2a2020-05-03 22:19:47 +0800487 reg = readl(&pdata->regs->regs_v2.ter);
488 reg &= ~TER_EN;
489 writel(reg, &pdata->regs->regs_v2.ter);
Peng Fan10de5792020-05-03 22:19:46 +0800490
Peng Fanbef7d2a2020-05-03 22:19:47 +0800491 reg &= ~TER_ALPF;
492 reg |= 0x1;
493 writel(reg, &pdata->regs->regs_v2.ter);
Peng Fan10de5792020-05-03 22:19:46 +0800494
Peng Fanbef7d2a2020-05-03 22:19:47 +0800495 /* Enable monitor */
496 reg |= TER_EN;
497 writel(reg, &pdata->regs->regs_v2.ter);
Ye Lib7662562023-04-28 12:08:07 +0800498 } else if (drv_data & FLAGS_VER4) {
499 reg = readl(&pdata->regs->regs_v4.tcmcfg);
500 reg |= (1 << 30) | (1 << 28);
501 reg &= ~0xF000; /* set SAR clk = IPG clk /16 */
502 writel(reg, &pdata->regs->regs_v4.tcmcfg);
503
504 /* Set ALPF*/
505 reg = readl(&pdata->regs->regs_v4.tmr);
506 reg |= TMR_ALPF;
507 writel(reg, &pdata->regs->regs_v4.tmr);
508
509 writel(1, &pdata->regs->regs_v4.tmsr);
510
511 /* Enable ME */
512 reg |= TMR_ME;
513 writel(reg, &pdata->regs->regs_v4.tmr);
Peng Fanbef7d2a2020-05-03 22:19:47 +0800514 } else {
515 /* Clear the ME before setting MSITE and ALPF*/
516 reg = readl(&pdata->regs->regs_v1.tmr);
517 reg &= ~TMR_ME;
518 writel(reg, &pdata->regs->regs_v1.tmr);
519
520 reg |= 1 << (15 - pdata->id);
521 reg |= TMR_ALPF;
522 writel(reg, &pdata->regs->regs_v1.tmr);
523
524 /* Enable ME */
525 reg |= TMR_ME;
526 writel(reg, &pdata->regs->regs_v1.tmr);
527 }
Peng Fan10de5792020-05-03 22:19:46 +0800528
529 return 0;
530}
531
532static int imx_tmu_bind(struct udevice *dev)
533{
Simon Glassfa20e932020-12-03 16:55:20 -0700534 struct imx_tmu_plat *pdata = dev_get_plat(dev);
Peng Fan10de5792020-05-03 22:19:46 +0800535 int ret;
536 ofnode node, offset;
537 const char *name;
538 const void *prop;
Tim Harvey83858252021-02-05 16:11:05 -0800539 int minc, maxc;
Peng Fan10de5792020-05-03 22:19:46 +0800540
Marek Vasut39779c62023-04-04 21:25:09 +0200541 dev_dbg(dev, "%s\n", __func__);
Peng Fan10de5792020-05-03 22:19:46 +0800542
543 prop = dev_read_prop(dev, "compatible", NULL);
544 if (!prop)
545 return 0;
546
547 pdata->zone_node = 1;
Tim Harvey83858252021-02-05 16:11:05 -0800548 /* default alert/crit temps based on temp grade */
549 get_cpu_temp_grade(&minc, &maxc);
550 pdata->critical = maxc * 1000;
551 pdata->alert = (maxc - 10) * 1000;
Peng Fan10de5792020-05-03 22:19:46 +0800552
553 node = ofnode_path("/thermal-zones");
554 ofnode_for_each_subnode(offset, node) {
555 /* Bind the subnode to this driver */
556 name = ofnode_get_name(offset);
557
558 ret = device_bind_with_driver_data(dev, dev->driver, name,
559 dev->driver_data, offset,
560 NULL);
561 if (ret)
Marek Vasut39779c62023-04-04 21:25:09 +0200562 dev_err(dev, "Error binding driver: %d\n", ret);
Peng Fan10de5792020-05-03 22:19:46 +0800563 }
564
565 return 0;
566}
567
568static int imx_tmu_parse_fdt(struct udevice *dev)
569{
Simon Glassfa20e932020-12-03 16:55:20 -0700570 struct imx_tmu_plat *pdata = dev_get_plat(dev), *p_parent_data;
Peng Fan10de5792020-05-03 22:19:46 +0800571 struct ofnode_phandle_args args;
572 ofnode trips_np;
573 int ret;
574
Marek Vasut39779c62023-04-04 21:25:09 +0200575 dev_dbg(dev, "%s\n", __func__);
Peng Fan10de5792020-05-03 22:19:46 +0800576
577 if (pdata->zone_node) {
Peng Fanbef7d2a2020-05-03 22:19:47 +0800578 pdata->regs = (union tmu_regs *)dev_read_addr_ptr(dev);
Peng Fan10de5792020-05-03 22:19:46 +0800579
580 if (!pdata->regs)
581 return -EINVAL;
582 return 0;
583 }
584
Simon Glassfa20e932020-12-03 16:55:20 -0700585 p_parent_data = dev_get_plat(dev->parent);
Peng Fan10de5792020-05-03 22:19:46 +0800586 if (p_parent_data->zone_node)
587 pdata->regs = p_parent_data->regs;
588
589 ret = dev_read_phandle_with_args(dev, "thermal-sensors",
590 "#thermal-sensor-cells",
591 0, 0, &args);
592 if (ret)
593 return ret;
594
595 if (!ofnode_equal(args.node, dev_ofnode(dev->parent)))
596 return -EFAULT;
597
598 if (args.args_count >= 1)
599 pdata->id = args.args[0];
600 else
601 pdata->id = 0;
602
Marek Vasut39779c62023-04-04 21:25:09 +0200603 dev_dbg(dev, "args.args_count %d, id %d\n", args.args_count, pdata->id);
Peng Fan10de5792020-05-03 22:19:46 +0800604
605 pdata->polling_delay = dev_read_u32_default(dev, "polling-delay", 1000);
606
607 trips_np = ofnode_path("/thermal-zones/cpu-thermal/trips");
608 ofnode_for_each_subnode(trips_np, trips_np) {
609 const char *type;
610
611 type = ofnode_get_property(trips_np, "type", NULL);
612 if (!type)
613 continue;
614 if (!strcmp(type, "critical"))
615 pdata->critical = ofnode_read_u32_default(trips_np, "temperature", 85);
616 else if (strcmp(type, "passive") == 0)
617 pdata->alert = ofnode_read_u32_default(trips_np, "temperature", 80);
618 else
619 continue;
620 }
621
Marek Vasut39779c62023-04-04 21:25:09 +0200622 dev_dbg(dev, "id %d polling_delay %d, critical %d, alert %d\n",
623 pdata->id, pdata->polling_delay, pdata->critical, pdata->alert);
Peng Fan10de5792020-05-03 22:19:46 +0800624
625 return 0;
626}
627
628static int imx_tmu_probe(struct udevice *dev)
629{
Simon Glassfa20e932020-12-03 16:55:20 -0700630 struct imx_tmu_plat *pdata = dev_get_plat(dev);
Peng Fan10de5792020-05-03 22:19:46 +0800631 int ret;
632
633 ret = imx_tmu_parse_fdt(dev);
634 if (ret) {
Marek Vasut39779c62023-04-04 21:25:09 +0200635 dev_err(dev, "Error in parsing TMU FDT %d\n", ret);
Peng Fan10de5792020-05-03 22:19:46 +0800636 return ret;
637 }
638
639 if (pdata->zone_node) {
Peng Fanbef7d2a2020-05-03 22:19:47 +0800640 imx_tmu_init(dev);
Peng Fan10de5792020-05-03 22:19:46 +0800641 imx_tmu_calibration(dev);
Tim Harvey83858252021-02-05 16:11:05 -0800642 imx_tmu_enable_msite(dev);
Peng Fan10de5792020-05-03 22:19:46 +0800643 } else {
644 imx_tmu_enable_msite(dev);
645 }
646
647 return 0;
648}
649
650static const struct udevice_id imx_tmu_ids[] = {
651 { .compatible = "fsl,imx8mq-tmu", },
Peng Fanbef7d2a2020-05-03 22:19:47 +0800652 { .compatible = "fsl,imx8mm-tmu", .data = FLAGS_VER2, },
Peng Fanfed211f2020-05-03 22:19:51 +0800653 { .compatible = "fsl,imx8mp-tmu", .data = FLAGS_VER3, },
Ye Lib7662562023-04-28 12:08:07 +0800654 { .compatible = "fsl,imx93-tmu", .data = FLAGS_VER4, },
Peng Fan10de5792020-05-03 22:19:46 +0800655 { }
656};
657
658U_BOOT_DRIVER(imx_tmu) = {
659 .name = "imx_tmu",
660 .id = UCLASS_THERMAL,
661 .ops = &imx_tmu_ops,
662 .of_match = imx_tmu_ids,
663 .bind = imx_tmu_bind,
664 .probe = imx_tmu_probe,
Simon Glass71fa5b42020-12-03 16:55:18 -0700665 .plat_auto = sizeof(struct imx_tmu_plat),
Peng Fan10de5792020-05-03 22:19:46 +0800666 .flags = DM_FLAG_PRE_RELOC,
667};