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