xref: /openbsd-src/sys/dev/fdt/rktemp.c (revision 8550894424f8a4aa4aafb6cd57229dd6ed7cd9dd)
1 /*	$OpenBSD: rktemp.c,v 1.11 2022/10/20 20:35:57 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/sensors.h>
22 
23 #include <machine/intr.h>
24 #include <machine/bus.h>
25 #include <machine/fdt.h>
26 
27 #include <dev/ofw/openfirm.h>
28 #include <dev/ofw/ofw_clock.h>
29 #include <dev/ofw/ofw_misc.h>
30 #include <dev/ofw/ofw_pinctrl.h>
31 #include <dev/ofw/ofw_thermal.h>
32 #include <dev/ofw/fdt.h>
33 
34 /* Registers */
35 #define TSADC_USER_CON		0x0000
36 #define TSADC_AUTO_CON		0x0004
37 #define  TSADC_AUTO_CON_TSHUT_POLARITY	(1 << 8)
38 #define  TSADC_AUTO_CON_SRC3_EN		(1 << 7)
39 #define  TSADC_AUTO_CON_SRC2_EN		(1 << 6)
40 #define  TSADC_AUTO_CON_SRC1_EN		(1 << 5)
41 #define  TSADC_AUTO_CON_SRC0_EN		(1 << 4)
42 #define  TSADC_AUTO_CON_TSADC_Q_SEL	(1 << 1)
43 #define  TSADC_AUTO_CON_AUTO_EN		(1 << 0)
44 #define TSADC_INT_EN		0x0008
45 #define  TSADC_INT_EN_TSHUT_2CRU_EN_SRC3	(1 << 11)
46 #define  TSADC_INT_EN_TSHUT_2CRU_EN_SRC2	(1 << 10)
47 #define  TSADC_INT_EN_TSHUT_2CRU_EN_SRC1	(1 << 9)
48 #define  TSADC_INT_EN_TSHUT_2CRU_EN_SRC0	(1 << 8)
49 #define  TSADC_INT_EN_TSHUT_2GPIO_EN_SRC3	(1 << 7)
50 #define  TSADC_INT_EN_TSHUT_2GPIO_EN_SRC2	(1 << 6)
51 #define  TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1	(1 << 5)
52 #define  TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0	(1 << 4)
53 #define TSADC_INT_PD		0x000c
54 #define  TSADC_INT_PD_TSHUT_O_SRC0		(1 << 4)
55 #define  TSADC_INT_PD_TSHUT_O_SRC1		(1 << 5)
56 #define  TSADC_INT_PD_TSHUT_O_SRC2		(1 << 6)
57 #define  TSADC_INT_PD_TSHUT_O_SRC3		(1 << 7)
58 #define TSADC_DATA0		0x0020
59 #define TSADC_DATA1		0x0024
60 #define TSADC_DATA2		0x0028
61 #define TSADC_DATA3		0x002c
62 #define TSADC_COMP0_INT		0x0030
63 #define TSADC_COMP1_INT		0x0034
64 #define TSADC_COMP2_INT		0x0038
65 #define TSADC_COMP3_INT		0x003c
66 #define TSADC_COMP0_SHUT	0x0040
67 #define TSADC_COMP1_SHUT	0x0044
68 #define TSADC_COMP2_SHUT	0x0048
69 #define TSADC_COMP3_SHUT	0x004c
70 #define TSADC_AUTO_PERIOD	0x0068
71 #define TSADC_AUTO_PERIOD_HT	0x006c
72 
73 #define HREAD4(sc, reg)							\
74 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
75 #define HWRITE4(sc, reg, val)						\
76 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
77 
78 struct rktemp_entry {
79 	int32_t temp;
80 	int32_t code;
81 };
82 
83 /* RK3288 conversion table. */
84 const struct rktemp_entry rk3288_temps[] = {
85 	{ -40000, 3800 },
86 	{ -35000, 3792 },
87 	{ -30000, 3783 },
88 	{ -25000, 3774 },
89 	{ -20000, 3765 },
90 	{ -15000, 3756 },
91 	{ -10000, 3747 },
92 	{  -5000, 3737 },
93 	{      0, 3728 },
94 	{   5000, 3718 },
95 	{  10000, 3708 },
96 	{  15000, 3698 },
97 	{  20000, 3688 },
98 	{  25000, 3678 },
99 	{  30000, 3667 },
100 	{  35000, 3656 },
101 	{  40000, 3645 },
102 	{  45000, 3634 },
103 	{  50000, 3623 },
104 	{  55000, 3611 },
105 	{  60000, 3600 },
106 	{  65000, 3588 },
107 	{  70000, 3575 },
108 	{  75000, 3563 },
109 	{  80000, 3550 },
110 	{  85000, 3537 },
111 	{  90000, 3524 },
112 	{  95000, 3510 },
113 	{ 100000, 3496 },
114 	{ 105000, 3482 },
115 	{ 110000, 3467 },
116 	{ 115000, 3452 },
117 	{ 120000, 3437 },
118 	{ 125000, 3421 },
119 };
120 
121 const char *const rk3288_names[] = { "", "CPU", "GPU" };
122 
123 /* RK3328 conversion table. */
124 const struct rktemp_entry rk3328_temps[] = {
125 	{ -40000, 296 },
126 	{ -35000, 304 },
127 	{ -30000, 313 },
128 	{ -20000, 331 },
129 	{ -15000, 340 },
130 	{ -10000, 349 },
131 	{  -5000, 359 },
132 	{      0, 368 },
133 	{   5000, 378 },
134 	{  10000, 388 },
135 	{  15000, 398 },
136 	{  20000, 408 },
137 	{  25000, 418 },
138 	{  30000, 429 },
139 	{  35000, 440 },
140 	{  40000, 451 },
141 	{  45000, 462 },
142 	{  50000, 473 },
143 	{  55000, 485 },
144 	{  60000, 496 },
145 	{  65000, 508 },
146 	{  70000, 521 },
147 	{  75000, 533 },
148 	{  80000, 546 },
149 	{  85000, 559 },
150 	{  90000, 572 },
151 	{  95000, 586 },
152 	{ 100000, 600 },
153 	{ 105000, 614 },
154 	{ 110000, 629 },
155 	{ 115000, 644 },
156 	{ 120000, 659 },
157 	{ 125000, 675 },
158 };
159 
160 const char *const rk3308_names[] = { "CPU", "GPU" };
161 const char *const rk3328_names[] = { "CPU" };
162 
163 /* RK3399 conversion table. */
164 const struct rktemp_entry rk3399_temps[] = {
165 	{ -40000, 402 },
166 	{ -35000, 410 },
167 	{ -30000, 419 },
168 	{ -25000, 427 },
169 	{ -20000, 436 },
170 	{ -15000, 444 },
171 	{ -10000, 453 },
172 	{  -5000, 461 },
173 	{      0, 470 },
174 	{   5000, 478 },
175 	{  10000, 487 },
176 	{  15000, 496 },
177 	{  20000, 504 },
178 	{  25000, 513 },
179 	{  30000, 521 },
180 	{  35000, 530 },
181 	{  40000, 538 },
182 	{  45000, 547 },
183 	{  50000, 555 },
184 	{  55000, 564 },
185 	{  60000, 573 },
186 	{  65000, 581 },
187 	{  70000, 590 },
188 	{  75000, 599 },
189 	{  80000, 607 },
190 	{  85000, 616 },
191 	{  90000, 624 },
192 	{  95000, 633 },
193 	{ 100000, 642 },
194 	{ 105000, 650 },
195 	{ 110000, 659 },
196 	{ 115000, 668 },
197 	{ 120000, 677 },
198 	{ 125000, 685 },
199 };
200 
201 const char *const rk3399_names[] = { "CPU", "GPU" };
202 
203 /* RK3568 conversion table. */
204 const struct rktemp_entry rk3568_temps[] = {
205 	{ -40000, 1584 },
206 	{ -35000, 1620 },
207 	{ -30000, 1652 },
208 	{ -25000, 1688 },
209 	{ -20000, 1720 },
210 	{ -15000, 1756 },
211 	{ -10000, 1788 },
212 	{  -5000, 1824 },
213 	{      0, 1856 },
214 	{   5000, 1892 },
215 	{  10000, 1924 },
216 	{  15000, 1956 },
217 	{  20000, 1992 },
218 	{  25000, 2024 },
219 	{  30000, 2060 },
220 	{  35000, 2092 },
221 	{  40000, 2128 },
222 	{  45000, 2160 },
223 	{  50000, 2196 },
224 	{  55000, 2228 },
225 	{  60000, 2264 },
226 	{  65000, 2300 },
227 	{  70000, 2332 },
228 	{  75000, 2368 },
229 	{  80000, 2400 },
230 	{  85000, 2436 },
231 	{  90000, 2468 },
232 	{  95000, 2500 },
233 	{ 100000, 2536 },
234 	{ 105000, 2572 },
235 	{ 110000, 2604 },
236 	{ 115000, 2636 },
237 	{ 120000, 2672 },
238 	{ 125000, 2704 },
239 };
240 
241 const char *const rk3568_names[] = { "CPU", "GPU" };
242 
243 struct rktemp_softc {
244 	struct device		sc_dev;
245 	bus_space_tag_t		sc_iot;
246 	bus_space_handle_t	sc_ioh;
247 
248 	const struct rktemp_entry *sc_temps;
249 	int			sc_ntemps;
250 
251 	struct ksensor		sc_sensors[3];
252 	int			sc_nsensors;
253 	struct ksensordev	sc_sensordev;
254 
255 	struct thermal_sensor	sc_ts;
256 };
257 
258 int	rktemp_match(struct device *, void *, void *);
259 void	rktemp_attach(struct device *, struct device *, void *);
260 
261 const struct cfattach rktemp_ca = {
262 	sizeof (struct rktemp_softc), rktemp_match, rktemp_attach
263 };
264 
265 struct cfdriver rktemp_cd = {
266 	NULL, "rktemp", DV_DULL
267 };
268 
269 int32_t rktemp_calc_code(struct rktemp_softc *, int32_t);
270 int32_t rktemp_calc_temp(struct rktemp_softc *, int32_t);
271 int	rktemp_valid(struct rktemp_softc *, int32_t);
272 void	rktemp_refresh_sensors(void *);
273 int32_t	rktemp_get_temperature(void *, uint32_t *);
274 
275 int
276 rktemp_match(struct device *parent, void *match, void *aux)
277 {
278 	struct fdt_attach_args *faa = aux;
279 
280 	return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-tsadc") ||
281 	    OF_is_compatible(faa->fa_node, "rockchip,rk3308-tsadc") ||
282 	    OF_is_compatible(faa->fa_node, "rockchip,rk3328-tsadc") ||
283 	    OF_is_compatible(faa->fa_node, "rockchip,rk3399-tsadc") ||
284 	    OF_is_compatible(faa->fa_node, "rockchip,rk3568-tsadc"));
285 }
286 
287 void
288 rktemp_attach(struct device *parent, struct device *self, void *aux)
289 {
290 	struct rktemp_softc *sc = (struct rktemp_softc *)self;
291 	struct fdt_attach_args *faa = aux;
292 	const char *const *names;
293 	uint32_t mode, polarity, temp;
294 	uint32_t auto_con, int_en;
295 	int node = faa->fa_node;
296 	int i;
297 
298 	if (faa->fa_nreg < 1) {
299 		printf(": no registers\n");
300 		return;
301 	}
302 
303 	sc->sc_iot = faa->fa_iot;
304 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
305 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
306 		printf(": can't map registers\n");
307 		return;
308 	}
309 
310 	printf("\n");
311 
312 	if (OF_is_compatible(node, "rockchip,rk3288-tsadc")) {
313 		sc->sc_temps = rk3288_temps;
314 		sc->sc_ntemps = nitems(rk3288_temps);
315 		sc->sc_nsensors = 3;
316 		names = rk3288_names;
317 	} else if (OF_is_compatible(node, "rockchip,rk3308-tsadc")) {
318 		sc->sc_temps = rk3328_temps;
319 		sc->sc_ntemps = nitems(rk3328_temps);
320 		sc->sc_nsensors = 2;
321 		names = rk3308_names;
322 	} else if (OF_is_compatible(node, "rockchip,rk3328-tsadc")) {
323 		sc->sc_temps = rk3328_temps;
324 		sc->sc_ntemps = nitems(rk3328_temps);
325 		sc->sc_nsensors = 1;
326 		names = rk3328_names;
327 	} else if (OF_is_compatible(node, "rockchip,rk3399-tsadc")) {
328 		sc->sc_temps = rk3399_temps;
329 		sc->sc_ntemps = nitems(rk3399_temps);
330 		sc->sc_nsensors = 2;
331 		names = rk3399_names;
332 	} else {
333 		sc->sc_temps = rk3568_temps;
334 		sc->sc_ntemps = nitems(rk3568_temps);
335 		sc->sc_nsensors = 2;
336 		names = rk3568_names;
337 	}
338 
339 	pinctrl_byname(node, "init");
340 
341 	clock_set_assigned(node);
342 	clock_enable(node, "tsadc");
343 	clock_enable(node, "apb_pclk");
344 
345 	/* Reset the TS-ADC controller block. */
346 	reset_assert(node, "tsadc-apb");
347 	delay(10);
348 	reset_deassert(node, "tsadc-apb");
349 
350 	mode = OF_getpropint(node, "rockchip,hw-tshut-mode", 1);
351 	polarity = OF_getpropint(node, "rockchip,hw-tshut-polarity", 0);
352 	temp = OF_getpropint(node, "rockchip,hw-tshut-temp", 95000);
353 
354 	auto_con = HREAD4(sc, TSADC_AUTO_CON);
355 	auto_con |= TSADC_AUTO_CON_TSADC_Q_SEL;
356 	if (polarity)
357 		auto_con |= TSADC_AUTO_CON_TSHUT_POLARITY;
358 	HWRITE4(sc, TSADC_AUTO_CON, auto_con);
359 
360 	/* Set shutdown limit. */
361 	for (i = 0; i < sc->sc_nsensors; i++) {
362 		HWRITE4(sc, TSADC_COMP0_SHUT + i * 4,
363 		    rktemp_calc_code(sc, temp));
364 		auto_con |= (TSADC_AUTO_CON_SRC0_EN << i);
365 	}
366 	HWRITE4(sc, TSADC_AUTO_CON, auto_con);
367 
368 	/* Clear shutdown output status. */
369 	for (i = 0; i < sc->sc_nsensors; i++)
370 		HWRITE4(sc, TSADC_INT_PD, (TSADC_INT_PD_TSHUT_O_SRC0 << i));
371 
372 	/* Configure mode. */
373 	int_en = HREAD4(sc, TSADC_INT_EN);
374 	for (i = 0; i < sc->sc_nsensors; i++) {
375 		if (mode)
376 			int_en |= (TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 << i);
377 		else
378 			int_en |= (TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 << i);
379 	}
380 	HWRITE4(sc, TSADC_INT_EN, int_en);
381 
382 	pinctrl_byname(faa->fa_node, "default");
383 
384 	/* Finally turn on the ADC. */
385 	auto_con |= TSADC_AUTO_CON_AUTO_EN;
386 	HWRITE4(sc, TSADC_AUTO_CON, auto_con);
387 
388 	/* Register sensors. */
389 	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
390 	    sizeof(sc->sc_sensordev.xname));
391 	for (i = 0; i < sc->sc_nsensors; i++) {
392 		strlcpy(sc->sc_sensors[i].desc, names[i],
393 		    sizeof(sc->sc_sensors[i].desc));
394 		sc->sc_sensors[i].type = SENSOR_TEMP;
395 		sc->sc_sensors[i].flags = SENSOR_FINVALID;
396 		sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
397 	}
398 	sensordev_install(&sc->sc_sensordev);
399 	sensor_task_register(sc, rktemp_refresh_sensors, 5);
400 
401 	sc->sc_ts.ts_node = node;
402 	sc->sc_ts.ts_cookie = sc;
403 	sc->sc_ts.ts_get_temperature = rktemp_get_temperature;
404 	thermal_sensor_register(&sc->sc_ts);
405 }
406 
407 int32_t
408 rktemp_calc_code(struct rktemp_softc *sc, int32_t temp)
409 {
410 	const int n = sc->sc_ntemps;
411 	int32_t code0, delta_code;
412 	int32_t temp0, delta_temp;
413 	int i;
414 
415 	if (temp <= sc->sc_temps[0].temp)
416 		return sc->sc_temps[0].code;
417 	if (temp >= sc->sc_temps[n - 1].temp)
418 		return sc->sc_temps[n - 1].code;
419 
420 	for (i = 1; i < n; i++) {
421 		if (temp < sc->sc_temps[i].temp)
422 			break;
423 	}
424 
425 	code0 = sc->sc_temps[i - 1].code;
426 	temp0 = sc->sc_temps[i - 1].temp;
427 	delta_code = sc->sc_temps[i].code - code0;
428 	delta_temp = sc->sc_temps[i].temp - temp0;
429 
430 	return code0 + (temp - temp0) * delta_code / delta_temp;
431 }
432 
433 int32_t
434 rktemp_calc_temp(struct rktemp_softc *sc, int32_t code)
435 {
436 	const int n = sc->sc_ntemps;
437 	int32_t code0, delta_code;
438 	int32_t temp0, delta_temp;
439 	int i;
440 
441 	/* Handle both negative and positive temperature coefficients. */
442 	if (sc->sc_temps[0].code > sc->sc_temps[1].code) {
443 		if (code >= sc->sc_temps[0].code)
444 			return sc->sc_temps[0].code;
445 		if (code <= sc->sc_temps[n - 1].code)
446 			return sc->sc_temps[n - 1].temp;
447 
448 		for (i = 1; i < n; i++) {
449 			if (code > sc->sc_temps[i].code)
450 				break;
451 		}
452 	} else {
453 		if (code <= sc->sc_temps[0].code)
454 			return sc->sc_temps[0].temp;
455 		if (code >= sc->sc_temps[n - 1].code)
456 			return sc->sc_temps[n - 1].temp;
457 
458 		for (i = 1; i < n; i++) {
459 			if (code < sc->sc_temps[i].code)
460 				break;
461 		}
462 	}
463 
464 	code0 = sc->sc_temps[i - 1].code;
465 	temp0 = sc->sc_temps[i - 1].temp;
466 	delta_code = sc->sc_temps[i].code - code0;
467 	delta_temp = sc->sc_temps[i].temp - temp0;
468 
469 	return temp0 + (code - code0) * delta_temp / delta_code;
470 }
471 
472 int
473 rktemp_valid(struct rktemp_softc *sc, int32_t code)
474 {
475 	const int n = sc->sc_ntemps;
476 
477 	if (sc->sc_temps[0].code > sc->sc_temps[1].code) {
478 		if (code > sc->sc_temps[0].code)
479 			return 0;
480 		if (code < sc->sc_temps[n - 1].code)
481 			return 0;
482 	} else {
483 		if (code < sc->sc_temps[0].code)
484 			return 0;
485 		if (code > sc->sc_temps[n - 1].code)
486 			return 0;
487 	}
488 	return 1;
489 }
490 
491 void
492 rktemp_refresh_sensors(void *arg)
493 {
494 	struct rktemp_softc *sc = arg;
495 	int32_t code, temp;
496 	int i;
497 
498 	for (i = 0; i < sc->sc_nsensors; i++) {
499 		code = HREAD4(sc, TSADC_DATA0 + i * 4);
500 		temp = rktemp_calc_temp(sc, code);
501 		sc->sc_sensors[i].value = 273150000 + 1000 * temp;
502 		if (rktemp_valid(sc, code))
503 			sc->sc_sensors[i].flags &= ~SENSOR_FINVALID;
504 		else
505 			sc->sc_sensors[i].flags |= SENSOR_FINVALID;
506 	}
507 }
508 
509 int32_t
510 rktemp_get_temperature(void *cookie, uint32_t *cells)
511 {
512 	struct rktemp_softc *sc = cookie;
513 	uint32_t idx = cells[0];
514 	int32_t code;
515 
516 	if (idx >= sc->sc_nsensors)
517 		return THERMAL_SENSOR_MAX;
518 
519 	code = HREAD4(sc, TSADC_DATA0 + idx * 4);
520 	if (rktemp_valid(sc, code))
521 		return rktemp_calc_temp(sc, code);
522 	else
523 		return THERMAL_SENSOR_MAX;
524 }
525