1*d914a3c1Smrg /* $NetBSD: rk_tsadc.c,v 1.16 2021/12/11 19:24:21 mrg Exp $ */
239e6bc2cSmrg
339e6bc2cSmrg /*
439e6bc2cSmrg * Copyright (c) 2019 Matthew R. Green
539e6bc2cSmrg * All rights reserved.
639e6bc2cSmrg *
739e6bc2cSmrg * Redistribution and use in source and binary forms, with or without
839e6bc2cSmrg * modification, are permitted provided that the following conditions
939e6bc2cSmrg * are met:
1039e6bc2cSmrg * 1. Redistributions of source code must retain the above copyright
1139e6bc2cSmrg * notice, this list of conditions and the following disclaimer.
1239e6bc2cSmrg * 2. Redistributions in binary form must reproduce the above copyright
1339e6bc2cSmrg * notice, this list of conditions and the following disclaimer in the
1439e6bc2cSmrg * documentation and/or other materials provided with the distribution.
1539e6bc2cSmrg *
1639e6bc2cSmrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1739e6bc2cSmrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1839e6bc2cSmrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1939e6bc2cSmrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2039e6bc2cSmrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2139e6bc2cSmrg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2239e6bc2cSmrg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2339e6bc2cSmrg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2439e6bc2cSmrg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2539e6bc2cSmrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2639e6bc2cSmrg * SUCH DAMAGE.
2739e6bc2cSmrg */
2839e6bc2cSmrg
2939e6bc2cSmrg #include <sys/cdefs.h>
3039e6bc2cSmrg
31*d914a3c1Smrg __KERNEL_RCSID(0, "$NetBSD: rk_tsadc.c,v 1.16 2021/12/11 19:24:21 mrg Exp $");
3239e6bc2cSmrg
3339e6bc2cSmrg /*
3439e6bc2cSmrg * Driver for the TSADC temperature sensor monitor in RK3328 and RK3399.
3539e6bc2cSmrg *
3639e6bc2cSmrg * TODO:
3739e6bc2cSmrg * - handle setting various temp values
3839e6bc2cSmrg * - handle DT trips/temp value defaults
3939e6bc2cSmrg * - interrupts aren't triggered (test by lowering warn/crit values), and
4039e6bc2cSmrg * once they work, make the interrupt do something
4139e6bc2cSmrg */
4239e6bc2cSmrg
4339e6bc2cSmrg #include <sys/param.h>
4439e6bc2cSmrg #include <sys/bus.h>
4539e6bc2cSmrg #include <sys/device.h>
4639e6bc2cSmrg #include <sys/intr.h>
4739e6bc2cSmrg #include <sys/systm.h>
4839e6bc2cSmrg #include <sys/time.h>
4939e6bc2cSmrg #include <sys/kmem.h>
5039e6bc2cSmrg
5139e6bc2cSmrg #include <dev/fdt/fdtvar.h>
5239e6bc2cSmrg #include <dev/fdt/syscon.h>
5339e6bc2cSmrg
5439e6bc2cSmrg #include <dev/sysmon/sysmonvar.h>
5539e6bc2cSmrg
5639e6bc2cSmrg #ifdef RKTSADC_DEBUG
5739e6bc2cSmrg #define DPRINTF(fmt, ...) \
5839e6bc2cSmrg printf("%s:%d: " fmt "\n", __func__, __LINE__, ## __VA_ARGS__)
5939e6bc2cSmrg #else
6039e6bc2cSmrg #define DPRINTF(fmt, ...)
6139e6bc2cSmrg #endif
6239e6bc2cSmrg
6339e6bc2cSmrg /* Register definitions */
6439e6bc2cSmrg #define TSADC_USER_CON 0x00
6539e6bc2cSmrg #define TSADC_USER_CON_ADC_STATUS __BIT(12)
6639e6bc2cSmrg #define TSADC_USER_CON_INTER_PD_SOC __BITS(11,6)
6739e6bc2cSmrg #define TSADC_USER_CON_START __BIT(5)
6839e6bc2cSmrg #define TSADC_USER_CON_START_MODE __BIT(4)
6939e6bc2cSmrg #define TSADC_USER_CON_ADC_POWER_CTRL __BIT(3)
7039e6bc2cSmrg #define TSADC_USER_CON_ADC_INPUT_SRC_SEL __BITS(2,0)
7139e6bc2cSmrg #define TSADC_AUTO_CON 0x04
7239e6bc2cSmrg #define TSADC_AUTO_CON_LAST_TSHUT_2CRU __BIT(25)
7339e6bc2cSmrg #define TSADC_AUTO_CON_LAST_TSHUT_2GPIO __BIT(24)
7439e6bc2cSmrg #define TSADC_AUTO_CON_SAMPLE_DLY_SEL __BIT(17)
7539e6bc2cSmrg #define TSADC_AUTO_CON_AUTO_STATUS __BIT(16)
7639e6bc2cSmrg #define TSADC_AUTO_CON_SRC1_LT_EN __BIT(13)
7739e6bc2cSmrg #define TSADC_AUTO_CON_SRC0_LT_EN __BIT(12)
7839e6bc2cSmrg #define TSADC_AUTO_CON_TSHUT_POLARITY __BIT(8)
7939e6bc2cSmrg #define TSADC_AUTO_CON_SRC1_EN __BIT(5)
8039e6bc2cSmrg #define TSADC_AUTO_CON_SRC0_EN __BIT(4)
8139e6bc2cSmrg #define TSADC_AUTO_CON_Q_SEL __BIT(1)
8239e6bc2cSmrg #define TSADC_AUTO_CON_AUTO_EN __BIT(0)
8339e6bc2cSmrg #define TSADC_INT_EN 0x08
8439e6bc2cSmrg #define TSADC_INT_EN_EOC_INT_EN __BIT(16)
8539e6bc2cSmrg #define TSADC_INT_EN_LT_INTEN_SRC1 __BIT(13)
8639e6bc2cSmrg #define TSADC_INT_EN_LT_INTEN_SRC0 __BIT(12)
8739e6bc2cSmrg #define TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 __BIT(9)
8839e6bc2cSmrg #define TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 __BIT(8)
8939e6bc2cSmrg #define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 __BIT(5)
9039e6bc2cSmrg #define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 __BIT(4)
9139e6bc2cSmrg #define TSADC_INT_EN_HT_INTEN_SRC1 __BIT(1)
9239e6bc2cSmrg #define TSADC_INT_EN_HT_INTEN_SRC0 __BIT(0)
9339e6bc2cSmrg #define TSADC_INT_PD 0x0c
94c5e7cb41Sjmcneill #define TSADC_INT_PD_EOC_INT_PD_V3 __BIT(16)
9539e6bc2cSmrg #define TSADC_INT_PD_LT_IRQ_SRC1 __BIT(13)
9639e6bc2cSmrg #define TSADC_INT_PD_LT_IRQ_SRC0 __BIT(12)
97c5e7cb41Sjmcneill #define TSADC_INT_PD_EOC_INT_PD_V2 __BIT(8)
9839e6bc2cSmrg #define TSADC_INT_PD_TSHUT_O_SRC1 __BIT(5)
9939e6bc2cSmrg #define TSADC_INT_PD_TSHUT_O_SRC0 __BIT(4)
10039e6bc2cSmrg #define TSADC_INT_PD_HT_IRQ_SRC1 __BIT(1)
10139e6bc2cSmrg #define TSADC_INT_PD_HT_IRQ_SRC0 __BIT(0)
10239e6bc2cSmrg #define TSADC_DATA0 0x20
10339e6bc2cSmrg #define TSADC_DATA0_ADC_DATA __BITS(11,0)
10439e6bc2cSmrg #define TSADC_DATA1 0x24
10539e6bc2cSmrg #define TSADC_DATA1_ADC_DATA __BITS(11,0)
10639e6bc2cSmrg #define TSADC_COMP0_INT 0x30
10739e6bc2cSmrg #define TSADC_COMP0_INT_COMP_SRC0 __BITS(11,0)
10839e6bc2cSmrg #define TSADC_COMP1_INT 0x34
10939e6bc2cSmrg #define TSADC_COMP1_INT_COMP_SRC1 __BITS(11,0)
11039e6bc2cSmrg #define TSADC_COMP0_SHUT 0x40
11139e6bc2cSmrg #define TSADC_COMP0_SHUT_COMP_SRC0 __BITS(11,0)
11239e6bc2cSmrg #define TSADC_COMP1_SHUT 0x44
11339e6bc2cSmrg #define TSADC_COMP1_SHUT_COMP_SRC1 __BITS(11,0)
11439e6bc2cSmrg #define TSADC_HIGH_INT_DEBOUNCE 0x60
11539e6bc2cSmrg #define TSADC_HIGH_INT_DEBOUNCE_TEMP __BITS(7,0)
11639e6bc2cSmrg #define TSADC_HIGH_TSHUT_DEBOUNCE 0x64
11739e6bc2cSmrg #define TSADC_HIGH_TSHUT_DEBOUNCE_TEMP __BITS(7,0)
11839e6bc2cSmrg #define TSADC_AUTO_PERIOD 0x68
11939e6bc2cSmrg #define TSADC_AUTO_PERIOD_TEMP __BITS(31,0)
12039e6bc2cSmrg #define TSADC_AUTO_PERIOD_HT 0x6c
12139e6bc2cSmrg #define TSADC_AUTO_PERIOD_HT_TEMP __BITS(31,0)
12239e6bc2cSmrg #define TSADC_COMP0_LOW_INT 0x80
12339e6bc2cSmrg #define TSADC_COMP0_LOW_INT_COMP_SRC0 __BITS(11,0)
12439e6bc2cSmrg #define TSADC_COMP1_LOW_INT 0x84
12539e6bc2cSmrg #define TSADC_COMP1_LOW_INT_COMP_SRC1 __BITS(11,0)
12639e6bc2cSmrg
127c5e7cb41Sjmcneill #define RK3288_TSADC_AUTO_PERIOD_TIME 250 /* 250ms */
128c5e7cb41Sjmcneill #define RK3288_TSADC_AUTO_PERIOD_HT_TIME 50 /* 50ms */
129863b2b98Smrg #define RK3328_TSADC_AUTO_PERIOD_TIME 250 /* 250ms */
130863b2b98Smrg #define RK3399_TSADC_AUTO_PERIOD_TIME 1875 /* 2.5ms */
13139e6bc2cSmrg #define TSADC_HT_DEBOUNCE_COUNT 4
13239e6bc2cSmrg
13339e6bc2cSmrg /*
13439e6bc2cSmrg * All this magic is taking from the Linux rockchip_thermal driver.
13539e6bc2cSmrg *
13639e6bc2cSmrg * VCM means "voltage common mode", but the documentation for RK3399
13739e6bc2cSmrg * does not mention this and I don't know what any of this really
13839e6bc2cSmrg * is for.
13939e6bc2cSmrg */
14039e6bc2cSmrg #define RK3399_GRF_SARADC_TESTBIT 0xe644
14139e6bc2cSmrg #define RK3399_GRF_SARADC_TESTBIT_ON (0x10001 << 2)
14239e6bc2cSmrg #define RK3399_GRF_TSADC_TESTBIT_L 0xe648
14339e6bc2cSmrg #define RK3399_GRF_TSADC_TESTBIT_VCM_EN_L (0x10001 << 7)
14439e6bc2cSmrg #define RK3399_GRF_TSADC_TESTBIT_H 0xe64c
14539e6bc2cSmrg #define RK3399_GRF_TSADC_TESTBIT_VCM_EN_H (0x10001 << 7)
14639e6bc2cSmrg #define RK3399_GRF_TSADC_TESTBIT_H_ON (0x10001 << 2)
14739e6bc2cSmrg
14839e6bc2cSmrg #define TEMP_uC_TO_uK 273150000
14939e6bc2cSmrg
15039e6bc2cSmrg #define TSHUT_MODE_CPU 0
15139e6bc2cSmrg #define TSHUT_MODE_GPIO 1
15239e6bc2cSmrg
15339e6bc2cSmrg #define TSHUT_LOW_ACTIVE 0
15439e6bc2cSmrg #define TSHUT_HIGH_ACTIVE 1
15539e6bc2cSmrg
15639e6bc2cSmrg #define TSHUT_DEF_TEMP 95000
15739e6bc2cSmrg
15839e6bc2cSmrg #define TSADC_DATA_MAX 0xfff
15939e6bc2cSmrg
1607ce6ce51Smrg #define MAX_SENSORS 2
16139e6bc2cSmrg
162863b2b98Smrg typedef struct rk_data_array {
16339e6bc2cSmrg uint32_t data; /* register value */
16439e6bc2cSmrg int temp; /* micro-degC */
165863b2b98Smrg } rk_data_array;
166863b2b98Smrg
167863b2b98Smrg struct rk_tsadc_softc;
1687ce6ce51Smrg typedef struct rk_data {
169c5e7cb41Sjmcneill const char *rd_name;
1707ce6ce51Smrg const rk_data_array *rd_array;
1717ce6ce51Smrg size_t rd_size;
1727ce6ce51Smrg void (*rd_init)(struct rk_tsadc_softc *, int, int);
1737ce6ce51Smrg bool rd_decr; /* lower values -> higher temp */
1747ce6ce51Smrg unsigned rd_min, rd_max;
1757ce6ce51Smrg unsigned rd_auto_period;
176c5e7cb41Sjmcneill unsigned rd_auto_period_ht;
1777ce6ce51Smrg unsigned rd_num_sensors;
178c5e7cb41Sjmcneill unsigned rd_version;
1797ce6ce51Smrg } rk_data;
18039e6bc2cSmrg
18139e6bc2cSmrg /* Per-sensor data */
18239e6bc2cSmrg struct rk_tsadc_sensor {
18339e6bc2cSmrg envsys_data_t s_data;
18439e6bc2cSmrg bool s_attached;
18539e6bc2cSmrg /* TSADC register offsets for this sensor */
18639e6bc2cSmrg unsigned s_data_reg;
18739e6bc2cSmrg unsigned s_comp_tshut;
18839e6bc2cSmrg unsigned s_comp_int;
1896bc30fa4Smrg /* enable bit in AUTO_CON register */
19039e6bc2cSmrg unsigned s_comp_int_en;
19139e6bc2cSmrg /* warn/crit values in micro Kelvin */
19239e6bc2cSmrg int s_warn;
19339e6bc2cSmrg int s_tshut;
19439e6bc2cSmrg };
19539e6bc2cSmrg
19639e6bc2cSmrg struct rk_tsadc_softc {
19739e6bc2cSmrg device_t sc_dev;
19839e6bc2cSmrg int sc_phandle;
19939e6bc2cSmrg bus_space_tag_t sc_bst;
20039e6bc2cSmrg bus_space_handle_t sc_bsh;
20139e6bc2cSmrg size_t sc_size;
20239e6bc2cSmrg uint32_t sc_data_mask;
20339e6bc2cSmrg void *sc_ih;
20439e6bc2cSmrg
20539e6bc2cSmrg struct sysmon_envsys *sc_sme;
2067ce6ce51Smrg struct rk_tsadc_sensor sc_sensors[MAX_SENSORS];
20739e6bc2cSmrg
20839e6bc2cSmrg struct clk *sc_clock;
20939e6bc2cSmrg struct clk *sc_clockapb;
21039e6bc2cSmrg struct fdtbus_reset *sc_reset;
21139e6bc2cSmrg struct syscon *sc_syscon;
212863b2b98Smrg
2137ce6ce51Smrg const rk_data *sc_rd;
21439e6bc2cSmrg };
21539e6bc2cSmrg
21639e6bc2cSmrg static int rk_tsadc_match(device_t, cfdata_t, void *);
21739e6bc2cSmrg static void rk_tsadc_attach(device_t, device_t, void *);
21839e6bc2cSmrg static int rk_tsadc_detach(device_t, int);
21939e6bc2cSmrg static int rk_tsadc_init_clocks(struct rk_tsadc_softc *);
22039e6bc2cSmrg static void rk_tsadc_init_counts(struct rk_tsadc_softc *);
22139e6bc2cSmrg static void rk_tsadc_tshut_set(struct rk_tsadc_softc *s);
22239e6bc2cSmrg static void rk_tsadc_init_tshut(struct rk_tsadc_softc *, int, int);
223c5e7cb41Sjmcneill static void rk_tsadc_init_common(struct rk_tsadc_softc *, int, int);
224863b2b98Smrg static void rk_tsadc_init_rk3399(struct rk_tsadc_softc *, int, int);
22539e6bc2cSmrg static void rk_tsadc_init_enable(struct rk_tsadc_softc *);
226863b2b98Smrg static void rk_tsadc_init(struct rk_tsadc_softc *, int, int);
22739e6bc2cSmrg static void rk_tsadc_refresh(struct sysmon_envsys *, envsys_data_t *);
22839e6bc2cSmrg static void rk_tsadc_get_limits(struct sysmon_envsys *, envsys_data_t *,
22939e6bc2cSmrg sysmon_envsys_lim_t *, uint32_t *);
23039e6bc2cSmrg
23139e6bc2cSmrg static int rk_tsadc_intr(void *);
23239e6bc2cSmrg static int rk_tsadc_data_to_temp(struct rk_tsadc_softc *, uint32_t);
23339e6bc2cSmrg static uint32_t rk_tsadc_temp_to_data(struct rk_tsadc_softc *, int);
23439e6bc2cSmrg
23539e6bc2cSmrg /* RK3328/RK3399 compatible sensors */
23639e6bc2cSmrg static const struct rk_tsadc_sensor rk_tsadc_sensors[] = {
23739e6bc2cSmrg {
23839e6bc2cSmrg .s_data = { .desc = "CPU" },
23939e6bc2cSmrg .s_data_reg = TSADC_DATA0,
24039e6bc2cSmrg .s_comp_tshut = TSADC_COMP0_SHUT,
24139e6bc2cSmrg .s_comp_int = TSADC_COMP0_INT,
24239e6bc2cSmrg .s_comp_int_en = TSADC_AUTO_CON_SRC0_EN,
24339e6bc2cSmrg /*
24439e6bc2cSmrg * XXX DT has:
24539e6bc2cSmrg * cpu_alert1: cpu_alert1 {
24639e6bc2cSmrg * temperature = <75000>;
24739e6bc2cSmrg * hysteresis = <2000>;
24839e6bc2cSmrg * cpu_crit: cpu_crit {
24939e6bc2cSmrg * temperature = <95000>;
25039e6bc2cSmrg * hysteresis = <2000>;
25139e6bc2cSmrg * pull out of here?
25239e6bc2cSmrg * do something with hysteresis? put in debounce?
25339e6bc2cSmrg *
254207defd0Sandvar * Note that tshut may be overridden by the board specific DT.
25539e6bc2cSmrg */
25639e6bc2cSmrg .s_warn = 75000000,
25739e6bc2cSmrg .s_tshut = 95000000,
25839e6bc2cSmrg }, {
25939e6bc2cSmrg .s_data = { .desc = "GPU" },
26039e6bc2cSmrg .s_data_reg = TSADC_DATA1,
26139e6bc2cSmrg .s_comp_tshut = TSADC_COMP1_SHUT,
26239e6bc2cSmrg .s_comp_int = TSADC_COMP1_INT,
26339e6bc2cSmrg .s_comp_int_en = TSADC_AUTO_CON_SRC1_EN,
26439e6bc2cSmrg .s_warn = 75000000,
26539e6bc2cSmrg .s_tshut = 95000000,
26639e6bc2cSmrg },
26739e6bc2cSmrg };
26839e6bc2cSmrg
2697ce6ce51Smrg /*
270c5e7cb41Sjmcneill * Table from RK3288 manual.
271c5e7cb41Sjmcneill */
272c5e7cb41Sjmcneill static const rk_data_array rk3288_data_array[] = {
273c5e7cb41Sjmcneill #define ENTRY(d,C) { .data = (d), .temp = (C) * 1000 * 1000, }
274c5e7cb41Sjmcneill ENTRY(TSADC_DATA_MAX, -40),
275c5e7cb41Sjmcneill ENTRY(3800, -40),
276c5e7cb41Sjmcneill ENTRY(3792, -35),
277c5e7cb41Sjmcneill ENTRY(3783, -30),
278c5e7cb41Sjmcneill ENTRY(3774, -25),
279c5e7cb41Sjmcneill ENTRY(3765, -20),
280c5e7cb41Sjmcneill ENTRY(3756, -15),
281c5e7cb41Sjmcneill ENTRY(3747, -10),
282c5e7cb41Sjmcneill ENTRY(3737, -5),
283c5e7cb41Sjmcneill ENTRY(3728, 0),
284c5e7cb41Sjmcneill ENTRY(3718, 5),
285c5e7cb41Sjmcneill ENTRY(3708, 10),
286c5e7cb41Sjmcneill ENTRY(3698, 15),
287c5e7cb41Sjmcneill ENTRY(3688, 20),
288c5e7cb41Sjmcneill ENTRY(3678, 25),
289c5e7cb41Sjmcneill ENTRY(3667, 30),
290c5e7cb41Sjmcneill ENTRY(3656, 35),
291c5e7cb41Sjmcneill ENTRY(3645, 40),
292c5e7cb41Sjmcneill ENTRY(3634, 45),
293c5e7cb41Sjmcneill ENTRY(3623, 50),
294c5e7cb41Sjmcneill ENTRY(3611, 55),
295c5e7cb41Sjmcneill ENTRY(3600, 60),
296c5e7cb41Sjmcneill ENTRY(3588, 65),
297c5e7cb41Sjmcneill ENTRY(3575, 70),
298c5e7cb41Sjmcneill ENTRY(3563, 75),
299c5e7cb41Sjmcneill ENTRY(3550, 80),
300c5e7cb41Sjmcneill ENTRY(3537, 85),
301c5e7cb41Sjmcneill ENTRY(3524, 90),
302c5e7cb41Sjmcneill ENTRY(3510, 95),
303c5e7cb41Sjmcneill ENTRY(3496, 100),
304c5e7cb41Sjmcneill ENTRY(3482, 105),
305c5e7cb41Sjmcneill ENTRY(3467, 110),
306c5e7cb41Sjmcneill ENTRY(3452, 115),
307c5e7cb41Sjmcneill ENTRY(3437, 120),
308c5e7cb41Sjmcneill ENTRY(3421, 125),
309c5e7cb41Sjmcneill ENTRY(0, 15),
310c5e7cb41Sjmcneill #undef ENTRY
311c5e7cb41Sjmcneill };
312c5e7cb41Sjmcneill
313c5e7cb41Sjmcneill /*
3147ce6ce51Smrg * Table from RK3328 manual. Note that the manual lists valid numbers as
3157ce6ce51Smrg * 4096 - number. This also means it is increasing not decreasing for
3167ce6ce51Smrg * higher temps, and the min and max are also offset from 4096.
3177ce6ce51Smrg */
3187ce6ce51Smrg #define RK3328_DATA_OFFSET (4096)
319863b2b98Smrg static const rk_data_array rk3328_data_array[] = {
3207ce6ce51Smrg #define ENTRY(d,C) \
3217ce6ce51Smrg { .data = RK3328_DATA_OFFSET - (d), .temp = (C) * 1000 * 1000, }
322863b2b98Smrg ENTRY(TSADC_DATA_MAX, -40),
323863b2b98Smrg ENTRY(3800, -40),
324863b2b98Smrg ENTRY(3792, -35),
325863b2b98Smrg ENTRY(3783, -30),
326863b2b98Smrg ENTRY(3774, -25),
327863b2b98Smrg ENTRY(3765, -20),
328863b2b98Smrg ENTRY(3756, -15),
329863b2b98Smrg ENTRY(3747, -10),
330863b2b98Smrg ENTRY(3737, -5),
331863b2b98Smrg ENTRY(3728, 0),
332863b2b98Smrg ENTRY(3718, 5),
333863b2b98Smrg ENTRY(3708, 10),
334863b2b98Smrg ENTRY(3698, 15),
335863b2b98Smrg ENTRY(3688, 20),
336863b2b98Smrg ENTRY(3678, 25),
337863b2b98Smrg ENTRY(3667, 30),
338863b2b98Smrg ENTRY(3656, 35),
339863b2b98Smrg ENTRY(3645, 40),
340863b2b98Smrg ENTRY(3634, 45),
341863b2b98Smrg ENTRY(3623, 50),
342863b2b98Smrg ENTRY(3611, 55),
343863b2b98Smrg ENTRY(3600, 60),
344863b2b98Smrg ENTRY(3588, 65),
345863b2b98Smrg ENTRY(3575, 70),
346863b2b98Smrg ENTRY(3563, 75),
347863b2b98Smrg ENTRY(3550, 80),
348863b2b98Smrg ENTRY(3537, 85),
349863b2b98Smrg ENTRY(3524, 90),
350863b2b98Smrg ENTRY(3510, 95),
351863b2b98Smrg ENTRY(3496, 100),
352863b2b98Smrg ENTRY(3482, 105),
353863b2b98Smrg ENTRY(3467, 110),
354863b2b98Smrg ENTRY(3452, 115),
355863b2b98Smrg ENTRY(3437, 120),
356863b2b98Smrg ENTRY(3421, 125),
357863b2b98Smrg ENTRY(0, 125),
358863b2b98Smrg #undef ENTRY
359863b2b98Smrg };
360863b2b98Smrg
361863b2b98Smrg /* Table from RK3399 manual */
362863b2b98Smrg static const rk_data_array rk3399_data_array[] = {
363863b2b98Smrg #define ENTRY(d,C) { .data = (d), .temp = (C) * 1000 * 1000, }
364863b2b98Smrg ENTRY(0, -40),
365863b2b98Smrg ENTRY(402, -40),
366863b2b98Smrg ENTRY(410, -35),
367863b2b98Smrg ENTRY(419, -30),
368863b2b98Smrg ENTRY(427, -25),
369863b2b98Smrg ENTRY(436, -20),
370863b2b98Smrg ENTRY(444, -15),
371863b2b98Smrg ENTRY(453, -10),
372863b2b98Smrg ENTRY(461, -5),
373863b2b98Smrg ENTRY(470, 0),
374863b2b98Smrg ENTRY(478, 5),
375863b2b98Smrg ENTRY(487, 10),
376863b2b98Smrg ENTRY(496, 15),
377863b2b98Smrg ENTRY(504, 20),
378863b2b98Smrg ENTRY(513, 25),
379863b2b98Smrg ENTRY(521, 30),
380863b2b98Smrg ENTRY(530, 35),
381863b2b98Smrg ENTRY(538, 40),
382863b2b98Smrg ENTRY(547, 45),
383863b2b98Smrg ENTRY(555, 50),
384863b2b98Smrg ENTRY(564, 55),
385863b2b98Smrg ENTRY(573, 60),
386863b2b98Smrg ENTRY(581, 65),
387863b2b98Smrg ENTRY(590, 70),
388863b2b98Smrg ENTRY(599, 75),
389863b2b98Smrg ENTRY(607, 80),
390863b2b98Smrg ENTRY(616, 85),
391863b2b98Smrg ENTRY(624, 90),
392863b2b98Smrg ENTRY(633, 95),
393863b2b98Smrg ENTRY(642, 100),
394863b2b98Smrg ENTRY(650, 105),
395863b2b98Smrg ENTRY(659, 110),
396863b2b98Smrg ENTRY(668, 115),
397863b2b98Smrg ENTRY(677, 120),
398863b2b98Smrg ENTRY(685, 125),
399863b2b98Smrg ENTRY(TSADC_DATA_MAX, 125),
400863b2b98Smrg #undef ENTRY
401863b2b98Smrg };
402863b2b98Smrg
403c5e7cb41Sjmcneill static const rk_data rk3288_data_table = {
404c5e7cb41Sjmcneill .rd_name = "RK3288",
405c5e7cb41Sjmcneill .rd_array = rk3288_data_array,
406c5e7cb41Sjmcneill .rd_size = __arraycount(rk3288_data_array),
407c5e7cb41Sjmcneill .rd_init = rk_tsadc_init_common,
408c5e7cb41Sjmcneill .rd_decr = true,
409c5e7cb41Sjmcneill .rd_max = 3800,
410c5e7cb41Sjmcneill .rd_min = 3421,
411c5e7cb41Sjmcneill .rd_auto_period = RK3288_TSADC_AUTO_PERIOD_TIME,
412c5e7cb41Sjmcneill .rd_auto_period_ht = RK3288_TSADC_AUTO_PERIOD_HT_TIME,
413c5e7cb41Sjmcneill .rd_num_sensors = 2,
414c5e7cb41Sjmcneill .rd_version = 2,
415c5e7cb41Sjmcneill };
416c5e7cb41Sjmcneill
4177ce6ce51Smrg static const rk_data rk3328_data_table = {
418c5e7cb41Sjmcneill .rd_name = "RK3328",
4197ce6ce51Smrg .rd_array = rk3328_data_array,
4207ce6ce51Smrg .rd_size = __arraycount(rk3328_data_array),
421c5e7cb41Sjmcneill .rd_init = rk_tsadc_init_common,
4227ce6ce51Smrg .rd_decr = false,
4237ce6ce51Smrg .rd_max = RK3328_DATA_OFFSET - 3420,
4247ce6ce51Smrg .rd_min = RK3328_DATA_OFFSET - 3801,
4257ce6ce51Smrg .rd_auto_period = RK3328_TSADC_AUTO_PERIOD_TIME,
426c5e7cb41Sjmcneill .rd_auto_period_ht = RK3328_TSADC_AUTO_PERIOD_TIME,
4277ce6ce51Smrg .rd_num_sensors = 1,
428c5e7cb41Sjmcneill .rd_version = 3,
429863b2b98Smrg };
430863b2b98Smrg
4317ce6ce51Smrg static const rk_data rk3399_data_table = {
432c5e7cb41Sjmcneill .rd_name = "RK3399",
4337ce6ce51Smrg .rd_array = rk3399_data_array,
4347ce6ce51Smrg .rd_size = __arraycount(rk3399_data_array),
4357ce6ce51Smrg .rd_init = rk_tsadc_init_rk3399,
4367ce6ce51Smrg .rd_decr = false,
4377ce6ce51Smrg .rd_max = 686,
4387ce6ce51Smrg .rd_min = 401,
4397ce6ce51Smrg .rd_auto_period = RK3399_TSADC_AUTO_PERIOD_TIME,
440c5e7cb41Sjmcneill .rd_auto_period_ht = RK3399_TSADC_AUTO_PERIOD_TIME,
4417ce6ce51Smrg .rd_num_sensors = 2,
442c5e7cb41Sjmcneill .rd_version = 3,
443863b2b98Smrg };
444863b2b98Smrg
445622c6ae7Sthorpej static const struct device_compatible_entry compat_data[] = {
446c5e7cb41Sjmcneill { .compat = "rockchip,rk3288-tsadc", .data = &rk3288_data_table },
447622c6ae7Sthorpej { .compat = "rockchip,rk3328-tsadc", .data = &rk3328_data_table },
448622c6ae7Sthorpej { .compat = "rockchip,rk3399-tsadc", .data = &rk3399_data_table },
449ec189949Sthorpej DEVICE_COMPAT_EOL
45039e6bc2cSmrg };
45139e6bc2cSmrg
45239e6bc2cSmrg #define TSADC_READ(sc, reg) \
45339e6bc2cSmrg bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
45439e6bc2cSmrg #define TSADC_WRITE(sc, reg, val) \
45539e6bc2cSmrg bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
45639e6bc2cSmrg
45739e6bc2cSmrg CFATTACH_DECL3_NEW(rk_tsadc, sizeof(struct rk_tsadc_softc),
45839e6bc2cSmrg rk_tsadc_match, rk_tsadc_attach, rk_tsadc_detach, NULL, NULL, NULL,
45939e6bc2cSmrg DVF_DETACH_SHUTDOWN);
46039e6bc2cSmrg
46139e6bc2cSmrg /* init/teardown support */
46239e6bc2cSmrg static int
rk_tsadc_match(device_t parent,cfdata_t cf,void * aux)46339e6bc2cSmrg rk_tsadc_match(device_t parent, cfdata_t cf, void *aux)
46439e6bc2cSmrg {
46539e6bc2cSmrg struct fdt_attach_args * const faa = aux;
46639e6bc2cSmrg
4676e54367aSthorpej return of_compatible_match(faa->faa_phandle, compat_data);
46839e6bc2cSmrg }
46939e6bc2cSmrg
47039e6bc2cSmrg static void
rk_tsadc_attach(device_t parent,device_t self,void * aux)47139e6bc2cSmrg rk_tsadc_attach(device_t parent, device_t self, void *aux)
47239e6bc2cSmrg {
47339e6bc2cSmrg struct rk_tsadc_softc * const sc = device_private(self);
47439e6bc2cSmrg struct fdt_attach_args * const faa = aux;
47539e6bc2cSmrg char intrstr[128];
47639e6bc2cSmrg const int phandle = faa->faa_phandle;
47739e6bc2cSmrg bus_addr_t addr;
47839e6bc2cSmrg int mode, polarity, tshut_temp;
47939e6bc2cSmrg
48039e6bc2cSmrg sc->sc_dev = self;
48139e6bc2cSmrg sc->sc_phandle = phandle;
48239e6bc2cSmrg sc->sc_bst = faa->faa_bst;
48339e6bc2cSmrg
48439e6bc2cSmrg sc->sc_sme = sysmon_envsys_create();
48539e6bc2cSmrg
48639e6bc2cSmrg sc->sc_sme->sme_name = device_xname(self);
48739e6bc2cSmrg sc->sc_sme->sme_cookie = sc;
48839e6bc2cSmrg sc->sc_sme->sme_refresh = rk_tsadc_refresh;
48939e6bc2cSmrg sc->sc_sme->sme_get_limits = rk_tsadc_get_limits;
4906bc30fa4Smrg sc->sc_data_mask = TSADC_DATA_MAX;
49139e6bc2cSmrg
49239e6bc2cSmrg pmf_device_register(self, NULL, NULL);
49339e6bc2cSmrg
4946e54367aSthorpej sc->sc_rd = of_compatible_lookup(faa->faa_phandle, compat_data)->data;
4957ce6ce51Smrg
496c5e7cb41Sjmcneill aprint_naive("\n");
497c5e7cb41Sjmcneill aprint_normal(": %s Temperature Sensor ADC\n", sc->sc_rd->rd_name);
498c5e7cb41Sjmcneill
49939e6bc2cSmrg /* Default to tshut via gpio and tshut low is active */
50039e6bc2cSmrg if (of_getprop_uint32(phandle, "rockchip,hw-tshut-mode",
50139e6bc2cSmrg &mode) != 0) {
50239e6bc2cSmrg aprint_error(": could not get TSHUT mode, default to GPIO");
50339e6bc2cSmrg mode = TSHUT_MODE_GPIO;
50439e6bc2cSmrg }
50539e6bc2cSmrg if (mode != TSHUT_MODE_CPU && mode != TSHUT_MODE_GPIO) {
50639e6bc2cSmrg aprint_error(": TSHUT mode should be 0 or 1\n");
50739e6bc2cSmrg goto fail;
50839e6bc2cSmrg }
50939e6bc2cSmrg
51039e6bc2cSmrg if (of_getprop_uint32(phandle, "rockchip,hw-tshut-polarity",
51139e6bc2cSmrg &polarity) != 0) {
51239e6bc2cSmrg aprint_error(": could not get TSHUT polarity, default to low");
51339e6bc2cSmrg polarity = TSHUT_LOW_ACTIVE;
51439e6bc2cSmrg }
51539e6bc2cSmrg if (of_getprop_uint32(phandle,
51639e6bc2cSmrg "rockchip,hw-tshut-temp", &tshut_temp) != 0) {
51739e6bc2cSmrg aprint_error(": could not get TSHUT temperature, default to %u",
51839e6bc2cSmrg TSHUT_DEF_TEMP);
51939e6bc2cSmrg tshut_temp = TSHUT_DEF_TEMP;
52039e6bc2cSmrg }
5217c8cb6a3Smrg tshut_temp *= 1000; /* convert fdt mK -> uK */
52239e6bc2cSmrg
52339e6bc2cSmrg memcpy(sc->sc_sensors, rk_tsadc_sensors, sizeof(sc->sc_sensors));
5247ce6ce51Smrg for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) {
52539e6bc2cSmrg struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
52639e6bc2cSmrg
52739e6bc2cSmrg rks->s_data.flags = ENVSYS_FMONLIMITS;
52839e6bc2cSmrg rks->s_data.units = ENVSYS_STEMP;
52939e6bc2cSmrg rks->s_data.state = ENVSYS_SINVALID;
53039e6bc2cSmrg
53139e6bc2cSmrg if (sysmon_envsys_sensor_attach(sc->sc_sme, &rks->s_data))
53239e6bc2cSmrg goto fail;
53339e6bc2cSmrg rks->s_attached = true;
53439e6bc2cSmrg rks->s_tshut = tshut_temp;
535e7c3d862Smrg #if 0
53639e6bc2cSmrg // testing
5376bc30fa4Smrg rks->s_tshut = 68000000;
5386bc30fa4Smrg rks->s_warn = 61000000;
53939e6bc2cSmrg #endif
54039e6bc2cSmrg }
54139e6bc2cSmrg
54239e6bc2cSmrg sc->sc_syscon = fdtbus_syscon_acquire(phandle, "rockchip,grf");
54339e6bc2cSmrg if (sc->sc_syscon == NULL) {
54439e6bc2cSmrg aprint_error(": couldn't get grf syscon\n");
54539e6bc2cSmrg goto fail;
54639e6bc2cSmrg }
54739e6bc2cSmrg if (fdtbus_get_reg(phandle, 0, &addr, &sc->sc_size) != 0) {
54839e6bc2cSmrg aprint_error(": couldn't get registers\n");
54939e6bc2cSmrg sc->sc_size = 0;
55039e6bc2cSmrg goto fail;
55139e6bc2cSmrg }
55239e6bc2cSmrg if (bus_space_map(sc->sc_bst, addr, sc->sc_size, 0, &sc->sc_bsh) != 0) {
55339e6bc2cSmrg aprint_error(": couldn't map registers\n");
55439e6bc2cSmrg sc->sc_size = 0;
55539e6bc2cSmrg goto fail;
55639e6bc2cSmrg }
55739e6bc2cSmrg
55839e6bc2cSmrg if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
55939e6bc2cSmrg aprint_error(": failed to decode interrupt\n");
56039e6bc2cSmrg goto fail;
56139e6bc2cSmrg }
56239e6bc2cSmrg
56364e248edSryo sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_VM, FDT_INTR_MPSAFE,
56464e248edSryo rk_tsadc_intr, sc, device_xname(self));
56539e6bc2cSmrg if (sc->sc_ih == NULL) {
56639e6bc2cSmrg aprint_error_dev(self, "couldn't establish interrupt on %s\n",
56739e6bc2cSmrg intrstr);
56839e6bc2cSmrg goto fail;
56939e6bc2cSmrg }
57039e6bc2cSmrg aprint_normal_dev(self, "interrupting on %s\n", intrstr);
57139e6bc2cSmrg
57239e6bc2cSmrg if (rk_tsadc_init_clocks(sc)) {
57339e6bc2cSmrg aprint_error(": couldn't enable clocks\n");
57439e6bc2cSmrg return;
57539e6bc2cSmrg }
57639e6bc2cSmrg
57739e6bc2cSmrg /*
57839e6bc2cSmrg * Manual says to setup auto period (both), high temp (interrupt),
57939e6bc2cSmrg * high temp (shutdown), enable high temp resets (TSHUT to GPIO
58039e6bc2cSmrg * or reset chip), set the debounce times, and, finally, enable the
58139e6bc2cSmrg * controller iself.
58239e6bc2cSmrg */
583863b2b98Smrg rk_tsadc_init(sc, mode, polarity);
58439e6bc2cSmrg
58539e6bc2cSmrg return;
58639e6bc2cSmrg
58739e6bc2cSmrg fail:
58839e6bc2cSmrg rk_tsadc_detach(self, 0);
58939e6bc2cSmrg }
59039e6bc2cSmrg
59139e6bc2cSmrg static int
rk_tsadc_detach(device_t self,int flags)59239e6bc2cSmrg rk_tsadc_detach(device_t self, int flags)
59339e6bc2cSmrg {
59439e6bc2cSmrg struct rk_tsadc_softc *sc = device_private(self);
59539e6bc2cSmrg
59639e6bc2cSmrg pmf_device_deregister(self);
59739e6bc2cSmrg
5987ce6ce51Smrg for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) {
59939e6bc2cSmrg struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
60039e6bc2cSmrg
60139e6bc2cSmrg if (rks->s_attached) {
60239e6bc2cSmrg sysmon_envsys_sensor_detach(sc->sc_sme, &rks->s_data);
60339e6bc2cSmrg rks->s_attached = false;
60439e6bc2cSmrg }
60539e6bc2cSmrg }
60639e6bc2cSmrg
60739e6bc2cSmrg sysmon_envsys_unregister(sc->sc_sme);
60839e6bc2cSmrg
60939e6bc2cSmrg if (sc->sc_clockapb)
61039e6bc2cSmrg clk_disable(sc->sc_clockapb);
61139e6bc2cSmrg if (sc->sc_clock)
61239e6bc2cSmrg clk_disable(sc->sc_clock);
61339e6bc2cSmrg
61439e6bc2cSmrg if (sc->sc_ih)
61539e6bc2cSmrg fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_ih);
61639e6bc2cSmrg
61739e6bc2cSmrg if (sc->sc_size)
61839e6bc2cSmrg bus_space_unmap(sc->sc_bst, sc->sc_bsh, sc->sc_size);
61939e6bc2cSmrg
62039e6bc2cSmrg sysmon_envsys_destroy(sc->sc_sme);
62139e6bc2cSmrg
62239e6bc2cSmrg return 0;
62339e6bc2cSmrg }
62439e6bc2cSmrg
62539e6bc2cSmrg static int
rk_tsadc_init_clocks(struct rk_tsadc_softc * sc)62639e6bc2cSmrg rk_tsadc_init_clocks(struct rk_tsadc_softc *sc)
62739e6bc2cSmrg {
62839e6bc2cSmrg int error;
62939e6bc2cSmrg
63039e6bc2cSmrg fdtbus_clock_assign(sc->sc_phandle);
63139e6bc2cSmrg
63239e6bc2cSmrg sc->sc_reset = fdtbus_reset_get(sc->sc_phandle, "tsadc-apb");
63339e6bc2cSmrg sc->sc_clock = fdtbus_clock_get(sc->sc_phandle, "tsadc");
63439e6bc2cSmrg sc->sc_clockapb = fdtbus_clock_get(sc->sc_phandle, "apb_pclk");
63539e6bc2cSmrg if (sc->sc_reset == NULL ||
63639e6bc2cSmrg sc->sc_clock == NULL ||
63739e6bc2cSmrg sc->sc_clockapb == NULL)
63839e6bc2cSmrg return EINVAL;
63939e6bc2cSmrg
64039e6bc2cSmrg fdtbus_reset_assert(sc->sc_reset);
64139e6bc2cSmrg
64239e6bc2cSmrg error = clk_enable(sc->sc_clock);
64339e6bc2cSmrg if (error) {
64439e6bc2cSmrg fdtbus_reset_deassert(sc->sc_reset);
64539e6bc2cSmrg return error;
64639e6bc2cSmrg }
64739e6bc2cSmrg
64839e6bc2cSmrg error = clk_enable(sc->sc_clockapb);
64939e6bc2cSmrg
65039e6bc2cSmrg DELAY(20);
65139e6bc2cSmrg fdtbus_reset_deassert(sc->sc_reset);
65239e6bc2cSmrg
65339e6bc2cSmrg return error;
65439e6bc2cSmrg }
65539e6bc2cSmrg
65639e6bc2cSmrg static void
rk_tsadc_init_counts(struct rk_tsadc_softc * sc)65739e6bc2cSmrg rk_tsadc_init_counts(struct rk_tsadc_softc *sc)
65839e6bc2cSmrg {
65939e6bc2cSmrg
6607ce6ce51Smrg TSADC_WRITE(sc, TSADC_AUTO_PERIOD, sc->sc_rd->rd_auto_period);
661c5e7cb41Sjmcneill TSADC_WRITE(sc, TSADC_AUTO_PERIOD_HT, sc->sc_rd->rd_auto_period_ht);
66239e6bc2cSmrg TSADC_WRITE(sc, TSADC_HIGH_INT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT);
66339e6bc2cSmrg TSADC_WRITE(sc, TSADC_HIGH_TSHUT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT);
66439e6bc2cSmrg }
66539e6bc2cSmrg
66639e6bc2cSmrg /* Configure the hardware with the tshut setup. */
66739e6bc2cSmrg static void
rk_tsadc_tshut_set(struct rk_tsadc_softc * sc)66839e6bc2cSmrg rk_tsadc_tshut_set(struct rk_tsadc_softc *sc)
66939e6bc2cSmrg {
67039e6bc2cSmrg uint32_t val = TSADC_READ(sc, TSADC_AUTO_CON);
67139e6bc2cSmrg
6727ce6ce51Smrg for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) {
67339e6bc2cSmrg struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
6747ce6ce51Smrg uint32_t data, warndata;
6757ce6ce51Smrg
6767ce6ce51Smrg if (!rks->s_attached)
6777ce6ce51Smrg continue;
6787ce6ce51Smrg
6797ce6ce51Smrg data = rk_tsadc_temp_to_data(sc, rks->s_tshut);
6807ce6ce51Smrg warndata = rk_tsadc_temp_to_data(sc, rks->s_warn);
68139e6bc2cSmrg
68239e6bc2cSmrg DPRINTF("(%s:%s): tshut/data %d/%u warn/data %d/%u",
68339e6bc2cSmrg sc->sc_sme->sme_name, rks->s_data.desc,
68439e6bc2cSmrg rks->s_tshut, data,
68539e6bc2cSmrg rks->s_warn, warndata);
68639e6bc2cSmrg
68739e6bc2cSmrg if (data == sc->sc_data_mask) {
68839e6bc2cSmrg aprint_error_dev(sc->sc_dev,
68939e6bc2cSmrg "Failed converting critical temp %u.%06u to code",
69039e6bc2cSmrg rks->s_tshut / 1000000, rks->s_tshut % 1000000);
69139e6bc2cSmrg continue;
69239e6bc2cSmrg }
69339e6bc2cSmrg if (warndata == sc->sc_data_mask) {
69439e6bc2cSmrg aprint_error_dev(sc->sc_dev,
69539e6bc2cSmrg "Failed converting warn temp %u.%06u to code",
69639e6bc2cSmrg rks->s_warn / 1000000, rks->s_warn % 1000000);
69739e6bc2cSmrg continue;
69839e6bc2cSmrg }
69939e6bc2cSmrg
70039e6bc2cSmrg TSADC_WRITE(sc, rks->s_comp_tshut, data);
70139e6bc2cSmrg TSADC_WRITE(sc, rks->s_comp_int, warndata);
70239e6bc2cSmrg
70339e6bc2cSmrg val |= rks->s_comp_int_en;
70439e6bc2cSmrg }
70539e6bc2cSmrg TSADC_WRITE(sc, TSADC_AUTO_CON, val);
70639e6bc2cSmrg }
70739e6bc2cSmrg
70839e6bc2cSmrg static void
rk_tsadc_init_tshut(struct rk_tsadc_softc * sc,int mode,int polarity)70939e6bc2cSmrg rk_tsadc_init_tshut(struct rk_tsadc_softc *sc, int mode, int polarity)
71039e6bc2cSmrg {
71139e6bc2cSmrg uint32_t val;
71239e6bc2cSmrg
71339e6bc2cSmrg /* Handle TSHUT temp setting. */
71439e6bc2cSmrg rk_tsadc_tshut_set(sc);
71539e6bc2cSmrg
71639e6bc2cSmrg /* Handle TSHUT mode setting. */
71739e6bc2cSmrg val = TSADC_READ(sc, TSADC_INT_EN);
71839e6bc2cSmrg if (mode == TSHUT_MODE_CPU) {
71939e6bc2cSmrg val |= TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 |
72039e6bc2cSmrg TSADC_INT_EN_TSHUT_2CRU_EN_SRC0;
72139e6bc2cSmrg val &= ~(TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 |
72239e6bc2cSmrg TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0);
72339e6bc2cSmrg } else {
72439e6bc2cSmrg KASSERT(mode == TSHUT_MODE_GPIO);
72539e6bc2cSmrg val &= ~(TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 |
72639e6bc2cSmrg TSADC_INT_EN_TSHUT_2CRU_EN_SRC0);
7270445ffd2Sjmcneill val |= TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 |
72839e6bc2cSmrg TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0;
72939e6bc2cSmrg }
73039e6bc2cSmrg TSADC_WRITE(sc, TSADC_INT_EN, val);
73139e6bc2cSmrg
73239e6bc2cSmrg /* Handle TSHUT polarity setting. */
73339e6bc2cSmrg val = TSADC_READ(sc, TSADC_AUTO_CON);
73439e6bc2cSmrg if (polarity == TSHUT_HIGH_ACTIVE)
73539e6bc2cSmrg val |= TSADC_AUTO_CON_TSHUT_POLARITY;
73639e6bc2cSmrg else
73739e6bc2cSmrg val &= ~TSADC_AUTO_CON_TSHUT_POLARITY;
73839e6bc2cSmrg TSADC_WRITE(sc, TSADC_AUTO_CON, val);
73939e6bc2cSmrg }
74039e6bc2cSmrg
74139e6bc2cSmrg static void
rk_tsadc_init_common(struct rk_tsadc_softc * sc,int mode,int polarity)742c5e7cb41Sjmcneill rk_tsadc_init_common(struct rk_tsadc_softc *sc, int mode, int polarity)
743863b2b98Smrg {
744863b2b98Smrg
745863b2b98Smrg rk_tsadc_init_tshut(sc, mode, polarity);
746863b2b98Smrg rk_tsadc_init_counts(sc);
747863b2b98Smrg }
748863b2b98Smrg
749863b2b98Smrg static void
rk_tsadc_init_rk3399(struct rk_tsadc_softc * sc,int mode,int polarity)750863b2b98Smrg rk_tsadc_init_rk3399(struct rk_tsadc_softc *sc, int mode, int polarity)
75139e6bc2cSmrg {
75239e6bc2cSmrg
75339e6bc2cSmrg syscon_lock(sc->sc_syscon);
75439e6bc2cSmrg syscon_write_4(sc->sc_syscon, RK3399_GRF_TSADC_TESTBIT_L,
75539e6bc2cSmrg RK3399_GRF_TSADC_TESTBIT_VCM_EN_L);
75639e6bc2cSmrg syscon_write_4(sc->sc_syscon, RK3399_GRF_TSADC_TESTBIT_H,
75739e6bc2cSmrg RK3399_GRF_TSADC_TESTBIT_VCM_EN_H);
75839e6bc2cSmrg
75939e6bc2cSmrg DELAY(20);
76039e6bc2cSmrg syscon_write_4(sc->sc_syscon, RK3399_GRF_SARADC_TESTBIT,
76139e6bc2cSmrg RK3399_GRF_SARADC_TESTBIT_ON);
76239e6bc2cSmrg syscon_write_4(sc->sc_syscon, RK3399_GRF_TSADC_TESTBIT_H,
76339e6bc2cSmrg RK3399_GRF_TSADC_TESTBIT_H_ON);
76439e6bc2cSmrg DELAY(100);
76539e6bc2cSmrg syscon_unlock(sc->sc_syscon);
766863b2b98Smrg
767c5e7cb41Sjmcneill rk_tsadc_init_common(sc, mode, polarity);
76839e6bc2cSmrg }
76939e6bc2cSmrg
77039e6bc2cSmrg static void
rk_tsadc_init_enable(struct rk_tsadc_softc * sc)77139e6bc2cSmrg rk_tsadc_init_enable(struct rk_tsadc_softc *sc)
77239e6bc2cSmrg {
77339e6bc2cSmrg uint32_t val;
77439e6bc2cSmrg
77539e6bc2cSmrg val = TSADC_READ(sc, TSADC_AUTO_CON);
77639e6bc2cSmrg val |= TSADC_AUTO_CON_AUTO_STATUS |
7776bc30fa4Smrg TSADC_AUTO_CON_SRC1_LT_EN | TSADC_AUTO_CON_SRC0_LT_EN;
77839e6bc2cSmrg TSADC_WRITE(sc, TSADC_AUTO_CON, val);
77939e6bc2cSmrg
78039e6bc2cSmrg /* Finally, register & enable the controller */
78139e6bc2cSmrg sysmon_envsys_register(sc->sc_sme);
78239e6bc2cSmrg
78339e6bc2cSmrg val = TSADC_READ(sc, TSADC_AUTO_CON);
784c5e7cb41Sjmcneill val |= TSADC_AUTO_CON_AUTO_EN;
785c5e7cb41Sjmcneill if (sc->sc_rd->rd_version >= 3) {
786c5e7cb41Sjmcneill val |= TSADC_AUTO_CON_Q_SEL;
787c5e7cb41Sjmcneill }
78839e6bc2cSmrg TSADC_WRITE(sc, TSADC_AUTO_CON, val);
78939e6bc2cSmrg }
79039e6bc2cSmrg
791863b2b98Smrg static void
rk_tsadc_init(struct rk_tsadc_softc * sc,int mode,int polarity)792863b2b98Smrg rk_tsadc_init(struct rk_tsadc_softc *sc, int mode, int polarity)
793863b2b98Smrg {
794863b2b98Smrg
7957ce6ce51Smrg (*sc->sc_rd->rd_init)(sc, mode, polarity);
796863b2b98Smrg rk_tsadc_init_enable(sc);
797863b2b98Smrg }
798863b2b98Smrg
79939e6bc2cSmrg /* run time support */
80039e6bc2cSmrg
8017ce6ce51Smrg /* given edata, find the matching rk sensor structure */
80239e6bc2cSmrg static struct rk_tsadc_sensor *
rk_tsadc_edata_to_sensor(struct rk_tsadc_softc * const sc,envsys_data_t * edata)80339e6bc2cSmrg rk_tsadc_edata_to_sensor(struct rk_tsadc_softc * const sc, envsys_data_t *edata)
80439e6bc2cSmrg {
805863b2b98Smrg
8067ce6ce51Smrg for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) {
80739e6bc2cSmrg struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
80839e6bc2cSmrg
80939e6bc2cSmrg if (&rks->s_data == edata)
81039e6bc2cSmrg return rks;
81139e6bc2cSmrg }
81239e6bc2cSmrg return NULL;
81339e6bc2cSmrg }
81439e6bc2cSmrg
81539e6bc2cSmrg static void
rk_tsadc_refresh(struct sysmon_envsys * sme,envsys_data_t * edata)81639e6bc2cSmrg rk_tsadc_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
81739e6bc2cSmrg {
81839e6bc2cSmrg struct rk_tsadc_softc * const sc = sme->sme_cookie;
81939e6bc2cSmrg struct rk_tsadc_sensor *rks = rk_tsadc_edata_to_sensor(sc, edata);
82039e6bc2cSmrg unsigned data;
82139e6bc2cSmrg int temp;
82239e6bc2cSmrg
82339e6bc2cSmrg if (rks == NULL)
82439e6bc2cSmrg return;
82539e6bc2cSmrg
82639e6bc2cSmrg data = TSADC_READ(sc, rks->s_data_reg) & sc->sc_data_mask;
82739e6bc2cSmrg temp = rk_tsadc_data_to_temp(sc, data);
82839e6bc2cSmrg
829863b2b98Smrg DPRINTF("(%s:%s): temp/data %d/%u",
830863b2b98Smrg sc->sc_sme->sme_name, rks->s_data.desc,
831863b2b98Smrg temp, data);
832863b2b98Smrg
83339e6bc2cSmrg if (temp == sc->sc_data_mask) {
83439e6bc2cSmrg edata->state = ENVSYS_SINVALID;
83539e6bc2cSmrg } else {
83639e6bc2cSmrg edata->value_cur = temp + TEMP_uC_TO_uK;
83739e6bc2cSmrg edata->state = ENVSYS_SVALID;
83839e6bc2cSmrg }
83939e6bc2cSmrg }
84039e6bc2cSmrg
84139e6bc2cSmrg static void
rk_tsadc_get_limits(struct sysmon_envsys * sme,envsys_data_t * edata,sysmon_envsys_lim_t * lim,uint32_t * props)84239e6bc2cSmrg rk_tsadc_get_limits(struct sysmon_envsys *sme,
84339e6bc2cSmrg envsys_data_t *edata,
84439e6bc2cSmrg sysmon_envsys_lim_t *lim,
84539e6bc2cSmrg uint32_t *props)
84639e6bc2cSmrg {
84739e6bc2cSmrg struct rk_tsadc_softc *sc = sme->sme_cookie;
84839e6bc2cSmrg struct rk_tsadc_sensor *rks = rk_tsadc_edata_to_sensor(sc, edata);
84939e6bc2cSmrg
85039e6bc2cSmrg if (rks == NULL)
85139e6bc2cSmrg return;
85239e6bc2cSmrg
85339e6bc2cSmrg lim->sel_critmax = rks->s_tshut + TEMP_uC_TO_uK;
85439e6bc2cSmrg lim->sel_warnmax = rks->s_warn + TEMP_uC_TO_uK;
85539e6bc2cSmrg
85639e6bc2cSmrg *props = PROP_CRITMAX | PROP_WARNMAX;
85739e6bc2cSmrg }
85839e6bc2cSmrg
85939e6bc2cSmrg /* XXX do something with interrupts that don't happen yet. */
86039e6bc2cSmrg static int
rk_tsadc_intr(void * arg)86139e6bc2cSmrg rk_tsadc_intr(void *arg)
86239e6bc2cSmrg {
86339e6bc2cSmrg struct rk_tsadc_softc * const sc = arg;
86439e6bc2cSmrg uint32_t val;
86539e6bc2cSmrg
86639e6bc2cSmrg /* XXX */
86739e6bc2cSmrg DPRINTF("(%s): interrupted", sc->sc_sme->sme_name);
868cd3d18e7Sjoerg for (unsigned n = 0; n < __arraycount(rk_tsadc_sensors); n++) {
86939e6bc2cSmrg struct rk_tsadc_sensor *rks = &sc->sc_sensors[n];
87039e6bc2cSmrg
87139e6bc2cSmrg rk_tsadc_refresh(sc->sc_sme, (envsys_data_t *)rks);
87239e6bc2cSmrg }
87339e6bc2cSmrg
87439e6bc2cSmrg /* ack interrupt */
87539e6bc2cSmrg val = TSADC_READ(sc, TSADC_INT_PD);
876c5e7cb41Sjmcneill if (sc->sc_rd->rd_version >= 3) {
877c5e7cb41Sjmcneill TSADC_WRITE(sc, TSADC_INT_PD,
878c5e7cb41Sjmcneill val & ~TSADC_INT_PD_EOC_INT_PD_V3);
879c5e7cb41Sjmcneill } else {
880c5e7cb41Sjmcneill TSADC_WRITE(sc, TSADC_INT_PD,
881c5e7cb41Sjmcneill val & ~TSADC_INT_PD_EOC_INT_PD_V2);
882c5e7cb41Sjmcneill }
88339e6bc2cSmrg
88439e6bc2cSmrg return 1;
88539e6bc2cSmrg }
88639e6bc2cSmrg
88739e6bc2cSmrg /*
88839e6bc2cSmrg * Convert TDASC data codes to temp and reverse. The manual only has codes
88939e6bc2cSmrg * and temperature values in 5 degC intervals, but says that interpolation
89039e6bc2cSmrg * can be done to achieve better resolution between these values, and that
89139e6bc2cSmrg * the spacing is linear.
89239e6bc2cSmrg */
89339e6bc2cSmrg static int
rk_tsadc_data_to_temp(struct rk_tsadc_softc * sc,uint32_t data)89439e6bc2cSmrg rk_tsadc_data_to_temp(struct rk_tsadc_softc *sc, uint32_t data)
89539e6bc2cSmrg {
89639e6bc2cSmrg unsigned i;
8977ce6ce51Smrg const rk_data *rd = sc->sc_rd;
89839e6bc2cSmrg
8997ce6ce51Smrg if (data > rd->rd_max || data < rd->rd_min) {
9007ce6ce51Smrg DPRINTF("data out of range (%u > %u || %u < %u)",
9017ce6ce51Smrg data, rd->rd_max, data, rd->rd_min);
902863b2b98Smrg return sc->sc_data_mask;
903863b2b98Smrg }
9047ce6ce51Smrg for (i = 1; i < rd->rd_size; i++) {
9057ce6ce51Smrg if (rd->rd_array[i].data >= data) {
9066bc30fa4Smrg int temprange, offset;
9076bc30fa4Smrg uint32_t datarange, datadiff;
908863b2b98Smrg unsigned first, secnd;
9096bc30fa4Smrg
9107ce6ce51Smrg if (rd->rd_array[i].data == data)
9117ce6ce51Smrg return rd->rd_array[i].temp;
9126bc30fa4Smrg
9136bc30fa4Smrg /* must interpolate */
9147ce6ce51Smrg if (rd->rd_decr) {
915863b2b98Smrg first = i;
916863b2b98Smrg secnd = i+1;
917863b2b98Smrg } else {
918863b2b98Smrg first = i;
919863b2b98Smrg secnd = i-1;
920863b2b98Smrg }
921863b2b98Smrg
9227ce6ce51Smrg temprange = rd->rd_array[first].temp -
9237ce6ce51Smrg rd->rd_array[secnd].temp;
9247ce6ce51Smrg datarange = rd->rd_array[first].data -
9257ce6ce51Smrg rd->rd_array[secnd].data;
9267ce6ce51Smrg datadiff = data - rd->rd_array[secnd].data;
9276bc30fa4Smrg
9286bc30fa4Smrg offset = (temprange * datadiff) / datarange;
9297ce6ce51Smrg return rd->rd_array[secnd].temp + offset;
93039e6bc2cSmrg }
93139e6bc2cSmrg }
932863b2b98Smrg panic("didn't find range");
93339e6bc2cSmrg }
93439e6bc2cSmrg
93539e6bc2cSmrg static uint32_t
rk_tsadc_temp_to_data(struct rk_tsadc_softc * sc,int temp)93639e6bc2cSmrg rk_tsadc_temp_to_data(struct rk_tsadc_softc *sc, int temp)
93739e6bc2cSmrg {
93839e6bc2cSmrg unsigned i;
9397ce6ce51Smrg const rk_data *rd = sc->sc_rd;
94039e6bc2cSmrg
9417ce6ce51Smrg for (i = 1; i < rd->rd_size; i++) {
9427ce6ce51Smrg if (rd->rd_array[i].temp >= temp) {
9436bc30fa4Smrg int temprange, tempdiff;
9446bc30fa4Smrg uint32_t datarange, offset;
945863b2b98Smrg unsigned first, secnd;
9466bc30fa4Smrg
9477ce6ce51Smrg if (rd->rd_array[i].temp == temp)
9487ce6ce51Smrg return rd->rd_array[i].data;
9496bc30fa4Smrg
9506bc30fa4Smrg /* must interpolate */
9517ce6ce51Smrg if (rd->rd_decr) {
952863b2b98Smrg first = i;
953863b2b98Smrg secnd = i+1;
954863b2b98Smrg } else {
955863b2b98Smrg first = i;
956863b2b98Smrg secnd = i-1;
957863b2b98Smrg }
958863b2b98Smrg
9597ce6ce51Smrg datarange = rd->rd_array[first].data -
9607ce6ce51Smrg rd->rd_array[secnd].data;
9617ce6ce51Smrg temprange = rd->rd_array[first].temp -
9627ce6ce51Smrg rd->rd_array[secnd].temp;
9637ce6ce51Smrg tempdiff = temp - rd->rd_array[secnd].temp;
9646bc30fa4Smrg
9656bc30fa4Smrg offset = (datarange * tempdiff) / temprange;
9667ce6ce51Smrg return rd->rd_array[secnd].data + offset;
96739e6bc2cSmrg }
96839e6bc2cSmrg }
96939e6bc2cSmrg
97039e6bc2cSmrg return sc->sc_data_mask;
97139e6bc2cSmrg }
972