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