Module Name: src Committed By: jmcneill Date: Mon Oct 9 14:28:01 UTC 2017
Modified Files: src/sys/arch/arm/sunxi: sunxi_ts.c Log Message: Add support for sun4i and sun6i, and enable temperature sensor support. To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/sunxi/sunxi_ts.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/sunxi/sunxi_ts.c diff -u src/sys/arch/arm/sunxi/sunxi_ts.c:1.1 src/sys/arch/arm/sunxi/sunxi_ts.c:1.2 --- src/sys/arch/arm/sunxi/sunxi_ts.c:1.1 Sun Aug 27 02:19:46 2017 +++ src/sys/arch/arm/sunxi/sunxi_ts.c Mon Oct 9 14:28:01 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sunxi_ts.c,v 1.1 2017/08/27 02:19:46 jmcneill Exp $ */ +/* $NetBSD: sunxi_ts.c,v 1.2 2017/10/09 14:28:01 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> @@ -28,7 +28,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sunxi_ts.c,v 1.1 2017/08/27 02:19:46 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sunxi_ts.c,v 1.2 2017/10/09 14:28:01 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -39,6 +39,8 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_ts.c,v #include <dev/fdt/fdtvar.h> +#include <dev/sysmon/sysmonvar.h> + #include <dev/wscons/wsconsio.h> #include <dev/wscons/wsmousevar.h> #include <dev/wscons/tpcalibvar.h> @@ -70,6 +72,7 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_ts.c,v #define TP_CTRL3_FILTER_EN __BIT(2) #define TP_CTRL3_FILTER_TYPE __BITS(1,0) #define TP_INT 0x10 +#define TP_INT_TEMP_IRQ_EN __BIT(18) #define TP_INT_OVERRUN_IRQ_EN __BIT(17) #define TP_INT_DATA_IRQ_EN __BIT(16) #define TP_INT_DATA_XY_CHANGE __BIT(13) @@ -79,26 +82,60 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_ts.c,v #define TP_INT_UP_IRQ_EN __BIT(1) #define TP_INT_DOWN_IRQ_EN __BIT(0) #define TP_FIFOCS 0x14 +#define TP_FIFOCS_TEMP_IRQ_PENDING __BIT(18) #define TP_FIFOCS_OVERRUN_PENDING __BIT(17) #define TP_FIFOCS_DATA_PENDING __BIT(16) #define TP_FIFOCS_RXA_CNT __BITS(12,8) #define TP_FIFOCS_IDLE_FLG __BIT(2) #define TP_FIFOCS_UP_PENDING __BIT(1) #define TP_FIFOCS_DOWN_PENDING __BIT(0) +#define TP_TPR 0x18 +#define TP_TPR_TEMP_EN __BIT(16) +#define TP_TPR_TEMP_PER __BITS(15,0) #define TP_CDAT 0x1c #define TP_CDAT_MASK __BITS(11,0) +#define TEMP_DATA 0x20 +#define TEMP_DATA_MASK __BITS(11,0) #define TP_DATA 0x24 #define TP_DATA_MASK __BITS(11,0) #define TP_IO_CONFIG 0x28 #define TP_PORT_DATA 0x2c #define TP_PORT_DATA_MASK __BITS(3,0) +#define TEMP_C_TO_K 273150000 + static int sunxi_ts_match(device_t, cfdata_t, void *); static void sunxi_ts_attach(device_t, device_t, void *); -static const char * const compatible[] = { - "allwinner,sun5i-a13-ts", - NULL +struct sunxi_ts_config { + int64_t temp_offset; + int64_t temp_step; + uint32_t tp_mode_en_mask; +}; + +static const struct sunxi_ts_config sun4i_a10_ts_config = { + .temp_offset = 257000000, + .temp_step = 133000, + .tp_mode_en_mask = TP_CTRL1_TP_MODE_EN, +}; + +static const struct sunxi_ts_config sun5i_a13_ts_config = { + .temp_offset = 144700000, + .temp_step = 100000, + .tp_mode_en_mask = TP_CTRL1_TP_MODE_EN, +}; + +static const struct sunxi_ts_config sun6i_a31_ts_config = { + .temp_offset = 271000000, + .temp_step = 167000, + .tp_mode_en_mask = TP_CTRL1_TP_DUAL_EN, +}; + +static const struct of_compat_data compat_data[] = { + { "allwinner,sun4i-a10-ts", (uintptr_t)&sun4i_a10_ts_config }, + { "allwinner,sun5i-a13-ts", (uintptr_t)&sun5i_a13_ts_config }, + { "allwinner,sun6i-a31-ts", (uintptr_t)&sun6i_a31_ts_config }, + { NULL } }; static struct wsmouse_calibcoords sunxi_ts_default_calib = { @@ -115,6 +152,8 @@ struct sunxi_ts_softc { bus_space_tag_t sc_bst; bus_space_handle_t sc_bsh; + const struct sunxi_ts_config *sc_conf; + bool sc_ts_attached; bool sc_ts_inverted_x; bool sc_ts_inverted_y; @@ -126,6 +165,9 @@ struct sunxi_ts_softc { u_int sc_tp_x; u_int sc_tp_y; u_int sc_tp_btns; + + struct sysmon_envsys *sc_sme; + envsys_data_t sc_temp_data; }; CFATTACH_DECL_NEW(sunxi_ts, sizeof(struct sunxi_ts_softc), @@ -140,6 +182,7 @@ static int sunxi_ts_enable(void *v) { struct sunxi_ts_softc * const sc = v; + uint32_t val; /* reset state */ sc->sc_ignoredata = true; @@ -148,9 +191,11 @@ sunxi_ts_enable(void *v) sc->sc_tp_btns = 0; /* Enable touchpanel IRQs */ - TS_WRITE(sc, TP_INT, - TP_INT_DATA_IRQ_EN | TP_INT_FIFO_FLUSH | TP_INT_UP_IRQ_EN | - __SHIFTIN(1, TP_INT_FIFO_TRIG_LEVEL)); + val = TS_READ(sc, TP_INT); + val |= TP_INT_DATA_IRQ_EN | TP_INT_FIFO_FLUSH | TP_INT_UP_IRQ_EN; + val &= ~TP_INT_FIFO_TRIG_LEVEL; + val |= __SHIFTIN(1, TP_INT_FIFO_TRIG_LEVEL); + TS_WRITE(sc, TP_INT, val); return 0; } @@ -159,9 +204,12 @@ static void sunxi_ts_disable(void *v) { struct sunxi_ts_softc * const sc = v; + uint32_t val; /* Disable touchpanel IRQs */ - TS_WRITE(sc, TP_INT, 0); + val = TS_READ(sc, TP_INT); + val &= ~(TP_INT_DATA_IRQ_EN | TP_INT_FIFO_FLUSH | TP_INT_UP_IRQ_EN); + TS_WRITE(sc, TP_INT, val); } static int @@ -207,6 +255,13 @@ sunxi_ts_intr(void *priv) fifocs = TS_READ(sc, TP_FIFOCS); + if (fifocs & TP_FIFOCS_TEMP_IRQ_PENDING) { + sc->sc_temp_data.value_cur = (TS_READ(sc, TEMP_DATA) * + sc->sc_conf->temp_step - sc->sc_conf->temp_offset) + + TEMP_C_TO_K; + sc->sc_temp_data.state = ENVSYS_SVALID; + } + if (fifocs & TP_FIFOCS_DATA_PENDING) { x = TS_READ(sc, TP_DATA); y = TS_READ(sc, TP_DATA); @@ -268,9 +323,19 @@ sunxi_ts_init(struct sunxi_ts_softc *sc) TP_CTRL3_FILTER_EN | __SHIFTIN(filter_type, TP_CTRL3_FILTER_TYPE)); TS_WRITE(sc, TP_CTRL1, - TP_CTRL1_TP_MODE_EN | + sc->sc_conf->tp_mode_en_mask | TP_CTRL1_STYLUS_UP_DEBOUNCE_EN | __SHIFTIN(5, TP_CTRL1_STYLUS_UP_DEBOUNCE)); + + /* Enable temperature sensor */ + TS_WRITE(sc, TP_TPR, + TP_TPR_TEMP_EN | __SHIFTIN(1953, TP_TPR_TEMP_PER)); + + /* Enable temperature sensor IRQ */ + TS_WRITE(sc, TP_INT, TP_INT_TEMP_IRQ_EN); + + /* Clear pending IRQs */ + TS_WRITE(sc, TP_FIFOCS, TS_READ(sc, TP_FIFOCS)); } static int @@ -278,7 +343,7 @@ sunxi_ts_match(device_t parent, cfdata_t { struct fdt_attach_args * const faa = aux; - return of_match_compatible(faa->faa_phandle, compatible); + return of_match_compat_data(faa->faa_phandle, compat_data); } static void @@ -310,6 +375,8 @@ sunxi_ts_attach(device_t parent, device_ aprint_error(": couldn't map registers\n"); return; } + sc->sc_conf = (void *)of_search_compatible(phandle, compat_data)->data; + sc->sc_ts_attached = of_getprop_bool(phandle, "allwinner,ts-attached"); sc->sc_ts_inverted_x = of_getprop_bool(phandle, "touchscreen-inverted-x"); @@ -329,6 +396,19 @@ sunxi_ts_attach(device_t parent, device_ } aprint_normal_dev(self, "interrupting on %s\n", intrstr); + sc->sc_sme = sysmon_envsys_create(); + sc->sc_sme->sme_name = device_xname(self); + sc->sc_sme->sme_cookie = sc; + sc->sc_sme->sme_flags = SME_DISABLE_REFRESH; + + sc->sc_temp_data.units = ENVSYS_STEMP; + sc->sc_temp_data.state = ENVSYS_SINVALID; + snprintf(sc->sc_temp_data.desc, sizeof(sc->sc_temp_data.desc), + "temperature"); + sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_temp_data); + + sysmon_envsys_register(sc->sc_sme); + if (sc->sc_ts_attached) { tpcalib_init(&sc->sc_tpcalib); tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,