xref: /openbsd/sys/dev/fdt/rktemp.c (revision 274d7c50)
1 /*	$OpenBSD: rktemp.c,v 1.5 2019/07/02 20:14:44 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_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 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 *rk3288_names[] = { "", "CPU", "GPU" };
118 
119 /* RK3328 conversion table. */
120 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 *rk3328_names[] = { "CPU" };
157 
158 /* RK3399 conversion table. */
159 struct rktemp_entry rk3399_temps[] = {
160 	{ -40000, 402 },
161 	{ -35000, 410 },
162 	{ -30000, 419 },
163 	{ -25000, 427 },
164 	{ -20000, 436 },
165 	{ -15000, 444 },
166 	{ -10000, 453 },
167 	{  -5000, 461 },
168 	{      0, 470 },
169 	{   5000, 478 },
170 	{  10000, 487 },
171 	{  15000, 496 },
172 	{  20000, 504 },
173 	{  25000, 513 },
174 	{  30000, 521 },
175 	{  35000, 530 },
176 	{  40000, 538 },
177 	{  45000, 547 },
178 	{  50000, 555 },
179 	{  55000, 564 },
180 	{  60000, 573 },
181 	{  65000, 581 },
182 	{  70000, 590 },
183 	{  75000, 599 },
184 	{  80000, 607 },
185 	{  85000, 616 },
186 	{  90000, 624 },
187 	{  95000, 633 },
188 	{ 100000, 642 },
189 	{ 105000, 650 },
190 	{ 110000, 659 },
191 	{ 115000, 668 },
192 	{ 120000, 677 },
193 	{ 125000, 685 },
194 };
195 
196 const char *rk3399_names[] = { "CPU", "GPU" };
197 
198 struct rktemp_softc {
199 	struct device		sc_dev;
200 	bus_space_tag_t		sc_iot;
201 	bus_space_handle_t	sc_ioh;
202 
203 	struct rktemp_entry	*sc_temps;
204 	int			sc_ntemps;
205 
206 	struct ksensor		sc_sensors[3];
207 	int			sc_nsensors;
208 	struct ksensordev	sc_sensordev;
209 
210 	struct thermal_sensor	sc_ts;
211 };
212 
213 int	rktemp_match(struct device *, void *, void *);
214 void	rktemp_attach(struct device *, struct device *, void *);
215 
216 struct cfattach	rktemp_ca = {
217 	sizeof (struct rktemp_softc), rktemp_match, rktemp_attach
218 };
219 
220 struct cfdriver rktemp_cd = {
221 	NULL, "rktemp", DV_DULL
222 };
223 
224 int32_t rktemp_calc_code(struct rktemp_softc *, int32_t);
225 int32_t rktemp_calc_temp(struct rktemp_softc *, int32_t);
226 int	rktemp_valid(struct rktemp_softc *, int32_t);
227 void	rktemp_refresh_sensors(void *);
228 int32_t	rktemp_get_temperature(void *, uint32_t *);
229 
230 int
231 rktemp_match(struct device *parent, void *match, void *aux)
232 {
233 	struct fdt_attach_args *faa = aux;
234 
235 	return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-tsadc") ||
236 	    OF_is_compatible(faa->fa_node, "rockchip,rk3328-tsadc") ||
237 	    OF_is_compatible(faa->fa_node, "rockchip,rk3399-tsadc"));
238 }
239 
240 void
241 rktemp_attach(struct device *parent, struct device *self, void *aux)
242 {
243 	struct rktemp_softc *sc = (struct rktemp_softc *)self;
244 	struct fdt_attach_args *faa = aux;
245 	const char **names;
246 	uint32_t mode, polarity, temp;
247 	uint32_t auto_con, int_en;
248 	int node = faa->fa_node;
249 	int i;
250 
251 	if (faa->fa_nreg < 1) {
252 		printf(": no registers\n");
253 		return;
254 	}
255 
256 	sc->sc_iot = faa->fa_iot;
257 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
258 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
259 		printf(": can't map registers\n");
260 		return;
261 	}
262 
263 	printf("\n");
264 
265 	if (OF_is_compatible(node, "rockchip,rk3288-tsadc")) {
266 		sc->sc_temps = rk3288_temps;
267 		sc->sc_ntemps = nitems(rk3288_temps);
268 		sc->sc_nsensors = 3;
269 		names = rk3288_names;
270 	} else if (OF_is_compatible(node, "rockchip,rk3328-tsadc")) {
271 		sc->sc_temps = rk3328_temps;
272 		sc->sc_ntemps = nitems(rk3328_temps);
273 		sc->sc_nsensors = 1;
274 		names = rk3328_names;
275 	} else {
276 		sc->sc_temps = rk3399_temps;
277 		sc->sc_ntemps = nitems(rk3399_temps);
278 		sc->sc_nsensors = 2;
279 		names = rk3399_names;
280 	}
281 
282 	pinctrl_byname(node, "init");
283 
284 	clock_set_assigned(node);
285 	clock_enable(node, "tsadc");
286 	clock_enable(node, "apb_pclk");
287 
288 	/* Reset the TS-ADC controller block. */
289 	reset_assert(node, "tsadc-apb");
290 	delay(10);
291 	reset_deassert(node, "tsadc-apb");
292 
293 	mode = OF_getpropint(node, "rockchip,hw-tshut-mode", 1);
294 	polarity = OF_getpropint(node, "rockchip,hw-tshut-polarity", 0);
295 	temp = OF_getpropint(node, "rockchip,hw-tshut-temp", 95000);
296 
297 	auto_con = HREAD4(sc, TSADC_AUTO_CON);
298 	auto_con |= TSADC_AUTO_CON_TSADC_Q_SEL;
299 	if (polarity)
300 		auto_con |= TSADC_AUTO_CON_TSHUT_POLARITY;
301 	HWRITE4(sc, TSADC_AUTO_CON, auto_con);
302 
303 	/* Configure mode. */
304 	int_en = HREAD4(sc, TSADC_INT_EN);
305 	for (i = 0; i < sc->sc_nsensors; i++) {
306 		if (mode)
307 			int_en |= (TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 << i);
308 		else
309 			int_en |= (TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 << i);
310 	}
311 	HWRITE4(sc, TSADC_INT_EN, int_en);
312 
313 	/* Set shutdown limit. */
314 	for (i = 0; i < sc->sc_nsensors; i++) {
315 		HWRITE4(sc, TSADC_COMP0_SHUT + i * 4,
316 		    rktemp_calc_code(sc, temp));
317 		auto_con |= (TSADC_AUTO_CON_SRC0_EN << i);
318 	}
319 	HWRITE4(sc, TSADC_AUTO_CON, auto_con);
320 
321 	pinctrl_byname(faa->fa_node, "default");
322 
323 	/* Finally turn on the ADC. */
324 	auto_con |= TSADC_AUTO_CON_AUTO_EN;
325 	HWRITE4(sc, TSADC_AUTO_CON, auto_con);
326 
327 	/* Register sensors. */
328 	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
329 	    sizeof(sc->sc_sensordev.xname));
330 	for (i = 0; i < sc->sc_nsensors; i++) {
331 		strlcpy(sc->sc_sensors[i].desc, names[i],
332 		    sizeof(sc->sc_sensors[i].desc));
333 		sc->sc_sensors[i].type = SENSOR_TEMP;
334 		sc->sc_sensors[i].flags = SENSOR_FINVALID;
335 		sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
336 	}
337 	sensordev_install(&sc->sc_sensordev);
338 	sensor_task_register(sc, rktemp_refresh_sensors, 5);
339 
340 	sc->sc_ts.ts_node = node;
341 	sc->sc_ts.ts_cookie = sc;
342 	sc->sc_ts.ts_get_temperature = rktemp_get_temperature;
343 	thermal_sensor_register(&sc->sc_ts);
344 }
345 
346 int32_t
347 rktemp_calc_code(struct rktemp_softc *sc, int32_t temp)
348 {
349 	const int n = sc->sc_ntemps;
350 	int32_t code0, delta_code;
351 	int32_t temp0, delta_temp;
352 	int i;
353 
354 	if (temp <= sc->sc_temps[0].temp)
355 		return sc->sc_temps[0].code;
356 	if (temp >= sc->sc_temps[n - 1].temp)
357 		return sc->sc_temps[n - 1].code;
358 
359 	for (i = 1; i < n; i++) {
360 		if (temp < sc->sc_temps[i].temp)
361 			break;
362 	}
363 
364 	code0 = sc->sc_temps[i - 1].code;
365 	temp0 = sc->sc_temps[i - 1].temp;
366 	delta_code = sc->sc_temps[i].code - code0;
367 	delta_temp = sc->sc_temps[i].temp - temp0;
368 
369 	return code0 + (temp - temp0) * delta_code / delta_temp;
370 }
371 
372 int32_t
373 rktemp_calc_temp(struct rktemp_softc *sc, int32_t code)
374 {
375 	const int n = sc->sc_ntemps;
376 	int32_t code0, delta_code;
377 	int32_t temp0, delta_temp;
378 	int i;
379 
380 	/* Handle both negative and postive temperature coefficients. */
381 	if (sc->sc_temps[0].code > sc->sc_temps[1].code) {
382 		if (code >= sc->sc_temps[0].code)
383 			return sc->sc_temps[0].code;
384 		if (code <= sc->sc_temps[n - 1].code)
385 			return sc->sc_temps[n - 1].temp;
386 
387 		for (i = 1; i < n; i++) {
388 			if (code > sc->sc_temps[i].code)
389 				break;
390 		}
391 	} else {
392 		if (code <= sc->sc_temps[0].code)
393 			return sc->sc_temps[0].temp;
394 		if (code >= sc->sc_temps[n - 1].code)
395 			return sc->sc_temps[n - 1].temp;
396 
397 		for (i = 1; i < n; i++) {
398 			if (code < sc->sc_temps[i].code)
399 				break;
400 		}
401 	}
402 
403 	code0 = sc->sc_temps[i - 1].code;
404 	temp0 = sc->sc_temps[i - 1].temp;
405 	delta_code = sc->sc_temps[i].code - code0;
406 	delta_temp = sc->sc_temps[i].temp - temp0;
407 
408 	return temp0 + (code - code0) * delta_temp / delta_code;
409 }
410 
411 int
412 rktemp_valid(struct rktemp_softc *sc, int32_t code)
413 {
414 	const int n = sc->sc_ntemps;
415 
416 	if (sc->sc_temps[0].code > sc->sc_temps[1].code) {
417 		if (code > sc->sc_temps[0].code)
418 			return 0;
419 		if (code < sc->sc_temps[n - 1].code)
420 			return 0;
421 	} else {
422 		if (code < sc->sc_temps[0].code)
423 			return 0;
424 		if (code > sc->sc_temps[n - 1].code)
425 			return 0;
426 	}
427 	return 1;
428 }
429 
430 void
431 rktemp_refresh_sensors(void *arg)
432 {
433 	struct rktemp_softc *sc = arg;
434 	int32_t code, temp;
435 	int i;
436 
437 	for (i = 0; i < sc->sc_nsensors; i++) {
438 		code = HREAD4(sc, TSADC_DATA0 + i * 4);
439 		temp = rktemp_calc_temp(sc, code);
440 		sc->sc_sensors[i].value = 273150000 + 1000 * temp;
441 		if (rktemp_valid(sc, code))
442 			sc->sc_sensors[i].flags &= ~SENSOR_FINVALID;
443 		else
444 			sc->sc_sensors[i].flags |= SENSOR_FINVALID;
445 	}
446 }
447 
448 int32_t
449 rktemp_get_temperature(void *cookie, uint32_t *cells)
450 {
451 	struct rktemp_softc *sc = cookie;
452 	uint32_t idx = cells[0];
453 	int32_t code;
454 
455 	if (idx >= sc->sc_nsensors)
456 		return THERMAL_SENSOR_MAX;
457 
458 	code = HREAD4(sc, TSADC_DATA0 + idx * 4);
459 	if (rktemp_valid(sc, code))
460 		return rktemp_calc_temp(sc, code);
461 	else
462 		return THERMAL_SENSOR_MAX;
463 }
464