rk_tsadc.c revision 1.2 1 /* $NetBSD: rk_tsadc.c,v 1.2 2019/04/26 10:20:09 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.2 2019/04/26 10:20:09 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 * - handle DT trips/temp value defaults
41 * - interrupts aren't triggered (test by lowering warn/crit values), and
42 * once they work, make the interrupt do something
43 * - test on RK3328, and port to other rockchips (will require moving some
44 * part into per-chipset sections, such as code<->temp tables)
45 */
46
47 #include <sys/param.h>
48 #include <sys/bus.h>
49 #include <sys/device.h>
50 #include <sys/intr.h>
51 #include <sys/systm.h>
52 #include <sys/time.h>
53 #include <sys/kmem.h>
54
55 #include <dev/fdt/fdtvar.h>
56 #include <dev/fdt/syscon.h>
57
58 #include <dev/sysmon/sysmonvar.h>
59
60 //#define RKTSADC_DEBUG
61 #ifdef RKTSADC_DEBUG
62 #define DPRINTF(fmt, ...) \
63 printf("%s:%d: " fmt "\n", __func__, __LINE__, ## __VA_ARGS__)
64 #else
65 #define DPRINTF(fmt, ...)
66 #endif
67
68 /* Register definitions */
69 #define TSADC_USER_CON 0x00
70 #define TSADC_USER_CON_ADC_STATUS __BIT(12)
71 #define TSADC_USER_CON_INTER_PD_SOC __BITS(11,6)
72 #define TSADC_USER_CON_START __BIT(5)
73 #define TSADC_USER_CON_START_MODE __BIT(4)
74 #define TSADC_USER_CON_ADC_POWER_CTRL __BIT(3)
75 #define TSADC_USER_CON_ADC_INPUT_SRC_SEL __BITS(2,0)
76 #define TSADC_AUTO_CON 0x04
77 #define TSADC_AUTO_CON_LAST_TSHUT_2CRU __BIT(25)
78 #define TSADC_AUTO_CON_LAST_TSHUT_2GPIO __BIT(24)
79 #define TSADC_AUTO_CON_SAMPLE_DLY_SEL __BIT(17)
80 #define TSADC_AUTO_CON_AUTO_STATUS __BIT(16)
81 #define TSADC_AUTO_CON_SRC1_LT_EN __BIT(13)
82 #define TSADC_AUTO_CON_SRC0_LT_EN __BIT(12)
83 #define TSADC_AUTO_CON_TSHUT_POLARITY __BIT(8)
84 #define TSADC_AUTO_CON_SRC1_EN __BIT(5)
85 #define TSADC_AUTO_CON_SRC0_EN __BIT(4)
86 #define TSADC_AUTO_CON_Q_SEL __BIT(1)
87 #define TSADC_AUTO_CON_AUTO_EN __BIT(0)
88 #define TSADC_INT_EN 0x08
89 #define TSADC_INT_EN_EOC_INT_EN __BIT(16)
90 #define TSADC_INT_EN_LT_INTEN_SRC1 __BIT(13)
91 #define TSADC_INT_EN_LT_INTEN_SRC0 __BIT(12)
92 #define TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 __BIT(9)
93 #define TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 __BIT(8)
94 #define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 __BIT(5)
95 #define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 __BIT(4)
96 #define TSADC_INT_EN_HT_INTEN_SRC1 __BIT(1)
97 #define TSADC_INT_EN_HT_INTEN_SRC0 __BIT(0)
98 #define TSADC_INT_PD 0x0c
99 #define TSADC_INT_PD_EOC_INT_PD __BIT(16)
100 #define TSADC_INT_PD_LT_IRQ_SRC1 __BIT(13)
101 #define TSADC_INT_PD_LT_IRQ_SRC0 __BIT(12)
102 #define TSADC_INT_PD_TSHUT_O_SRC1 __BIT(5)
103 #define TSADC_INT_PD_TSHUT_O_SRC0 __BIT(4)
104 #define TSADC_INT_PD_HT_IRQ_SRC1 __BIT(1)
105 #define TSADC_INT_PD_HT_IRQ_SRC0 __BIT(0)
106 #define TSADC_DATA0 0x20
107 #define TSADC_DATA0_ADC_DATA __BITS(11,0)
108 #define TSADC_DATA1 0x24
109 #define TSADC_DATA1_ADC_DATA __BITS(11,0)
110 #define TSADC_COMP0_INT 0x30
111 #define TSADC_COMP0_INT_COMP_SRC0 __BITS(11,0)
112 #define TSADC_COMP1_INT 0x34
113 #define TSADC_COMP1_INT_COMP_SRC1 __BITS(11,0)
114 #define TSADC_COMP0_SHUT 0x40
115 #define TSADC_COMP0_SHUT_COMP_SRC0 __BITS(11,0)
116 #define TSADC_COMP1_SHUT 0x44
117 #define TSADC_COMP1_SHUT_COMP_SRC1 __BITS(11,0)
118 #define TSADC_HIGH_INT_DEBOUNCE 0x60
119 #define TSADC_HIGH_INT_DEBOUNCE_TEMP __BITS(7,0)
120 #define TSADC_HIGH_TSHUT_DEBOUNCE 0x64
121 #define TSADC_HIGH_TSHUT_DEBOUNCE_TEMP __BITS(7,0)
122 #define TSADC_AUTO_PERIOD 0x68
123 #define TSADC_AUTO_PERIOD_TEMP __BITS(31,0)
124 #define TSADC_AUTO_PERIOD_HT 0x6c
125 #define TSADC_AUTO_PERIOD_HT_TEMP __BITS(31,0)
126 #define TSADC_COMP0_LOW_INT 0x80
127 #define TSADC_COMP0_LOW_INT_COMP_SRC0 __BITS(11,0)
128 #define TSADC_COMP1_LOW_INT 0x84
129 #define TSADC_COMP1_LOW_INT_COMP_SRC1 __BITS(11,0)
130
131 #define TSADC_AUTO_PERIOD_TIME 1875 /* 2.5ms */
132 #define TSADC_HT_DEBOUNCE_COUNT 4
133
134 /*
135 * All this magic is taking from the Linux rockchip_thermal driver.
136 *
137 * VCM means "voltage common mode", but the documentation for RK3399
138 * does not mention this and I don't know what any of this really
139 * is for.
140 */
141 #define RK3399_GRF_SARADC_TESTBIT 0xe644
142 #define RK3399_GRF_SARADC_TESTBIT_ON (0x10001 << 2)
143 #define RK3399_GRF_TSADC_TESTBIT_L 0xe648
144 #define RK3399_GRF_TSADC_TESTBIT_VCM_EN_L (0x10001 << 7)
145 #define RK3399_GRF_TSADC_TESTBIT_H 0xe64c
146 #define RK3399_GRF_TSADC_TESTBIT_VCM_EN_H (0x10001 << 7)
147 #define RK3399_GRF_TSADC_TESTBIT_H_ON (0x10001 << 2)
148
149 #define TEMP_uC_TO_uK 273150000
150
151 #define TSHUT_MODE_CPU 0
152 #define TSHUT_MODE_GPIO 1
153
154 #define TSHUT_LOW_ACTIVE 0
155 #define TSHUT_HIGH_ACTIVE 1
156
157 #define TSHUT_DEF_TEMP 95000
158
159 #define TSADC_DATA_MAX 0xfff
160
161 #define NUM_SENSORS 2
162
163 /* Table from RK3399 manual */
164 static const struct {
165 uint32_t data; /* register value */
166 int temp; /* micro-degC */
167 } rk3399_data_table[] = {
168 #define ENTRY(d,C) { .data = (d), .temp = (C) * 1000 * 1000, }
169 ENTRY(0, -40),
170 ENTRY(402, -40),
171 ENTRY(410, -35),
172 ENTRY(419, -30),
173 ENTRY(427, -25),
174 ENTRY(436, -20),
175 ENTRY(444, -15),
176 ENTRY(453, -10),
177 ENTRY(461, -5),
178 ENTRY(470, 0),
179 ENTRY(478, 5),
180 ENTRY(487, 10),
181 ENTRY(496, 15),
182 ENTRY(504, 20),
183 ENTRY(513, 25),
184 ENTRY(521, 30),
185 ENTRY(530, 35),
186 ENTRY(538, 40),
187 ENTRY(547, 45),
188 ENTRY(555, 50),
189 ENTRY(564, 55),
190 ENTRY(573, 60),
191 ENTRY(581, 65),
192 ENTRY(590, 70),
193 ENTRY(599, 75),
194 ENTRY(607, 80),
195 ENTRY(616, 85),
196 ENTRY(624, 90),
197 ENTRY(633, 95),
198 ENTRY(642, 100),
199 ENTRY(650, 105),
200 ENTRY(659, 110),
201 ENTRY(668, 115),
202 ENTRY(677, 120),
203 ENTRY(685, 125),
204 ENTRY(TSADC_DATA_MAX, 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 /* enable bit in AUTO_CON register */
217 unsigned s_comp_int_en;
218 /* warn/crit values in micro Kelvin */
219 int s_warn;
220 int s_tshut;
221 };
222
223 struct rk_tsadc_softc {
224 device_t sc_dev;
225 int sc_phandle;
226 bus_space_tag_t sc_bst;
227 bus_space_handle_t sc_bsh;
228 size_t sc_size;
229 uint32_t sc_data_mask;
230 void *sc_ih;
231
232 struct sysmon_envsys *sc_sme;
233 struct rk_tsadc_sensor sc_sensors[NUM_SENSORS];
234
235 struct clk *sc_clock;
236 struct clk *sc_clockapb;
237 struct fdtbus_reset *sc_reset;
238 struct syscon *sc_syscon;
239 };
240
241 static int rk_tsadc_match(device_t, cfdata_t, void *);
242 static void rk_tsadc_attach(device_t, device_t, void *);
243 static int rk_tsadc_detach(device_t, int);
244 static int rk_tsadc_init_clocks(struct rk_tsadc_softc *);
245 static void rk_tsadc_init_counts(struct rk_tsadc_softc *);
246 static void rk_tsadc_tshut_set(struct rk_tsadc_softc *s);
247 static void rk_tsadc_init_tshut(struct rk_tsadc_softc *, int, int);
248 static void rk_tsadc_init_grf(struct rk_tsadc_softc *);
249 static void rk_tsadc_init_enable(struct rk_tsadc_softc *);
250 static void rk_tsadc_refresh(struct sysmon_envsys *, envsys_data_t *);
251 static void rk_tsadc_get_limits(struct sysmon_envsys *, envsys_data_t *,
252 sysmon_envsys_lim_t *, uint32_t *);
253
254 static int rk_tsadc_intr(void *);
255 static int rk_tsadc_data_to_temp(struct rk_tsadc_softc *, uint32_t);
256 static uint32_t rk_tsadc_temp_to_data(struct rk_tsadc_softc *, int);
257
258 /* RK3328/RK3399 compatible sensors */
259 static const struct rk_tsadc_sensor rk_tsadc_sensors[] = {
260 {
261 .s_data = { .desc = "CPU" },
262 .s_data_reg = TSADC_DATA0,
263 .s_comp_tshut = TSADC_COMP0_SHUT,
264 .s_comp_int = TSADC_COMP0_INT,
265 .s_comp_int_en = TSADC_AUTO_CON_SRC0_EN,
266 /*
267 * XXX DT has:
268 * cpu_alert1: cpu_alert1 {
269 * temperature = <75000>;
270 * hysteresis = <2000>;
271 * cpu_crit: cpu_crit {
272 * temperature = <95000>;
273 * hysteresis = <2000>;
274 * pull out of here?
275 * do something with hysteresis? put in debounce?
276 *
277 * Note that tshut may be overriden by the board specific DT.
278 */
279 .s_warn = 75000000,
280 .s_tshut = 95000000,
281 }, {
282 .s_data = { .desc = "GPU" },
283 .s_data_reg = TSADC_DATA1,
284 .s_comp_tshut = TSADC_COMP1_SHUT,
285 .s_comp_int = TSADC_COMP1_INT,
286 .s_comp_int_en = TSADC_AUTO_CON_SRC1_EN,
287 .s_warn = 75000000,
288 .s_tshut = 95000000,
289 },
290 };
291
292 static const char * const compatible[] = {
293 "rockchip,rk3328-tsadc",
294 "rockchip,rk3399-tsadc",
295 NULL
296 };
297
298 #define TSADC_READ(sc, reg) \
299 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
300 #define TSADC_WRITE(sc, reg, val) \
301 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
302
303 CFATTACH_DECL3_NEW(rk_tsadc, sizeof(struct rk_tsadc_softc),
304 rk_tsadc_match, rk_tsadc_attach, rk_tsadc_detach, NULL, NULL, NULL,
305 DVF_DETACH_SHUTDOWN);
306
307 /* init/teardown support */
308 static int
309 rk_tsadc_match(device_t parent, cfdata_t cf, void *aux)
310 {
311 struct fdt_attach_args * const faa = aux;
312
313 return of_match_compatible(faa->faa_phandle, compatible);
314 }
315
316 static void
317 rk_tsadc_attach(device_t parent, device_t self, void *aux)
318 {
319 struct rk_tsadc_softc * const sc = device_private(self);
320 struct fdt_attach_args * const faa = aux;
321 char intrstr[128];
322 const int phandle = faa->faa_phandle;
323 bus_addr_t addr;
324 int mode, polarity, tshut_temp;
325
326 sc->sc_dev = self;
327 sc->sc_phandle = phandle;
328 sc->sc_bst = faa->faa_bst;
329
330 aprint_naive("\n");
331 aprint_normal(": RK3328/3399 Temperature Sensor ADC\n");
332
333 sc->sc_sme = sysmon_envsys_create();
334
335 sc->sc_sme->sme_name = device_xname(self);
336 sc->sc_sme->sme_cookie = sc;
337 sc->sc_sme->sme_refresh = rk_tsadc_refresh;
338 sc->sc_sme->sme_get_limits = rk_tsadc_get_limits;
339 sc->sc_data_mask = TSADC_DATA_MAX;
340
341 pmf_device_register(self, NULL, NULL);
342
343 /* Default to tshut via gpio and tshut low is active */
344 if (of_getprop_uint32(phandle, "rockchip,hw-tshut-mode",
345 &mode) != 0) {
346 aprint_error(": could not get TSHUT mode, default to GPIO");
347 mode = TSHUT_MODE_GPIO;
348 }
349 if (mode != TSHUT_MODE_CPU && mode != TSHUT_MODE_GPIO) {
350 aprint_error(": TSHUT mode should be 0 or 1\n");
351 goto fail;
352 }
353
354 if (of_getprop_uint32(phandle, "rockchip,hw-tshut-polarity",
355 &polarity) != 0) {
356 aprint_error(": could not get TSHUT polarity, default to low");
357 polarity = TSHUT_LOW_ACTIVE;
358 }
359 if (of_getprop_uint32(phandle,
360 "rockchip,hw-tshut-temp", &tshut_temp) != 0) {
361 aprint_error(": could not get TSHUT temperature, default to %u",
362 TSHUT_DEF_TEMP);
363 tshut_temp = TSHUT_DEF_TEMP;
364 }
365 tshut_temp *= 1000; /* convert fdt ms -> us */
366
367 memcpy(sc->sc_sensors, rk_tsadc_sensors, sizeof(sc->sc_sensors));
368 for (unsigned n = 0; n < NUM_SENSORS; n++) {
369 struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
370
371 rks->s_data.flags = ENVSYS_FMONLIMITS;
372 rks->s_data.units = ENVSYS_STEMP;
373 rks->s_data.state = ENVSYS_SINVALID;
374
375 if (sysmon_envsys_sensor_attach(sc->sc_sme, &rks->s_data))
376 goto fail;
377 rks->s_attached = true;
378 rks->s_tshut = tshut_temp;
379 #if 1
380 // testing
381 rks->s_tshut = 68000000;
382 rks->s_warn = 61000000;
383 #endif
384 }
385
386 sc->sc_syscon = fdtbus_syscon_acquire(phandle, "rockchip,grf");
387 if (sc->sc_syscon == NULL) {
388 aprint_error(": couldn't get grf syscon\n");
389 goto fail;
390 }
391 if (fdtbus_get_reg(phandle, 0, &addr, &sc->sc_size) != 0) {
392 aprint_error(": couldn't get registers\n");
393 sc->sc_size = 0;
394 goto fail;
395 }
396 if (bus_space_map(sc->sc_bst, addr, sc->sc_size, 0, &sc->sc_bsh) != 0) {
397 aprint_error(": couldn't map registers\n");
398 sc->sc_size = 0;
399 goto fail;
400 }
401
402 if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
403 aprint_error(": failed to decode interrupt\n");
404 goto fail;
405 }
406
407 sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_VM, FDT_INTR_MPSAFE,
408 rk_tsadc_intr, sc);
409 if (sc->sc_ih == NULL) {
410 aprint_error_dev(self, "couldn't establish interrupt on %s\n",
411 intrstr);
412 goto fail;
413 }
414 aprint_normal_dev(self, "interrupting on %s\n", intrstr);
415
416 if (rk_tsadc_init_clocks(sc)) {
417 aprint_error(": couldn't enable clocks\n");
418 return;
419 }
420
421 /*
422 * Manual says to setup auto period (both), high temp (interrupt),
423 * high temp (shutdown), enable high temp resets (TSHUT to GPIO
424 * or reset chip), set the debounce times, and, finally, enable the
425 * controller iself.
426 */
427 rk_tsadc_init_counts(sc);
428 rk_tsadc_init_tshut(sc, mode, polarity);
429 rk_tsadc_init_grf(sc);
430 rk_tsadc_init_enable(sc);
431
432 return;
433
434 fail:
435 rk_tsadc_detach(self, 0);
436 }
437
438 static int
439 rk_tsadc_detach(device_t self, int flags)
440 {
441 struct rk_tsadc_softc *sc = device_private(self);
442
443 pmf_device_deregister(self);
444
445 for (unsigned n = 0; n < NUM_SENSORS; n++) {
446 struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
447
448 if (rks->s_attached) {
449 sysmon_envsys_sensor_detach(sc->sc_sme, &rks->s_data);
450 rks->s_attached = false;
451 }
452 }
453
454 sysmon_envsys_unregister(sc->sc_sme);
455
456 if (sc->sc_clockapb)
457 clk_disable(sc->sc_clockapb);
458 if (sc->sc_clock)
459 clk_disable(sc->sc_clock);
460
461 if (sc->sc_ih)
462 fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_ih);
463
464 if (sc->sc_size)
465 bus_space_unmap(sc->sc_bst, sc->sc_bsh, sc->sc_size);
466
467 sysmon_envsys_destroy(sc->sc_sme);
468
469 return 0;
470 }
471
472 static int
473 rk_tsadc_init_clocks(struct rk_tsadc_softc *sc)
474 {
475 int error;
476
477 fdtbus_clock_assign(sc->sc_phandle);
478
479 sc->sc_reset = fdtbus_reset_get(sc->sc_phandle, "tsadc-apb");
480 sc->sc_clock = fdtbus_clock_get(sc->sc_phandle, "tsadc");
481 sc->sc_clockapb = fdtbus_clock_get(sc->sc_phandle, "apb_pclk");
482 if (sc->sc_reset == NULL ||
483 sc->sc_clock == NULL ||
484 sc->sc_clockapb == NULL)
485 return EINVAL;
486
487 fdtbus_reset_assert(sc->sc_reset);
488
489 error = clk_enable(sc->sc_clock);
490 if (error) {
491 fdtbus_reset_deassert(sc->sc_reset);
492 return error;
493 }
494
495 error = clk_enable(sc->sc_clockapb);
496
497 DELAY(20);
498 fdtbus_reset_deassert(sc->sc_reset);
499
500 return error;
501 }
502
503 static void
504 rk_tsadc_init_counts(struct rk_tsadc_softc *sc)
505 {
506
507 TSADC_WRITE(sc, TSADC_AUTO_PERIOD, TSADC_AUTO_PERIOD_TIME);
508 TSADC_WRITE(sc, TSADC_AUTO_PERIOD_HT, TSADC_AUTO_PERIOD_TIME);
509 TSADC_WRITE(sc, TSADC_HIGH_INT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT);
510 TSADC_WRITE(sc, TSADC_HIGH_TSHUT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT);
511 }
512
513 /* Configure the hardware with the tshut setup. */
514 static void
515 rk_tsadc_tshut_set(struct rk_tsadc_softc *sc)
516 {
517 uint32_t val = TSADC_READ(sc, TSADC_AUTO_CON);
518
519 for (unsigned n = 0; n < NUM_SENSORS; n++) {
520 struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
521 uint32_t data = rk_tsadc_temp_to_data(sc, rks->s_tshut);
522 uint32_t warndata = rk_tsadc_temp_to_data(sc, rks->s_warn);
523
524 DPRINTF("(%s:%s): tshut/data %d/%u warn/data %d/%u",
525 sc->sc_sme->sme_name, rks->s_data.desc,
526 rks->s_tshut, data,
527 rks->s_warn, warndata);
528
529 if (data == sc->sc_data_mask) {
530 aprint_error_dev(sc->sc_dev,
531 "Failed converting critical temp %u.%06u to code",
532 rks->s_tshut / 1000000, rks->s_tshut % 1000000);
533 continue;
534 }
535 if (warndata == sc->sc_data_mask) {
536 aprint_error_dev(sc->sc_dev,
537 "Failed converting warn temp %u.%06u to code",
538 rks->s_warn / 1000000, rks->s_warn % 1000000);
539 continue;
540 }
541
542 TSADC_WRITE(sc, rks->s_comp_tshut, data);
543 TSADC_WRITE(sc, rks->s_comp_int, warndata);
544
545 val |= rks->s_comp_int_en;
546 }
547 TSADC_WRITE(sc, TSADC_AUTO_CON, val);
548 }
549
550 static void
551 rk_tsadc_init_tshut(struct rk_tsadc_softc *sc, int mode, int polarity)
552 {
553 uint32_t val;
554
555 /* Handle TSHUT temp setting. */
556 rk_tsadc_tshut_set(sc);
557
558 /* Handle TSHUT mode setting. */
559 val = TSADC_READ(sc, TSADC_INT_EN);
560 if (mode == TSHUT_MODE_CPU) {
561 val |= TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 |
562 TSADC_INT_EN_TSHUT_2CRU_EN_SRC0;
563 val &= ~(TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 |
564 TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0);
565 } else {
566 KASSERT(mode == TSHUT_MODE_GPIO);
567 val &= ~(TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 |
568 TSADC_INT_EN_TSHUT_2CRU_EN_SRC0);
569 val &= TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 |
570 TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0;
571 }
572 TSADC_WRITE(sc, TSADC_INT_EN, val);
573
574 /* Handle TSHUT polarity setting. */
575 val = TSADC_READ(sc, TSADC_AUTO_CON);
576 if (polarity == TSHUT_HIGH_ACTIVE)
577 val |= TSADC_AUTO_CON_TSHUT_POLARITY;
578 else
579 val &= ~TSADC_AUTO_CON_TSHUT_POLARITY;
580 TSADC_WRITE(sc, TSADC_AUTO_CON, val);
581 }
582
583 static void
584 rk_tsadc_init_grf(struct rk_tsadc_softc *sc)
585 {
586
587 syscon_lock(sc->sc_syscon);
588 syscon_write_4(sc->sc_syscon, RK3399_GRF_TSADC_TESTBIT_L,
589 RK3399_GRF_TSADC_TESTBIT_VCM_EN_L);
590 syscon_write_4(sc->sc_syscon, RK3399_GRF_TSADC_TESTBIT_H,
591 RK3399_GRF_TSADC_TESTBIT_VCM_EN_H);
592
593 DELAY(20);
594 syscon_write_4(sc->sc_syscon, RK3399_GRF_SARADC_TESTBIT,
595 RK3399_GRF_SARADC_TESTBIT_ON);
596 syscon_write_4(sc->sc_syscon, RK3399_GRF_TSADC_TESTBIT_H,
597 RK3399_GRF_TSADC_TESTBIT_H_ON);
598 DELAY(100);
599 syscon_unlock(sc->sc_syscon);
600 }
601
602 static void
603 rk_tsadc_init_enable(struct rk_tsadc_softc *sc)
604 {
605 uint32_t val;
606
607 val = TSADC_READ(sc, TSADC_AUTO_CON);
608 val |= TSADC_AUTO_CON_AUTO_STATUS |
609 TSADC_AUTO_CON_SRC1_LT_EN | TSADC_AUTO_CON_SRC0_LT_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 static int
703 rk_tsadc_data_to_temp(struct rk_tsadc_softc *sc, uint32_t data)
704 {
705 unsigned i;
706
707 for (i = 1; i < __arraycount(rk3399_data_table) - 1; i++) {
708 if (rk3399_data_table[i].data >= data) {
709 int temprange, offset;
710 uint32_t datarange, datadiff;
711
712 if (rk3399_data_table[i].data == data)
713 return rk3399_data_table[i].temp;
714
715 /* must interpolate */
716 temprange = rk3399_data_table[i].temp -
717 rk3399_data_table[i-1].temp;
718 datarange = rk3399_data_table[i].data -
719 rk3399_data_table[i-1].data;
720 datadiff = data - rk3399_data_table[i-1].data;
721
722 offset = (temprange * datadiff) / datarange;
723 return rk3399_data_table[i-1].temp + offset;
724 }
725 }
726
727 return rk3399_data_table[i].temp;
728 }
729
730 static uint32_t
731 rk_tsadc_temp_to_data(struct rk_tsadc_softc *sc, int temp)
732 {
733 unsigned i;
734
735 for (i = 1; i < __arraycount(rk3399_data_table); i++) {
736 if (rk3399_data_table[i].temp >= temp) {
737 int temprange, tempdiff;
738 uint32_t datarange, offset;
739
740 if (rk3399_data_table[i].temp == temp)
741 return rk3399_data_table[i].data;
742
743 /* must interpolate */
744 datarange = rk3399_data_table[i].data -
745 rk3399_data_table[i-1].data;
746 temprange = rk3399_data_table[i].temp -
747 rk3399_data_table[i-1].temp;
748 tempdiff = temp - rk3399_data_table[i-1].temp;
749
750 offset = (datarange * tempdiff) / temprange;
751 return rk3399_data_table[i-1].data + offset;
752 }
753 }
754
755 return sc->sc_data_mask;
756 }
757