WS cleanup: remove SPACE(s) followed by TAB
[platform/kernel/u-boot.git] / drivers / thermal / imx_tmu.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2017~2020 NXP
4  *
5  */
6
7 #include <config.h>
8 #include <common.h>
9 #include <asm/global_data.h>
10 #include <asm/io.h>
11 #include <asm/arch/clock.h>
12 #include <asm/arch/sys_proto.h>
13 #include <dm.h>
14 #include <dm/device-internal.h>
15 #include <dm/device.h>
16 #include <errno.h>
17 #include <fuse.h>
18 #include <linux/delay.h>
19 #include <malloc.h>
20 #include <thermal.h>
21
22 DECLARE_GLOBAL_DATA_PTR;
23
24 #define SITES_MAX       16
25 #define FLAGS_VER2      0x1
26 #define FLAGS_VER3      0x2
27
28 #define TMR_DISABLE     0x0
29 #define TMR_ME          0x80000000
30 #define TMR_ALPF        0x0c000000
31 #define TMTMIR_DEFAULT  0x00000002
32 #define TIER_DISABLE    0x0
33
34 #define TER_EN                  0x80000000
35 #define TER_ADC_PD              0x40000000
36 #define TER_ALPF                0x3
37
38 /*
39  * i.MX TMU Registers
40  */
41 struct imx_tmu_site_regs {
42         u32 tritsr;             /* Immediate Temperature Site Register */
43         u32 tratsr;             /* Average Temperature Site Register */
44         u8 res0[0x8];
45 };
46
47 struct imx_tmu_regs {
48         u32 tmr;        /* Mode Register */
49         u32 tsr;        /* Status Register */
50         u32 tmtmir;     /* Temperature measurement interval Register */
51         u8 res0[0x14];
52         u32 tier;       /* Interrupt Enable Register */
53         u32 tidr;       /* Interrupt Detect Register */
54         u32 tiscr;      /* Interrupt Site Capture Register */
55         u32 ticscr;     /* Interrupt Critical Site Capture Register */
56         u8 res1[0x10];
57         u32 tmhtcrh;    /* High Temperature Capture Register */
58         u32 tmhtcrl;    /* Low Temperature Capture Register */
59         u8 res2[0x8];
60         u32 tmhtitr;    /* High Temperature Immediate Threshold */
61         u32 tmhtatr;    /* High Temperature Average Threshold */
62         u32 tmhtactr;   /* High Temperature Average Crit Threshold */
63         u8 res3[0x24];
64         u32 ttcfgr;     /* Temperature Configuration Register */
65         u32 tscfgr;     /* Sensor Configuration Register */
66         u8 res4[0x78];
67         struct imx_tmu_site_regs site[SITES_MAX];
68         u8 res5[0x9f8];
69         u32 ipbrr0;     /* IP Block Revision Register 0 */
70         u32 ipbrr1;     /* IP Block Revision Register 1 */
71         u8 res6[0x310];
72         u32 ttr0cr;     /* Temperature Range 0 Control Register */
73         u32 ttr1cr;     /* Temperature Range 1 Control Register */
74         u32 ttr2cr;     /* Temperature Range 2 Control Register */
75         u32 ttr3cr;     /* Temperature Range 3 Control Register */
76 };
77
78 struct imx_tmu_regs_v2 {
79         u32 ter;        /* TMU enable Register */
80         u32 tsr;        /* Status Register */
81         u32 tier;       /* Interrupt enable register */
82         u32 tidr;       /* Interrupt detect  register */
83         u32 tmhtitr;    /* Monitor high temperature immediate threshold register */
84         u32 tmhtatr;    /* Monitor high temperature average threshold register */
85         u32 tmhtactr;   /* TMU monitor high temperature average critical  threshold register */
86         u32 tscr;       /* Sensor value capture register */
87         u32 tritsr;     /* Report immediate temperature site register 0 */
88         u32 tratsr;     /* Report average temperature site register 0 */
89         u32 tasr;       /* Amplifier setting register */
90         u32 ttmc;       /* Test MUX control */
91         u32 tcaliv;
92 };
93
94 struct imx_tmu_regs_v3 {
95         u32 ter;        /* TMU enable Register */
96         u32 tps;        /* Status Register */
97         u32 tier;       /* Interrupt enable register */
98         u32 tidr;       /* Interrupt detect  register */
99         u32 tmhtitr;    /* Monitor high temperature immediate threshold register */
100         u32 tmhtatr;    /* Monitor high temperature average threshold register */
101         u32 tmhtactr;   /* TMU monitor high temperature average critical  threshold register */
102         u32 tscr;       /* Sensor value capture register */
103         u32 tritsr;     /* Report immediate temperature site register 0 */
104         u32 tratsr;     /* Report average temperature site register 0 */
105         u32 tasr;       /* Amplifier setting register */
106         u32 ttmc;       /* Test MUX control */
107         u32 tcaliv0;
108         u32 tcaliv1;
109         u32 tcaliv_m40;
110         u32 trim;
111 };
112
113 union tmu_regs {
114         struct imx_tmu_regs regs_v1;
115         struct imx_tmu_regs_v2 regs_v2;
116         struct imx_tmu_regs_v3 regs_v3;
117 };
118
119 struct imx_tmu_plat {
120         int critical;
121         int alert;
122         int polling_delay;
123         int id;
124         bool zone_node;
125         union tmu_regs *regs;
126 };
127
128 static int read_temperature(struct udevice *dev, int *temp)
129 {
130         struct imx_tmu_plat *pdata = dev_get_plat(dev);
131         ulong drv_data = dev_get_driver_data(dev);
132         u32 val;
133         u32 retry = 10;
134         u32 valid = 0;
135
136         do {
137                 mdelay(100);
138                 retry--;
139
140                 if (drv_data & FLAGS_VER3) {
141                         val = readl(&pdata->regs->regs_v3.tritsr);
142                         valid = val & (1 << (30 + pdata->id));
143                 } else if (drv_data & FLAGS_VER2) {
144                         val = readl(&pdata->regs->regs_v2.tritsr);
145                         /*
146                          * Check if TEMP is in valid range, the V bit in TRITSR
147                          * only reflects the RAW uncalibrated data
148                          */
149                         valid =  ((val & 0xff) < 10 || (val & 0xff) > 125) ? 0 : 1;
150                 } else {
151                         val = readl(&pdata->regs->regs_v1.site[pdata->id].tritsr);
152                         valid = val & 0x80000000;
153                 }
154         } while (!valid && retry > 0);
155
156         if (retry > 0) {
157                 if (drv_data & FLAGS_VER3) {
158                         val = (val >> (pdata->id * 16)) & 0xff;
159                         if (val & 0x80) /* Negative */
160                                 val = (~(val & 0x7f) + 1);
161
162                         *temp = val;
163                         if (*temp < -40 || *temp > 125) /* Check the range */
164                                 return -EINVAL;
165
166                         *temp *= 1000;
167                 } else {
168                         *temp = (val & 0xff) * 1000;
169                 }
170         } else {
171                 return -EINVAL;
172         }
173
174         return 0;
175 }
176
177 int imx_tmu_get_temp(struct udevice *dev, int *temp)
178 {
179         struct imx_tmu_plat *pdata = dev_get_plat(dev);
180         int cpu_tmp = 0;
181         int ret;
182
183         ret = read_temperature(dev, &cpu_tmp);
184         if (ret)
185                 return ret;
186
187         while (cpu_tmp >= pdata->alert) {
188                 printf("CPU Temperature (%dC) has beyond alert (%dC), close to critical (%dC)", cpu_tmp, pdata->alert, pdata->critical);
189                 puts(" waiting...\n");
190                 mdelay(pdata->polling_delay);
191                 ret = read_temperature(dev, &cpu_tmp);
192                 if (ret)
193                         return ret;
194         }
195
196         *temp = cpu_tmp / 1000;
197
198         return 0;
199 }
200
201 static const struct dm_thermal_ops imx_tmu_ops = {
202         .get_temp       = imx_tmu_get_temp,
203 };
204
205 static int imx_tmu_calibration(struct udevice *dev)
206 {
207         int i, val, len, ret;
208         u32 range[4];
209         const fdt32_t *calibration;
210         struct imx_tmu_plat *pdata = dev_get_plat(dev);
211         ulong drv_data = dev_get_driver_data(dev);
212
213         debug("%s\n", __func__);
214
215         if (drv_data & (FLAGS_VER2 | FLAGS_VER3))
216                 return 0;
217
218         ret = dev_read_u32_array(dev, "fsl,tmu-range", range, 4);
219         if (ret) {
220                 printf("TMU: missing calibration range, ret = %d.\n", ret);
221                 return ret;
222         }
223
224         /* Init temperature range registers */
225         writel(range[0], &pdata->regs->regs_v1.ttr0cr);
226         writel(range[1], &pdata->regs->regs_v1.ttr1cr);
227         writel(range[2], &pdata->regs->regs_v1.ttr2cr);
228         writel(range[3], &pdata->regs->regs_v1.ttr3cr);
229
230         calibration = dev_read_prop(dev, "fsl,tmu-calibration", &len);
231         if (!calibration || len % 8) {
232                 printf("TMU: invalid calibration data.\n");
233                 return -ENODEV;
234         }
235
236         for (i = 0; i < len; i += 8, calibration += 2) {
237                 val = fdt32_to_cpu(*calibration);
238                 writel(val, &pdata->regs->regs_v1.ttcfgr);
239                 val = fdt32_to_cpu(*(calibration + 1));
240                 writel(val, &pdata->regs->regs_v1.tscfgr);
241         }
242
243         return 0;
244 }
245
246 void __weak imx_tmu_arch_init(void *reg_base)
247 {
248 }
249
250 static void imx_tmu_init(struct udevice *dev)
251 {
252         struct imx_tmu_plat *pdata = dev_get_plat(dev);
253         ulong drv_data = dev_get_driver_data(dev);
254
255         debug("%s\n", __func__);
256
257         if (drv_data & FLAGS_VER3) {
258                 /* Disable monitoring */
259                 writel(0x0, &pdata->regs->regs_v3.ter);
260
261                 /* Disable interrupt, using polling instead */
262                 writel(0x0, &pdata->regs->regs_v3.tier);
263
264         } else if (drv_data & FLAGS_VER2) {
265                 /* Disable monitoring */
266                 writel(0x0, &pdata->regs->regs_v2.ter);
267
268                 /* Disable interrupt, using polling instead */
269                 writel(0x0, &pdata->regs->regs_v2.tier);
270         } else {
271                 /* Disable monitoring */
272                 writel(TMR_DISABLE, &pdata->regs->regs_v1.tmr);
273
274                 /* Disable interrupt, using polling instead */
275                 writel(TIER_DISABLE, &pdata->regs->regs_v1.tier);
276
277                 /* Set update_interval */
278                 writel(TMTMIR_DEFAULT, &pdata->regs->regs_v1.tmtmir);
279         }
280
281         imx_tmu_arch_init((void *)pdata->regs);
282 }
283
284 static int imx_tmu_enable_msite(struct udevice *dev)
285 {
286         struct imx_tmu_plat *pdata = dev_get_plat(dev);
287         ulong drv_data = dev_get_driver_data(dev);
288         u32 reg;
289
290         debug("%s\n", __func__);
291
292         if (!pdata->regs)
293                 return -EIO;
294
295         if (drv_data & FLAGS_VER3) {
296                 reg = readl(&pdata->regs->regs_v3.ter);
297                 reg &= ~TER_EN;
298                 writel(reg, &pdata->regs->regs_v3.ter);
299
300                 writel(pdata->id << 30, &pdata->regs->regs_v3.tps);
301
302                 reg &= ~TER_ALPF;
303                 reg |= 0x1;
304                 reg &= ~TER_ADC_PD;
305                 writel(reg, &pdata->regs->regs_v3.ter);
306
307                 /* Enable monitor */
308                 reg |= TER_EN;
309                 writel(reg, &pdata->regs->regs_v3.ter);
310         } else if (drv_data & FLAGS_VER2) {
311                 reg = readl(&pdata->regs->regs_v2.ter);
312                 reg &= ~TER_EN;
313                 writel(reg, &pdata->regs->regs_v2.ter);
314
315                 reg &= ~TER_ALPF;
316                 reg |= 0x1;
317                 writel(reg, &pdata->regs->regs_v2.ter);
318
319                 /* Enable monitor */
320                 reg |= TER_EN;
321                 writel(reg, &pdata->regs->regs_v2.ter);
322         } else {
323                 /* Clear the ME before setting MSITE and ALPF*/
324                 reg = readl(&pdata->regs->regs_v1.tmr);
325                 reg &= ~TMR_ME;
326                 writel(reg, &pdata->regs->regs_v1.tmr);
327
328                 reg |= 1 << (15 - pdata->id);
329                 reg |= TMR_ALPF;
330                 writel(reg, &pdata->regs->regs_v1.tmr);
331
332                 /* Enable ME */
333                 reg |= TMR_ME;
334                 writel(reg, &pdata->regs->regs_v1.tmr);
335         }
336
337         return 0;
338 }
339
340 static int imx_tmu_bind(struct udevice *dev)
341 {
342         struct imx_tmu_plat *pdata = dev_get_plat(dev);
343         int ret;
344         ofnode node, offset;
345         const char *name;
346         const void *prop;
347         int minc, maxc;
348
349         debug("%s dev name %s\n", __func__, dev->name);
350
351         prop = dev_read_prop(dev, "compatible", NULL);
352         if (!prop)
353                 return 0;
354
355         pdata->zone_node = 1;
356         /* default alert/crit temps based on temp grade */
357         get_cpu_temp_grade(&minc, &maxc);
358         pdata->critical = maxc * 1000;
359         pdata->alert = (maxc - 10) * 1000;
360
361         node = ofnode_path("/thermal-zones");
362         ofnode_for_each_subnode(offset, node) {
363                 /* Bind the subnode to this driver */
364                 name = ofnode_get_name(offset);
365
366                 ret = device_bind_with_driver_data(dev, dev->driver, name,
367                                                    dev->driver_data, offset,
368                                                    NULL);
369                 if (ret)
370                         printf("Error binding driver '%s': %d\n",
371                                dev->driver->name, ret);
372         }
373
374         return 0;
375 }
376
377 static int imx_tmu_parse_fdt(struct udevice *dev)
378 {
379         struct imx_tmu_plat *pdata = dev_get_plat(dev), *p_parent_data;
380         struct ofnode_phandle_args args;
381         ofnode trips_np;
382         int ret;
383
384         debug("%s dev name %s\n", __func__, dev->name);
385
386         if (pdata->zone_node) {
387                 pdata->regs = (union tmu_regs *)dev_read_addr_ptr(dev);
388
389                 if (!pdata->regs)
390                         return -EINVAL;
391                 return 0;
392         }
393
394         p_parent_data = dev_get_plat(dev->parent);
395         if (p_parent_data->zone_node)
396                 pdata->regs = p_parent_data->regs;
397
398         ret = dev_read_phandle_with_args(dev, "thermal-sensors",
399                                          "#thermal-sensor-cells",
400                                          0, 0, &args);
401         if (ret)
402                 return ret;
403
404         if (!ofnode_equal(args.node, dev_ofnode(dev->parent)))
405                 return -EFAULT;
406
407         if (args.args_count >= 1)
408                 pdata->id = args.args[0];
409         else
410                 pdata->id = 0;
411
412         debug("args.args_count %d, id %d\n", args.args_count, pdata->id);
413
414         pdata->polling_delay = dev_read_u32_default(dev, "polling-delay", 1000);
415
416         trips_np = ofnode_path("/thermal-zones/cpu-thermal/trips");
417         ofnode_for_each_subnode(trips_np, trips_np) {
418                 const char *type;
419
420                 type = ofnode_get_property(trips_np, "type", NULL);
421                 if (!type)
422                         continue;
423                 if (!strcmp(type, "critical"))
424                         pdata->critical = ofnode_read_u32_default(trips_np, "temperature", 85);
425                 else if (strcmp(type, "passive") == 0)
426                         pdata->alert = ofnode_read_u32_default(trips_np, "temperature", 80);
427                 else
428                         continue;
429         }
430
431         debug("id %d polling_delay %d, critical %d, alert %d\n",
432               pdata->id, pdata->polling_delay, pdata->critical, pdata->alert);
433
434         return 0;
435 }
436
437 static int imx_tmu_probe(struct udevice *dev)
438 {
439         struct imx_tmu_plat *pdata = dev_get_plat(dev);
440         int ret;
441
442         ret = imx_tmu_parse_fdt(dev);
443         if (ret) {
444                 printf("Error in parsing TMU FDT %d\n", ret);
445                 return ret;
446         }
447
448         if (pdata->zone_node) {
449                 imx_tmu_init(dev);
450                 imx_tmu_calibration(dev);
451                 imx_tmu_enable_msite(dev);
452         } else {
453                 imx_tmu_enable_msite(dev);
454         }
455
456         return 0;
457 }
458
459 static const struct udevice_id imx_tmu_ids[] = {
460         { .compatible = "fsl,imx8mq-tmu", },
461         { .compatible = "fsl,imx8mm-tmu", .data = FLAGS_VER2, },
462         { .compatible = "fsl,imx8mp-tmu", .data = FLAGS_VER3, },
463         { }
464 };
465
466 U_BOOT_DRIVER(imx_tmu) = {
467         .name   = "imx_tmu",
468         .id     = UCLASS_THERMAL,
469         .ops    = &imx_tmu_ops,
470         .of_match = imx_tmu_ids,
471         .bind = imx_tmu_bind,
472         .probe  = imx_tmu_probe,
473         .plat_auto      = sizeof(struct imx_tmu_plat),
474         .flags  = DM_FLAG_PRE_RELOC,
475 };