]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/rockchip/rk_tsadc.c
arm64: rockchip: rk808: Only init regulator not enabled
[FreeBSD/FreeBSD.git] / sys / arm64 / rockchip / rk_tsadc.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 /*
32  * Thermometer and thermal zones driver for RockChip SoCs.
33  * Calibration data are taken from Linux, because this part of SoC
34  * is undocumented in TRM.
35  */
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/bus.h>
40 #include <sys/gpio.h>
41 #include <sys/kernel.h>
42 #include <sys/module.h>
43 #include <sys/malloc.h>
44 #include <sys/rman.h>
45 #include <sys/sysctl.h>
46
47 #include <machine/bus.h>
48
49 #include <dev/extres/clk/clk.h>
50 #include <dev/extres/hwreset/hwreset.h>
51 #include <dev/extres/syscon/syscon.h>
52 #include <dev/ofw/ofw_bus.h>
53 #include <dev/ofw/ofw_bus_subr.h>
54
55 #include "syscon_if.h"
56 #include "rk_tsadc_if.h"
57
58 /* Global registers */
59 #define TSADC_USER_CON                          0x000
60 #define TSADC_AUTO_CON                          0x004
61 #define  TSADC_AUTO_CON_POL_HI                          (1 << 8)
62 #define  TSADC_AUTO_SRC_EN(x)                           (1 << (4 + (x)))
63 #define  TSADC_AUTO_Q_SEL                               (1 << 1) /* V3 only */
64 #define  TSADC_AUTO_CON_AUTO                            (1 << 0)
65
66 #define TSADC_INT_EN                            0x008
67 #define  TSADC_INT_EN_2CRU_EN_SRC(x)                    (1 << (8 + (x)))
68 #define  TSADC_INT_EN_2GPIO_EN_SRC(x)                   (1 << (4 + (x)))
69 #define TSADC_INT_PD                            0x00c
70 #define TSADC_DATA(x)                           (0x20 + (x) * 0x04)
71 #define TSADC_COMP_INT(x)                       (0x30 + (x) * 0x04)
72 #define  TSADC_COMP_INT_SRC_EN(x)                       (1 << (0 + (x)))
73 #define TSADC_COMP_SHUT(x)                      (0x40 + (x) * 0x04)
74 #define TSADC_HIGHT_INT_DEBOUNCE                0x060
75 #define TSADC_HIGHT_TSHUT_DEBOUNCE              0x064
76 #define TSADC_AUTO_PERIOD                       0x068
77 #define TSADC_AUTO_PERIOD_HT                    0x06c
78 #define TSADC_COMP0_LOW_INT                     0x080   /* V3 only */
79 #define TSADC_COMP1_LOW_INT                     0x084   /* V3 only */
80
81 /* GFR Bits */
82 #define GRF_SARADC_TESTBIT                      0x0e644
83 #define  GRF_SARADC_TESTBIT_ON                          (0x10001 << 2)
84 #define GRF_TSADC_TESTBIT_L                     0x0e648
85 #define  GRF_TSADC_VCM_EN_L                             (0x10001 << 7)
86 #define GRF_TSADC_TESTBIT_H                     0x0e64c
87 #define  GRF_TSADC_VCM_EN_H                             (0x10001 << 7)
88 #define  GRF_TSADC_TESTBIT_H_ON                         (0x10001 << 2)
89
90 #define WR4(_sc, _r, _v)        bus_write_4((_sc)->mem_res, (_r), (_v))
91 #define RD4(_sc, _r)            bus_read_4((_sc)->mem_res, (_r))
92
93 static struct sysctl_ctx_list tsadc_sysctl_ctx;
94
95 struct tsensor {
96         char                    *name;
97         int                     id;
98         int                     channel;
99 };
100
101 enum tsadc_type {
102         RK_TSADC_V2,
103         RK_TSADC_V3
104 };
105
106 struct rk_calib_entry {
107         uint32_t        raw;
108         int             temp;
109 };
110
111 struct tsadc_calib_info {
112         bool decrement_mode;
113         struct rk_calib_entry   *table;
114         int                     nentries;
115 };
116
117 struct tsadc_conf {
118         enum tsadc_type         type;
119         int                     shutdown_temp;
120         int                     shutdown_mode;
121         int                     shutdown_pol;
122         struct tsensor          *tsensors;
123         int                     ntsensors;
124         struct tsadc_calib_info calib_info;
125 };
126
127 struct tsadc_softc {
128         device_t                dev;
129         struct resource         *mem_res;
130         struct resource         *irq_res;
131         void                    *irq_ih;
132
133         clk_t                   tsadc_clk;
134         clk_t                   apb_pclk_clk;
135         hwreset_t               hwreset;
136         struct syscon           *grf;
137
138         struct tsadc_conf       *conf;
139
140         int                     shutdown_temp;
141         int                     shutdown_mode;
142         int                     shutdown_pol;
143
144         int                     alarm_temp;
145 };
146
147 static struct rk_calib_entry rk3288_calib_data[] = {
148         {3800, -40000},
149         {3792, -35000},
150         {3783, -30000},
151         {3774, -25000},
152         {3765, -20000},
153         {3756, -15000},
154         {3747, -10000},
155         {3737, -5000},
156         {3728, 0},
157         {3718, 5000},
158         {3708, 10000},
159         {3698, 15000},
160         {3688, 20000},
161         {3678, 25000},
162         {3667, 30000},
163         {3656, 35000},
164         {3645, 40000},
165         {3634, 45000},
166         {3623, 50000},
167         {3611, 55000},
168         {3600, 60000},
169         {3588, 65000},
170         {3575, 70000},
171         {3563, 75000},
172         {3550, 80000},
173         {3537, 85000},
174         {3524, 90000},
175         {3510, 95000},
176         {3496, 100000},
177         {3482, 105000},
178         {3467, 110000},
179         {3452, 115000},
180         {3437, 120000},
181         {3421, 125000},
182 };
183
184 struct tsensor rk3288_tsensors[] = {
185         { .channel = 0, .id = 2, .name = "reserved"},
186         { .channel = 1, .id = 0, .name = "CPU"},
187         { .channel = 2, .id = 1, .name = "GPU"},
188 };
189
190 struct tsadc_conf rk3288_tsadc_conf = {
191         .type =                 RK_TSADC_V2,
192         .shutdown_temp =        95000,
193         .shutdown_mode =        1, /* GPIO */
194         .shutdown_pol =         0, /* Low  */
195         .tsensors =             rk3288_tsensors,
196         .ntsensors =            nitems(rk3288_tsensors),
197         .calib_info =   {
198                         .table = rk3288_calib_data,
199                         .nentries = nitems(rk3288_calib_data),
200         }
201 };
202
203 static struct rk_calib_entry rk3328_calib_data[] = {
204         {296, -40000},
205         {304, -35000},
206         {313, -30000},
207         {331, -20000},
208         {340, -15000},
209         {349, -10000},
210         {359, -5000},
211         {368, 0},
212         {378, 5000},
213         {388, 10000},
214         {398, 15000},
215         {408, 20000},
216         {418, 25000},
217         {429, 30000},
218         {440, 35000},
219         {451, 40000},
220         {462, 45000},
221         {473, 50000},
222         {485, 55000},
223         {496, 60000},
224         {508, 65000},
225         {521, 70000},
226         {533, 75000},
227         {546, 80000},
228         {559, 85000},
229         {572, 90000},
230         {586, 95000},
231         {600, 100000},
232         {614, 105000},
233         {629, 110000},
234         {644, 115000},
235         {659, 120000},
236         {675, 125000},
237 };
238
239 static struct tsensor rk3328_tsensors[] = {
240         { .channel = 0, .id = 0, .name = "CPU"},
241 };
242
243 static struct tsadc_conf rk3328_tsadc_conf = {
244         .type =                 RK_TSADC_V3,
245         .shutdown_temp =        95000,
246         .shutdown_mode =        0, /* CRU */
247         .shutdown_pol =         0, /* Low  */
248         .tsensors =             rk3328_tsensors,
249         .ntsensors =            nitems(rk3328_tsensors),
250         .calib_info =   {
251                         .table = rk3328_calib_data,
252                         .nentries = nitems(rk3328_calib_data),
253         }
254 };
255
256 static struct rk_calib_entry rk3399_calib_data[] = {
257         {402, -40000},
258         {410, -35000},
259         {419, -30000},
260         {427, -25000},
261         {436, -20000},
262         {444, -15000},
263         {453, -10000},
264         {461, -5000},
265         {470, 0},
266         {478, 5000},
267         {487, 10000},
268         {496, 15000},
269         {504, 20000},
270         {513, 25000},
271         {521, 30000},
272         {530, 35000},
273         {538, 40000},
274         {547, 45000},
275         {555, 50000},
276         {564, 55000},
277         {573, 60000},
278         {581, 65000},
279         {590, 70000},
280         {599, 75000},
281         {607, 80000},
282         {616, 85000},
283         {624, 90000},
284         {633, 95000},
285         {642, 100000},
286         {650, 105000},
287         {659, 110000},
288         {668, 115000},
289         {677, 120000},
290         {685, 125000},
291 };
292
293 static struct tsensor rk3399_tsensors[] = {
294         { .channel = 0, .id = 0, .name = "CPU"},
295         { .channel = 1, .id = 1, .name = "GPU"},
296 };
297
298 static struct tsadc_conf rk3399_tsadc_conf = {
299         .type =                 RK_TSADC_V3,
300         .shutdown_temp =        95000,
301         .shutdown_mode =        1, /* GPIO */
302         .shutdown_pol =         0, /* Low  */
303         .tsensors =             rk3399_tsensors,
304         .ntsensors =            nitems(rk3399_tsensors),
305         .calib_info =   {
306                         .table = rk3399_calib_data,
307                         .nentries = nitems(rk3399_calib_data),
308         }
309 };
310
311 static struct ofw_compat_data compat_data[] = {
312         {"rockchip,rk3288-tsadc",       (uintptr_t)&rk3288_tsadc_conf},
313         {"rockchip,rk3328-tsadc",       (uintptr_t)&rk3328_tsadc_conf},
314         {"rockchip,rk3399-tsadc",       (uintptr_t)&rk3399_tsadc_conf},
315         {NULL,          0}
316 };
317
318 static uint32_t
319 tsadc_temp_to_raw(struct tsadc_softc *sc, int temp)
320 {
321         struct rk_calib_entry *tbl;
322         int denom, ntbl, raw, i;
323
324         tbl = sc->conf->calib_info.table;
325         ntbl = sc->conf->calib_info.nentries;
326
327         if (temp <= tbl[0].temp)
328                 return (tbl[0].raw);
329
330         if (temp >= tbl[ntbl - 1].temp)
331                 return (tbl[ntbl - 1].raw);
332
333         for (i = 1; i < (ntbl - 1); i++) {
334                 /* Exact match */
335                 if (temp == tbl[i].temp)
336                         return (tbl[i].raw);
337                 if (temp < tbl[i].temp)
338                         break;
339         }
340
341         /*
342         * Translated value is between i and i - 1 table entries.
343         * Do linear interpolation for it.
344         */
345         raw = (int)tbl[i - 1].raw - (int)tbl[i].raw;
346         raw *= temp - tbl[i - 1].temp;
347         denom = tbl[i - 1].temp - tbl[i].temp;
348         raw = tbl[i - 1].raw + raw / denom;
349         return (raw);
350 }
351
352 static int
353 tsadc_raw_to_temp(struct tsadc_softc *sc, uint32_t raw)
354 {
355         struct rk_calib_entry *tbl;
356         int denom, ntbl, temp, i;
357         bool descending;
358
359         tbl = sc->conf->calib_info.table;
360         ntbl = sc->conf->calib_info.nentries;
361         descending = tbl[0].raw > tbl[1].raw;
362
363         if (descending) {
364                 /* Raw column is in descending order. */
365                 if (raw >= tbl[0].raw)
366                         return (tbl[0].temp);
367                 if (raw <= tbl[ntbl - 1].raw)
368                         return (tbl[ntbl - 1].temp);
369
370                 for (i = ntbl - 2; i > 0; i--) {
371                         /* Exact match */
372                         if (raw == tbl[i].raw)
373                                 return (tbl[i].temp);
374                         if (raw < tbl[i].raw)
375                                 break;
376                 }
377         } else {
378                 /* Raw column is in ascending order. */
379                 if (raw <= tbl[0].raw)
380                         return (tbl[0].temp);
381                 if (raw >= tbl[ntbl - 1].raw)
382                         return (tbl[ntbl - 1].temp);
383                 for (i = 1; i < (ntbl - 1); i++) {
384                         /* Exact match */
385                         if (raw == tbl[i].raw)
386                                 return (tbl[i].temp);
387                         if (raw < tbl[i].raw)
388                                 break;
389                 }
390         }
391
392
393         /*
394         * Translated value is between i and i - 1 table entries.
395         * Do linear interpolation for it.
396         */
397         temp  = (int)tbl[i - 1].temp - (int)tbl[i].temp;
398         temp *= raw - tbl[i - 1].raw;
399         denom = tbl[i - 1].raw - tbl[i].raw;
400         temp = tbl[i - 1].temp + temp / denom;
401         return (temp);
402 }
403
404 static void
405 tsadc_init_tsensor(struct tsadc_softc *sc, struct tsensor *sensor)
406 {
407         uint32_t val;
408
409         /* Shutdown mode */
410         val = RD4(sc, TSADC_INT_EN);
411         if (sc->shutdown_mode != 0) {
412                 /* Signal shutdown of GPIO pin */
413                 val &= ~TSADC_INT_EN_2CRU_EN_SRC(sensor->channel);
414                 val |= TSADC_INT_EN_2GPIO_EN_SRC(sensor->channel);
415         } else {
416                 val |= TSADC_INT_EN_2CRU_EN_SRC(sensor->channel);
417                 val &= ~TSADC_INT_EN_2GPIO_EN_SRC(sensor->channel);
418         }
419         WR4(sc, TSADC_INT_EN, val);
420
421         /* Shutdown temperature */
422         val =  tsadc_raw_to_temp(sc, sc->shutdown_temp);
423         WR4(sc, TSADC_COMP_SHUT(sensor->channel), val);
424         val = RD4(sc, TSADC_AUTO_CON);
425         val |= TSADC_AUTO_SRC_EN(sensor->channel);
426         WR4(sc, TSADC_AUTO_CON, val);
427
428         /* Alarm temperature */
429         val =  tsadc_temp_to_raw(sc, sc->alarm_temp);
430         WR4(sc, TSADC_COMP_INT(sensor->channel), val);
431         val = RD4(sc, TSADC_INT_EN);
432         val |= TSADC_COMP_INT_SRC_EN(sensor->channel);
433         WR4(sc, TSADC_INT_EN, val);
434 }
435
436 static void
437 tsadc_init(struct tsadc_softc *sc)
438 {
439         uint32_t val;
440
441         /* Common part */
442         val = 0;        /* XXX Is this right? */
443         if (sc->shutdown_pol != 0)
444                 val |= TSADC_AUTO_CON_POL_HI;
445         else
446                 val &= ~TSADC_AUTO_CON_POL_HI;
447         if (sc->conf->type == RK_TSADC_V3)
448                 val |= TSADC_AUTO_Q_SEL;
449         WR4(sc, TSADC_AUTO_CON, val);
450
451         if (sc->conf->type == RK_TSADC_V2) {
452                 /* V2 init */
453                 WR4(sc, TSADC_AUTO_PERIOD, 250);        /* 250 ms */
454                 WR4(sc, TSADC_AUTO_PERIOD_HT, 50);      /*  50 ms */
455                 WR4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
456                 WR4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
457         } else {
458                 /* V3 init */
459                 if (sc->grf == NULL) {
460                         /* Errata: adjust interleave to working value */
461                         WR4(sc, TSADC_USER_CON, 13 << 6);       /* 13 clks */
462                 } else {
463                         SYSCON_WRITE_4(sc->grf, GRF_TSADC_TESTBIT_L,
464                             GRF_TSADC_VCM_EN_L);
465                         SYSCON_WRITE_4(sc->grf, GRF_TSADC_TESTBIT_H,
466                             GRF_TSADC_VCM_EN_H);
467                         DELAY(30);  /* 15 usec min */
468
469                         SYSCON_WRITE_4(sc->grf, GRF_SARADC_TESTBIT,
470                             GRF_SARADC_TESTBIT_ON);
471                         SYSCON_WRITE_4(sc->grf, GRF_TSADC_TESTBIT_H,
472                             GRF_TSADC_TESTBIT_H_ON);
473                         DELAY(180);  /* 90 usec min */
474                 }
475                 WR4(sc, TSADC_AUTO_PERIOD, 1875);       /* 2.5 ms */
476                 WR4(sc, TSADC_AUTO_PERIOD_HT, 1875);    /* 2.5 ms */
477                 WR4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
478                 WR4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
479         }
480 }
481
482 static int
483 tsadc_read_temp(struct tsadc_softc *sc, struct tsensor *sensor, int *temp)
484 {
485         uint32_t val;
486
487         val = RD4(sc, TSADC_DATA(sensor->channel));
488         *temp = tsadc_raw_to_temp(sc, val);
489
490 #ifdef DEBUG
491         printf("%s: Sensor(id: %d, ch: %d), temp: %d\n", __func__,
492             sensor->id, sensor->channel, *temp);
493         printf(" status: 0x%08X, 0x%08X\n",
494             RD4(sc, TSADC_USER_CON),
495             RD4(sc, TSADC_AUTO_CON));
496         printf(" Data: 0x%08X, 0x%08X, 0x%08X\n",
497             RD4(sc, TSADC_DATA(sensor->channel)),
498             RD4(sc, TSADC_COMP_INT(sensor->channel)),
499             RD4(sc, TSADC_COMP_SHUT(sensor->channel)));
500 #endif
501         return (0);
502 }
503
504 static int
505 tsadc_get_temp(device_t dev, device_t cdev, uintptr_t id, int *val)
506 {
507         struct tsadc_softc *sc;
508         int i, rv;
509
510         sc = device_get_softc(dev);
511
512         if (id >= sc->conf->ntsensors)
513                 return (ERANGE);
514
515         for (i = 0; i < sc->conf->ntsensors; i++) {
516                 if (sc->conf->tsensors->id == id) {
517                         rv =tsadc_read_temp(sc, sc->conf->tsensors + id, val);
518                         return (rv);
519                 }
520         }
521         return (ERANGE);
522 }
523
524 static int
525 tsadc_sysctl_temperature(SYSCTL_HANDLER_ARGS)
526 {
527         struct tsadc_softc *sc;
528         int val;
529         int rv;
530         int id;
531
532         /* Write request */
533         if (req->newptr != NULL)
534                 return (EINVAL);
535
536         sc = arg1;
537         id = arg2;
538
539         if (id >= sc->conf->ntsensors)
540                 return (ERANGE);
541         rv =  tsadc_read_temp(sc, sc->conf->tsensors + id, &val);
542         if (rv != 0)
543                 return (rv);
544
545         val = val / 100;
546         val +=  2731;
547         rv = sysctl_handle_int(oidp, &val, 0, req);
548         return (rv);
549 }
550
551 static int
552 tsadc_init_sysctl(struct tsadc_softc *sc)
553 {
554         int i;
555         struct sysctl_oid *oid, *tmp;
556
557         sysctl_ctx_init(&tsadc_sysctl_ctx);
558         /* create node for hw.temp */
559         oid = SYSCTL_ADD_NODE(&tsadc_sysctl_ctx,
560             SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "temperature",
561             CTLFLAG_RD, NULL, "");
562         if (oid == NULL)
563                 return (ENXIO);
564
565         /* Add sensors */
566         for (i = sc->conf->ntsensors  - 1; i >= 0; i--) {
567                 tmp = SYSCTL_ADD_PROC(&tsadc_sysctl_ctx,
568                     SYSCTL_CHILDREN(oid), OID_AUTO, sc->conf->tsensors[i].name,
569                     CTLTYPE_INT | CTLFLAG_RD, sc, i,
570                     tsadc_sysctl_temperature, "IK", "SoC Temperature");
571                 if (tmp == NULL)
572                         return (ENXIO);
573         }
574
575         return (0);
576 }
577
578 static int
579 tsadc_intr(void *arg)
580 {
581         struct tsadc_softc *sc;
582         uint32_t val;
583
584         sc = (struct tsadc_softc *)arg;
585
586         val = RD4(sc, TSADC_INT_PD);
587         WR4(sc, TSADC_INT_PD, val);
588
589         /* XXX Handle shutdown and alarm interrupts. */
590         if (val & 0x00F0) {
591                 device_printf(sc->dev, "Alarm: device temperature "
592                     "is above of shutdown level.\n");
593         } else if (val & 0x000F) {
594                 device_printf(sc->dev, "Alarm: device temperature "
595                     "is above of alarm level.\n");
596         }
597         return (FILTER_HANDLED);
598 }
599
600 static int
601 tsadc_probe(device_t dev)
602 {
603
604         if (!ofw_bus_status_okay(dev))
605                 return (ENXIO);
606
607         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
608                 return (ENXIO);
609
610         device_set_desc(dev, "RockChip temperature sensors");
611         return (BUS_PROBE_DEFAULT);
612 }
613
614 static int
615 tsadc_attach(device_t dev)
616 {
617         struct tsadc_softc *sc;
618         phandle_t node;
619         uint32_t val;
620         int i, rid, rv;
621
622         sc = device_get_softc(dev);
623         sc->dev = dev;
624         node = ofw_bus_get_node(sc->dev);
625         sc->conf = (struct tsadc_conf *)
626             ofw_bus_search_compatible(dev, compat_data)->ocd_data;
627         sc->alarm_temp = 90000;
628
629         rid = 0;
630         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
631             RF_ACTIVE);
632         if (sc->mem_res == NULL) {
633                 device_printf(dev, "Cannot allocate memory resources\n");
634                 goto fail;
635         }
636
637         rid = 0;
638         sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
639         if (sc->irq_res == NULL) {
640                 device_printf(dev, "Cannot allocate IRQ resources\n");
641                 goto fail;
642         }
643
644         if ((bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
645             tsadc_intr, NULL, sc, &sc->irq_ih))) {
646                 device_printf(dev,
647                     "WARNING: unable to register interrupt handler\n");
648                 goto fail;
649         }
650
651         /* FDT resources */
652         rv = hwreset_get_by_ofw_name(dev, 0, "tsadc-apb", &sc->hwreset);
653         if (rv != 0) {
654                 device_printf(dev, "Cannot get 'tsadc-apb' reset\n");
655                 goto fail;
656         }
657         rv = clk_get_by_ofw_name(dev, 0, "tsadc", &sc->tsadc_clk);
658         if (rv != 0) {
659                 device_printf(dev, "Cannot get 'tsadc' clock: %d\n", rv);
660                 goto fail;
661         }
662         rv = clk_get_by_ofw_name(dev, 0, "apb_pclk", &sc->apb_pclk_clk);
663         if (rv != 0) {
664                 device_printf(dev, "Cannot get 'apb_pclk' clock: %d\n", rv);
665                 goto fail;
666         }
667
668         /* grf is optional */
669         rv = syscon_get_by_ofw_property(dev, node, "rockchip,grf", &sc->grf);
670         if (rv != 0 && rv != ENOENT) {
671                 device_printf(dev, "Cannot get 'grf' syscon: %d\n", rv);
672                 goto fail;
673         }
674
675         rv = OF_getencprop(node, "rockchip,hw-tshut-temp",
676             &sc->shutdown_temp, sizeof(sc->shutdown_temp));
677         if (rv <= 0)
678                 sc->shutdown_temp = sc->conf->shutdown_temp;
679
680         rv = OF_getencprop(node, "rockchip,hw-tshut-mode",
681             &sc->shutdown_mode, sizeof(sc->shutdown_mode));
682         if (rv <= 0)
683                 sc->shutdown_mode = sc->conf->shutdown_mode;
684
685         rv = OF_getencprop(node, "rockchip,hw-tshut-polarity",
686             &sc->shutdown_pol, sizeof(sc->shutdown_pol));
687         if (rv <= 0)
688                 sc->shutdown_pol = sc->conf->shutdown_pol;
689
690         /* Wakeup controller */
691         rv = hwreset_assert(sc->hwreset);
692         if (rv != 0) {
693                 device_printf(dev, "Cannot assert reset\n");
694                 goto fail;
695         }
696
697         /* Set the assigned clocks parent and freq */
698         if (clk_set_assigned(sc->dev, node) != 0) {
699                 device_printf(dev, "clk_set_assigned failed\n");
700                 goto fail;
701         }
702
703         rv = clk_enable(sc->tsadc_clk);
704         if (rv != 0) {
705                 device_printf(dev, "Cannot enable 'tsadc_clk' clock: %d\n", rv);
706                 goto fail;
707         }
708         rv = clk_enable(sc->apb_pclk_clk);
709         if (rv != 0) {
710                 device_printf(dev, "Cannot enable 'apb_pclk' clock: %d\n", rv);
711                 goto fail;
712         }
713         rv = hwreset_deassert(sc->hwreset);
714         if (rv != 0) {
715                 device_printf(dev, "Cannot deassert reset\n");
716                 goto fail;
717         }
718
719         tsadc_init(sc);
720         for (i = 0; i < sc->conf->ntsensors; i++)
721                 tsadc_init_tsensor(sc, sc->conf->tsensors + i);
722
723         /* Enable auto mode */
724         val = RD4(sc, TSADC_AUTO_CON);
725         val |= TSADC_AUTO_CON_AUTO;
726         WR4(sc, TSADC_AUTO_CON, val);
727
728         rv = tsadc_init_sysctl(sc);
729         if (rv != 0) {
730                 device_printf(sc->dev, "Cannot initialize sysctls\n");
731                 goto fail_sysctl;
732         }
733
734         OF_device_register_xref(OF_xref_from_node(node), dev);
735         return (bus_generic_attach(dev));
736
737 fail_sysctl:
738         sysctl_ctx_free(&tsadc_sysctl_ctx);
739 fail:
740         if (sc->irq_ih != NULL)
741                 bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
742         if (sc->tsadc_clk != NULL)
743                 clk_release(sc->tsadc_clk);
744         if (sc->apb_pclk_clk != NULL)
745                 clk_release(sc->apb_pclk_clk);
746         if (sc->hwreset != NULL)
747                 hwreset_release(sc->hwreset);
748         if (sc->irq_res != NULL)
749                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
750         if (sc->mem_res != NULL)
751                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
752
753         return (ENXIO);
754 }
755
756 static int
757 tsadc_detach(device_t dev)
758 {
759         struct tsadc_softc *sc;
760         sc = device_get_softc(dev);
761
762         if (sc->irq_ih != NULL)
763                 bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
764         sysctl_ctx_free(&tsadc_sysctl_ctx);
765         if (sc->tsadc_clk != NULL)
766                 clk_release(sc->tsadc_clk);
767         if (sc->apb_pclk_clk != NULL)
768                 clk_release(sc->apb_pclk_clk);
769         if (sc->hwreset != NULL)
770                 hwreset_release(sc->hwreset);
771         if (sc->irq_res != NULL)
772                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
773         if (sc->mem_res != NULL)
774                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
775
776         return (ENXIO);
777 }
778
779 static device_method_t rk_tsadc_methods[] = {
780         /* Device interface */
781         DEVMETHOD(device_probe,                 tsadc_probe),
782         DEVMETHOD(device_attach,                tsadc_attach),
783         DEVMETHOD(device_detach,                tsadc_detach),
784
785         /* TSADC interface */
786         DEVMETHOD(rk_tsadc_get_temperature,     tsadc_get_temp),
787
788         DEVMETHOD_END
789 };
790
791 static devclass_t rk_tsadc_devclass;
792 static DEFINE_CLASS_0(rk_tsadc, rk_tsadc_driver, rk_tsadc_methods,
793     sizeof(struct tsadc_softc));
794 EARLY_DRIVER_MODULE(rk_tsadc, simplebus, rk_tsadc_driver,
795     rk_tsadc_devclass, NULL, NULL, BUS_PASS_TIMER + BUS_PASS_ORDER_LAST);