xref: /openbsd-src/sys/dev/fdt/rktemp.c (revision 25c4e8bd056e974b28f4a0ffd39d76c190a56013)
1 /*	$OpenBSD: rktemp.c,v 1.10 2022/06/28 23:43:12 naddy 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_DATA0		0x0020
55 #define TSADC_DATA1		0x0024
56 #define TSADC_DATA2		0x0028
57 #define TSADC_DATA3		0x002c
58 #define TSADC_COMP0_INT		0x0030
59 #define TSADC_COMP1_INT		0x0034
60 #define TSADC_COMP2_INT		0x0038
61 #define TSADC_COMP3_INT		0x003c
62 #define TSADC_COMP0_SHUT	0x0040
63 #define TSADC_COMP1_SHUT	0x0044
64 #define TSADC_COMP2_SHUT	0x0048
65 #define TSADC_COMP3_SHUT	0x004c
66 #define TSADC_AUTO_PERIOD	0x0068
67 #define TSADC_AUTO_PERIOD_HT	0x006c
68 
69 #define HREAD4(sc, reg)							\
70 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
71 #define HWRITE4(sc, reg, val)						\
72 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
73 
74 struct rktemp_entry {
75 	int32_t temp;
76 	int32_t code;
77 };
78 
79 /* RK3288 conversion table. */
80 const struct rktemp_entry rk3288_temps[] = {
81 	{ -40000, 3800 },
82 	{ -35000, 3792 },
83 	{ -30000, 3783 },
84 	{ -25000, 3774 },
85 	{ -20000, 3765 },
86 	{ -15000, 3756 },
87 	{ -10000, 3747 },
88 	{  -5000, 3737 },
89 	{      0, 3728 },
90 	{   5000, 3718 },
91 	{  10000, 3708 },
92 	{  15000, 3698 },
93 	{  20000, 3688 },
94 	{  25000, 3678 },
95 	{  30000, 3667 },
96 	{  35000, 3656 },
97 	{  40000, 3645 },
98 	{  45000, 3634 },
99 	{  50000, 3623 },
100 	{  55000, 3611 },
101 	{  60000, 3600 },
102 	{  65000, 3588 },
103 	{  70000, 3575 },
104 	{  75000, 3563 },
105 	{  80000, 3550 },
106 	{  85000, 3537 },
107 	{  90000, 3524 },
108 	{  95000, 3510 },
109 	{ 100000, 3496 },
110 	{ 105000, 3482 },
111 	{ 110000, 3467 },
112 	{ 115000, 3452 },
113 	{ 120000, 3437 },
114 	{ 125000, 3421 },
115 };
116 
117 const char *const rk3288_names[] = { "", "CPU", "GPU" };
118 
119 /* RK3328 conversion table. */
120 const struct rktemp_entry rk3328_temps[] = {
121 	{ -40000, 296 },
122 	{ -35000, 304 },
123 	{ -30000, 313 },
124 	{ -20000, 331 },
125 	{ -15000, 340 },
126 	{ -10000, 349 },
127 	{  -5000, 359 },
128 	{      0, 368 },
129 	{   5000, 378 },
130 	{  10000, 388 },
131 	{  15000, 398 },
132 	{  20000, 408 },
133 	{  25000, 418 },
134 	{  30000, 429 },
135 	{  35000, 440 },
136 	{  40000, 451 },
137 	{  45000, 462 },
138 	{  50000, 473 },
139 	{  55000, 485 },
140 	{  60000, 496 },
141 	{  65000, 508 },
142 	{  70000, 521 },
143 	{  75000, 533 },
144 	{  80000, 546 },
145 	{  85000, 559 },
146 	{  90000, 572 },
147 	{  95000, 586 },
148 	{ 100000, 600 },
149 	{ 105000, 614 },
150 	{ 110000, 629 },
151 	{ 115000, 644 },
152 	{ 120000, 659 },
153 	{ 125000, 675 },
154 };
155 
156 const char *const rk3308_names[] = { "CPU", "GPU" };
157 const char *const rk3328_names[] = { "CPU" };
158 
159 /* RK3399 conversion table. */
160 const struct rktemp_entry rk3399_temps[] = {
161 	{ -40000, 402 },
162 	{ -35000, 410 },
163 	{ -30000, 419 },
164 	{ -25000, 427 },
165 	{ -20000, 436 },
166 	{ -15000, 444 },
167 	{ -10000, 453 },
168 	{  -5000, 461 },
169 	{      0, 470 },
170 	{   5000, 478 },
171 	{  10000, 487 },
172 	{  15000, 496 },
173 	{  20000, 504 },
174 	{  25000, 513 },
175 	{  30000, 521 },
176 	{  35000, 530 },
177 	{  40000, 538 },
178 	{  45000, 547 },
179 	{  50000, 555 },
180 	{  55000, 564 },
181 	{  60000, 573 },
182 	{  65000, 581 },
183 	{  70000, 590 },
184 	{  75000, 599 },
185 	{  80000, 607 },
186 	{  85000, 616 },
187 	{  90000, 624 },
188 	{  95000, 633 },
189 	{ 100000, 642 },
190 	{ 105000, 650 },
191 	{ 110000, 659 },
192 	{ 115000, 668 },
193 	{ 120000, 677 },
194 	{ 125000, 685 },
195 };
196 
197 const char *const rk3399_names[] = { "CPU", "GPU" };
198 
199 struct rktemp_softc {
200 	struct device		sc_dev;
201 	bus_space_tag_t		sc_iot;
202 	bus_space_handle_t	sc_ioh;
203 
204 	const struct rktemp_entry *sc_temps;
205 	int			sc_ntemps;
206 
207 	struct ksensor		sc_sensors[3];
208 	int			sc_nsensors;
209 	struct ksensordev	sc_sensordev;
210 
211 	struct thermal_sensor	sc_ts;
212 };
213 
214 int	rktemp_match(struct device *, void *, void *);
215 void	rktemp_attach(struct device *, struct device *, void *);
216 
217 const struct cfattach rktemp_ca = {
218 	sizeof (struct rktemp_softc), rktemp_match, rktemp_attach
219 };
220 
221 struct cfdriver rktemp_cd = {
222 	NULL, "rktemp", DV_DULL
223 };
224 
225 int32_t rktemp_calc_code(struct rktemp_softc *, int32_t);
226 int32_t rktemp_calc_temp(struct rktemp_softc *, int32_t);
227 int	rktemp_valid(struct rktemp_softc *, int32_t);
228 void	rktemp_refresh_sensors(void *);
229 int32_t	rktemp_get_temperature(void *, uint32_t *);
230 
231 int
232 rktemp_match(struct device *parent, void *match, void *aux)
233 {
234 	struct fdt_attach_args *faa = aux;
235 
236 	return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-tsadc") ||
237 	    OF_is_compatible(faa->fa_node, "rockchip,rk3308-tsadc") ||
238 	    OF_is_compatible(faa->fa_node, "rockchip,rk3328-tsadc") ||
239 	    OF_is_compatible(faa->fa_node, "rockchip,rk3399-tsadc"));
240 }
241 
242 void
243 rktemp_attach(struct device *parent, struct device *self, void *aux)
244 {
245 	struct rktemp_softc *sc = (struct rktemp_softc *)self;
246 	struct fdt_attach_args *faa = aux;
247 	const char *const *names;
248 	uint32_t mode, polarity, temp;
249 	uint32_t auto_con, int_en;
250 	int node = faa->fa_node;
251 	int i;
252 
253 	if (faa->fa_nreg < 1) {
254 		printf(": no registers\n");
255 		return;
256 	}
257 
258 	sc->sc_iot = faa->fa_iot;
259 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
260 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
261 		printf(": can't map registers\n");
262 		return;
263 	}
264 
265 	printf("\n");
266 
267 	if (OF_is_compatible(node, "rockchip,rk3288-tsadc")) {
268 		sc->sc_temps = rk3288_temps;
269 		sc->sc_ntemps = nitems(rk3288_temps);
270 		sc->sc_nsensors = 3;
271 		names = rk3288_names;
272 	} else if (OF_is_compatible(node, "rockchip,rk3308-tsadc")) {
273 		sc->sc_temps = rk3328_temps;
274 		sc->sc_ntemps = nitems(rk3328_temps);
275 		sc->sc_nsensors = 2;
276 		names = rk3308_names;
277 	} else if (OF_is_compatible(node, "rockchip,rk3328-tsadc")) {
278 		sc->sc_temps = rk3328_temps;
279 		sc->sc_ntemps = nitems(rk3328_temps);
280 		sc->sc_nsensors = 1;
281 		names = rk3328_names;
282 	} else {
283 		sc->sc_temps = rk3399_temps;
284 		sc->sc_ntemps = nitems(rk3399_temps);
285 		sc->sc_nsensors = 2;
286 		names = rk3399_names;
287 	}
288 
289 	pinctrl_byname(node, "init");
290 
291 	clock_set_assigned(node);
292 	clock_enable(node, "tsadc");
293 	clock_enable(node, "apb_pclk");
294 
295 	/* Reset the TS-ADC controller block. */
296 	reset_assert(node, "tsadc-apb");
297 	delay(10);
298 	reset_deassert(node, "tsadc-apb");
299 
300 	mode = OF_getpropint(node, "rockchip,hw-tshut-mode", 1);
301 	polarity = OF_getpropint(node, "rockchip,hw-tshut-polarity", 0);
302 	temp = OF_getpropint(node, "rockchip,hw-tshut-temp", 95000);
303 
304 	auto_con = HREAD4(sc, TSADC_AUTO_CON);
305 	auto_con |= TSADC_AUTO_CON_TSADC_Q_SEL;
306 	if (polarity)
307 		auto_con |= TSADC_AUTO_CON_TSHUT_POLARITY;
308 	HWRITE4(sc, TSADC_AUTO_CON, auto_con);
309 
310 	/* Configure mode. */
311 	int_en = HREAD4(sc, TSADC_INT_EN);
312 	for (i = 0; i < sc->sc_nsensors; i++) {
313 		if (mode)
314 			int_en |= (TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 << i);
315 		else
316 			int_en |= (TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 << i);
317 	}
318 	HWRITE4(sc, TSADC_INT_EN, int_en);
319 
320 	/* Set shutdown limit. */
321 	for (i = 0; i < sc->sc_nsensors; i++) {
322 		HWRITE4(sc, TSADC_COMP0_SHUT + i * 4,
323 		    rktemp_calc_code(sc, temp));
324 		auto_con |= (TSADC_AUTO_CON_SRC0_EN << i);
325 	}
326 	HWRITE4(sc, TSADC_AUTO_CON, auto_con);
327 
328 	pinctrl_byname(faa->fa_node, "default");
329 
330 	/* Finally turn on the ADC. */
331 	auto_con |= TSADC_AUTO_CON_AUTO_EN;
332 	HWRITE4(sc, TSADC_AUTO_CON, auto_con);
333 
334 	/* Register sensors. */
335 	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
336 	    sizeof(sc->sc_sensordev.xname));
337 	for (i = 0; i < sc->sc_nsensors; i++) {
338 		strlcpy(sc->sc_sensors[i].desc, names[i],
339 		    sizeof(sc->sc_sensors[i].desc));
340 		sc->sc_sensors[i].type = SENSOR_TEMP;
341 		sc->sc_sensors[i].flags = SENSOR_FINVALID;
342 		sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
343 	}
344 	sensordev_install(&sc->sc_sensordev);
345 	sensor_task_register(sc, rktemp_refresh_sensors, 5);
346 
347 	sc->sc_ts.ts_node = node;
348 	sc->sc_ts.ts_cookie = sc;
349 	sc->sc_ts.ts_get_temperature = rktemp_get_temperature;
350 	thermal_sensor_register(&sc->sc_ts);
351 }
352 
353 int32_t
354 rktemp_calc_code(struct rktemp_softc *sc, int32_t temp)
355 {
356 	const int n = sc->sc_ntemps;
357 	int32_t code0, delta_code;
358 	int32_t temp0, delta_temp;
359 	int i;
360 
361 	if (temp <= sc->sc_temps[0].temp)
362 		return sc->sc_temps[0].code;
363 	if (temp >= sc->sc_temps[n - 1].temp)
364 		return sc->sc_temps[n - 1].code;
365 
366 	for (i = 1; i < n; i++) {
367 		if (temp < sc->sc_temps[i].temp)
368 			break;
369 	}
370 
371 	code0 = sc->sc_temps[i - 1].code;
372 	temp0 = sc->sc_temps[i - 1].temp;
373 	delta_code = sc->sc_temps[i].code - code0;
374 	delta_temp = sc->sc_temps[i].temp - temp0;
375 
376 	return code0 + (temp - temp0) * delta_code / delta_temp;
377 }
378 
379 int32_t
380 rktemp_calc_temp(struct rktemp_softc *sc, int32_t code)
381 {
382 	const int n = sc->sc_ntemps;
383 	int32_t code0, delta_code;
384 	int32_t temp0, delta_temp;
385 	int i;
386 
387 	/* Handle both negative and positive temperature coefficients. */
388 	if (sc->sc_temps[0].code > sc->sc_temps[1].code) {
389 		if (code >= sc->sc_temps[0].code)
390 			return sc->sc_temps[0].code;
391 		if (code <= sc->sc_temps[n - 1].code)
392 			return sc->sc_temps[n - 1].temp;
393 
394 		for (i = 1; i < n; i++) {
395 			if (code > sc->sc_temps[i].code)
396 				break;
397 		}
398 	} else {
399 		if (code <= sc->sc_temps[0].code)
400 			return sc->sc_temps[0].temp;
401 		if (code >= sc->sc_temps[n - 1].code)
402 			return sc->sc_temps[n - 1].temp;
403 
404 		for (i = 1; i < n; i++) {
405 			if (code < sc->sc_temps[i].code)
406 				break;
407 		}
408 	}
409 
410 	code0 = sc->sc_temps[i - 1].code;
411 	temp0 = sc->sc_temps[i - 1].temp;
412 	delta_code = sc->sc_temps[i].code - code0;
413 	delta_temp = sc->sc_temps[i].temp - temp0;
414 
415 	return temp0 + (code - code0) * delta_temp / delta_code;
416 }
417 
418 int
419 rktemp_valid(struct rktemp_softc *sc, int32_t code)
420 {
421 	const int n = sc->sc_ntemps;
422 
423 	if (sc->sc_temps[0].code > sc->sc_temps[1].code) {
424 		if (code > sc->sc_temps[0].code)
425 			return 0;
426 		if (code < sc->sc_temps[n - 1].code)
427 			return 0;
428 	} else {
429 		if (code < sc->sc_temps[0].code)
430 			return 0;
431 		if (code > sc->sc_temps[n - 1].code)
432 			return 0;
433 	}
434 	return 1;
435 }
436 
437 void
438 rktemp_refresh_sensors(void *arg)
439 {
440 	struct rktemp_softc *sc = arg;
441 	int32_t code, temp;
442 	int i;
443 
444 	for (i = 0; i < sc->sc_nsensors; i++) {
445 		code = HREAD4(sc, TSADC_DATA0 + i * 4);
446 		temp = rktemp_calc_temp(sc, code);
447 		sc->sc_sensors[i].value = 273150000 + 1000 * temp;
448 		if (rktemp_valid(sc, code))
449 			sc->sc_sensors[i].flags &= ~SENSOR_FINVALID;
450 		else
451 			sc->sc_sensors[i].flags |= SENSOR_FINVALID;
452 	}
453 }
454 
455 int32_t
456 rktemp_get_temperature(void *cookie, uint32_t *cells)
457 {
458 	struct rktemp_softc *sc = cookie;
459 	uint32_t idx = cells[0];
460 	int32_t code;
461 
462 	if (idx >= sc->sc_nsensors)
463 		return THERMAL_SENSOR_MAX;
464 
465 	code = HREAD4(sc, TSADC_DATA0 + idx * 4);
466 	if (rktemp_valid(sc, code))
467 		return rktemp_calc_temp(sc, code);
468 	else
469 		return THERMAL_SENSOR_MAX;
470 }
471