sunxi_ts.c revision 1.8
11.8Sthorpej/* $NetBSD: sunxi_ts.c,v 1.8 2021/01/27 03:10:20 thorpej Exp $ */ 21.1Sjmcneill 31.1Sjmcneill/*- 41.1Sjmcneill * Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca> 51.1Sjmcneill * All rights reserved. 61.1Sjmcneill * 71.1Sjmcneill * Redistribution and use in source and binary forms, with or without 81.1Sjmcneill * modification, are permitted provided that the following conditions 91.1Sjmcneill * are met: 101.1Sjmcneill * 1. Redistributions of source code must retain the above copyright 111.1Sjmcneill * notice, this list of conditions and the following disclaimer. 121.1Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright 131.1Sjmcneill * notice, this list of conditions and the following disclaimer in the 141.1Sjmcneill * documentation and/or other materials provided with the distribution. 151.1Sjmcneill * 161.1Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Sjmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Sjmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Sjmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Sjmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Sjmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Sjmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Sjmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Sjmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Sjmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Sjmcneill * POSSIBILITY OF SUCH DAMAGE. 271.1Sjmcneill */ 281.1Sjmcneill 291.1Sjmcneill#include <sys/cdefs.h> 301.1Sjmcneill 311.8Sthorpej__KERNEL_RCSID(0, "$NetBSD: sunxi_ts.c,v 1.8 2021/01/27 03:10:20 thorpej Exp $"); 321.1Sjmcneill 331.1Sjmcneill#include <sys/param.h> 341.1Sjmcneill#include <sys/bus.h> 351.1Sjmcneill#include <sys/device.h> 361.1Sjmcneill#include <sys/intr.h> 371.1Sjmcneill#include <sys/systm.h> 381.1Sjmcneill#include <sys/time.h> 391.1Sjmcneill 401.1Sjmcneill#include <dev/fdt/fdtvar.h> 411.1Sjmcneill 421.2Sjmcneill#include <dev/sysmon/sysmonvar.h> 431.2Sjmcneill 441.1Sjmcneill#include <dev/wscons/wsconsio.h> 451.1Sjmcneill#include <dev/wscons/wsmousevar.h> 461.1Sjmcneill#include <dev/wscons/tpcalibvar.h> 471.1Sjmcneill 481.1Sjmcneill#define TS_TP_SENSITIVITY_ADJUST_DEFAULT 15 491.1Sjmcneill#define TS_FILTER_TYPE_DEFAULT 1 501.1Sjmcneill 511.1Sjmcneill#define TP_CTRL0 0x00 521.1Sjmcneill#define TP_CTRL0_ADC_FIRST_DLY __BITS(31,24) 531.1Sjmcneill#define TP_CTRL0_ADC_FIRST_DLY_MODE __BIT(23) 541.1Sjmcneill#define TP_CTRL0_ADC_CLK_SELECT __BIT(22) 551.1Sjmcneill#define TP_CTRL0_ADC_CLK_DIVIDER __BITS(21,20) 561.1Sjmcneill#define TP_CTRL0_FS_DIV __BITS(19,16) 571.1Sjmcneill#define TP_CTRL0_T_ACQ __BITS(15,0) 581.1Sjmcneill#define TP_CTRL1 0x04 591.1Sjmcneill#define TP_CTRL1_STYLUS_UP_DEBOUNCE __BITS(19,12) 601.1Sjmcneill#define TP_CTRL1_STYLUS_UP_DEBOUNCE_EN __BIT(9) 611.1Sjmcneill#define TP_CTRL1_TOUCH_PAN_CALI_EN __BIT(6) 621.1Sjmcneill#define TP_CTRL1_TP_DUAL_EN __BIT(5) 631.1Sjmcneill#define TP_CTRL1_TP_MODE_EN __BIT(4) 641.1Sjmcneill#define TP_CTRL1_TP_ADC_SELECT __BIT(3) 651.1Sjmcneill#define TP_CTRL1_ADC_CHAN_SELECT __BITS(2,0) 661.1Sjmcneill#define TP_CTRL2 0x08 671.1Sjmcneill#define TP_CTRL2_SENSITIVE_ADJUST __BITS(31,28) 681.1Sjmcneill#define TP_CTRL2_MODE_SELECT __BITS(27,26) 691.1Sjmcneill#define TP_CTRL2_PRE_MEA_EN __BIT(24) 701.1Sjmcneill#define TP_CTRL2_PRE_MEA_THRE_CNT __BITS(23,0) 711.1Sjmcneill#define TP_CTRL3 0x0c 721.1Sjmcneill#define TP_CTRL3_FILTER_EN __BIT(2) 731.1Sjmcneill#define TP_CTRL3_FILTER_TYPE __BITS(1,0) 741.1Sjmcneill#define TP_INT 0x10 751.2Sjmcneill#define TP_INT_TEMP_IRQ_EN __BIT(18) 761.1Sjmcneill#define TP_INT_OVERRUN_IRQ_EN __BIT(17) 771.1Sjmcneill#define TP_INT_DATA_IRQ_EN __BIT(16) 781.1Sjmcneill#define TP_INT_DATA_XY_CHANGE __BIT(13) 791.1Sjmcneill#define TP_INT_FIFO_TRIG_LEVEL __BITS(12,8) 801.1Sjmcneill#define TP_INT_DATA_DRQ_EN __BIT(7) 811.1Sjmcneill#define TP_INT_FIFO_FLUSH __BIT(4) 821.1Sjmcneill#define TP_INT_UP_IRQ_EN __BIT(1) 831.1Sjmcneill#define TP_INT_DOWN_IRQ_EN __BIT(0) 841.1Sjmcneill#define TP_FIFOCS 0x14 851.2Sjmcneill#define TP_FIFOCS_TEMP_IRQ_PENDING __BIT(18) 861.1Sjmcneill#define TP_FIFOCS_OVERRUN_PENDING __BIT(17) 871.1Sjmcneill#define TP_FIFOCS_DATA_PENDING __BIT(16) 881.1Sjmcneill#define TP_FIFOCS_RXA_CNT __BITS(12,8) 891.1Sjmcneill#define TP_FIFOCS_IDLE_FLG __BIT(2) 901.1Sjmcneill#define TP_FIFOCS_UP_PENDING __BIT(1) 911.1Sjmcneill#define TP_FIFOCS_DOWN_PENDING __BIT(0) 921.2Sjmcneill#define TP_TPR 0x18 931.2Sjmcneill#define TP_TPR_TEMP_EN __BIT(16) 941.2Sjmcneill#define TP_TPR_TEMP_PER __BITS(15,0) 951.1Sjmcneill#define TP_CDAT 0x1c 961.1Sjmcneill#define TP_CDAT_MASK __BITS(11,0) 971.2Sjmcneill#define TEMP_DATA 0x20 981.2Sjmcneill#define TEMP_DATA_MASK __BITS(11,0) 991.1Sjmcneill#define TP_DATA 0x24 1001.1Sjmcneill#define TP_DATA_MASK __BITS(11,0) 1011.1Sjmcneill#define TP_IO_CONFIG 0x28 1021.1Sjmcneill#define TP_PORT_DATA 0x2c 1031.1Sjmcneill#define TP_PORT_DATA_MASK __BITS(3,0) 1041.1Sjmcneill 1051.2Sjmcneill#define TEMP_C_TO_K 273150000 1061.2Sjmcneill 1071.1Sjmcneillstatic int sunxi_ts_match(device_t, cfdata_t, void *); 1081.1Sjmcneillstatic void sunxi_ts_attach(device_t, device_t, void *); 1091.1Sjmcneill 1101.2Sjmcneillstruct sunxi_ts_config { 1111.2Sjmcneill int64_t temp_offset; 1121.2Sjmcneill int64_t temp_step; 1131.2Sjmcneill uint32_t tp_mode_en_mask; 1141.2Sjmcneill}; 1151.2Sjmcneill 1161.2Sjmcneillstatic const struct sunxi_ts_config sun4i_a10_ts_config = { 1171.2Sjmcneill .temp_offset = 257000000, 1181.2Sjmcneill .temp_step = 133000, 1191.2Sjmcneill .tp_mode_en_mask = TP_CTRL1_TP_MODE_EN, 1201.2Sjmcneill}; 1211.2Sjmcneill 1221.2Sjmcneillstatic const struct sunxi_ts_config sun5i_a13_ts_config = { 1231.2Sjmcneill .temp_offset = 144700000, 1241.2Sjmcneill .temp_step = 100000, 1251.2Sjmcneill .tp_mode_en_mask = TP_CTRL1_TP_MODE_EN, 1261.2Sjmcneill}; 1271.2Sjmcneill 1281.2Sjmcneillstatic const struct sunxi_ts_config sun6i_a31_ts_config = { 1291.2Sjmcneill .temp_offset = 271000000, 1301.2Sjmcneill .temp_step = 167000, 1311.2Sjmcneill .tp_mode_en_mask = TP_CTRL1_TP_DUAL_EN, 1321.2Sjmcneill}; 1331.2Sjmcneill 1341.5Sthorpejstatic const struct device_compatible_entry compat_data[] = { 1351.5Sthorpej { .compat = "allwinner,sun4i-a10-ts", .data = &sun4i_a10_ts_config }, 1361.5Sthorpej { .compat = "allwinner,sun5i-a13-ts", .data = &sun5i_a13_ts_config }, 1371.5Sthorpej { .compat = "allwinner,sun6i-a31-ts", .data = &sun6i_a31_ts_config }, 1381.7Sthorpej DEVICE_COMPAT_EOL 1391.1Sjmcneill}; 1401.1Sjmcneill 1411.1Sjmcneillstatic struct wsmouse_calibcoords sunxi_ts_default_calib = { 1421.1Sjmcneill .minx = 0, 1431.1Sjmcneill .miny = 0, 1441.1Sjmcneill .maxx = __SHIFTOUT_MASK(TP_DATA_MASK), 1451.1Sjmcneill .maxy = __SHIFTOUT_MASK(TP_DATA_MASK), 1461.1Sjmcneill .samplelen = WSMOUSE_CALIBCOORDS_RESET, 1471.1Sjmcneill}; 1481.1Sjmcneill 1491.1Sjmcneillstruct sunxi_ts_softc { 1501.1Sjmcneill device_t sc_dev; 1511.1Sjmcneill int sc_phandle; 1521.1Sjmcneill bus_space_tag_t sc_bst; 1531.1Sjmcneill bus_space_handle_t sc_bsh; 1541.1Sjmcneill 1551.2Sjmcneill const struct sunxi_ts_config *sc_conf; 1561.2Sjmcneill 1571.1Sjmcneill bool sc_ts_attached; 1581.1Sjmcneill bool sc_ts_inverted_x; 1591.1Sjmcneill bool sc_ts_inverted_y; 1601.1Sjmcneill 1611.1Sjmcneill struct tpcalib_softc sc_tpcalib; 1621.1Sjmcneill device_t sc_wsmousedev; 1631.1Sjmcneill bool sc_ignoredata; 1641.1Sjmcneill 1651.1Sjmcneill u_int sc_tp_x; 1661.1Sjmcneill u_int sc_tp_y; 1671.1Sjmcneill u_int sc_tp_btns; 1681.2Sjmcneill 1691.2Sjmcneill struct sysmon_envsys *sc_sme; 1701.2Sjmcneill envsys_data_t sc_temp_data; 1711.1Sjmcneill}; 1721.1Sjmcneill 1731.1SjmcneillCFATTACH_DECL_NEW(sunxi_ts, sizeof(struct sunxi_ts_softc), 1741.1Sjmcneill sunxi_ts_match, sunxi_ts_attach, NULL, NULL); 1751.1Sjmcneill 1761.1Sjmcneill#define TS_READ(sc, reg) \ 1771.1Sjmcneill bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 1781.1Sjmcneill#define TS_WRITE(sc, reg, val) \ 1791.1Sjmcneill bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 1801.1Sjmcneill 1811.1Sjmcneillstatic int 1821.1Sjmcneillsunxi_ts_enable(void *v) 1831.1Sjmcneill{ 1841.1Sjmcneill struct sunxi_ts_softc * const sc = v; 1851.2Sjmcneill uint32_t val; 1861.1Sjmcneill 1871.1Sjmcneill /* reset state */ 1881.1Sjmcneill sc->sc_ignoredata = true; 1891.1Sjmcneill sc->sc_tp_x = 0; 1901.1Sjmcneill sc->sc_tp_y = 0; 1911.1Sjmcneill sc->sc_tp_btns = 0; 1921.1Sjmcneill 1931.1Sjmcneill /* Enable touchpanel IRQs */ 1941.2Sjmcneill val = TS_READ(sc, TP_INT); 1951.2Sjmcneill val |= TP_INT_DATA_IRQ_EN | TP_INT_FIFO_FLUSH | TP_INT_UP_IRQ_EN; 1961.2Sjmcneill val &= ~TP_INT_FIFO_TRIG_LEVEL; 1971.2Sjmcneill val |= __SHIFTIN(1, TP_INT_FIFO_TRIG_LEVEL); 1981.2Sjmcneill TS_WRITE(sc, TP_INT, val); 1991.1Sjmcneill 2001.1Sjmcneill return 0; 2011.1Sjmcneill} 2021.1Sjmcneill 2031.1Sjmcneillstatic void 2041.1Sjmcneillsunxi_ts_disable(void *v) 2051.1Sjmcneill{ 2061.1Sjmcneill struct sunxi_ts_softc * const sc = v; 2071.2Sjmcneill uint32_t val; 2081.1Sjmcneill 2091.1Sjmcneill /* Disable touchpanel IRQs */ 2101.2Sjmcneill val = TS_READ(sc, TP_INT); 2111.2Sjmcneill val &= ~(TP_INT_DATA_IRQ_EN | TP_INT_FIFO_FLUSH | TP_INT_UP_IRQ_EN); 2121.2Sjmcneill TS_WRITE(sc, TP_INT, val); 2131.1Sjmcneill} 2141.1Sjmcneill 2151.1Sjmcneillstatic int 2161.1Sjmcneillsunxi_ts_ioctl(void *v, u_long cmd, void *data, int flag, lwp_t *l) 2171.1Sjmcneill{ 2181.1Sjmcneill struct sunxi_ts_softc * const sc = v; 2191.1Sjmcneill struct wsmouse_id *id; 2201.1Sjmcneill 2211.1Sjmcneill switch (cmd) { 2221.1Sjmcneill case WSMOUSEIO_GTYPE: 2231.1Sjmcneill *(int *)data = WSMOUSE_TYPE_TPANEL; 2241.1Sjmcneill return 0; 2251.1Sjmcneill 2261.1Sjmcneill case WSMOUSEIO_GETID: 2271.1Sjmcneill id = data; 2281.1Sjmcneill if (id->type != WSMOUSE_ID_TYPE_UIDSTR) 2291.1Sjmcneill return EINVAL; 2301.1Sjmcneill snprintf(id->data, WSMOUSE_ID_MAXLEN, 2311.1Sjmcneill "Allwinner TS SN000000"); 2321.1Sjmcneill id->length = strlen(id->data); 2331.1Sjmcneill return 0; 2341.1Sjmcneill 2351.1Sjmcneill case WSMOUSEIO_SCALIBCOORDS: 2361.1Sjmcneill case WSMOUSEIO_GCALIBCOORDS: 2371.1Sjmcneill return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, l); 2381.1Sjmcneill } 2391.1Sjmcneill 2401.1Sjmcneill return EPASSTHROUGH; 2411.1Sjmcneill} 2421.1Sjmcneill 2431.1Sjmcneillstatic const struct wsmouse_accessops sunxi_ts_accessops = { 2441.1Sjmcneill .enable = sunxi_ts_enable, 2451.1Sjmcneill .disable = sunxi_ts_disable, 2461.1Sjmcneill .ioctl = sunxi_ts_ioctl, 2471.1Sjmcneill}; 2481.1Sjmcneill 2491.1Sjmcneillstatic int 2501.1Sjmcneillsunxi_ts_intr(void *priv) 2511.1Sjmcneill{ 2521.1Sjmcneill struct sunxi_ts_softc * const sc = priv; 2531.1Sjmcneill uint32_t fifocs, x, y; 2541.1Sjmcneill int s; 2551.1Sjmcneill 2561.1Sjmcneill fifocs = TS_READ(sc, TP_FIFOCS); 2571.1Sjmcneill 2581.2Sjmcneill if (fifocs & TP_FIFOCS_TEMP_IRQ_PENDING) { 2591.2Sjmcneill sc->sc_temp_data.value_cur = (TS_READ(sc, TEMP_DATA) * 2601.2Sjmcneill sc->sc_conf->temp_step - sc->sc_conf->temp_offset) + 2611.2Sjmcneill TEMP_C_TO_K; 2621.2Sjmcneill sc->sc_temp_data.state = ENVSYS_SVALID; 2631.2Sjmcneill } 2641.2Sjmcneill 2651.1Sjmcneill if (fifocs & TP_FIFOCS_DATA_PENDING) { 2661.1Sjmcneill x = TS_READ(sc, TP_DATA); 2671.1Sjmcneill y = TS_READ(sc, TP_DATA); 2681.1Sjmcneill if (sc->sc_ignoredata) { 2691.1Sjmcneill /* Discard the first report */ 2701.1Sjmcneill sc->sc_ignoredata = false; 2711.3Sthorpej } else if (sc->sc_wsmousedev != NULL) { 2721.1Sjmcneill if (sc->sc_ts_inverted_x) 2731.1Sjmcneill x = __SHIFTOUT_MASK(TP_DATA_MASK) - x; 2741.1Sjmcneill if (sc->sc_ts_inverted_y) 2751.1Sjmcneill y = __SHIFTOUT_MASK(TP_DATA_MASK) - y; 2761.1Sjmcneill tpcalib_trans(&sc->sc_tpcalib, x, y, 2771.1Sjmcneill &sc->sc_tp_x, &sc->sc_tp_y); 2781.1Sjmcneill sc->sc_tp_btns |= 1; 2791.1Sjmcneill 2801.1Sjmcneill s = spltty(); 2811.1Sjmcneill wsmouse_input(sc->sc_wsmousedev, 2821.1Sjmcneill sc->sc_tp_btns, sc->sc_tp_x, sc->sc_tp_y, 0, 0, 2831.1Sjmcneill WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 2841.1Sjmcneill splx(s); 2851.1Sjmcneill } 2861.1Sjmcneill } 2871.1Sjmcneill 2881.1Sjmcneill if (fifocs & TP_FIFOCS_UP_PENDING) { 2891.1Sjmcneill sc->sc_ignoredata = true; 2901.1Sjmcneill sc->sc_tp_btns &= ~1; 2911.1Sjmcneill s = spltty(); 2921.1Sjmcneill wsmouse_input(sc->sc_wsmousedev, 2931.1Sjmcneill sc->sc_tp_btns, sc->sc_tp_x, sc->sc_tp_y, 0, 0, 2941.1Sjmcneill WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 2951.1Sjmcneill splx(s); 2961.1Sjmcneill } 2971.1Sjmcneill 2981.1Sjmcneill TS_WRITE(sc, TP_FIFOCS, fifocs); 2991.1Sjmcneill 3001.1Sjmcneill return 1; 3011.1Sjmcneill} 3021.1Sjmcneill 3031.1Sjmcneillstatic void 3041.1Sjmcneillsunxi_ts_init(struct sunxi_ts_softc *sc) 3051.1Sjmcneill{ 3061.1Sjmcneill u_int tp_sensitivity_adjust = TS_TP_SENSITIVITY_ADJUST_DEFAULT; 3071.1Sjmcneill u_int filter_type = TS_FILTER_TYPE_DEFAULT; 3081.1Sjmcneill 3091.1Sjmcneill of_getprop_uint32(sc->sc_phandle, "allwinner,tp-sensitive-adjust", 3101.1Sjmcneill &tp_sensitivity_adjust); 3111.1Sjmcneill of_getprop_uint32(sc->sc_phandle, "allwinner,filter-type", 3121.1Sjmcneill &filter_type); 3131.1Sjmcneill 3141.1Sjmcneill TS_WRITE(sc, TP_CTRL0, 3151.1Sjmcneill __SHIFTIN(0, TP_CTRL0_ADC_CLK_SELECT) | 3161.1Sjmcneill __SHIFTIN(2, TP_CTRL0_ADC_CLK_DIVIDER) | 3171.1Sjmcneill __SHIFTIN(7, TP_CTRL0_FS_DIV) | 3181.1Sjmcneill __SHIFTIN(63, TP_CTRL0_T_ACQ)); 3191.1Sjmcneill TS_WRITE(sc, TP_CTRL2, 3201.1Sjmcneill __SHIFTIN(0, TP_CTRL2_MODE_SELECT) | 3211.1Sjmcneill __SHIFTIN(tp_sensitivity_adjust, TP_CTRL2_SENSITIVE_ADJUST)); 3221.1Sjmcneill TS_WRITE(sc, TP_CTRL3, 3231.1Sjmcneill TP_CTRL3_FILTER_EN | 3241.1Sjmcneill __SHIFTIN(filter_type, TP_CTRL3_FILTER_TYPE)); 3251.1Sjmcneill TS_WRITE(sc, TP_CTRL1, 3261.2Sjmcneill sc->sc_conf->tp_mode_en_mask | 3271.1Sjmcneill TP_CTRL1_STYLUS_UP_DEBOUNCE_EN | 3281.1Sjmcneill __SHIFTIN(5, TP_CTRL1_STYLUS_UP_DEBOUNCE)); 3291.2Sjmcneill 3301.2Sjmcneill /* Enable temperature sensor */ 3311.2Sjmcneill TS_WRITE(sc, TP_TPR, 3321.2Sjmcneill TP_TPR_TEMP_EN | __SHIFTIN(1953, TP_TPR_TEMP_PER)); 3331.2Sjmcneill 3341.2Sjmcneill /* Enable temperature sensor IRQ */ 3351.2Sjmcneill TS_WRITE(sc, TP_INT, TP_INT_TEMP_IRQ_EN); 3361.2Sjmcneill 3371.2Sjmcneill /* Clear pending IRQs */ 3381.2Sjmcneill TS_WRITE(sc, TP_FIFOCS, TS_READ(sc, TP_FIFOCS)); 3391.1Sjmcneill} 3401.1Sjmcneill 3411.1Sjmcneillstatic int 3421.1Sjmcneillsunxi_ts_match(device_t parent, cfdata_t cf, void *aux) 3431.1Sjmcneill{ 3441.1Sjmcneill struct fdt_attach_args * const faa = aux; 3451.1Sjmcneill 3461.8Sthorpej return of_compatible_match(faa->faa_phandle, compat_data); 3471.1Sjmcneill} 3481.1Sjmcneill 3491.1Sjmcneillstatic void 3501.1Sjmcneillsunxi_ts_attach(device_t parent, device_t self, void *aux) 3511.1Sjmcneill{ 3521.1Sjmcneill struct sunxi_ts_softc * const sc = device_private(self); 3531.1Sjmcneill struct fdt_attach_args * const faa = aux; 3541.1Sjmcneill const int phandle = faa->faa_phandle; 3551.1Sjmcneill struct wsmousedev_attach_args a; 3561.1Sjmcneill char intrstr[128]; 3571.1Sjmcneill bus_addr_t addr; 3581.1Sjmcneill bus_size_t size; 3591.1Sjmcneill void *ih; 3601.1Sjmcneill 3611.1Sjmcneill if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 3621.1Sjmcneill aprint_error(": couldn't get registers\n"); 3631.1Sjmcneill return; 3641.1Sjmcneill } 3651.1Sjmcneill 3661.1Sjmcneill if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { 3671.1Sjmcneill aprint_error(": failed to decode interrupt\n"); 3681.1Sjmcneill return; 3691.1Sjmcneill } 3701.1Sjmcneill 3711.1Sjmcneill sc->sc_dev = self; 3721.1Sjmcneill sc->sc_phandle = phandle; 3731.1Sjmcneill sc->sc_bst = faa->faa_bst; 3741.1Sjmcneill if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 3751.1Sjmcneill aprint_error(": couldn't map registers\n"); 3761.1Sjmcneill return; 3771.1Sjmcneill } 3781.8Sthorpej sc->sc_conf = of_compatible_lookup(phandle, compat_data)->data; 3791.2Sjmcneill 3801.1Sjmcneill sc->sc_ts_attached = of_getprop_bool(phandle, "allwinner,ts-attached"); 3811.1Sjmcneill sc->sc_ts_inverted_x = of_getprop_bool(phandle, 3821.1Sjmcneill "touchscreen-inverted-x"); 3831.1Sjmcneill sc->sc_ts_inverted_y = of_getprop_bool(phandle, 3841.1Sjmcneill "touchscreen-inverted-y"); 3851.1Sjmcneill 3861.1Sjmcneill aprint_naive("\n"); 3871.1Sjmcneill aprint_normal(": Touch Screen Controller\n"); 3881.1Sjmcneill 3891.1Sjmcneill sunxi_ts_init(sc); 3901.1Sjmcneill 3911.4Sjmcneill ih = fdtbus_intr_establish_xname(phandle, 0, IPL_VM, 0, sunxi_ts_intr, 3921.4Sjmcneill sc, device_xname(self)); 3931.1Sjmcneill if (ih == NULL) { 3941.1Sjmcneill aprint_error_dev(self, "couldn't establish interrupt on %s\n", 3951.1Sjmcneill intrstr); 3961.1Sjmcneill return; 3971.1Sjmcneill } 3981.1Sjmcneill aprint_normal_dev(self, "interrupting on %s\n", intrstr); 3991.1Sjmcneill 4001.2Sjmcneill sc->sc_sme = sysmon_envsys_create(); 4011.2Sjmcneill sc->sc_sme->sme_name = device_xname(self); 4021.2Sjmcneill sc->sc_sme->sme_cookie = sc; 4031.2Sjmcneill sc->sc_sme->sme_flags = SME_DISABLE_REFRESH; 4041.2Sjmcneill 4051.2Sjmcneill sc->sc_temp_data.units = ENVSYS_STEMP; 4061.2Sjmcneill sc->sc_temp_data.state = ENVSYS_SINVALID; 4071.2Sjmcneill snprintf(sc->sc_temp_data.desc, sizeof(sc->sc_temp_data.desc), 4081.2Sjmcneill "temperature"); 4091.2Sjmcneill sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_temp_data); 4101.2Sjmcneill 4111.2Sjmcneill sysmon_envsys_register(sc->sc_sme); 4121.2Sjmcneill 4131.1Sjmcneill if (sc->sc_ts_attached) { 4141.1Sjmcneill tpcalib_init(&sc->sc_tpcalib); 4151.1Sjmcneill tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 4161.1Sjmcneill &sunxi_ts_default_calib, 0, 0); 4171.1Sjmcneill 4181.1Sjmcneill memset(&a, 0, sizeof(a)); 4191.1Sjmcneill a.accessops = &sunxi_ts_accessops; 4201.1Sjmcneill a.accesscookie = sc; 4211.1Sjmcneill sc->sc_wsmousedev = config_found_ia(self, "wsmousedev", 4221.1Sjmcneill &a, wsmousedevprint); 4231.1Sjmcneill } 4241.1Sjmcneill} 425