Module Name: src Committed By: mrg Date: Wed May 15 01:24:43 UTC 2019
Modified Files: src/sys/arch/arm/rockchip: rk3328_cru.c rk_tsadc.c Log Message: support RK3328 tsadc: - add clk_24m, clk_tsadc and pclk_tsadc rk3328 clocks - rk3328 data<->temp conversion table is is wrong. the actual values seen are 4096 - <expected>, and the linux driver has these values in the inverted value directly - the above means the rk3328 is increasing data for increasing temp, and the min/max values are also inverted and swapped - move auto-period into the rk_data - rk3328 only has one sensor, deal with this - rename rk_data_table as rk_data, and also s/rdt/rd/ thanks to jmcneill who helped clean up clocks confusion, and pointed out the linux driver values matched my own inverted data experience. To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/rockchip/rk3328_cru.c \ src/sys/arch/arm/rockchip/rk_tsadc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/rockchip/rk3328_cru.c diff -u src/sys/arch/arm/rockchip/rk3328_cru.c:1.4 src/sys/arch/arm/rockchip/rk3328_cru.c:1.5 --- src/sys/arch/arm/rockchip/rk3328_cru.c:1.4 Sun Aug 12 16:48:04 2018 +++ src/sys/arch/arm/rockchip/rk3328_cru.c Wed May 15 01:24:43 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: rk3328_cru.c,v 1.4 2018/08/12 16:48:04 jmcneill Exp $ */ +/* $NetBSD: rk3328_cru.c,v 1.5 2019/05/15 01:24:43 mrg Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -28,7 +28,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: rk3328_cru.c,v 1.4 2018/08/12 16:48:04 jmcneill Exp $"); +__KERNEL_RCSID(1, "$NetBSD: rk3328_cru.c,v 1.5 2019/05/15 01:24:43 mrg Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -147,6 +147,7 @@ static const char * mux_uart1_parents[] static const char * mux_uart2_parents[] = { "clk_uart2_div", "clk_uart2_frac", "xin24m" }; static const char * mux_mac2io_src_parents[] = { "clk_mac2io_src", "gmac_clkin" }; static const char * mux_mac2io_ext_parents[] = { "clk_mac2io", "gmac_clkin" }; +static const char * mux_clk_tsadc_parents[] = { "clk_24m" }; static const char * mux_2plls_parents[] = { "cpll", "gpll" }; static const char * mux_2plls_hdmiphy_parents[] = { "cpll", "gpll", "dummy_hdmiphy" }; static const char * comp_uart_parents[] = { "cpll", "gpll", "usb480m" }; @@ -329,6 +330,15 @@ static struct rk_cru_clk rk3328_cru_clks CLKGATE_CON(2), /* gate_reg */ __BIT(12), /* gate_mask */ 0), + RK_COMPOSITE(RK3328_SCLK_TSADC, "clk_tsadc", mux_clk_tsadc_parents, + CLKSEL_CON(22), /* muxdiv_reg */ + 0, /* mux_mask */ + __BITS(9,0), /* div_mask */ + CLKGATE_CON(2), /* gate_reg */ + __BIT(6), /* gate_mask */ + 0), + + RK_DIV(0, "clk_24m", "xin24m", CLKSEL_CON(2), __BITS(12,8), 0), RK_GATE(0, "apll_core", "apll", CLKGATE_CON(0), 0), RK_GATE(0, "dpll_core", "dpll", CLKGATE_CON(0), 1), @@ -351,6 +361,7 @@ static struct rk_cru_clk rk3328_cru_clks RK_GATE(RK3328_PCLK_UART0, "pclk_uart0", "pclk_bus", CLKGATE_CON(16), 11), RK_GATE(RK3328_PCLK_UART1, "pclk_uart1", "pclk_bus", CLKGATE_CON(16), 12), RK_GATE(RK3328_PCLK_UART2, "pclk_uart2", "pclk_bus", CLKGATE_CON(16), 13), + RK_GATE(RK3328_PCLK_TSADC, "pclk_tsadc", "pclk_bus", CLKGATE_CON(16), 14), RK_GATE(RK3328_SCLK_MAC2IO_REF, "clk_mac2io_ref", "clk_mac2io", CLKGATE_CON(9), 7), RK_GATE(RK3328_SCLK_MAC2IO_RX, "clk_mac2io_rx", "clk_mac2io", CLKGATE_CON(9), 4), RK_GATE(RK3328_SCLK_MAC2IO_TX, "clk_mac2io_tx", "clk_mac2io", CLKGATE_CON(9), 5), Index: src/sys/arch/arm/rockchip/rk_tsadc.c diff -u src/sys/arch/arm/rockchip/rk_tsadc.c:1.4 src/sys/arch/arm/rockchip/rk_tsadc.c:1.5 --- src/sys/arch/arm/rockchip/rk_tsadc.c:1.4 Tue May 14 07:45:03 2019 +++ src/sys/arch/arm/rockchip/rk_tsadc.c Wed May 15 01:24:43 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_tsadc.c,v 1.4 2019/05/14 07:45:03 mrg Exp $ */ +/* $NetBSD: rk_tsadc.c,v 1.5 2019/05/15 01:24:43 mrg Exp $ */ /* * Copyright (c) 2019 Matthew R. Green @@ -30,7 +30,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rk_tsadc.c,v 1.4 2019/05/14 07:45:03 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_tsadc.c,v 1.5 2019/05/15 01:24:43 mrg Exp $"); /* * Driver for the TSADC temperature sensor monitor in RK3328 and RK3399. @@ -40,8 +40,6 @@ __KERNEL_RCSID(0, "$NetBSD: rk_tsadc.c,v * - handle DT trips/temp value defaults * - interrupts aren't triggered (test by lowering warn/crit values), and * once they work, make the interrupt do something - * - fix for RK3328, and port to other rockchips (will require moving some - * part into per-chipset sections, such as code<->temp tables) */ #include <sys/param.h> @@ -57,7 +55,6 @@ __KERNEL_RCSID(0, "$NetBSD: rk_tsadc.c,v #include <dev/sysmon/sysmonvar.h> -//#define RKTSADC_DEBUG #ifdef RKTSADC_DEBUG #define DPRINTF(fmt, ...) \ printf("%s:%d: " fmt "\n", __func__, __LINE__, ## __VA_ARGS__) @@ -159,7 +156,7 @@ __KERNEL_RCSID(0, "$NetBSD: rk_tsadc.c,v #define TSADC_DATA_MAX 0xfff -#define NUM_SENSORS 2 +#define MAX_SENSORS 2 typedef struct rk_data_array { uint32_t data; /* register value */ @@ -167,14 +164,15 @@ typedef struct rk_data_array { } rk_data_array; struct rk_tsadc_softc; -typedef struct rk_data_table { - const rk_data_array *rdt_array; - size_t rdt_size; - void (*rdt_init)(struct rk_tsadc_softc *, int, int); - bool rdt_decr; /* lower values -> higher temp */ - unsigned rdt_min, rdt_max; - unsigned rdt_auto_period; -} rk_data_table; +typedef struct rk_data { + const rk_data_array *rd_array; + size_t rd_size; + void (*rd_init)(struct rk_tsadc_softc *, int, int); + bool rd_decr; /* lower values -> higher temp */ + unsigned rd_min, rd_max; + unsigned rd_auto_period; + unsigned rd_num_sensors; +} rk_data; /* Per-sensor data */ struct rk_tsadc_sensor { @@ -201,14 +199,14 @@ struct rk_tsadc_softc { void *sc_ih; struct sysmon_envsys *sc_sme; - struct rk_tsadc_sensor sc_sensors[NUM_SENSORS]; + struct rk_tsadc_sensor sc_sensors[MAX_SENSORS]; struct clk *sc_clock; struct clk *sc_clockapb; struct fdtbus_reset *sc_reset; struct syscon *sc_syscon; - const rk_data_table *sc_rdt; + const rk_data *sc_rd; }; static int rk_tsadc_match(device_t, cfdata_t, void *); @@ -264,9 +262,15 @@ static const struct rk_tsadc_sensor rk_t }, }; -/* Table from RK3328 manual */ +/* + * Table from RK3328 manual. Note that the manual lists valid numbers as + * 4096 - number. This also means it is increasing not decreasing for + * higher temps, and the min and max are also offset from 4096. + */ +#define RK3328_DATA_OFFSET (4096) static const rk_data_array rk3328_data_array[] = { -#define ENTRY(d,C) { .data = (d), .temp = (C) * 1000 * 1000, } +#define ENTRY(d,C) \ + { .data = RK3328_DATA_OFFSET - (d), .temp = (C) * 1000 * 1000, } ENTRY(TSADC_DATA_MAX, -40), ENTRY(3800, -40), ENTRY(3792, -35), @@ -348,34 +352,30 @@ static const rk_data_array rk3399_data_a #undef ENTRY }; -static const rk_data_table rk3328_data_table = { - .rdt_array = rk3328_data_array, - .rdt_size = __arraycount(rk3328_data_array), - .rdt_init = rk_tsadc_init_rk3328, - .rdt_decr = true, - .rdt_max = 3801, - .rdt_min = 3420, - .rdt_auto_period = RK3328_TSADC_AUTO_PERIOD_TIME, +static const rk_data rk3328_data_table = { + .rd_array = rk3328_data_array, + .rd_size = __arraycount(rk3328_data_array), + .rd_init = rk_tsadc_init_rk3328, + .rd_decr = false, + .rd_max = RK3328_DATA_OFFSET - 3420, + .rd_min = RK3328_DATA_OFFSET - 3801, + .rd_auto_period = RK3328_TSADC_AUTO_PERIOD_TIME, + .rd_num_sensors = 1, }; -static const rk_data_table rk3399_data_table = { - .rdt_array = rk3399_data_array, - .rdt_size = __arraycount(rk3399_data_array), - .rdt_init = rk_tsadc_init_rk3399, - .rdt_decr = false, - .rdt_max = 686, - .rdt_min = 401, - .rdt_auto_period = RK3399_TSADC_AUTO_PERIOD_TIME, +static const rk_data rk3399_data_table = { + .rd_array = rk3399_data_array, + .rd_size = __arraycount(rk3399_data_array), + .rd_init = rk_tsadc_init_rk3399, + .rd_decr = false, + .rd_max = 686, + .rd_min = 401, + .rd_auto_period = RK3399_TSADC_AUTO_PERIOD_TIME, + .rd_num_sensors = 2, }; static const char * const compatible_rk3328[] = { -#if 0 - /* - * does not yet report sane values. should be between 3421 and 3800, - * but CPU tends to report < 1000 and the GPU reports 600-1600. - */ "rockchip,rk3328-tsadc", -#endif NULL }; @@ -430,6 +430,13 @@ rk_tsadc_attach(device_t parent, device_ pmf_device_register(self, NULL, NULL); + if (of_match_compatible(faa->faa_phandle, compatible_rk3328)) { + sc->sc_rd = &rk3328_data_table; + } else { + KASSERT(of_match_compatible(faa->faa_phandle, compatible_rk3399)); + sc->sc_rd = &rk3399_data_table; + } + /* Default to tshut via gpio and tshut low is active */ if (of_getprop_uint32(phandle, "rockchip,hw-tshut-mode", &mode) != 0) { @@ -455,7 +462,7 @@ rk_tsadc_attach(device_t parent, device_ tshut_temp *= 1000; /* convert fdt ms -> us */ memcpy(sc->sc_sensors, rk_tsadc_sensors, sizeof(sc->sc_sensors)); - for (unsigned n = 0; n < NUM_SENSORS; n++) { + for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) { struct rk_tsadc_sensor *rks = &sc->sc_sensors[n]; rks->s_data.flags = ENVSYS_FMONLIMITS; @@ -508,13 +515,6 @@ rk_tsadc_attach(device_t parent, device_ return; } - if (of_match_compatible(faa->faa_phandle, compatible_rk3328)) { - sc->sc_rdt = &rk3328_data_table; - } else { - KASSERT(of_match_compatible(faa->faa_phandle, compatible_rk3399)); - sc->sc_rdt = &rk3399_data_table; - } - /* * Manual says to setup auto period (both), high temp (interrupt), * high temp (shutdown), enable high temp resets (TSHUT to GPIO @@ -536,7 +536,7 @@ rk_tsadc_detach(device_t self, int flags pmf_device_deregister(self); - for (unsigned n = 0; n < NUM_SENSORS; n++) { + for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) { struct rk_tsadc_sensor *rks = &sc->sc_sensors[n]; if (rks->s_attached) { @@ -598,8 +598,8 @@ static void rk_tsadc_init_counts(struct rk_tsadc_softc *sc) { - TSADC_WRITE(sc, TSADC_AUTO_PERIOD, sc->sc_rdt->rdt_auto_period); - TSADC_WRITE(sc, TSADC_AUTO_PERIOD_HT, sc->sc_rdt->rdt_auto_period); + TSADC_WRITE(sc, TSADC_AUTO_PERIOD, sc->sc_rd->rd_auto_period); + TSADC_WRITE(sc, TSADC_AUTO_PERIOD_HT, sc->sc_rd->rd_auto_period); TSADC_WRITE(sc, TSADC_HIGH_INT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT); TSADC_WRITE(sc, TSADC_HIGH_TSHUT_DEBOUNCE, TSADC_HT_DEBOUNCE_COUNT); } @@ -610,10 +610,15 @@ rk_tsadc_tshut_set(struct rk_tsadc_softc { uint32_t val = TSADC_READ(sc, TSADC_AUTO_CON); - for (unsigned n = 0; n < NUM_SENSORS; n++) { + for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) { struct rk_tsadc_sensor *rks = &sc->sc_sensors[n]; - uint32_t data = rk_tsadc_temp_to_data(sc, rks->s_tshut); - uint32_t warndata = rk_tsadc_temp_to_data(sc, rks->s_warn); + uint32_t data, warndata; + + if (!rks->s_attached) + continue; + + data = rk_tsadc_temp_to_data(sc, rks->s_tshut); + warndata = rk_tsadc_temp_to_data(sc, rks->s_warn); DPRINTF("(%s:%s): tshut/data %d/%u warn/data %d/%u", sc->sc_sme->sme_name, rks->s_data.desc, @@ -726,17 +731,18 @@ static void rk_tsadc_init(struct rk_tsadc_softc *sc, int mode, int polarity) { - (*sc->sc_rdt->rdt_init)(sc, mode, polarity); + (*sc->sc_rd->rd_init)(sc, mode, polarity); rk_tsadc_init_enable(sc); } /* run time support */ +/* given edata, find the matching rk sensor structure */ static struct rk_tsadc_sensor * rk_tsadc_edata_to_sensor(struct rk_tsadc_softc * const sc, envsys_data_t *edata) { - for (unsigned n = 0; n < NUM_SENSORS; n++) { + for (unsigned n = 0; n < sc->sc_rd->rd_num_sensors; n++) { struct rk_tsadc_sensor *rks = &sc->sc_sensors[n]; if (&rks->s_data == edata) @@ -821,23 +827,24 @@ static int rk_tsadc_data_to_temp(struct rk_tsadc_softc *sc, uint32_t data) { unsigned i; - const rk_data_table *rdt = sc->sc_rdt; + const rk_data *rd = sc->sc_rd; - if (data > rdt->rdt_max || data < rdt->rdt_min) { - DPRINTF("data out of range (%u > %u || %u < %u)", data, rdt->rdt_max, data, rdt->rdt_min); + if (data > rd->rd_max || data < rd->rd_min) { + DPRINTF("data out of range (%u > %u || %u < %u)", + data, rd->rd_max, data, rd->rd_min); return sc->sc_data_mask; } - for (i = 1; i < rdt->rdt_size; i++) { - if (rdt->rdt_array[i].data >= data) { + for (i = 1; i < rd->rd_size; i++) { + if (rd->rd_array[i].data >= data) { int temprange, offset; uint32_t datarange, datadiff; unsigned first, secnd; - if (rdt->rdt_array[i].data == data) - return rdt->rdt_array[i].temp; + if (rd->rd_array[i].data == data) + return rd->rd_array[i].temp; /* must interpolate */ - if (rdt->rdt_decr) { + if (rd->rd_decr) { first = i; secnd = i+1; } else { @@ -845,14 +852,14 @@ rk_tsadc_data_to_temp(struct rk_tsadc_so secnd = i-1; } - temprange = rdt->rdt_array[first].temp - - rdt->rdt_array[secnd].temp; - datarange = rdt->rdt_array[first].data - - rdt->rdt_array[secnd].data; - datadiff = data - rdt->rdt_array[secnd].data; + temprange = rd->rd_array[first].temp - + rd->rd_array[secnd].temp; + datarange = rd->rd_array[first].data - + rd->rd_array[secnd].data; + datadiff = data - rd->rd_array[secnd].data; offset = (temprange * datadiff) / datarange; - return rdt->rdt_array[secnd].temp + offset; + return rd->rd_array[secnd].temp + offset; } } panic("didn't find range"); @@ -862,19 +869,19 @@ static uint32_t rk_tsadc_temp_to_data(struct rk_tsadc_softc *sc, int temp) { unsigned i; - const rk_data_table *rdt = sc->sc_rdt; + const rk_data *rd = sc->sc_rd; - for (i = 1; i < rdt->rdt_size; i++) { - if (rdt->rdt_array[i].temp >= temp) { + for (i = 1; i < rd->rd_size; i++) { + if (rd->rd_array[i].temp >= temp) { int temprange, tempdiff; uint32_t datarange, offset; unsigned first, secnd; - if (rdt->rdt_array[i].temp == temp) - return rdt->rdt_array[i].data; + if (rd->rd_array[i].temp == temp) + return rd->rd_array[i].data; /* must interpolate */ - if (rdt->rdt_decr) { + if (rd->rd_decr) { first = i; secnd = i+1; } else { @@ -882,14 +889,14 @@ rk_tsadc_temp_to_data(struct rk_tsadc_so secnd = i-1; } - datarange = rdt->rdt_array[first].data - - rdt->rdt_array[secnd].data; - temprange = rdt->rdt_array[first].temp - - rdt->rdt_array[secnd].temp; - tempdiff = temp - rdt->rdt_array[secnd].temp; + datarange = rd->rd_array[first].data - + rd->rd_array[secnd].data; + temprange = rd->rd_array[first].temp - + rd->rd_array[secnd].temp; + tempdiff = temp - rd->rd_array[secnd].temp; offset = (datarange * tempdiff) / temprange; - return rdt->rdt_array[secnd].data + offset; + return rd->rd_array[secnd].data + offset; } }