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