sunxi_ts.c revision 1.5
11.5Sthorpej/* $NetBSD: sunxi_ts.c,v 1.5 2021/01/18 02:35:49 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.5Sthorpej__KERNEL_RCSID(0, "$NetBSD: sunxi_ts.c,v 1.5 2021/01/18 02:35:49 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.5Sthorpej 1391.5Sthorpej { 0 } 1401.1Sjmcneill}; 1411.1Sjmcneill 1421.1Sjmcneillstatic struct wsmouse_calibcoords sunxi_ts_default_calib = { 1431.1Sjmcneill .minx = 0, 1441.1Sjmcneill .miny = 0, 1451.1Sjmcneill .maxx = __SHIFTOUT_MASK(TP_DATA_MASK), 1461.1Sjmcneill .maxy = __SHIFTOUT_MASK(TP_DATA_MASK), 1471.1Sjmcneill .samplelen = WSMOUSE_CALIBCOORDS_RESET, 1481.1Sjmcneill}; 1491.1Sjmcneill 1501.1Sjmcneillstruct sunxi_ts_softc { 1511.1Sjmcneill device_t sc_dev; 1521.1Sjmcneill int sc_phandle; 1531.1Sjmcneill bus_space_tag_t sc_bst; 1541.1Sjmcneill bus_space_handle_t sc_bsh; 1551.1Sjmcneill 1561.2Sjmcneill const struct sunxi_ts_config *sc_conf; 1571.2Sjmcneill 1581.1Sjmcneill bool sc_ts_attached; 1591.1Sjmcneill bool sc_ts_inverted_x; 1601.1Sjmcneill bool sc_ts_inverted_y; 1611.1Sjmcneill 1621.1Sjmcneill struct tpcalib_softc sc_tpcalib; 1631.1Sjmcneill device_t sc_wsmousedev; 1641.1Sjmcneill bool sc_ignoredata; 1651.1Sjmcneill 1661.1Sjmcneill u_int sc_tp_x; 1671.1Sjmcneill u_int sc_tp_y; 1681.1Sjmcneill u_int sc_tp_btns; 1691.2Sjmcneill 1701.2Sjmcneill struct sysmon_envsys *sc_sme; 1711.2Sjmcneill envsys_data_t sc_temp_data; 1721.1Sjmcneill}; 1731.1Sjmcneill 1741.1SjmcneillCFATTACH_DECL_NEW(sunxi_ts, sizeof(struct sunxi_ts_softc), 1751.1Sjmcneill sunxi_ts_match, sunxi_ts_attach, NULL, NULL); 1761.1Sjmcneill 1771.1Sjmcneill#define TS_READ(sc, reg) \ 1781.1Sjmcneill bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 1791.1Sjmcneill#define TS_WRITE(sc, reg, val) \ 1801.1Sjmcneill bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 1811.1Sjmcneill 1821.1Sjmcneillstatic int 1831.1Sjmcneillsunxi_ts_enable(void *v) 1841.1Sjmcneill{ 1851.1Sjmcneill struct sunxi_ts_softc * const sc = v; 1861.2Sjmcneill uint32_t val; 1871.1Sjmcneill 1881.1Sjmcneill /* reset state */ 1891.1Sjmcneill sc->sc_ignoredata = true; 1901.1Sjmcneill sc->sc_tp_x = 0; 1911.1Sjmcneill sc->sc_tp_y = 0; 1921.1Sjmcneill sc->sc_tp_btns = 0; 1931.1Sjmcneill 1941.1Sjmcneill /* Enable touchpanel IRQs */ 1951.2Sjmcneill val = TS_READ(sc, TP_INT); 1961.2Sjmcneill val |= TP_INT_DATA_IRQ_EN | TP_INT_FIFO_FLUSH | TP_INT_UP_IRQ_EN; 1971.2Sjmcneill val &= ~TP_INT_FIFO_TRIG_LEVEL; 1981.2Sjmcneill val |= __SHIFTIN(1, TP_INT_FIFO_TRIG_LEVEL); 1991.2Sjmcneill TS_WRITE(sc, TP_INT, val); 2001.1Sjmcneill 2011.1Sjmcneill return 0; 2021.1Sjmcneill} 2031.1Sjmcneill 2041.1Sjmcneillstatic void 2051.1Sjmcneillsunxi_ts_disable(void *v) 2061.1Sjmcneill{ 2071.1Sjmcneill struct sunxi_ts_softc * const sc = v; 2081.2Sjmcneill uint32_t val; 2091.1Sjmcneill 2101.1Sjmcneill /* Disable touchpanel IRQs */ 2111.2Sjmcneill val = TS_READ(sc, TP_INT); 2121.2Sjmcneill val &= ~(TP_INT_DATA_IRQ_EN | TP_INT_FIFO_FLUSH | TP_INT_UP_IRQ_EN); 2131.2Sjmcneill TS_WRITE(sc, TP_INT, val); 2141.1Sjmcneill} 2151.1Sjmcneill 2161.1Sjmcneillstatic int 2171.1Sjmcneillsunxi_ts_ioctl(void *v, u_long cmd, void *data, int flag, lwp_t *l) 2181.1Sjmcneill{ 2191.1Sjmcneill struct sunxi_ts_softc * const sc = v; 2201.1Sjmcneill struct wsmouse_id *id; 2211.1Sjmcneill 2221.1Sjmcneill switch (cmd) { 2231.1Sjmcneill case WSMOUSEIO_GTYPE: 2241.1Sjmcneill *(int *)data = WSMOUSE_TYPE_TPANEL; 2251.1Sjmcneill return 0; 2261.1Sjmcneill 2271.1Sjmcneill case WSMOUSEIO_GETID: 2281.1Sjmcneill id = data; 2291.1Sjmcneill if (id->type != WSMOUSE_ID_TYPE_UIDSTR) 2301.1Sjmcneill return EINVAL; 2311.1Sjmcneill snprintf(id->data, WSMOUSE_ID_MAXLEN, 2321.1Sjmcneill "Allwinner TS SN000000"); 2331.1Sjmcneill id->length = strlen(id->data); 2341.1Sjmcneill return 0; 2351.1Sjmcneill 2361.1Sjmcneill case WSMOUSEIO_SCALIBCOORDS: 2371.1Sjmcneill case WSMOUSEIO_GCALIBCOORDS: 2381.1Sjmcneill return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, l); 2391.1Sjmcneill } 2401.1Sjmcneill 2411.1Sjmcneill return EPASSTHROUGH; 2421.1Sjmcneill} 2431.1Sjmcneill 2441.1Sjmcneillstatic const struct wsmouse_accessops sunxi_ts_accessops = { 2451.1Sjmcneill .enable = sunxi_ts_enable, 2461.1Sjmcneill .disable = sunxi_ts_disable, 2471.1Sjmcneill .ioctl = sunxi_ts_ioctl, 2481.1Sjmcneill}; 2491.1Sjmcneill 2501.1Sjmcneillstatic int 2511.1Sjmcneillsunxi_ts_intr(void *priv) 2521.1Sjmcneill{ 2531.1Sjmcneill struct sunxi_ts_softc * const sc = priv; 2541.1Sjmcneill uint32_t fifocs, x, y; 2551.1Sjmcneill int s; 2561.1Sjmcneill 2571.1Sjmcneill fifocs = TS_READ(sc, TP_FIFOCS); 2581.1Sjmcneill 2591.2Sjmcneill if (fifocs & TP_FIFOCS_TEMP_IRQ_PENDING) { 2601.2Sjmcneill sc->sc_temp_data.value_cur = (TS_READ(sc, TEMP_DATA) * 2611.2Sjmcneill sc->sc_conf->temp_step - sc->sc_conf->temp_offset) + 2621.2Sjmcneill TEMP_C_TO_K; 2631.2Sjmcneill sc->sc_temp_data.state = ENVSYS_SVALID; 2641.2Sjmcneill } 2651.2Sjmcneill 2661.1Sjmcneill if (fifocs & TP_FIFOCS_DATA_PENDING) { 2671.1Sjmcneill x = TS_READ(sc, TP_DATA); 2681.1Sjmcneill y = TS_READ(sc, TP_DATA); 2691.1Sjmcneill if (sc->sc_ignoredata) { 2701.1Sjmcneill /* Discard the first report */ 2711.1Sjmcneill sc->sc_ignoredata = false; 2721.3Sthorpej } else if (sc->sc_wsmousedev != NULL) { 2731.1Sjmcneill if (sc->sc_ts_inverted_x) 2741.1Sjmcneill x = __SHIFTOUT_MASK(TP_DATA_MASK) - x; 2751.1Sjmcneill if (sc->sc_ts_inverted_y) 2761.1Sjmcneill y = __SHIFTOUT_MASK(TP_DATA_MASK) - y; 2771.1Sjmcneill tpcalib_trans(&sc->sc_tpcalib, x, y, 2781.1Sjmcneill &sc->sc_tp_x, &sc->sc_tp_y); 2791.1Sjmcneill sc->sc_tp_btns |= 1; 2801.1Sjmcneill 2811.1Sjmcneill s = spltty(); 2821.1Sjmcneill wsmouse_input(sc->sc_wsmousedev, 2831.1Sjmcneill sc->sc_tp_btns, sc->sc_tp_x, sc->sc_tp_y, 0, 0, 2841.1Sjmcneill WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 2851.1Sjmcneill splx(s); 2861.1Sjmcneill } 2871.1Sjmcneill } 2881.1Sjmcneill 2891.1Sjmcneill if (fifocs & TP_FIFOCS_UP_PENDING) { 2901.1Sjmcneill sc->sc_ignoredata = true; 2911.1Sjmcneill sc->sc_tp_btns &= ~1; 2921.1Sjmcneill s = spltty(); 2931.1Sjmcneill wsmouse_input(sc->sc_wsmousedev, 2941.1Sjmcneill sc->sc_tp_btns, sc->sc_tp_x, sc->sc_tp_y, 0, 0, 2951.1Sjmcneill WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 2961.1Sjmcneill splx(s); 2971.1Sjmcneill } 2981.1Sjmcneill 2991.1Sjmcneill TS_WRITE(sc, TP_FIFOCS, fifocs); 3001.1Sjmcneill 3011.1Sjmcneill return 1; 3021.1Sjmcneill} 3031.1Sjmcneill 3041.1Sjmcneillstatic void 3051.1Sjmcneillsunxi_ts_init(struct sunxi_ts_softc *sc) 3061.1Sjmcneill{ 3071.1Sjmcneill u_int tp_sensitivity_adjust = TS_TP_SENSITIVITY_ADJUST_DEFAULT; 3081.1Sjmcneill u_int filter_type = TS_FILTER_TYPE_DEFAULT; 3091.1Sjmcneill 3101.1Sjmcneill of_getprop_uint32(sc->sc_phandle, "allwinner,tp-sensitive-adjust", 3111.1Sjmcneill &tp_sensitivity_adjust); 3121.1Sjmcneill of_getprop_uint32(sc->sc_phandle, "allwinner,filter-type", 3131.1Sjmcneill &filter_type); 3141.1Sjmcneill 3151.1Sjmcneill TS_WRITE(sc, TP_CTRL0, 3161.1Sjmcneill __SHIFTIN(0, TP_CTRL0_ADC_CLK_SELECT) | 3171.1Sjmcneill __SHIFTIN(2, TP_CTRL0_ADC_CLK_DIVIDER) | 3181.1Sjmcneill __SHIFTIN(7, TP_CTRL0_FS_DIV) | 3191.1Sjmcneill __SHIFTIN(63, TP_CTRL0_T_ACQ)); 3201.1Sjmcneill TS_WRITE(sc, TP_CTRL2, 3211.1Sjmcneill __SHIFTIN(0, TP_CTRL2_MODE_SELECT) | 3221.1Sjmcneill __SHIFTIN(tp_sensitivity_adjust, TP_CTRL2_SENSITIVE_ADJUST)); 3231.1Sjmcneill TS_WRITE(sc, TP_CTRL3, 3241.1Sjmcneill TP_CTRL3_FILTER_EN | 3251.1Sjmcneill __SHIFTIN(filter_type, TP_CTRL3_FILTER_TYPE)); 3261.1Sjmcneill TS_WRITE(sc, TP_CTRL1, 3271.2Sjmcneill sc->sc_conf->tp_mode_en_mask | 3281.1Sjmcneill TP_CTRL1_STYLUS_UP_DEBOUNCE_EN | 3291.1Sjmcneill __SHIFTIN(5, TP_CTRL1_STYLUS_UP_DEBOUNCE)); 3301.2Sjmcneill 3311.2Sjmcneill /* Enable temperature sensor */ 3321.2Sjmcneill TS_WRITE(sc, TP_TPR, 3331.2Sjmcneill TP_TPR_TEMP_EN | __SHIFTIN(1953, TP_TPR_TEMP_PER)); 3341.2Sjmcneill 3351.2Sjmcneill /* Enable temperature sensor IRQ */ 3361.2Sjmcneill TS_WRITE(sc, TP_INT, TP_INT_TEMP_IRQ_EN); 3371.2Sjmcneill 3381.2Sjmcneill /* Clear pending IRQs */ 3391.2Sjmcneill TS_WRITE(sc, TP_FIFOCS, TS_READ(sc, TP_FIFOCS)); 3401.1Sjmcneill} 3411.1Sjmcneill 3421.1Sjmcneillstatic int 3431.1Sjmcneillsunxi_ts_match(device_t parent, cfdata_t cf, void *aux) 3441.1Sjmcneill{ 3451.1Sjmcneill struct fdt_attach_args * const faa = aux; 3461.1Sjmcneill 3471.2Sjmcneill return of_match_compat_data(faa->faa_phandle, compat_data); 3481.1Sjmcneill} 3491.1Sjmcneill 3501.1Sjmcneillstatic void 3511.1Sjmcneillsunxi_ts_attach(device_t parent, device_t self, void *aux) 3521.1Sjmcneill{ 3531.1Sjmcneill struct sunxi_ts_softc * const sc = device_private(self); 3541.1Sjmcneill struct fdt_attach_args * const faa = aux; 3551.1Sjmcneill const int phandle = faa->faa_phandle; 3561.1Sjmcneill struct wsmousedev_attach_args a; 3571.1Sjmcneill char intrstr[128]; 3581.1Sjmcneill bus_addr_t addr; 3591.1Sjmcneill bus_size_t size; 3601.1Sjmcneill void *ih; 3611.1Sjmcneill 3621.1Sjmcneill if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 3631.1Sjmcneill aprint_error(": couldn't get registers\n"); 3641.1Sjmcneill return; 3651.1Sjmcneill } 3661.1Sjmcneill 3671.1Sjmcneill if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { 3681.1Sjmcneill aprint_error(": failed to decode interrupt\n"); 3691.1Sjmcneill return; 3701.1Sjmcneill } 3711.1Sjmcneill 3721.1Sjmcneill sc->sc_dev = self; 3731.1Sjmcneill sc->sc_phandle = phandle; 3741.1Sjmcneill sc->sc_bst = faa->faa_bst; 3751.1Sjmcneill if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 3761.1Sjmcneill aprint_error(": couldn't map registers\n"); 3771.1Sjmcneill return; 3781.1Sjmcneill } 3791.5Sthorpej sc->sc_conf = of_search_compatible(phandle, compat_data)->data; 3801.2Sjmcneill 3811.1Sjmcneill sc->sc_ts_attached = of_getprop_bool(phandle, "allwinner,ts-attached"); 3821.1Sjmcneill sc->sc_ts_inverted_x = of_getprop_bool(phandle, 3831.1Sjmcneill "touchscreen-inverted-x"); 3841.1Sjmcneill sc->sc_ts_inverted_y = of_getprop_bool(phandle, 3851.1Sjmcneill "touchscreen-inverted-y"); 3861.1Sjmcneill 3871.1Sjmcneill aprint_naive("\n"); 3881.1Sjmcneill aprint_normal(": Touch Screen Controller\n"); 3891.1Sjmcneill 3901.1Sjmcneill sunxi_ts_init(sc); 3911.1Sjmcneill 3921.4Sjmcneill ih = fdtbus_intr_establish_xname(phandle, 0, IPL_VM, 0, sunxi_ts_intr, 3931.4Sjmcneill sc, device_xname(self)); 3941.1Sjmcneill if (ih == NULL) { 3951.1Sjmcneill aprint_error_dev(self, "couldn't establish interrupt on %s\n", 3961.1Sjmcneill intrstr); 3971.1Sjmcneill return; 3981.1Sjmcneill } 3991.1Sjmcneill aprint_normal_dev(self, "interrupting on %s\n", intrstr); 4001.1Sjmcneill 4011.2Sjmcneill sc->sc_sme = sysmon_envsys_create(); 4021.2Sjmcneill sc->sc_sme->sme_name = device_xname(self); 4031.2Sjmcneill sc->sc_sme->sme_cookie = sc; 4041.2Sjmcneill sc->sc_sme->sme_flags = SME_DISABLE_REFRESH; 4051.2Sjmcneill 4061.2Sjmcneill sc->sc_temp_data.units = ENVSYS_STEMP; 4071.2Sjmcneill sc->sc_temp_data.state = ENVSYS_SINVALID; 4081.2Sjmcneill snprintf(sc->sc_temp_data.desc, sizeof(sc->sc_temp_data.desc), 4091.2Sjmcneill "temperature"); 4101.2Sjmcneill sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_temp_data); 4111.2Sjmcneill 4121.2Sjmcneill sysmon_envsys_register(sc->sc_sme); 4131.2Sjmcneill 4141.1Sjmcneill if (sc->sc_ts_attached) { 4151.1Sjmcneill tpcalib_init(&sc->sc_tpcalib); 4161.1Sjmcneill tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 4171.1Sjmcneill &sunxi_ts_default_calib, 0, 0); 4181.1Sjmcneill 4191.1Sjmcneill memset(&a, 0, sizeof(a)); 4201.1Sjmcneill a.accessops = &sunxi_ts_accessops; 4211.1Sjmcneill a.accesscookie = sc; 4221.1Sjmcneill sc->sc_wsmousedev = config_found_ia(self, "wsmousedev", 4231.1Sjmcneill &a, wsmousedevprint); 4241.1Sjmcneill } 4251.1Sjmcneill} 426