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