rk_tsadc.c revision 1.1 1 /* $NetBSD: rk_tsadc.c,v 1.1 2019/04/26 08:28:11 mrg Exp $ */
2
3 /*
4 * Copyright (c) 2019 Matthew R. Green
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32
33 __KERNEL_RCSID(0, "$NetBSD: rk_tsadc.c,v 1.1 2019/04/26 08:28:11 mrg Exp $");
34
35 /*
36 * Driver for the TSADC temperature sensor monitor in RK3328 and RK3399.
37 *
38 * TODO:
39 * - handle setting various temp values
40 * - add interpolation between the 5degC intervals in sample data
41 * - handle DT trips/temp value defaults
42 * - interrupts aren't triggered (test by lowering warn/crit values), and
43 * once they work, make the interrupt do something
44 * - test on RK3328, and port to other rockchips (will require moving some
45 * part into per-chipset sections, such as code<->temp tables)
46 */
47
48 #include <sys/param.h>
49 #include <sys/bus.h>
50 #include <sys/device.h>
51 #include <sys/intr.h>
52 #include <sys/systm.h>
53 #include <sys/time.h>
54 #include <sys/kmem.h>
55
56 #include <dev/fdt/fdtvar.h>
57 #include <dev/fdt/syscon.h>
58
59 #include <dev/sysmon/sysmonvar.h>
60
61 //#define RKTSADC_DEBUG
62 #ifdef RKTSADC_DEBUG
63 #define DPRINTF(fmt, ...) \
64 printf("%s:%d: " fmt "\n", __func__, __LINE__, ## __VA_ARGS__)
65 #else
66 #define DPRINTF(fmt, ...)
67 #endif
68
69 /* Register definitions */
70 #define TSADC_USER_CON 0x00
71 #define TSADC_USER_CON_ADC_STATUS __BIT(12)
72 #define TSADC_USER_CON_INTER_PD_SOC __BITS(11,6)
73 #define TSADC_USER_CON_START __BIT(5)
74 #define TSADC_USER_CON_START_MODE __BIT(4)
75 #define TSADC_USER_CON_ADC_POWER_CTRL __BIT(3)
76 #define TSADC_USER_CON_ADC_INPUT_SRC_SEL __BITS(2,0)
77 #define TSADC_AUTO_CON 0x04
78 #define TSADC_AUTO_CON_LAST_TSHUT_2CRU __BIT(25)
79 #define TSADC_AUTO_CON_LAST_TSHUT_2GPIO __BIT(24)
80 #define TSADC_AUTO_CON_SAMPLE_DLY_SEL __BIT(17)
81 #define TSADC_AUTO_CON_AUTO_STATUS __BIT(16)
82 #define TSADC_AUTO_CON_SRC1_LT_EN __BIT(13)
83 #define TSADC_AUTO_CON_SRC0_LT_EN __BIT(12)
84 #define TSADC_AUTO_CON_TSHUT_POLARITY __BIT(8)
85 #define TSADC_AUTO_CON_SRC1_EN __BIT(5)
86 #define TSADC_AUTO_CON_SRC0_EN __BIT(4)
87 #define TSADC_AUTO_CON_Q_SEL __BIT(1)
88 #define TSADC_AUTO_CON_AUTO_EN __BIT(0)
89 #define TSADC_INT_EN 0x08
90 #define TSADC_INT_EN_EOC_INT_EN __BIT(16)
91 #define TSADC_INT_EN_LT_INTEN_SRC1 __BIT(13)
92 #define TSADC_INT_EN_LT_INTEN_SRC0 __BIT(12)
93 #define TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 __BIT(9)
94 #define TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 __BIT(8)
95 #define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 __BIT(5)
96 #define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 __BIT(4)
97 #define TSADC_INT_EN_HT_INTEN_SRC1 __BIT(1)
98 #define TSADC_INT_EN_HT_INTEN_SRC0 __BIT(0)
99 #define TSADC_INT_PD 0x0c
100 #define TSADC_INT_PD_EOC_INT_PD __BIT(16)
101 #define TSADC_INT_PD_LT_IRQ_SRC1 __BIT(13)
102 #define TSADC_INT_PD_LT_IRQ_SRC0 __BIT(12)
103 #define TSADC_INT_PD_TSHUT_O_SRC1 __BIT(5)
104 #define TSADC_INT_PD_TSHUT_O_SRC0 __BIT(4)
105 #define TSADC_INT_PD_HT_IRQ_SRC1 __BIT(1)
106 #define TSADC_INT_PD_HT_IRQ_SRC0 __BIT(0)
107 #define TSADC_DATA0 0x20
108 #define TSADC_DATA0_ADC_DATA __BITS(11,0)
109 #define TSADC_DATA1 0x24
110 #define TSADC_DATA1_ADC_DATA __BITS(11,0)
111 #define TSADC_COMP0_INT 0x30
112 #define TSADC_COMP0_INT_COMP_SRC0 __BITS(11,0)
113 #define TSADC_COMP1_INT 0x34
114 #define TSADC_COMP1_INT_COMP_SRC1 __BITS(11,0)
115 #define TSADC_COMP0_SHUT 0x40
116 #define TSADC_COMP0_SHUT_COMP_SRC0 __BITS(11,0)
117 #define TSADC_COMP1_SHUT 0x44
118 #define TSADC_COMP1_SHUT_COMP_SRC1 __BITS(11,0)
119 #define TSADC_HIGH_INT_DEBOUNCE 0x60
120 #define TSADC_HIGH_INT_DEBOUNCE_TEMP __BITS(7,0)
121 #define TSADC_HIGH_TSHUT_DEBOUNCE 0x64
122 #define TSADC_HIGH_TSHUT_DEBOUNCE_TEMP __BITS(7,0)
123 #define TSADC_AUTO_PERIOD 0x68
124 #define TSADC_AUTO_PERIOD_TEMP __BITS(31,0)
125 #define TSADC_AUTO_PERIOD_HT 0x6c
126 #define TSADC_AUTO_PERIOD_HT_TEMP __BITS(31,0)
127 #define TSADC_COMP0_LOW_INT 0x80
128 #define TSADC_COMP0_LOW_INT_COMP_SRC0 __BITS(11,0)
129 #define TSADC_COMP1_LOW_INT 0x84
130 #define TSADC_COMP1_LOW_INT_COMP_SRC1 __BITS(11,0)
131
132 #define TSADC_AUTO_PERIOD_TIME 1875 /* 2.5ms */
133 #define TSADC_HT_DEBOUNCE_COUNT 4
134
135 /*
136 * All this magic is taking from the Linux rockchip_thermal driver.
137 *
138 * VCM means "voltage common mode", but the documentation for RK3399
139 * does not mention this and I don't know what any of this really
140 * is for.
141 */
142 #define RK3399_GRF_SARADC_TESTBIT 0xe644
143 #define RK3399_GRF_SARADC_TESTBIT_ON (0x10001 << 2)
144 #define RK3399_GRF_TSADC_TESTBIT_L 0xe648
145 #define RK3399_GRF_TSADC_TESTBIT_VCM_EN_L (0x10001 << 7)
146 #define RK3399_GRF_TSADC_TESTBIT_H 0xe64c
147 #define RK3399_GRF_TSADC_TESTBIT_VCM_EN_H (0x10001 << 7)
148 #define RK3399_GRF_TSADC_TESTBIT_H_ON (0x10001 << 2)
149
150 #define TEMP_uC_TO_uK 273150000
151
152 #define TSHUT_MODE_CPU 0
153 #define TSHUT_MODE_GPIO 1
154
155 #define TSHUT_LOW_ACTIVE 0
156 #define TSHUT_HIGH_ACTIVE 1
157
158 #define TSHUT_DEF_TEMP 95000
159
160 #define TSADC_DATA_MAX 0xfff
161
162 #define NUM_SENSORS 2
163
164 /* Table from RK3399 manual */
165 static const struct {
166 uint32_t data; /* register value */
167 int temp; /* micro-degC */
168 } rk3399_data_table[] = {
169 #define ENTRY(d,C) { .data = (d), .temp = (C) * 1000 * 1000, }
170 ENTRY(0, -40),
171 ENTRY(402, -40),
172 ENTRY(410, -35),
173 ENTRY(419, -30),
174 ENTRY(427, -25),
175 ENTRY(436, -20),
176 ENTRY(444, -15),
177 ENTRY(453, -10),
178 ENTRY(461, -5),
179 ENTRY(470, 0),
180 ENTRY(478, 5),
181 ENTRY(487, 10),
182 ENTRY(496, 15),
183 ENTRY(504, 20),
184 ENTRY(513, 25),
185 ENTRY(521, 30),
186 ENTRY(530, 35),
187 ENTRY(538, 40),
188 ENTRY(547, 45),
189 ENTRY(555, 50),
190 ENTRY(564, 55),
191 ENTRY(573, 60),
192 ENTRY(581, 65),
193 ENTRY(590, 70),
194 ENTRY(599, 75),
195 ENTRY(607, 80),
196 ENTRY(616, 85),
197 ENTRY(624, 90),
198 ENTRY(633, 95),
199 ENTRY(642, 100),
200 ENTRY(650, 105),
201 ENTRY(659, 110),
202 ENTRY(668, 115),
203 ENTRY(677, 120),
204 ENTRY(685, 125),
205 #undef ENTRY
206 };
207
208 /* Per-sensor data */
209 struct rk_tsadc_sensor {
210 envsys_data_t s_data;
211 bool s_attached;
212 /* TSADC register offsets for this sensor */
213 unsigned s_data_reg;
214 unsigned s_comp_tshut;
215 unsigned s_comp_int;
216 unsigned s_comp_int_en;
217 /* warn/crit values in micro Kelvin */
218 int s_warn;
219 int s_tshut;
220 };
221
222 struct rk_tsadc_softc {
223 device_t sc_dev;
224 int sc_phandle;
225 bus_space_tag_t sc_bst;
226 bus_space_handle_t sc_bsh;
227 size_t sc_size;
228 uint32_t sc_data_mask;
229 void *sc_ih;
230
231 struct sysmon_envsys *sc_sme;
232 struct rk_tsadc_sensor sc_sensors[NUM_SENSORS];
233
234 struct clk *sc_clock;
235 struct clk *sc_clockapb;
236 struct fdtbus_reset *sc_reset;
237 struct syscon *sc_syscon;
238 };
239
240 static int rk_tsadc_match(device_t, cfdata_t, void *);
241 static void rk_tsadc_attach(device_t, device_t, void *);
242 static int rk_tsadc_detach(device_t, int);
243 static int rk_tsadc_init_clocks(struct rk_tsadc_softc *);
244 static void rk_tsadc_init_counts(struct rk_tsadc_softc *);
245 static void rk_tsadc_tshut_set(struct rk_tsadc_softc *s);
246 static void rk_tsadc_init_tshut(struct rk_tsadc_softc *, int, int);
247 static void rk_tsadc_init_grf(struct rk_tsadc_softc *);
248 static void rk_tsadc_init_enable(struct rk_tsadc_softc *);
249 static void rk_tsadc_refresh(struct sysmon_envsys *, envsys_data_t *);
250 static void rk_tsadc_get_limits(struct sysmon_envsys *, envsys_data_t *,
251 sysmon_envsys_lim_t *, uint32_t *);
252
253 static int rk_tsadc_intr(void *);
254 static int rk_tsadc_data_to_temp(struct rk_tsadc_softc *, uint32_t);
255 static uint32_t rk_tsadc_temp_to_data(struct rk_tsadc_softc *, int);
256
257 /* RK3328/RK3399 compatible sensors */
258 static const struct rk_tsadc_sensor rk_tsadc_sensors[] = {
259 {
260 .s_data = { .desc = "CPU" },
261 .s_data_reg = TSADC_DATA0,
262 .s_comp_tshut = TSADC_COMP0_SHUT,
263 .s_comp_int = TSADC_COMP0_INT,
264 .s_comp_int_en = TSADC_AUTO_CON_SRC0_EN,
265 /*
266 * XXX DT has:
267 * cpu_alert1: cpu_alert1 {
268 * temperature = <75000>;
269 * hysteresis = <2000>;
270 * cpu_crit: cpu_crit {
271 * temperature = <95000>;
272 * hysteresis = <2000>;
273 * pull out of here?
274 * do something with hysteresis? put in debounce?
275 *
276 * Note that tshut may be overriden by the board specific DT.
277 */
278 .s_warn = 75000000,
279 .s_tshut = 95000000,
280 }, {
281 .s_data = { .desc = "GPU" },
282 .s_data_reg = TSADC_DATA1,
283 .s_comp_tshut = TSADC_COMP1_SHUT,
284 .s_comp_int = TSADC_COMP1_INT,
285 .s_comp_int_en = TSADC_AUTO_CON_SRC1_EN,
286 .s_warn = 75000000,
287 .s_tshut = 95000000,
288 },
289 };
290
291 static const char * const compatible[] = {
292 "rockchip,rk3328-tsadc",
293 "rockchip,rk3399-tsadc",
294 NULL
295 };
296
297 #define TSADC_READ(sc, reg) \
298 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
299 #define TSADC_WRITE(sc, reg, val) \
300 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
301
302 CFATTACH_DECL3_NEW(rk_tsadc, sizeof(struct rk_tsadc_softc),
303 rk_tsadc_match, rk_tsadc_attach, rk_tsadc_detach, NULL, NULL, NULL,
304 DVF_DETACH_SHUTDOWN);
305
306 /* init/teardown support */
307 static int
308 rk_tsadc_match(device_t parent, cfdata_t cf, void *aux)
309 {
310 struct fdt_attach_args * const faa = aux;
311
312 return of_match_compatible(faa->faa_phandle, compatible);
313 }
314
315 static void
316 rk_tsadc_attach(device_t parent, device_t self, void *aux)
317 {
318 struct rk_tsadc_softc * const sc = device_private(self);
319 struct fdt_attach_args * const faa = aux;
320 char intrstr[128];
321 const int phandle = faa->faa_phandle;
322 bus_addr_t addr;
323 int mode, polarity, tshut_temp;
324
325 sc->sc_dev = self;
326 sc->sc_phandle = phandle;
327 sc->sc_bst = faa->faa_bst;
328
329 aprint_naive("\n");
330 aprint_normal(": RK3328/3399 Temperature Sensor ADC\n");
331
332 sc->sc_sme = sysmon_envsys_create();
333
334 sc->sc_sme->sme_name = device_xname(self);
335 sc->sc_sme->sme_cookie = sc;
336 sc->sc_sme->sme_refresh = rk_tsadc_refresh;
337 sc->sc_sme->sme_get_limits = rk_tsadc_get_limits;
338 sc->sc_data_mask = 0xfff;
339
340 pmf_device_register(self, NULL, NULL);
341
342 /* Default to tshut via gpio and tshut low is active */
343 if (of_getprop_uint32(phandle, "rockchip,hw-tshut-mode",
344 &mode) != 0) {
345 aprint_error(": could not get TSHUT mode, default to GPIO");
346 mode = TSHUT_MODE_GPIO;
347 }
348 if (mode != TSHUT_MODE_CPU && mode != TSHUT_MODE_GPIO) {
349 aprint_error(": TSHUT mode should be 0 or 1\n");
350 goto fail;
351 }
352
353 if (of_getprop_uint32(phandle, "rockchip,hw-tshut-polarity",
354 &polarity) != 0) {
355 aprint_error(": could not get TSHUT polarity, default to low");
356 polarity = TSHUT_LOW_ACTIVE;
357 }
358 if (of_getprop_uint32(phandle,
359 "rockchip,hw-tshut-temp", &tshut_temp) != 0) {
360 aprint_error(": could not get TSHUT temperature, default to %u",
361 TSHUT_DEF_TEMP);
362 tshut_temp = TSHUT_DEF_TEMP;
363 }
364 tshut_temp *= 1000; /* convert fdt ms -> us */
365
366 memcpy(sc->sc_sensors, rk_tsadc_sensors, sizeof(sc->sc_sensors));
367 for (unsigned n = 0; n < NUM_SENSORS; n++) {
368 struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
369
370 rks->s_data.flags = ENVSYS_FMONLIMITS;
371 rks->s_data.units = ENVSYS_STEMP;
372 rks->s_data.state = ENVSYS_SINVALID;
373
374 if (sysmon_envsys_sensor_attach(sc->sc_sme, &rks->s_data))
375 goto fail;
376 rks->s_attached = true;
377 rks->s_tshut = tshut_temp;
378 #if 0
379 // testing
380 rks->s_tshut = 65000000;
381 rks->s_warn = 60000000;
382 #endif
383 }
384
385 sc->sc_syscon = fdtbus_syscon_acquire(phandle, "rockchip,grf");
386 if (sc->sc_syscon == NULL) {
387 aprint_error(": couldn't get grf syscon\n");
388 goto fail;
389 }
390 if (fdtbus_get_reg(phandle, 0, &addr, &sc->sc_size) != 0) {
391 aprint_error(": couldn't get registers\n");
392 sc->sc_size = 0;
393 goto fail;
394 }
395 if (bus_space_map(sc->sc_bst, addr, sc->sc_size, 0, &sc->sc_bsh) != 0) {
396 aprint_error(": couldn't map registers\n");
397 sc->sc_size = 0;
398 goto fail;
399 }
400
401 if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
402 aprint_error(": failed to decode interrupt\n");
403 goto fail;
404 }
405
406 sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_VM, FDT_INTR_MPSAFE,
407 rk_tsadc_intr, sc);
408 if (sc->sc_ih == NULL) {
409 aprint_error_dev(self, "couldn't establish interrupt on %s\n",
410 intrstr);
411 goto fail;
412 }
413 aprint_normal_dev(self, "interrupting on %s\n", intrstr);
414
415 if (rk_tsadc_init_clocks(sc)) {
416 aprint_error(": couldn't enable clocks\n");
417 return;
418 }
419
420 /*
421 * Manual says to setup auto period (both), high temp (interrupt),
422 * high temp (shutdown), enable high temp resets (TSHUT to GPIO
423 * or reset chip), set the debounce times, and, finally, enable the
424 * controller iself.
425 */
426 rk_tsadc_init_counts(sc);
427 rk_tsadc_init_tshut(sc, mode, polarity);
428 rk_tsadc_init_grf(sc);
429 rk_tsadc_init_enable(sc);
430
431 return;
432
433 fail:
434 rk_tsadc_detach(self, 0);
435 }
436
437 static int
438 rk_tsadc_detach(device_t self, int flags)
439 {
440 struct rk_tsadc_softc *sc = device_private(self);
441
442 pmf_device_deregister(self);
443
444 for (unsigned n = 0; n < NUM_SENSORS; n++) {
445 struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
446
447 if (rks->s_attached) {
448 sysmon_envsys_sensor_detach(sc->sc_sme, &rks->s_data);
449 rks->s_attached = false;
450 }
451 }
452
453 sysmon_envsys_unregister(sc->sc_sme);
454
455 if (sc->sc_clockapb)
456 clk_disable(sc->sc_clockapb);
457 if (sc->sc_clock)
458 clk_disable(sc->sc_clock);
459
460 if (sc->sc_ih)
461 fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_ih);
462
463 if (sc->sc_size)
464 bus_space_unmap(sc->sc_bst, sc->sc_bsh, sc->sc_size);
465
466 sysmon_envsys_destroy(sc->sc_sme);
467
468 return 0;
469 }
470
471 static int
472 rk_tsadc_init_clocks(struct rk_tsadc_softc *sc)
473 {
474 int error;
475
476 fdtbus_clock_assign(sc->sc_phandle);
477
478 sc->sc_reset = fdtbus_reset_get(sc->sc_phandle, "tsadc-apb");
479 sc->sc_clock = fdtbus_clock_get(sc->sc_phandle, "tsadc");
480 sc->sc_clockapb = fdtbus_clock_get(sc->sc_phandle, "apb_pclk");
481 if (sc->sc_reset == NULL ||
482 sc->sc_clock == NULL ||
483 sc->sc_clockapb == NULL)
484 return EINVAL;
485
486 fdtbus_reset_assert(sc->sc_reset);
487
488 error = clk_enable(sc->sc_clock);
489 if (error) {
490 fdtbus_reset_deassert(sc->sc_reset);
491 return error;
492 }
493
494 error = clk_enable(sc->sc_clockapb);
495
496 DELAY(20);
497 fdtbus_reset_deassert(sc->sc_reset);
498
499 return error;
500 }
501
502 static void
503 rk_tsadc_init_counts(struct rk_tsadc_softc *sc)
504 {
505
506 TSADC_WRITE(sc, TSADC_AUTO_PERIOD, TSADC_AUTO_PERIOD_TIME);
507 TSADC_WRITE(sc, TSADC_AUTO_PERIOD_HT, TSADC_AUTO_PERIOD_TIME);
508 TSADC_WRITE(sc, TSADC_HIGH_INT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT);
509 TSADC_WRITE(sc, TSADC_HIGH_TSHUT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT);
510 }
511
512 /* Configure the hardware with the tshut setup. */
513 static void
514 rk_tsadc_tshut_set(struct rk_tsadc_softc *sc)
515 {
516 uint32_t val = TSADC_READ(sc, TSADC_AUTO_CON);
517
518 for (unsigned n = 0; n < NUM_SENSORS; n++) {
519 struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
520 uint32_t data = rk_tsadc_temp_to_data(sc, rks->s_tshut);
521 uint32_t warndata = rk_tsadc_temp_to_data(sc, rks->s_warn);
522
523 DPRINTF("(%s:%s): tshut/data %d/%u warn/data %d/%u",
524 sc->sc_sme->sme_name, rks->s_data.desc,
525 rks->s_tshut, data,
526 rks->s_warn, warndata);
527
528 if (data == sc->sc_data_mask) {
529 aprint_error_dev(sc->sc_dev,
530 "Failed converting critical temp %u.%06u to code",
531 rks->s_tshut / 1000000, rks->s_tshut % 1000000);
532 continue;
533 }
534 if (warndata == sc->sc_data_mask) {
535 aprint_error_dev(sc->sc_dev,
536 "Failed converting warn temp %u.%06u to code",
537 rks->s_warn / 1000000, rks->s_warn % 1000000);
538 continue;
539 }
540
541 TSADC_WRITE(sc, rks->s_comp_tshut, data);
542 TSADC_WRITE(sc, rks->s_comp_int, warndata);
543
544 val |= rks->s_comp_int_en;
545 }
546 TSADC_WRITE(sc, TSADC_AUTO_CON, val);
547 }
548
549 static void
550 rk_tsadc_init_tshut(struct rk_tsadc_softc *sc, int mode, int polarity)
551 {
552 uint32_t val;
553
554 /* Handle TSHUT temp setting. */
555 rk_tsadc_tshut_set(sc);
556
557 /* Handle TSHUT mode setting. */
558 val = TSADC_READ(sc, TSADC_INT_EN);
559 if (mode == TSHUT_MODE_CPU) {
560 val |= TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 |
561 TSADC_INT_EN_TSHUT_2CRU_EN_SRC0;
562 val &= ~(TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 |
563 TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0);
564 } else {
565 KASSERT(mode == TSHUT_MODE_GPIO);
566 val &= ~(TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 |
567 TSADC_INT_EN_TSHUT_2CRU_EN_SRC0);
568 val &= TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 |
569 TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0;
570 }
571 TSADC_WRITE(sc, TSADC_INT_EN, val);
572
573 /* Handle TSHUT polarity setting. */
574 val = TSADC_READ(sc, TSADC_AUTO_CON);
575 if (polarity == TSHUT_HIGH_ACTIVE)
576 val |= TSADC_AUTO_CON_TSHUT_POLARITY;
577 else
578 val &= ~TSADC_AUTO_CON_TSHUT_POLARITY;
579 TSADC_WRITE(sc, TSADC_AUTO_CON, val);
580 }
581
582 static void
583 rk_tsadc_init_grf(struct rk_tsadc_softc *sc)
584 {
585
586 syscon_lock(sc->sc_syscon);
587 syscon_write_4(sc->sc_syscon, RK3399_GRF_TSADC_TESTBIT_L,
588 RK3399_GRF_TSADC_TESTBIT_VCM_EN_L);
589 syscon_write_4(sc->sc_syscon, RK3399_GRF_TSADC_TESTBIT_H,
590 RK3399_GRF_TSADC_TESTBIT_VCM_EN_H);
591
592 DELAY(20);
593 syscon_write_4(sc->sc_syscon, RK3399_GRF_SARADC_TESTBIT,
594 RK3399_GRF_SARADC_TESTBIT_ON);
595 syscon_write_4(sc->sc_syscon, RK3399_GRF_TSADC_TESTBIT_H,
596 RK3399_GRF_TSADC_TESTBIT_H_ON);
597 DELAY(100);
598 syscon_unlock(sc->sc_syscon);
599 }
600
601 static void
602 rk_tsadc_init_enable(struct rk_tsadc_softc *sc)
603 {
604 uint32_t val;
605
606 val = TSADC_READ(sc, TSADC_AUTO_CON);
607 val |= TSADC_AUTO_CON_AUTO_STATUS |
608 TSADC_AUTO_CON_SRC1_LT_EN | TSADC_AUTO_CON_SRC0_LT_EN |
609 TSADC_AUTO_CON_SRC1_EN | TSADC_AUTO_CON_SRC0_EN;
610 TSADC_WRITE(sc, TSADC_AUTO_CON, val);
611
612 /* Finally, register & enable the controller */
613 sysmon_envsys_register(sc->sc_sme);
614
615 val = TSADC_READ(sc, TSADC_AUTO_CON);
616 val |= TSADC_AUTO_CON_AUTO_EN | TSADC_AUTO_CON_Q_SEL;
617 TSADC_WRITE(sc, TSADC_AUTO_CON, val);
618 }
619
620 /* run time support */
621
622 static struct rk_tsadc_sensor *
623 rk_tsadc_edata_to_sensor(struct rk_tsadc_softc * const sc, envsys_data_t *edata)
624 {
625 for (unsigned n = 0; n < NUM_SENSORS; n++) {
626 struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
627
628 if (&rks->s_data == edata)
629 return rks;
630 }
631 return NULL;
632 }
633
634 static void
635 rk_tsadc_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
636 {
637 struct rk_tsadc_softc * const sc = sme->sme_cookie;
638 struct rk_tsadc_sensor *rks = rk_tsadc_edata_to_sensor(sc, edata);
639 unsigned data;
640 int temp;
641
642 if (rks == NULL)
643 return;
644
645 data = TSADC_READ(sc, rks->s_data_reg) & sc->sc_data_mask;
646 temp = rk_tsadc_data_to_temp(sc, data);
647
648 if (temp == sc->sc_data_mask) {
649 edata->state = ENVSYS_SINVALID;
650 } else {
651 edata->value_cur = temp + TEMP_uC_TO_uK;
652 edata->state = ENVSYS_SVALID;
653 }
654 }
655
656 static void
657 rk_tsadc_get_limits(struct sysmon_envsys *sme,
658 envsys_data_t *edata,
659 sysmon_envsys_lim_t *lim,
660 uint32_t *props)
661 {
662 struct rk_tsadc_softc *sc = sme->sme_cookie;
663 struct rk_tsadc_sensor *rks = rk_tsadc_edata_to_sensor(sc, edata);
664
665 if (rks == NULL)
666 return;
667
668 lim->sel_critmax = rks->s_tshut + TEMP_uC_TO_uK;
669 lim->sel_warnmax = rks->s_warn + TEMP_uC_TO_uK;
670
671 *props = PROP_CRITMAX | PROP_WARNMAX;
672 }
673
674 /* XXX do something with interrupts that don't happen yet. */
675 static int
676 rk_tsadc_intr(void *arg)
677 {
678 struct rk_tsadc_softc * const sc = arg;
679 uint32_t val;
680
681 /* XXX */
682 DPRINTF("(%s): interrupted", sc->sc_sme->sme_name);
683 for (unsigned n; n < __arraycount(rk_tsadc_sensors); n++) {
684 struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
685
686 rk_tsadc_refresh(sc->sc_sme, (envsys_data_t *)rks);
687 }
688
689 /* ack interrupt */
690 val = TSADC_READ(sc, TSADC_INT_PD);
691 TSADC_WRITE(sc, TSADC_INT_PD, val & ~TSADC_INT_PD_EOC_INT_PD);
692
693 return 1;
694 }
695
696 /*
697 * Convert TDASC data codes to temp and reverse. The manual only has codes
698 * and temperature values in 5 degC intervals, but says that interpolation
699 * can be done to achieve better resolution between these values, and that
700 * the spacing is linear.
701 *
702 * XXX The sub-entry interpolation is not yet done.
703 */
704 static int
705 rk_tsadc_data_to_temp(struct rk_tsadc_softc *sc, uint32_t data)
706 {
707 unsigned i;
708
709 for (i = 1; i < __arraycount(rk3399_data_table); i++) {
710 if (rk3399_data_table[i].data >= data) {
711 if (rk3399_data_table[i].data == data)
712 return rk3399_data_table[i].temp;
713 /* XXX interpolate */
714 return rk3399_data_table[i-1].temp;
715 }
716 }
717
718 return rk3399_data_table[i-1].temp;
719 }
720
721 static uint32_t
722 rk_tsadc_temp_to_data(struct rk_tsadc_softc *sc, int temp)
723 {
724 unsigned i;
725
726 for (i = 1; i < __arraycount(rk3399_data_table); i++) {
727 if (rk3399_data_table[i].temp >= temp) {
728 if (rk3399_data_table[i].temp == temp)
729 return rk3399_data_table[i].data;
730 /* XXX interpolate */
731 return rk3399_data_table[i-1].data;
732 }
733 }
734
735 return sc->sc_data_mask;
736 }
737