xref: /freebsd/sys/arm64/rockchip/rk_tsadc.c (revision ba3c1f5972d7b90feb6e6da47905ff2757e0fe57)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
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 /* Version of HW */
59 #define	TSADC_V2				1
60 #define	TSADC_V3				2
61 #define	TSADC_V7				3
62 
63 /* Global registers */
64 #define	TSADC_USER_CON				0x000
65 #define	TSADC_AUTO_CON				0x004
66 #define	 TSADC_AUTO_CON_POL_HI				(1 << 8)
67 #define	 TSADC_AUTO_SRC_EN(x)				(1 << (4 + (x)))
68 #define	 TSADC_AUTO_Q_SEL				(1 << 1) /* V3 only */
69 #define	 TSADC_AUTO_CON_AUTO				(1 << 0)
70 
71 #define	TSADC_INT_EN				0x008
72 #define	 TSADC_INT_EN_2CRU_EN_SRC(x)			(1 << (8 + (x)))
73 #define	 TSADC_INT_EN_2GPIO_EN_SRC(x)			(1 << (4 + (x)))
74 #define	TSADC_INT_PD				0x00c
75 #define	TSADC_DATA(x)				(0x20 + (x) * 0x04)
76 #define	TSADC_COMP_INT(x)			(0x30 + (x) * 0x04)
77 #define	 TSADC_COMP_INT_SRC_EN(x)			(1 << (0 + (x)))
78 #define	TSADC_COMP_SHUT(x)			(0x40 + (x) * 0x04)
79 #define	TSADC_HIGHT_INT_DEBOUNCE		0x060
80 #define	TSADC_HIGHT_TSHUT_DEBOUNCE		0x064
81 #define	TSADC_AUTO_PERIOD			0x068
82 #define	TSADC_AUTO_PERIOD_HT			0x06c
83 #define	TSADC_COMP0_LOW_INT			0x080	/* V3 only */
84 #define	TSADC_COMP1_LOW_INT			0x084	/* V3 only */
85 
86 /* V3 GFR registers */
87 #define	GRF_SARADC_TESTBIT			0x0e644
88 #define	 GRF_SARADC_TESTBIT_ON				(0x10001 << 2)
89 #define GRF_TSADC_TESTBIT_L			0x0e648
90 #define	 GRF_TSADC_VCM_EN_L				(0x10001 << 7)
91 #define	GRF_TSADC_TESTBIT_H			0x0e64c
92 #define	 GRF_TSADC_VCM_EN_H				(0x10001 << 7)
93 #define	 GRF_TSADC_TESTBIT_H_ON				(0x10001 << 2)
94 
95 /* V7 GRF register */
96 #define	GRF_TSADC_CON				0x0600
97 #define	 GRF_TSADC_ANA_REG0			(0x10001 << 0)
98 #define	 GRF_TSADC_ANA_REG1			(0x10001 << 1)
99 #define	 GRF_TSADC_ANA_REG2			(0x10001 << 2)
100 #define	 GRF_TSADC_TSEN				(0x10001 << 8)
101 
102 #define	WR4(_sc, _r, _v)	bus_write_4((_sc)->mem_res, (_r), (_v))
103 #define	RD4(_sc, _r)		bus_read_4((_sc)->mem_res, (_r))
104 
105 static struct sysctl_ctx_list tsadc_sysctl_ctx;
106 
107 struct tsensor {
108 	char 			*name;
109 	int			id;
110 	int			channel;
111 };
112 
113 struct rk_calib_entry {
114 	uint32_t	raw;
115 	int		temp;
116 };
117 
118 struct tsadc_calib_info {
119 	struct rk_calib_entry	*table;
120 	int			nentries;
121 };
122 
123 struct tsadc_conf {
124 	int			version;
125 	int			q_sel_ntc;
126 	int			shutdown_temp;
127 	int			shutdown_mode;
128 	int			shutdown_pol;
129 	struct tsensor		*tsensors;
130 	int			ntsensors;
131 	struct tsadc_calib_info	calib_info;
132 };
133 
134 struct tsadc_softc {
135 	device_t		dev;
136 	struct resource		*mem_res;
137 	struct resource		*irq_res;
138 	void			*irq_ih;
139 
140 	clk_t			tsadc_clk;
141 	clk_t			apb_pclk_clk;
142 	hwreset_array_t		hwreset;
143 	struct syscon		*grf;
144 
145 	struct tsadc_conf	*conf;
146 
147 	int			shutdown_temp;
148 	int			shutdown_mode;
149 	int			shutdown_pol;
150 
151 	int			alarm_temp;
152 };
153 
154 static struct rk_calib_entry rk3288_calib_data[] = {
155 	{3800, -40000},
156 	{3792, -35000},
157 	{3783, -30000},
158 	{3774, -25000},
159 	{3765, -20000},
160 	{3756, -15000},
161 	{3747, -10000},
162 	{3737, -5000},
163 	{3728, 0},
164 	{3718, 5000},
165 	{3708, 10000},
166 	{3698, 15000},
167 	{3688, 20000},
168 	{3678, 25000},
169 	{3667, 30000},
170 	{3656, 35000},
171 	{3645, 40000},
172 	{3634, 45000},
173 	{3623, 50000},
174 	{3611, 55000},
175 	{3600, 60000},
176 	{3588, 65000},
177 	{3575, 70000},
178 	{3563, 75000},
179 	{3550, 80000},
180 	{3537, 85000},
181 	{3524, 90000},
182 	{3510, 95000},
183 	{3496, 100000},
184 	{3482, 105000},
185 	{3467, 110000},
186 	{3452, 115000},
187 	{3437, 120000},
188 	{3421, 125000},
189 };
190 
191 struct tsensor rk3288_tsensors[] = {
192 	{ .channel = 0, .id = 2, .name = "reserved"},
193 	{ .channel = 1, .id = 0, .name = "CPU"},
194 	{ .channel = 2, .id = 1, .name = "GPU"},
195 };
196 
197 struct tsadc_conf rk3288_tsadc_conf = {
198 	.version =		TSADC_V2,
199 	.q_sel_ntc =		0,
200 	.shutdown_temp =	95000,
201 	.shutdown_mode =	1, /* GPIO */
202 	.shutdown_pol =		0, /* Low  */
203 	.tsensors = 		rk3288_tsensors,
204 	.ntsensors = 		nitems(rk3288_tsensors),
205 	.calib_info = 	{
206 			.table = rk3288_calib_data,
207 			.nentries = nitems(rk3288_calib_data),
208 	}
209 };
210 
211 static struct rk_calib_entry rk3328_calib_data[] = {
212 	{296, -40000},
213 	{304, -35000},
214 	{313, -30000},
215 	{331, -20000},
216 	{340, -15000},
217 	{349, -10000},
218 	{359, -5000},
219 	{368, 0},
220 	{378, 5000},
221 	{388, 10000},
222 	{398, 15000},
223 	{408, 20000},
224 	{418, 25000},
225 	{429, 30000},
226 	{440, 35000},
227 	{451, 40000},
228 	{462, 45000},
229 	{473, 50000},
230 	{485, 55000},
231 	{496, 60000},
232 	{508, 65000},
233 	{521, 70000},
234 	{533, 75000},
235 	{546, 80000},
236 	{559, 85000},
237 	{572, 90000},
238 	{586, 95000},
239 	{600, 100000},
240 	{614, 105000},
241 	{629, 110000},
242 	{644, 115000},
243 	{659, 120000},
244 	{675, 125000},
245 };
246 
247 static struct tsensor rk3328_tsensors[] = {
248 	{ .channel = 0, .id = 0, .name = "CPU"},
249 };
250 
251 static struct tsadc_conf rk3328_tsadc_conf = {
252 	.version =		TSADC_V2,
253 	.q_sel_ntc =		1,
254 	.shutdown_temp =	95000,
255 	.shutdown_mode =	0, /* CRU */
256 	.shutdown_pol =		0, /* Low  */
257 	.tsensors = 		rk3328_tsensors,
258 	.ntsensors = 		nitems(rk3328_tsensors),
259 	.calib_info = 	{
260 			.table = rk3328_calib_data,
261 			.nentries = nitems(rk3328_calib_data),
262 	}
263 };
264 
265 static struct rk_calib_entry rk3399_calib_data[] = {
266 	{402, -40000},
267 	{410, -35000},
268 	{419, -30000},
269 	{427, -25000},
270 	{436, -20000},
271 	{444, -15000},
272 	{453, -10000},
273 	{461, -5000},
274 	{470, 0},
275 	{478, 5000},
276 	{487, 10000},
277 	{496, 15000},
278 	{504, 20000},
279 	{513, 25000},
280 	{521, 30000},
281 	{530, 35000},
282 	{538, 40000},
283 	{547, 45000},
284 	{555, 50000},
285 	{564, 55000},
286 	{573, 60000},
287 	{581, 65000},
288 	{590, 70000},
289 	{599, 75000},
290 	{607, 80000},
291 	{616, 85000},
292 	{624, 90000},
293 	{633, 95000},
294 	{642, 100000},
295 	{650, 105000},
296 	{659, 110000},
297 	{668, 115000},
298 	{677, 120000},
299 	{685, 125000},
300 };
301 
302 static struct tsensor rk3399_tsensors[] = {
303 	{ .channel = 0, .id = 0, .name = "CPU"},
304 	{ .channel = 1, .id = 1, .name = "GPU"},
305 };
306 
307 static struct tsadc_conf rk3399_tsadc_conf = {
308 	.version =		TSADC_V3,
309 	.q_sel_ntc =		1,
310 	.shutdown_temp =	95000,
311 	.shutdown_mode =	1, /* GPIO */
312 	.shutdown_pol =		0, /* Low  */
313 	.tsensors = 		rk3399_tsensors,
314 	.ntsensors = 		nitems(rk3399_tsensors),
315 	.calib_info = 	{
316 			.table = rk3399_calib_data,
317 			.nentries = nitems(rk3399_calib_data),
318 	}
319 };
320 
321 static struct rk_calib_entry rk3568_calib_data[] = {
322 	{0, -40000},
323 	{1584, -40000},
324 	{1620, -35000},
325 	{1652, -30000},
326 	{1688, -25000},
327 	{1720, -20000},
328 	{1756, -15000},
329 	{1788, -10000},
330 	{1824, -5000},
331 	{1856, 0},
332 	{1892, 5000},
333 	{1924, 10000},
334 	{1956, 15000},
335 	{1992, 20000},
336 	{2024, 25000},
337 	{2060, 30000},
338 	{2092, 35000},
339 	{2128, 40000},
340 	{2160, 45000},
341 	{2196, 50000},
342 	{2228, 55000},
343 	{2264, 60000},
344 	{2300, 65000},
345 	{2332, 70000},
346 	{2368, 75000},
347 	{2400, 80000},
348 	{2436, 85000},
349 	{2468, 90000},
350 	{2500, 95000},
351 	{2536, 100000},
352 	{2572, 105000},
353 	{2604, 110000},
354 	{2636, 115000},
355 	{2672, 120000},
356 	{2704, 125000},
357 };
358 
359 static struct tsensor rk3568_tsensors[] = {
360 	{ .channel = 0, .id = 0, .name = "CPU"},
361 	{ .channel = 1, .id = 1, .name = "GPU"},
362 };
363 
364 static struct tsadc_conf rk3568_tsadc_conf = {
365 	.version =		TSADC_V7,
366 	.q_sel_ntc =		1,
367 	.shutdown_temp =        95000,
368 	.shutdown_mode =	1, /* GPIO */
369 	.shutdown_pol =		0, /* Low  */
370 	.tsensors =		rk3568_tsensors,
371 	.ntsensors =		nitems(rk3568_tsensors),
372 	.calib_info =	{
373 			.table = rk3568_calib_data,
374 			.nentries = nitems(rk3568_calib_data),
375 	}
376 };
377 
378 static struct ofw_compat_data compat_data[] = {
379 	{"rockchip,rk3288-tsadc",	(uintptr_t)&rk3288_tsadc_conf},
380 	{"rockchip,rk3328-tsadc",	(uintptr_t)&rk3328_tsadc_conf},
381 	{"rockchip,rk3399-tsadc",	(uintptr_t)&rk3399_tsadc_conf},
382 	{"rockchip,rk3568-tsadc",	(uintptr_t)&rk3568_tsadc_conf},
383 	{NULL,		0}
384 };
385 
386 static uint32_t
387 tsadc_temp_to_raw(struct tsadc_softc *sc, int temp)
388 {
389 	struct rk_calib_entry *tbl;
390 	int denom, ntbl, raw, i;
391 
392 	tbl = sc->conf->calib_info.table;
393 	ntbl = sc->conf->calib_info.nentries;
394 
395 	if (temp <= tbl[0].temp)
396 		return (tbl[0].raw);
397 
398 	if (temp >= tbl[ntbl - 1].temp)
399 		return (tbl[ntbl - 1].raw);
400 
401 	for (i = 1; i < (ntbl - 1); i++) {
402 		/* Exact match */
403 		if (temp == tbl[i].temp)
404 			return (tbl[i].raw);
405 		if (temp < tbl[i].temp)
406 			break;
407 	}
408 
409 	/*
410 	* Translated value is between i and i - 1 table entries.
411 	* Do linear interpolation for it.
412 	*/
413 	raw = (int)tbl[i - 1].raw - (int)tbl[i].raw;
414 	raw *= temp - tbl[i - 1].temp;
415 	denom = tbl[i - 1].temp - tbl[i].temp;
416 	raw = tbl[i - 1].raw + raw / denom;
417 	return (raw);
418 }
419 
420 static int
421 tsadc_raw_to_temp(struct tsadc_softc *sc, uint32_t raw)
422 {
423 	struct rk_calib_entry *tbl;
424 	int denom, ntbl, temp, i;
425 	bool descending;
426 
427 	tbl = sc->conf->calib_info.table;
428 	ntbl = sc->conf->calib_info.nentries;
429 	descending = tbl[0].raw > tbl[1].raw;
430 
431 	if (descending) {
432 		/* Raw column is in descending order. */
433 		if (raw >= tbl[0].raw)
434 			return (tbl[0].temp);
435 		if (raw <= tbl[ntbl - 1].raw)
436 			return (tbl[ntbl - 1].temp);
437 
438 		for (i = ntbl - 2; i > 0; i--) {
439 			/* Exact match */
440 			if (raw == tbl[i].raw)
441 				return (tbl[i].temp);
442 			if (raw < tbl[i].raw)
443 				break;
444 		}
445 	} else {
446 		/* Raw column is in ascending order. */
447 		if (raw <= tbl[0].raw)
448 			return (tbl[0].temp);
449 		if (raw >= tbl[ntbl - 1].raw)
450 			return (tbl[ntbl - 1].temp);
451 		for (i = 1; i < (ntbl - 1); i++) {
452 			/* Exact match */
453 			if (raw == tbl[i].raw)
454 				return (tbl[i].temp);
455 			if (raw < tbl[i].raw)
456 				break;
457 		}
458 	}
459 
460 	/*
461 	* Translated value is between i and i - 1 table entries.
462 	* Do linear interpolation for it.
463 	*/
464 	temp  = (int)tbl[i - 1].temp - (int)tbl[i].temp;
465 	temp *= raw - tbl[i - 1].raw;
466 	denom = tbl[i - 1].raw - tbl[i].raw;
467 	temp = tbl[i - 1].temp + temp / denom;
468 	return (temp);
469 }
470 
471 static void
472 tsadc_init_tsensor(struct tsadc_softc *sc, struct tsensor *sensor)
473 {
474 	uint32_t val;
475 
476 	/* Shutdown mode */
477 	val = RD4(sc, TSADC_INT_EN);
478 	if (sc->shutdown_mode != 0) {
479 		/* Signal shutdown of GPIO pin */
480 		val &= ~TSADC_INT_EN_2CRU_EN_SRC(sensor->channel);
481 		val |= TSADC_INT_EN_2GPIO_EN_SRC(sensor->channel);
482 	} else {
483 		val |= TSADC_INT_EN_2CRU_EN_SRC(sensor->channel);
484 		val &= ~TSADC_INT_EN_2GPIO_EN_SRC(sensor->channel);
485 	}
486 	WR4(sc, TSADC_INT_EN, val);
487 
488 	/* Shutdown temperature */
489 	val =  tsadc_raw_to_temp(sc, sc->shutdown_temp);
490 	WR4(sc, TSADC_COMP_SHUT(sensor->channel), val);
491 	val = RD4(sc, TSADC_AUTO_CON);
492 	val |= TSADC_AUTO_SRC_EN(sensor->channel);
493 	WR4(sc, TSADC_AUTO_CON, val);
494 
495 	/* Alarm temperature */
496 	val =  tsadc_temp_to_raw(sc, sc->alarm_temp);
497 	WR4(sc, TSADC_COMP_INT(sensor->channel), val);
498 	val = RD4(sc, TSADC_INT_EN);
499 	val |= TSADC_COMP_INT_SRC_EN(sensor->channel);
500 	WR4(sc, TSADC_INT_EN, val);
501 }
502 
503 static void
504 tsadc_init(struct tsadc_softc *sc)
505 {
506 	uint32_t val;
507 
508 	/* Common part */
509 	val = 0;	/* XXX Is this right? */
510 	if (sc->shutdown_pol != 0)
511 		val |= TSADC_AUTO_CON_POL_HI;
512 	else
513 		val &= ~TSADC_AUTO_CON_POL_HI;
514 	if (sc->conf->q_sel_ntc)
515 		val |= TSADC_AUTO_Q_SEL;
516 	WR4(sc, TSADC_AUTO_CON, val);
517 
518 	switch (sc->conf->version) {
519 	case TSADC_V2:
520 		/* V2 init */
521 		WR4(sc, TSADC_AUTO_PERIOD, 250); 	/* 250 ms */
522 		WR4(sc, TSADC_AUTO_PERIOD_HT, 50);	/*  50 ms */
523 		WR4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
524 		WR4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
525 		break;
526 	case TSADC_V3:
527 		/* V3 init */
528 		if (sc->grf == NULL) {
529 			/* Errata: adjust interleave to working value */
530 			WR4(sc, TSADC_USER_CON, 13 << 6); 	/* 13 clks */
531 		} else {
532 			SYSCON_WRITE_4(sc->grf, GRF_TSADC_TESTBIT_L,
533 			    GRF_TSADC_VCM_EN_L);
534 			SYSCON_WRITE_4(sc->grf, GRF_TSADC_TESTBIT_H,
535 			    GRF_TSADC_VCM_EN_H);
536 			DELAY(30);  /* 15 usec min */
537 
538 			SYSCON_WRITE_4(sc->grf, GRF_SARADC_TESTBIT,
539 			    GRF_SARADC_TESTBIT_ON);
540 			SYSCON_WRITE_4(sc->grf, GRF_TSADC_TESTBIT_H,
541 			    GRF_TSADC_TESTBIT_H_ON);
542 			DELAY(180);  /* 90 usec min */
543 		}
544 		WR4(sc, TSADC_AUTO_PERIOD, 1875); 	/* 2.5 ms */
545 		WR4(sc, TSADC_AUTO_PERIOD_HT, 1875);	/* 2.5 ms */
546 		WR4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
547 		WR4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
548 		break;
549 	case TSADC_V7:
550 		/* V7 init */
551 		WR4(sc, TSADC_USER_CON, 0xfc0);		/* 97us, at least 90us */
552 		WR4(sc, TSADC_AUTO_PERIOD, 1622);	/* 2.5ms */
553 		WR4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
554 		WR4(sc, TSADC_AUTO_PERIOD_HT, 1622);	/* 2.5ms */
555 		WR4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
556 		if (sc->grf) {
557 			SYSCON_WRITE_4(sc->grf, GRF_TSADC_CON, GRF_TSADC_TSEN);
558 			DELAY(15);			/* 10 usec min */
559 			SYSCON_WRITE_4(sc->grf, GRF_TSADC_CON,
560 			    GRF_TSADC_ANA_REG0);
561 			SYSCON_WRITE_4(sc->grf, GRF_TSADC_CON,
562 			    GRF_TSADC_ANA_REG1);
563 			SYSCON_WRITE_4(sc->grf, GRF_TSADC_CON,
564 			    GRF_TSADC_ANA_REG2);
565 			DELAY(100);			/* 90 usec min */
566 		}
567 		break;
568 	}
569 }
570 
571 static int
572 tsadc_read_temp(struct tsadc_softc *sc, struct tsensor *sensor, int *temp)
573 {
574 	uint32_t val;
575 
576 	val = RD4(sc, TSADC_DATA(sensor->channel));
577 	*temp = tsadc_raw_to_temp(sc, val);
578 
579 #ifdef DEBUG
580 	device_printf(sc->dev, "%s: Sensor(id: %d, ch: %d), val: %d temp: %d\n",
581 	    __func__, sensor->id, sensor->channel, val, *temp);
582 	device_printf(sc->dev, "%s: user_con=0x%08x auto_con=0x%08x "
583 	    "comp_int=0x%08x comp_shut=0x%08x\n",
584 	    __func__, RD4(sc, TSADC_USER_CON), RD4(sc, TSADC_AUTO_CON),
585 	    RD4(sc, TSADC_COMP_INT(sensor->channel)),
586 	    RD4(sc, TSADC_COMP_SHUT(sensor->channel)));
587 #endif
588 	return (0);
589 }
590 
591 static int
592 tsadc_get_temp(device_t dev, device_t cdev, uintptr_t id, int *val)
593 {
594 	struct tsadc_softc *sc;
595 	int i, rv;
596 
597 	sc = device_get_softc(dev);
598 
599 	if (id >= sc->conf->ntsensors)
600 		return (ERANGE);
601 
602 	for (i = 0; i < sc->conf->ntsensors; i++) {
603 		if (sc->conf->tsensors->id == id) {
604 			rv =tsadc_read_temp(sc, sc->conf->tsensors + id, val);
605 			return (rv);
606 		}
607 	}
608 	return (ERANGE);
609 }
610 
611 static int
612 tsadc_sysctl_temperature(SYSCTL_HANDLER_ARGS)
613 {
614 	struct tsadc_softc *sc;
615 	int val;
616 	int rv;
617 	int id;
618 
619 	/* Write request */
620 	if (req->newptr != NULL)
621 		return (EINVAL);
622 
623 	sc = arg1;
624 	id = arg2;
625 
626 	if (id >= sc->conf->ntsensors)
627 		return (ERANGE);
628 	rv =  tsadc_read_temp(sc, sc->conf->tsensors + id, &val);
629 	if (rv != 0)
630 		return (rv);
631 
632 	val = val / 100;
633 	val +=  2731;
634 	rv = sysctl_handle_int(oidp, &val, 0, req);
635 	return (rv);
636 }
637 
638 static int
639 tsadc_init_sysctl(struct tsadc_softc *sc)
640 {
641 	int i;
642 	struct sysctl_oid *oid, *tmp;
643 
644 	sysctl_ctx_init(&tsadc_sysctl_ctx);
645 	/* create node for hw.temp */
646 	oid = SYSCTL_ADD_NODE(&tsadc_sysctl_ctx,
647 	    SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "temperature",
648 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "");
649 	if (oid == NULL)
650 		return (ENXIO);
651 
652 	/* Add sensors */
653 	for (i = sc->conf->ntsensors  - 1; i >= 0; i--) {
654 		tmp = SYSCTL_ADD_PROC(&tsadc_sysctl_ctx,
655 		    SYSCTL_CHILDREN(oid), OID_AUTO, sc->conf->tsensors[i].name,
656 		    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, i,
657 		    tsadc_sysctl_temperature, "IK", "SoC Temperature");
658 		if (tmp == NULL)
659 			return (ENXIO);
660 	}
661 
662 	return (0);
663 }
664 
665 static int
666 tsadc_intr(void *arg)
667 {
668 	struct tsadc_softc *sc;
669 	uint32_t val;
670 
671 	sc = (struct tsadc_softc *)arg;
672 
673 	val = RD4(sc, TSADC_INT_PD);
674 	WR4(sc, TSADC_INT_PD, val);
675 
676 	/* XXX Handle shutdown and alarm interrupts. */
677 	if (val & 0x00F0) {
678 		device_printf(sc->dev, "Alarm: device temperature "
679 		    "is above of shutdown level.\n");
680 	} else if (val & 0x000F) {
681 		device_printf(sc->dev, "Alarm: device temperature "
682 		    "is above of alarm level.\n");
683 	}
684 	return (FILTER_HANDLED);
685 }
686 
687 static int
688 tsadc_probe(device_t dev)
689 {
690 
691 	if (!ofw_bus_status_okay(dev))
692 		return (ENXIO);
693 
694 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
695 		return (ENXIO);
696 
697 	device_set_desc(dev, "RockChip temperature sensors");
698 	return (BUS_PROBE_DEFAULT);
699 }
700 
701 static int
702 tsadc_attach(device_t dev)
703 {
704 	struct tsadc_softc *sc;
705 	phandle_t node;
706 	uint32_t val;
707 	int i, rid, rv;
708 
709 	sc = device_get_softc(dev);
710 	sc->dev = dev;
711 	node = ofw_bus_get_node(sc->dev);
712 	sc->conf = (struct tsadc_conf *)
713 	    ofw_bus_search_compatible(dev, compat_data)->ocd_data;
714 	sc->alarm_temp = 90000;
715 
716 	rid = 0;
717 	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
718 	    RF_ACTIVE);
719 	if (sc->mem_res == NULL) {
720 		device_printf(dev, "Cannot allocate memory resources\n");
721 		goto fail;
722 	}
723 
724 	rid = 0;
725 	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
726 	if (sc->irq_res == NULL) {
727 		device_printf(dev, "Cannot allocate IRQ resources\n");
728 		goto fail;
729 	}
730 
731 	if ((bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
732 	    tsadc_intr, NULL, sc, &sc->irq_ih))) {
733 		device_printf(dev,
734 		    "WARNING: unable to register interrupt handler\n");
735 		goto fail;
736 	}
737 
738 	/* FDT resources */
739 	rv = hwreset_array_get_ofw(dev, 0, &sc->hwreset);
740 	if (rv != 0) {
741 		device_printf(dev, "Cannot get resets\n");
742 		goto fail;
743 	}
744 	rv = clk_get_by_ofw_name(dev, 0, "tsadc", &sc->tsadc_clk);
745 	if (rv != 0) {
746 		device_printf(dev, "Cannot get 'tsadc' clock: %d\n", rv);
747 		goto fail;
748 	}
749 	rv = clk_get_by_ofw_name(dev, 0, "apb_pclk", &sc->apb_pclk_clk);
750 	if (rv != 0) {
751 		device_printf(dev, "Cannot get 'apb_pclk' clock: %d\n", rv);
752 		goto fail;
753 	}
754 
755 	/* grf is optional */
756 	rv = syscon_get_by_ofw_property(dev, node, "rockchip,grf", &sc->grf);
757 	if (rv != 0 && rv != ENOENT) {
758 		device_printf(dev, "Cannot get 'grf' syscon: %d\n", rv);
759 		goto fail;
760 	}
761 
762 	rv = OF_getencprop(node, "rockchip,hw-tshut-temp",
763 	    &sc->shutdown_temp, sizeof(sc->shutdown_temp));
764 	if (rv <= 0)
765 		sc->shutdown_temp = sc->conf->shutdown_temp;
766 
767 	rv = OF_getencprop(node, "rockchip,hw-tshut-mode",
768 	    &sc->shutdown_mode, sizeof(sc->shutdown_mode));
769 	if (rv <= 0)
770 		sc->shutdown_mode = sc->conf->shutdown_mode;
771 
772 	rv = OF_getencprop(node, "rockchip,hw-tshut-polarity",
773 	    &sc->shutdown_pol, sizeof(sc->shutdown_pol));
774 	if (rv <= 0)
775 		sc->shutdown_pol = sc->conf->shutdown_pol;
776 
777 	/* Wakeup controller */
778 	rv = hwreset_array_assert(sc->hwreset);
779 	if (rv != 0) {
780 		device_printf(dev, "Cannot assert reset\n");
781 		goto fail;
782 	}
783 
784 	/* Set the assigned clocks parent and freq */
785 	rv = clk_set_assigned(sc->dev, node);
786 	if (rv != 0 && rv != ENOENT) {
787 		device_printf(dev, "clk_set_assigned failed\n");
788 		goto fail;
789 	}
790 
791 	rv = clk_enable(sc->tsadc_clk);
792 	if (rv != 0) {
793 		device_printf(dev, "Cannot enable 'tsadc_clk' clock: %d\n", rv);
794 		goto fail;
795 	}
796 	rv = clk_enable(sc->apb_pclk_clk);
797 	if (rv != 0) {
798 		device_printf(dev, "Cannot enable 'apb_pclk' clock: %d\n", rv);
799 		goto fail;
800 	}
801 	rv = hwreset_array_deassert(sc->hwreset);
802 	if (rv != 0) {
803 		device_printf(dev, "Cannot deassert reset\n");
804 		goto fail;
805 	}
806 
807 	tsadc_init(sc);
808 	for (i = 0; i < sc->conf->ntsensors; i++)
809 		tsadc_init_tsensor(sc, sc->conf->tsensors + i);
810 
811 	/* Enable auto mode */
812 	val = RD4(sc, TSADC_AUTO_CON);
813 	val |= TSADC_AUTO_CON_AUTO;
814 	WR4(sc, TSADC_AUTO_CON, val);
815 
816 	rv = tsadc_init_sysctl(sc);
817 	if (rv != 0) {
818 		device_printf(sc->dev, "Cannot initialize sysctls\n");
819 		goto fail_sysctl;
820 	}
821 
822 	OF_device_register_xref(OF_xref_from_node(node), dev);
823 	return (bus_generic_attach(dev));
824 
825 fail_sysctl:
826 	sysctl_ctx_free(&tsadc_sysctl_ctx);
827 fail:
828 	if (sc->irq_ih != NULL)
829 		bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
830 	if (sc->tsadc_clk != NULL)
831 		clk_release(sc->tsadc_clk);
832 	if (sc->apb_pclk_clk != NULL)
833 		clk_release(sc->apb_pclk_clk);
834 	if (sc->hwreset != NULL)
835 		hwreset_array_release(sc->hwreset);
836 	if (sc->irq_res != NULL)
837 		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
838 	if (sc->mem_res != NULL)
839 		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
840 
841 	return (ENXIO);
842 }
843 
844 static int
845 tsadc_detach(device_t dev)
846 {
847 	struct tsadc_softc *sc;
848 	sc = device_get_softc(dev);
849 
850 	if (sc->irq_ih != NULL)
851 		bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
852 	sysctl_ctx_free(&tsadc_sysctl_ctx);
853 	if (sc->tsadc_clk != NULL)
854 		clk_release(sc->tsadc_clk);
855 	if (sc->apb_pclk_clk != NULL)
856 		clk_release(sc->apb_pclk_clk);
857 	if (sc->hwreset != NULL)
858 		hwreset_array_release(sc->hwreset);
859 	if (sc->irq_res != NULL)
860 		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
861 	if (sc->mem_res != NULL)
862 		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
863 
864 	return (ENXIO);
865 }
866 
867 static device_method_t rk_tsadc_methods[] = {
868 	/* Device interface */
869 	DEVMETHOD(device_probe,			tsadc_probe),
870 	DEVMETHOD(device_attach,		tsadc_attach),
871 	DEVMETHOD(device_detach,		tsadc_detach),
872 
873 	/* TSADC interface */
874 	DEVMETHOD(rk_tsadc_get_temperature,	tsadc_get_temp),
875 
876 	DEVMETHOD_END
877 };
878 
879 static DEFINE_CLASS_0(rk_tsadc, rk_tsadc_driver, rk_tsadc_methods,
880     sizeof(struct tsadc_softc));
881 EARLY_DRIVER_MODULE(rk_tsadc, simplebus, rk_tsadc_driver, NULL, NULL,
882     BUS_PASS_TIMER + BUS_PASS_ORDER_LAST);
883