Home | History | Annotate | Line # | Download | only in rockchip
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