1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2ffa458c1SDavid Brownell /* 3ffa458c1SDavid Brownell * ADS7846 based touchscreen and sensor driver 4ffa458c1SDavid Brownell * 5ffa458c1SDavid Brownell * Copyright (c) 2005 David Brownell 67de90a8cSImre Deak * Copyright (c) 2006 Nokia Corporation 77de90a8cSImre Deak * Various changes: Imre Deak <imre.deak@nokia.com> 8ffa458c1SDavid Brownell * 9ffa458c1SDavid Brownell * Using code from: 10ffa458c1SDavid Brownell * - corgi_ts.c 11ffa458c1SDavid Brownell * Copyright (C) 2004-2005 Richard Purdie 12ffa458c1SDavid Brownell * - omap_ts.[hc], ads7846.h, ts_osk.c 13ffa458c1SDavid Brownell * Copyright (C) 2002 MontaVista Software 14ffa458c1SDavid Brownell * Copyright (C) 2004 Texas Instruments 15ffa458c1SDavid Brownell * Copyright (C) 2005 Dirk Behme 16ffa458c1SDavid Brownell */ 172991a1caSJason Wang #include <linux/types.h> 182c8dc071SDavid Brownell #include <linux/hwmon.h> 192c8dc071SDavid Brownell #include <linux/err.h> 202991a1caSJason Wang #include <linux/sched.h> 21ffa458c1SDavid Brownell #include <linux/delay.h> 22ffa458c1SDavid Brownell #include <linux/input.h> 23a2f99330SMarco Felsch #include <linux/input/touchscreen.h> 24ffa458c1SDavid Brownell #include <linux/interrupt.h> 25ffa458c1SDavid Brownell #include <linux/slab.h> 263c36e719SMark Brown #include <linux/pm.h> 27a608026eSDaniel Mack #include <linux/of.h> 28a608026eSDaniel Mack #include <linux/of_gpio.h> 29a608026eSDaniel Mack #include <linux/of_device.h> 304d5975e5SEric Miao #include <linux/gpio.h> 31ffa458c1SDavid Brownell #include <linux/spi/spi.h> 32ffa458c1SDavid Brownell #include <linux/spi/ads7846.h> 3391143379SGrazvydas Ignotas #include <linux/regulator/consumer.h> 34d2d8442dSPaul Gortmaker #include <linux/module.h> 3503e2c9c7SDmitry Torokhov #include <asm/unaligned.h> 36ffa458c1SDavid Brownell 37ffa458c1SDavid Brownell /* 389084533eSDavid Brownell * This code has been heavily tested on a Nokia 770, and lightly 3952ce4eaaSPavel Machek * tested on other ads7846 devices (OSK/Mistral, Lubbock, Spitz). 40bff0de5fSDavid Brownell * TSC2046 is just newer ads7846 silicon. 41969111e9SNicolas Ferre * Support for ads7843 tested on Atmel at91sam926x-EK. 42969111e9SNicolas Ferre * Support for ads7845 has only been stubbed in. 4306a09124SMichael Hennerich * Support for Analog Devices AD7873 and AD7843 tested. 44ffa458c1SDavid Brownell * 457de90a8cSImre Deak * IRQ handling needs a workaround because of a shortcoming in handling 467de90a8cSImre Deak * edge triggered IRQs on some platforms like the OMAP1/2. These 477de90a8cSImre Deak * platforms don't handle the ARM lazy IRQ disabling properly, thus we 487de90a8cSImre Deak * have to maintain our own SW IRQ disabled status. This should be 497de90a8cSImre Deak * removed as soon as the affected platform's IRQ handling is fixed. 507de90a8cSImre Deak * 5152ce4eaaSPavel Machek * App note sbaa036 talks in more detail about accurate sampling... 52ffa458c1SDavid Brownell * that ought to help in situations like LCDs inducing noise (which 53ffa458c1SDavid Brownell * can also be helped by using synch signals) and more generally. 547de90a8cSImre Deak * This driver tries to utilize the measures described in the app 557de90a8cSImre Deak * note. The strength of filtering can be set in the board-* specific 567de90a8cSImre Deak * files. 57ffa458c1SDavid Brownell */ 58ffa458c1SDavid Brownell 592991a1caSJason Wang #define TS_POLL_DELAY 1 /* ms delay before the first sample */ 602991a1caSJason Wang #define TS_POLL_PERIOD 5 /* ms delay between samples */ 61ffa458c1SDavid Brownell 62d93f70b2SDavid Brownell /* this driver doesn't aim at the peak continuous sample rate */ 63d93f70b2SDavid Brownell #define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) 64d93f70b2SDavid Brownell 659c950971SOleksij Rempel struct ads7846_buf { 669c950971SOleksij Rempel u8 cmd; 67*6965eeceSOleksij Rempel __be16 data; 689c950971SOleksij Rempel } __packed; 699c950971SOleksij Rempel 70*6965eeceSOleksij Rempel struct ads7846_buf_layout { 71*6965eeceSOleksij Rempel unsigned int offset; 72*6965eeceSOleksij Rempel unsigned int count; 73*6965eeceSOleksij Rempel unsigned int skip; 74ffa458c1SDavid Brownell }; 75ffa458c1SDavid Brownell 76e8f462d2SDmitry Torokhov /* 77e8f462d2SDmitry Torokhov * We allocate this separately to avoid cache line sharing issues when 78e8f462d2SDmitry Torokhov * driver is used with DMA-based SPI controllers (like atmel_spi) on 79e8f462d2SDmitry Torokhov * systems where main memory is not DMA-coherent (most non-x86 boards). 80e8f462d2SDmitry Torokhov */ 81e8f462d2SDmitry Torokhov struct ads7846_packet { 82*6965eeceSOleksij Rempel unsigned int count; 83*6965eeceSOleksij Rempel unsigned int count_skip; 84*6965eeceSOleksij Rempel unsigned int cmds; 85*6965eeceSOleksij Rempel unsigned int last_cmd_idx; 86*6965eeceSOleksij Rempel struct ads7846_buf_layout l[5]; 87*6965eeceSOleksij Rempel struct ads7846_buf *rx; 88*6965eeceSOleksij Rempel struct ads7846_buf *tx; 89*6965eeceSOleksij Rempel 909c950971SOleksij Rempel struct ads7846_buf pwrdown_cmd; 91*6965eeceSOleksij Rempel 92*6965eeceSOleksij Rempel bool ignore; 93*6965eeceSOleksij Rempel u16 x, y, z1, z2; 94e8f462d2SDmitry Torokhov }; 95e8f462d2SDmitry Torokhov 96ffa458c1SDavid Brownell struct ads7846 { 97a90f7e98SDmitry Torokhov struct input_dev *input; 98ffa458c1SDavid Brownell char phys[32]; 99b58895f8SMichael Roth char name[32]; 100ffa458c1SDavid Brownell 101ffa458c1SDavid Brownell struct spi_device *spi; 10291143379SGrazvydas Ignotas struct regulator *reg; 1032c8dc071SDavid Brownell 104c52b4fc7SFabio Estevam #if IS_ENABLED(CONFIG_HWMON) 1051beeffe4STony Jones struct device *hwmon; 1062c8dc071SDavid Brownell #endif 1072c8dc071SDavid Brownell 108ffa458c1SDavid Brownell u16 model; 1097c6d0ee1SDavid Brownell u16 vref_mv; 110ffa458c1SDavid Brownell u16 vref_delay_usecs; 111ffa458c1SDavid Brownell u16 x_plate_ohms; 112d5b415c9SImre Deak u16 pressure_max; 113ffa458c1SDavid Brownell 11486579a4cSMichael Roth bool swap_xy; 115ebcaaad9SAlexander Stein bool use_internal; 11686579a4cSMichael Roth 117e8f462d2SDmitry Torokhov struct ads7846_packet *packet; 118ffa458c1SDavid Brownell 119e4f48861SSemih Hazar struct spi_transfer xfer[18]; 1200b7018aaSImre Deak struct spi_message msg[5]; 1212991a1caSJason Wang int msg_count; 1222991a1caSJason Wang wait_queue_head_t wait; 1232991a1caSJason Wang 1242991a1caSJason Wang bool pendown; 1252991a1caSJason Wang 1260b7018aaSImre Deak int read_cnt; 127d5b415c9SImre Deak int read_rep; 1280b7018aaSImre Deak int last_read; 1290b7018aaSImre Deak 1300b7018aaSImre Deak u16 debounce_max; 1310b7018aaSImre Deak u16 debounce_tol; 132d5b415c9SImre Deak u16 debounce_rep; 133ffa458c1SDavid Brownell 1341d25891fSSemih Hazar u16 penirq_recheck_delay_usecs; 1351d25891fSSemih Hazar 136a2f99330SMarco Felsch struct touchscreen_properties core_prop; 137a2f99330SMarco Felsch 1382991a1caSJason Wang struct mutex lock; 1392991a1caSJason Wang bool stopped; /* P: lock */ 1402991a1caSJason Wang bool disabled; /* P: lock */ 1412991a1caSJason Wang bool suspended; /* P: lock */ 142c9e617a5SImre Deak 143da970e69SImre Deak int (*filter)(void *data, int data_idx, int *val); 144da970e69SImre Deak void *filter_data; 145da970e69SImre Deak void (*filter_cleanup)(void *data); 146c9e617a5SImre Deak int (*get_pendown_state)(void); 1474d5975e5SEric Miao int gpio_pendown; 148fd746d54SEric Miao 149fd746d54SEric Miao void (*wait_for_sync)(void); 150ffa458c1SDavid Brownell }; 151ffa458c1SDavid Brownell 152ffa458c1SDavid Brownell /* leave chip selected when we're done, for quicker re-select? */ 153ffa458c1SDavid Brownell #if 0 154ffa458c1SDavid Brownell #define CS_CHANGE(xfer) ((xfer).cs_change = 1) 155ffa458c1SDavid Brownell #else 156ffa458c1SDavid Brownell #define CS_CHANGE(xfer) ((xfer).cs_change = 0) 157ffa458c1SDavid Brownell #endif 158ffa458c1SDavid Brownell 159ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 160ffa458c1SDavid Brownell 161ffa458c1SDavid Brownell /* The ADS7846 has touchscreen and other sensors. 162ffa458c1SDavid Brownell * Earlier ads784x chips are somewhat compatible. 163ffa458c1SDavid Brownell */ 164ffa458c1SDavid Brownell #define ADS_START (1 << 7) 165ffa458c1SDavid Brownell #define ADS_A2A1A0_d_y (1 << 4) /* differential */ 166ffa458c1SDavid Brownell #define ADS_A2A1A0_d_z1 (3 << 4) /* differential */ 167ffa458c1SDavid Brownell #define ADS_A2A1A0_d_z2 (4 << 4) /* differential */ 168ffa458c1SDavid Brownell #define ADS_A2A1A0_d_x (5 << 4) /* differential */ 169ffa458c1SDavid Brownell #define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */ 170ffa458c1SDavid Brownell #define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */ 171ffa458c1SDavid Brownell #define ADS_A2A1A0_vaux (6 << 4) /* non-differential */ 172ffa458c1SDavid Brownell #define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */ 173ffa458c1SDavid Brownell #define ADS_8_BIT (1 << 3) 174ffa458c1SDavid Brownell #define ADS_12_BIT (0 << 3) 175ffa458c1SDavid Brownell #define ADS_SER (1 << 2) /* non-differential */ 176ffa458c1SDavid Brownell #define ADS_DFR (0 << 2) /* differential */ 177ffa458c1SDavid Brownell #define ADS_PD10_PDOWN (0 << 0) /* low power mode + penirq */ 178ffa458c1SDavid Brownell #define ADS_PD10_ADC_ON (1 << 0) /* ADC on */ 179ffa458c1SDavid Brownell #define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */ 180ffa458c1SDavid Brownell #define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ 181ffa458c1SDavid Brownell 182ffa458c1SDavid Brownell #define MAX_12BIT ((1<<12)-1) 183ffa458c1SDavid Brownell 184ffa458c1SDavid Brownell /* leave ADC powered up (disables penirq) between differential samples */ 185de2defd9SImre Deak #define READ_12BIT_DFR(x, adc, vref) (ADS_START | ADS_A2A1A0_d_ ## x \ 186de2defd9SImre Deak | ADS_12_BIT | ADS_DFR | \ 187de2defd9SImre Deak (adc ? ADS_PD10_ADC_ON : 0) | (vref ? ADS_PD10_REF_ON : 0)) 188ffa458c1SDavid Brownell 189de2defd9SImre Deak #define READ_Y(vref) (READ_12BIT_DFR(y, 1, vref)) 190de2defd9SImre Deak #define READ_Z1(vref) (READ_12BIT_DFR(z1, 1, vref)) 191de2defd9SImre Deak #define READ_Z2(vref) (READ_12BIT_DFR(z2, 1, vref)) 192de2defd9SImre Deak #define READ_X(vref) (READ_12BIT_DFR(x, 1, vref)) 193de2defd9SImre Deak #define PWRDOWN (READ_12BIT_DFR(y, 0, 0)) /* LAST */ 194ffa458c1SDavid Brownell 195ffa458c1SDavid Brownell /* single-ended samples need to first power up reference voltage; 196ffa458c1SDavid Brownell * we leave both ADC and VREF powered 197ffa458c1SDavid Brownell */ 198ffa458c1SDavid Brownell #define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \ 199ffa458c1SDavid Brownell | ADS_12_BIT | ADS_SER) 200ffa458c1SDavid Brownell 201de2defd9SImre Deak #define REF_ON (READ_12BIT_DFR(x, 1, 1)) 202de2defd9SImre Deak #define REF_OFF (READ_12BIT_DFR(y, 0, 0)) 203ffa458c1SDavid Brownell 204*6965eeceSOleksij Rempel /* Order commands in the most optimal way to reduce Vref switching and 205*6965eeceSOleksij Rempel * settling time: 206*6965eeceSOleksij Rempel * Measure: X; Vref: X+, X-; IN: Y+ 207*6965eeceSOleksij Rempel * Measure: Y; Vref: Y+, Y-; IN: X+ 208*6965eeceSOleksij Rempel * Measure: Z1; Vref: Y+, X-; IN: X+ 209*6965eeceSOleksij Rempel * Measure: Z2; Vref: Y+, X-; IN: Y- 210*6965eeceSOleksij Rempel */ 211*6965eeceSOleksij Rempel enum ads7846_cmds { 212*6965eeceSOleksij Rempel ADS7846_X, 213*6965eeceSOleksij Rempel ADS7846_Y, 214*6965eeceSOleksij Rempel ADS7846_Z1, 215*6965eeceSOleksij Rempel ADS7846_Z2, 216*6965eeceSOleksij Rempel ADS7846_PWDOWN, 217*6965eeceSOleksij Rempel }; 218*6965eeceSOleksij Rempel 219e52cd628SDavid Jander static int get_pendown_state(struct ads7846 *ts) 220e52cd628SDavid Jander { 221e52cd628SDavid Jander if (ts->get_pendown_state) 222e52cd628SDavid Jander return ts->get_pendown_state(); 223e52cd628SDavid Jander 224e52cd628SDavid Jander return !gpio_get_value(ts->gpio_pendown); 225e52cd628SDavid Jander } 226e52cd628SDavid Jander 227e52cd628SDavid Jander static void ads7846_report_pen_up(struct ads7846 *ts) 228e52cd628SDavid Jander { 229e52cd628SDavid Jander struct input_dev *input = ts->input; 230e52cd628SDavid Jander 231e52cd628SDavid Jander input_report_key(input, BTN_TOUCH, 0); 232e52cd628SDavid Jander input_report_abs(input, ABS_PRESSURE, 0); 233e52cd628SDavid Jander input_sync(input); 234e52cd628SDavid Jander 235e52cd628SDavid Jander ts->pendown = false; 236e52cd628SDavid Jander dev_vdbg(&ts->spi->dev, "UP\n"); 237e52cd628SDavid Jander } 238e52cd628SDavid Jander 2392991a1caSJason Wang /* Must be called with ts->lock held */ 2402991a1caSJason Wang static void ads7846_stop(struct ads7846 *ts) 2412991a1caSJason Wang { 2422991a1caSJason Wang if (!ts->disabled && !ts->suspended) { 2432991a1caSJason Wang /* Signal IRQ thread to stop polling and disable the handler. */ 2442991a1caSJason Wang ts->stopped = true; 2452991a1caSJason Wang mb(); 2462991a1caSJason Wang wake_up(&ts->wait); 2472991a1caSJason Wang disable_irq(ts->spi->irq); 2482991a1caSJason Wang } 2492991a1caSJason Wang } 2502991a1caSJason Wang 2512991a1caSJason Wang /* Must be called with ts->lock held */ 2522991a1caSJason Wang static void ads7846_restart(struct ads7846 *ts) 2532991a1caSJason Wang { 2542991a1caSJason Wang if (!ts->disabled && !ts->suspended) { 255e52cd628SDavid Jander /* Check if pen was released since last stop */ 256e52cd628SDavid Jander if (ts->pendown && !get_pendown_state(ts)) 257e52cd628SDavid Jander ads7846_report_pen_up(ts); 258e52cd628SDavid Jander 2592991a1caSJason Wang /* Tell IRQ thread that it may poll the device. */ 2602991a1caSJason Wang ts->stopped = false; 2612991a1caSJason Wang mb(); 2622991a1caSJason Wang enable_irq(ts->spi->irq); 2632991a1caSJason Wang } 2642991a1caSJason Wang } 2652991a1caSJason Wang 2662991a1caSJason Wang /* Must be called with ts->lock held */ 2672991a1caSJason Wang static void __ads7846_disable(struct ads7846 *ts) 2682991a1caSJason Wang { 2692991a1caSJason Wang ads7846_stop(ts); 2702991a1caSJason Wang regulator_disable(ts->reg); 2712991a1caSJason Wang 2722991a1caSJason Wang /* 2732991a1caSJason Wang * We know the chip's in low power mode since we always 2742991a1caSJason Wang * leave it that way after every request 2752991a1caSJason Wang */ 2762991a1caSJason Wang } 2772991a1caSJason Wang 2782991a1caSJason Wang /* Must be called with ts->lock held */ 2792991a1caSJason Wang static void __ads7846_enable(struct ads7846 *ts) 2802991a1caSJason Wang { 281f94352f8SMark Brown int error; 282f94352f8SMark Brown 283f94352f8SMark Brown error = regulator_enable(ts->reg); 284f94352f8SMark Brown if (error != 0) 285f94352f8SMark Brown dev_err(&ts->spi->dev, "Failed to enable supply: %d\n", error); 286f94352f8SMark Brown 2872991a1caSJason Wang ads7846_restart(ts); 2882991a1caSJason Wang } 2892991a1caSJason Wang 2902991a1caSJason Wang static void ads7846_disable(struct ads7846 *ts) 2912991a1caSJason Wang { 2922991a1caSJason Wang mutex_lock(&ts->lock); 2932991a1caSJason Wang 2942991a1caSJason Wang if (!ts->disabled) { 2952991a1caSJason Wang 2962991a1caSJason Wang if (!ts->suspended) 2972991a1caSJason Wang __ads7846_disable(ts); 2982991a1caSJason Wang 2992991a1caSJason Wang ts->disabled = true; 3002991a1caSJason Wang } 3012991a1caSJason Wang 3022991a1caSJason Wang mutex_unlock(&ts->lock); 3032991a1caSJason Wang } 3042991a1caSJason Wang 3052991a1caSJason Wang static void ads7846_enable(struct ads7846 *ts) 3062991a1caSJason Wang { 3072991a1caSJason Wang mutex_lock(&ts->lock); 3082991a1caSJason Wang 3092991a1caSJason Wang if (ts->disabled) { 3102991a1caSJason Wang 3112991a1caSJason Wang ts->disabled = false; 3122991a1caSJason Wang 3132991a1caSJason Wang if (!ts->suspended) 3142991a1caSJason Wang __ads7846_enable(ts); 3152991a1caSJason Wang } 3162991a1caSJason Wang 3172991a1caSJason Wang mutex_unlock(&ts->lock); 3182991a1caSJason Wang } 3192991a1caSJason Wang 320ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 321ffa458c1SDavid Brownell 322ffa458c1SDavid Brownell /* 323ffa458c1SDavid Brownell * Non-touchscreen sensors only use single-ended conversions. 3242c8dc071SDavid Brownell * The range is GND..vREF. The ads7843 and ads7835 must use external vREF; 3252c8dc071SDavid Brownell * ads7846 lets that pin be unconnected, to use internal vREF. 326ffa458c1SDavid Brownell */ 327ffa458c1SDavid Brownell 328ffa458c1SDavid Brownell struct ser_req { 329d93f70b2SDavid Brownell u8 ref_on; 330ffa458c1SDavid Brownell u8 command; 331d93f70b2SDavid Brownell u8 ref_off; 332ffa458c1SDavid Brownell u16 scratch; 333ffa458c1SDavid Brownell struct spi_message msg; 334ffa458c1SDavid Brownell struct spi_transfer xfer[6]; 3351dbe7dadSAlexander Stein /* 3361dbe7dadSAlexander Stein * DMA (thus cache coherency maintenance) requires the 3371dbe7dadSAlexander Stein * transfer buffers to live in their own cache lines. 3381dbe7dadSAlexander Stein */ 3391dbe7dadSAlexander Stein __be16 sample ____cacheline_aligned; 340ffa458c1SDavid Brownell }; 341ffa458c1SDavid Brownell 3423eac5c7eSAnatolij Gustschin struct ads7845_ser_req { 3433eac5c7eSAnatolij Gustschin u8 command[3]; 3443eac5c7eSAnatolij Gustschin struct spi_message msg; 3453eac5c7eSAnatolij Gustschin struct spi_transfer xfer[2]; 3461dbe7dadSAlexander Stein /* 3471dbe7dadSAlexander Stein * DMA (thus cache coherency maintenance) requires the 3481dbe7dadSAlexander Stein * transfer buffers to live in their own cache lines. 3491dbe7dadSAlexander Stein */ 3501dbe7dadSAlexander Stein u8 sample[3] ____cacheline_aligned; 3513eac5c7eSAnatolij Gustschin }; 3523eac5c7eSAnatolij Gustschin 353ffa458c1SDavid Brownell static int ads7846_read12_ser(struct device *dev, unsigned command) 354ffa458c1SDavid Brownell { 355ffa458c1SDavid Brownell struct spi_device *spi = to_spi_device(dev); 356ffa458c1SDavid Brownell struct ads7846 *ts = dev_get_drvdata(dev); 3572991a1caSJason Wang struct ser_req *req; 358ffa458c1SDavid Brownell int status; 359ffa458c1SDavid Brownell 3602991a1caSJason Wang req = kzalloc(sizeof *req, GFP_KERNEL); 361ffa458c1SDavid Brownell if (!req) 362ffa458c1SDavid Brownell return -ENOMEM; 363ffa458c1SDavid Brownell 3640b7018aaSImre Deak spi_message_init(&req->msg); 3658275c642SVitaly Wool 3662c8dc071SDavid Brownell /* maybe turn on internal vREF, and let it settle */ 367ebcaaad9SAlexander Stein if (ts->use_internal) { 368d93f70b2SDavid Brownell req->ref_on = REF_ON; 369d93f70b2SDavid Brownell req->xfer[0].tx_buf = &req->ref_on; 370ffa458c1SDavid Brownell req->xfer[0].len = 1; 3712c8dc071SDavid Brownell spi_message_add_tail(&req->xfer[0], &req->msg); 3722c8dc071SDavid Brownell 373ffa458c1SDavid Brownell req->xfer[1].rx_buf = &req->scratch; 374ffa458c1SDavid Brownell req->xfer[1].len = 2; 375ffa458c1SDavid Brownell 3762c8dc071SDavid Brownell /* for 1uF, settle for 800 usec; no cap, 100 usec. */ 3770dfed6dcSAlexandru Ardelean req->xfer[1].delay.value = ts->vref_delay_usecs; 3780dfed6dcSAlexandru Ardelean req->xfer[1].delay.unit = SPI_DELAY_UNIT_USECS; 3792c8dc071SDavid Brownell spi_message_add_tail(&req->xfer[1], &req->msg); 380ebcaaad9SAlexander Stein 381ebcaaad9SAlexander Stein /* Enable reference voltage */ 382ebcaaad9SAlexander Stein command |= ADS_PD10_REF_ON; 3832c8dc071SDavid Brownell } 384ffa458c1SDavid Brownell 385ebcaaad9SAlexander Stein /* Enable ADC in every case */ 386ebcaaad9SAlexander Stein command |= ADS_PD10_ADC_ON; 387ebcaaad9SAlexander Stein 388ffa458c1SDavid Brownell /* take sample */ 389ffa458c1SDavid Brownell req->command = (u8) command; 390ffa458c1SDavid Brownell req->xfer[2].tx_buf = &req->command; 391ffa458c1SDavid Brownell req->xfer[2].len = 1; 3922c8dc071SDavid Brownell spi_message_add_tail(&req->xfer[2], &req->msg); 3932c8dc071SDavid Brownell 394ffa458c1SDavid Brownell req->xfer[3].rx_buf = &req->sample; 395ffa458c1SDavid Brownell req->xfer[3].len = 2; 3962c8dc071SDavid Brownell spi_message_add_tail(&req->xfer[3], &req->msg); 397ffa458c1SDavid Brownell 398ffa458c1SDavid Brownell /* REVISIT: take a few more samples, and compare ... */ 399ffa458c1SDavid Brownell 400969111e9SNicolas Ferre /* converter in low power mode & enable PENIRQ */ 401969111e9SNicolas Ferre req->ref_off = PWRDOWN; 402d93f70b2SDavid Brownell req->xfer[4].tx_buf = &req->ref_off; 403ffa458c1SDavid Brownell req->xfer[4].len = 1; 4042c8dc071SDavid Brownell spi_message_add_tail(&req->xfer[4], &req->msg); 4052c8dc071SDavid Brownell 406ffa458c1SDavid Brownell req->xfer[5].rx_buf = &req->scratch; 407ffa458c1SDavid Brownell req->xfer[5].len = 2; 408ffa458c1SDavid Brownell CS_CHANGE(req->xfer[5]); 4092c8dc071SDavid Brownell spi_message_add_tail(&req->xfer[5], &req->msg); 410ffa458c1SDavid Brownell 4112991a1caSJason Wang mutex_lock(&ts->lock); 4122991a1caSJason Wang ads7846_stop(ts); 413ffa458c1SDavid Brownell status = spi_sync(spi, &req->msg); 4142991a1caSJason Wang ads7846_restart(ts); 4152991a1caSJason Wang mutex_unlock(&ts->lock); 416ffa458c1SDavid Brownell 417c24b2602SMarc Pignat if (status == 0) { 4189084533eSDavid Brownell /* on-wire is a must-ignore bit, a BE12 value, then padding */ 4197c6d0ee1SDavid Brownell status = be16_to_cpu(req->sample); 4207c6d0ee1SDavid Brownell status = status >> 3; 4217c6d0ee1SDavid Brownell status &= 0x0fff; 422c24b2602SMarc Pignat } 4239084533eSDavid Brownell 4249084533eSDavid Brownell kfree(req); 4257c6d0ee1SDavid Brownell return status; 426ffa458c1SDavid Brownell } 427ffa458c1SDavid Brownell 4283eac5c7eSAnatolij Gustschin static int ads7845_read12_ser(struct device *dev, unsigned command) 4293eac5c7eSAnatolij Gustschin { 4303eac5c7eSAnatolij Gustschin struct spi_device *spi = to_spi_device(dev); 4313eac5c7eSAnatolij Gustschin struct ads7846 *ts = dev_get_drvdata(dev); 4322991a1caSJason Wang struct ads7845_ser_req *req; 4333eac5c7eSAnatolij Gustschin int status; 4343eac5c7eSAnatolij Gustschin 4352991a1caSJason Wang req = kzalloc(sizeof *req, GFP_KERNEL); 4363eac5c7eSAnatolij Gustschin if (!req) 4373eac5c7eSAnatolij Gustschin return -ENOMEM; 4383eac5c7eSAnatolij Gustschin 4393eac5c7eSAnatolij Gustschin spi_message_init(&req->msg); 4403eac5c7eSAnatolij Gustschin 4413eac5c7eSAnatolij Gustschin req->command[0] = (u8) command; 4423eac5c7eSAnatolij Gustschin req->xfer[0].tx_buf = req->command; 4433eac5c7eSAnatolij Gustschin req->xfer[0].rx_buf = req->sample; 4443eac5c7eSAnatolij Gustschin req->xfer[0].len = 3; 4453eac5c7eSAnatolij Gustschin spi_message_add_tail(&req->xfer[0], &req->msg); 4463eac5c7eSAnatolij Gustschin 4472991a1caSJason Wang mutex_lock(&ts->lock); 4482991a1caSJason Wang ads7846_stop(ts); 4493eac5c7eSAnatolij Gustschin status = spi_sync(spi, &req->msg); 4502991a1caSJason Wang ads7846_restart(ts); 4512991a1caSJason Wang mutex_unlock(&ts->lock); 4523eac5c7eSAnatolij Gustschin 4533eac5c7eSAnatolij Gustschin if (status == 0) { 4543eac5c7eSAnatolij Gustschin /* BE12 value, then padding */ 45503e2c9c7SDmitry Torokhov status = get_unaligned_be16(&req->sample[1]); 4563eac5c7eSAnatolij Gustschin status = status >> 3; 4573eac5c7eSAnatolij Gustschin status &= 0x0fff; 4583eac5c7eSAnatolij Gustschin } 4593eac5c7eSAnatolij Gustschin 4603eac5c7eSAnatolij Gustschin kfree(req); 4613eac5c7eSAnatolij Gustschin return status; 4623eac5c7eSAnatolij Gustschin } 4633eac5c7eSAnatolij Gustschin 464c52b4fc7SFabio Estevam #if IS_ENABLED(CONFIG_HWMON) 4652c8dc071SDavid Brownell 4662c8dc071SDavid Brownell #define SHOW(name, var, adjust) static ssize_t \ 467ffa458c1SDavid Brownell name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ 468ffa458c1SDavid Brownell { \ 4692c8dc071SDavid Brownell struct ads7846 *ts = dev_get_drvdata(dev); \ 4702fdf4cd9SAlexander Stein ssize_t v = ads7846_read12_ser(&ts->spi->dev, \ 471ebcaaad9SAlexander Stein READ_12BIT_SER(var)); \ 472ffa458c1SDavid Brownell if (v < 0) \ 473ffa458c1SDavid Brownell return v; \ 4742c8dc071SDavid Brownell return sprintf(buf, "%u\n", adjust(ts, v)); \ 475ffa458c1SDavid Brownell } \ 476ffa458c1SDavid Brownell static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); 477ffa458c1SDavid Brownell 4782c8dc071SDavid Brownell 479b731d7b6SAdam Buchbinder /* Sysfs conventions report temperatures in millidegrees Celsius. 4802c8dc071SDavid Brownell * ADS7846 could use the low-accuracy two-sample scheme, but can't do the high 4812c8dc071SDavid Brownell * accuracy scheme without calibration data. For now we won't try either; 4822c8dc071SDavid Brownell * userspace sees raw sensor values, and must scale/calibrate appropriately. 4832c8dc071SDavid Brownell */ 4842c8dc071SDavid Brownell static inline unsigned null_adjust(struct ads7846 *ts, ssize_t v) 4852c8dc071SDavid Brownell { 4862c8dc071SDavid Brownell return v; 4872c8dc071SDavid Brownell } 4882c8dc071SDavid Brownell 4892c8dc071SDavid Brownell SHOW(temp0, temp0, null_adjust) /* temp1_input */ 4902c8dc071SDavid Brownell SHOW(temp1, temp1, null_adjust) /* temp2_input */ 4912c8dc071SDavid Brownell 4922c8dc071SDavid Brownell 4932c8dc071SDavid Brownell /* sysfs conventions report voltages in millivolts. We can convert voltages 4942c8dc071SDavid Brownell * if we know vREF. userspace may need to scale vAUX to match the board's 4952c8dc071SDavid Brownell * external resistors; we assume that vBATT only uses the internal ones. 4962c8dc071SDavid Brownell */ 4972c8dc071SDavid Brownell static inline unsigned vaux_adjust(struct ads7846 *ts, ssize_t v) 4982c8dc071SDavid Brownell { 4992c8dc071SDavid Brownell unsigned retval = v; 5002c8dc071SDavid Brownell 5012c8dc071SDavid Brownell /* external resistors may scale vAUX into 0..vREF */ 5027c6d0ee1SDavid Brownell retval *= ts->vref_mv; 5032c8dc071SDavid Brownell retval = retval >> 12; 5042991a1caSJason Wang 5052c8dc071SDavid Brownell return retval; 5062c8dc071SDavid Brownell } 5072c8dc071SDavid Brownell 5082c8dc071SDavid Brownell static inline unsigned vbatt_adjust(struct ads7846 *ts, ssize_t v) 5092c8dc071SDavid Brownell { 5102c8dc071SDavid Brownell unsigned retval = vaux_adjust(ts, v); 5112c8dc071SDavid Brownell 5122c8dc071SDavid Brownell /* ads7846 has a resistor ladder to scale this signal down */ 5132c8dc071SDavid Brownell if (ts->model == 7846) 5142c8dc071SDavid Brownell retval *= 4; 5152991a1caSJason Wang 5162c8dc071SDavid Brownell return retval; 5172c8dc071SDavid Brownell } 5182c8dc071SDavid Brownell 5192c8dc071SDavid Brownell SHOW(in0_input, vaux, vaux_adjust) 5202c8dc071SDavid Brownell SHOW(in1_input, vbatt, vbatt_adjust) 5212c8dc071SDavid Brownell 522e585c40bSGuenter Roeck static umode_t ads7846_is_visible(struct kobject *kobj, struct attribute *attr, 523e585c40bSGuenter Roeck int index) 524e585c40bSGuenter Roeck { 5253fe781f4SWang Qing struct device *dev = kobj_to_dev(kobj); 526e585c40bSGuenter Roeck struct ads7846 *ts = dev_get_drvdata(dev); 527e585c40bSGuenter Roeck 528e585c40bSGuenter Roeck if (ts->model == 7843 && index < 2) /* in0, in1 */ 529e585c40bSGuenter Roeck return 0; 530e585c40bSGuenter Roeck if (ts->model == 7845 && index != 2) /* in0 */ 531e585c40bSGuenter Roeck return 0; 532e585c40bSGuenter Roeck 533e585c40bSGuenter Roeck return attr->mode; 534e585c40bSGuenter Roeck } 535e585c40bSGuenter Roeck 5362c8dc071SDavid Brownell static struct attribute *ads7846_attributes[] = { 537e585c40bSGuenter Roeck &dev_attr_temp0.attr, /* 0 */ 538e585c40bSGuenter Roeck &dev_attr_temp1.attr, /* 1 */ 539e585c40bSGuenter Roeck &dev_attr_in0_input.attr, /* 2 */ 540e585c40bSGuenter Roeck &dev_attr_in1_input.attr, /* 3 */ 5412c8dc071SDavid Brownell NULL, 5422c8dc071SDavid Brownell }; 5432c8dc071SDavid Brownell 5449e938decSArvind Yadav static const struct attribute_group ads7846_attr_group = { 5452c8dc071SDavid Brownell .attrs = ads7846_attributes, 546e585c40bSGuenter Roeck .is_visible = ads7846_is_visible, 5472c8dc071SDavid Brownell }; 548e585c40bSGuenter Roeck __ATTRIBUTE_GROUPS(ads7846_attr); 5492c8dc071SDavid Brownell 5502c8dc071SDavid Brownell static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts) 5512c8dc071SDavid Brownell { 5522c8dc071SDavid Brownell /* hwmon sensors need a reference voltage */ 5532c8dc071SDavid Brownell switch (ts->model) { 5542c8dc071SDavid Brownell case 7846: 5557c6d0ee1SDavid Brownell if (!ts->vref_mv) { 5562c8dc071SDavid Brownell dev_dbg(&spi->dev, "assuming 2.5V internal vREF\n"); 5577c6d0ee1SDavid Brownell ts->vref_mv = 2500; 558ebcaaad9SAlexander Stein ts->use_internal = true; 5592c8dc071SDavid Brownell } 5602c8dc071SDavid Brownell break; 5612c8dc071SDavid Brownell case 7845: 5622c8dc071SDavid Brownell case 7843: 5637c6d0ee1SDavid Brownell if (!ts->vref_mv) { 5642c8dc071SDavid Brownell dev_warn(&spi->dev, 5652c8dc071SDavid Brownell "external vREF for ADS%d not specified\n", 5662c8dc071SDavid Brownell ts->model); 5672c8dc071SDavid Brownell return 0; 5682c8dc071SDavid Brownell } 5692c8dc071SDavid Brownell break; 5702c8dc071SDavid Brownell } 5712c8dc071SDavid Brownell 572e585c40bSGuenter Roeck ts->hwmon = hwmon_device_register_with_groups(&spi->dev, spi->modalias, 573e585c40bSGuenter Roeck ts, ads7846_attr_groups); 5742c8dc071SDavid Brownell 575c4517f82SJavier Martinez Canillas return PTR_ERR_OR_ZERO(ts->hwmon); 5762c8dc071SDavid Brownell } 5772c8dc071SDavid Brownell 5782c8dc071SDavid Brownell static void ads784x_hwmon_unregister(struct spi_device *spi, 5792c8dc071SDavid Brownell struct ads7846 *ts) 5802c8dc071SDavid Brownell { 581e585c40bSGuenter Roeck if (ts->hwmon) 5822c8dc071SDavid Brownell hwmon_device_unregister(ts->hwmon); 5832c8dc071SDavid Brownell } 5842c8dc071SDavid Brownell 5852c8dc071SDavid Brownell #else 5862c8dc071SDavid Brownell static inline int ads784x_hwmon_register(struct spi_device *spi, 5872c8dc071SDavid Brownell struct ads7846 *ts) 5882c8dc071SDavid Brownell { 5892c8dc071SDavid Brownell return 0; 5902c8dc071SDavid Brownell } 5912c8dc071SDavid Brownell 5922c8dc071SDavid Brownell static inline void ads784x_hwmon_unregister(struct spi_device *spi, 5932c8dc071SDavid Brownell struct ads7846 *ts) 5942c8dc071SDavid Brownell { 5952c8dc071SDavid Brownell } 5962c8dc071SDavid Brownell #endif 597ffa458c1SDavid Brownell 598438f2a74SImre Deak static ssize_t ads7846_pen_down_show(struct device *dev, 599438f2a74SImre Deak struct device_attribute *attr, char *buf) 600438f2a74SImre Deak { 6012991a1caSJason Wang struct ads7846 *ts = dev_get_drvdata(dev); 6022991a1caSJason Wang 6032991a1caSJason Wang return sprintf(buf, "%u\n", ts->pendown); 604438f2a74SImre Deak } 605438f2a74SImre Deak 606438f2a74SImre Deak static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL); 607438f2a74SImre Deak 6087de90a8cSImre Deak static ssize_t ads7846_disable_show(struct device *dev, 6097de90a8cSImre Deak struct device_attribute *attr, char *buf) 6107de90a8cSImre Deak { 6117de90a8cSImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 6127de90a8cSImre Deak 6137de90a8cSImre Deak return sprintf(buf, "%u\n", ts->disabled); 6147de90a8cSImre Deak } 6157de90a8cSImre Deak 6167de90a8cSImre Deak static ssize_t ads7846_disable_store(struct device *dev, 6177de90a8cSImre Deak struct device_attribute *attr, 6187de90a8cSImre Deak const char *buf, size_t count) 6197de90a8cSImre Deak { 6207de90a8cSImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 62176496e7aSJJ Ding unsigned int i; 62276496e7aSJJ Ding int err; 6237de90a8cSImre Deak 62476496e7aSJJ Ding err = kstrtouint(buf, 10, &i); 62576496e7aSJJ Ding if (err) 62676496e7aSJJ Ding return err; 627160f1fefSJoe Rouvier 6287de90a8cSImre Deak if (i) 6297de90a8cSImre Deak ads7846_disable(ts); 6307de90a8cSImre Deak else 6317de90a8cSImre Deak ads7846_enable(ts); 6327de90a8cSImre Deak 6337de90a8cSImre Deak return count; 6347de90a8cSImre Deak } 6357de90a8cSImre Deak 6367de90a8cSImre Deak static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); 6377de90a8cSImre Deak 6382c8dc071SDavid Brownell static struct attribute *ads784x_attributes[] = { 6398dd51650SDmitry Torokhov &dev_attr_pen_down.attr, 6408dd51650SDmitry Torokhov &dev_attr_disable.attr, 6418dd51650SDmitry Torokhov NULL, 6428dd51650SDmitry Torokhov }; 6438dd51650SDmitry Torokhov 6449e938decSArvind Yadav static const struct attribute_group ads784x_attr_group = { 6452c8dc071SDavid Brownell .attrs = ads784x_attributes, 6468dd51650SDmitry Torokhov }; 6478dd51650SDmitry Torokhov 648ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 649ffa458c1SDavid Brownell 650fd746d54SEric Miao static void null_wait_for_sync(void) 651fd746d54SEric Miao { 652fd746d54SEric Miao } 653fd746d54SEric Miao 6542991a1caSJason Wang static int ads7846_debounce_filter(void *ads, int data_idx, int *val) 655ffa458c1SDavid Brownell { 656ffa458c1SDavid Brownell struct ads7846 *ts = ads; 6572991a1caSJason Wang 6582991a1caSJason Wang if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) { 6592991a1caSJason Wang /* Start over collecting consistent readings. */ 6602991a1caSJason Wang ts->read_rep = 0; 6612991a1caSJason Wang /* 6622991a1caSJason Wang * Repeat it, if this was the first read or the read 6632991a1caSJason Wang * wasn't consistent enough. 6642991a1caSJason Wang */ 6652991a1caSJason Wang if (ts->read_cnt < ts->debounce_max) { 6662991a1caSJason Wang ts->last_read = *val; 6672991a1caSJason Wang ts->read_cnt++; 6682991a1caSJason Wang return ADS7846_FILTER_REPEAT; 6692991a1caSJason Wang } else { 6702991a1caSJason Wang /* 6712991a1caSJason Wang * Maximum number of debouncing reached and still 6722991a1caSJason Wang * not enough number of consistent readings. Abort 6732991a1caSJason Wang * the whole sample, repeat it in the next sampling 6742991a1caSJason Wang * period. 6752991a1caSJason Wang */ 6762991a1caSJason Wang ts->read_cnt = 0; 6772991a1caSJason Wang return ADS7846_FILTER_IGNORE; 6782991a1caSJason Wang } 6792991a1caSJason Wang } else { 6802991a1caSJason Wang if (++ts->read_rep > ts->debounce_rep) { 6812991a1caSJason Wang /* 6822991a1caSJason Wang * Got a good reading for this coordinate, 6832991a1caSJason Wang * go for the next one. 6842991a1caSJason Wang */ 6852991a1caSJason Wang ts->read_cnt = 0; 6862991a1caSJason Wang ts->read_rep = 0; 6872991a1caSJason Wang return ADS7846_FILTER_OK; 6882991a1caSJason Wang } else { 6892991a1caSJason Wang /* Read more values that are consistent. */ 6902991a1caSJason Wang ts->read_cnt++; 6912991a1caSJason Wang return ADS7846_FILTER_REPEAT; 6922991a1caSJason Wang } 6932991a1caSJason Wang } 6942991a1caSJason Wang } 6952991a1caSJason Wang 6962991a1caSJason Wang static int ads7846_no_filter(void *ads, int data_idx, int *val) 6972991a1caSJason Wang { 6982991a1caSJason Wang return ADS7846_FILTER_OK; 6992991a1caSJason Wang } 7002991a1caSJason Wang 701*6965eeceSOleksij Rempel static int ads7846_get_value(struct ads7846_buf *buf) 7022991a1caSJason Wang { 703879f2feaSAndrey Gelman int value; 7042991a1caSJason Wang 705*6965eeceSOleksij Rempel value = be16_to_cpup(&buf->data); 706879f2feaSAndrey Gelman 707879f2feaSAndrey Gelman /* enforce ADC output is 12 bits width */ 708879f2feaSAndrey Gelman return (value >> 3) & 0xfff; 7092991a1caSJason Wang } 7102991a1caSJason Wang 711*6965eeceSOleksij Rempel static void ads7846_set_cmd_val(struct ads7846 *ts, enum ads7846_cmds cmd_idx, 712*6965eeceSOleksij Rempel u16 val) 7132991a1caSJason Wang { 714*6965eeceSOleksij Rempel struct ads7846_packet *packet = ts->packet; 7152991a1caSJason Wang 716*6965eeceSOleksij Rempel switch (cmd_idx) { 717*6965eeceSOleksij Rempel case ADS7846_Y: 718*6965eeceSOleksij Rempel packet->y = val; 719*6965eeceSOleksij Rempel break; 720*6965eeceSOleksij Rempel case ADS7846_X: 721*6965eeceSOleksij Rempel packet->x = val; 722*6965eeceSOleksij Rempel break; 723*6965eeceSOleksij Rempel case ADS7846_Z1: 724*6965eeceSOleksij Rempel packet->z1 = val; 725*6965eeceSOleksij Rempel break; 726*6965eeceSOleksij Rempel case ADS7846_Z2: 727*6965eeceSOleksij Rempel packet->z2 = val; 728*6965eeceSOleksij Rempel break; 729*6965eeceSOleksij Rempel default: 730*6965eeceSOleksij Rempel WARN_ON_ONCE(1); 731*6965eeceSOleksij Rempel } 732*6965eeceSOleksij Rempel } 733*6965eeceSOleksij Rempel 734*6965eeceSOleksij Rempel static u8 ads7846_get_cmd(enum ads7846_cmds cmd_idx, int vref) 735*6965eeceSOleksij Rempel { 736*6965eeceSOleksij Rempel switch (cmd_idx) { 737*6965eeceSOleksij Rempel case ADS7846_Y: 738*6965eeceSOleksij Rempel return READ_Y(vref); 739*6965eeceSOleksij Rempel case ADS7846_X: 740*6965eeceSOleksij Rempel return READ_X(vref); 741*6965eeceSOleksij Rempel 742*6965eeceSOleksij Rempel /* 7846 specific commands */ 743*6965eeceSOleksij Rempel case ADS7846_Z1: 744*6965eeceSOleksij Rempel return READ_Z1(vref); 745*6965eeceSOleksij Rempel case ADS7846_Z2: 746*6965eeceSOleksij Rempel return READ_Z2(vref); 747*6965eeceSOleksij Rempel case ADS7846_PWDOWN: 748*6965eeceSOleksij Rempel return PWRDOWN; 749*6965eeceSOleksij Rempel default: 750*6965eeceSOleksij Rempel WARN_ON_ONCE(1); 751*6965eeceSOleksij Rempel } 752*6965eeceSOleksij Rempel 753*6965eeceSOleksij Rempel return 0; 754*6965eeceSOleksij Rempel } 755*6965eeceSOleksij Rempel 756*6965eeceSOleksij Rempel static bool ads7846_cmd_need_settle(enum ads7846_cmds cmd_idx) 757*6965eeceSOleksij Rempel { 758*6965eeceSOleksij Rempel switch (cmd_idx) { 759*6965eeceSOleksij Rempel case ADS7846_X: 760*6965eeceSOleksij Rempel case ADS7846_Y: 761*6965eeceSOleksij Rempel case ADS7846_Z1: 762*6965eeceSOleksij Rempel case ADS7846_Z2: 763*6965eeceSOleksij Rempel return true; 764*6965eeceSOleksij Rempel case ADS7846_PWDOWN: 765*6965eeceSOleksij Rempel return false; 766*6965eeceSOleksij Rempel default: 767*6965eeceSOleksij Rempel WARN_ON_ONCE(1); 768*6965eeceSOleksij Rempel } 769*6965eeceSOleksij Rempel 770*6965eeceSOleksij Rempel return false; 771*6965eeceSOleksij Rempel } 772*6965eeceSOleksij Rempel 773*6965eeceSOleksij Rempel static int ads7846_filter(struct ads7846 *ts) 774*6965eeceSOleksij Rempel { 775*6965eeceSOleksij Rempel struct ads7846_packet *packet = ts->packet; 776*6965eeceSOleksij Rempel int action; 777*6965eeceSOleksij Rempel int val; 778*6965eeceSOleksij Rempel unsigned int cmd_idx, b; 779*6965eeceSOleksij Rempel 780*6965eeceSOleksij Rempel packet->ignore = false; 781*6965eeceSOleksij Rempel for (cmd_idx = packet->last_cmd_idx; cmd_idx < packet->cmds - 1; cmd_idx++) { 782*6965eeceSOleksij Rempel struct ads7846_buf_layout *l = &packet->l[cmd_idx]; 783*6965eeceSOleksij Rempel 784*6965eeceSOleksij Rempel packet->last_cmd_idx = cmd_idx; 785*6965eeceSOleksij Rempel 786*6965eeceSOleksij Rempel for (b = l->skip; b < l->count; b++) { 787*6965eeceSOleksij Rempel val = ads7846_get_value(&packet->rx[l->offset + b]); 788*6965eeceSOleksij Rempel 789*6965eeceSOleksij Rempel action = ts->filter(ts->filter_data, cmd_idx, &val); 790*6965eeceSOleksij Rempel if (action == ADS7846_FILTER_REPEAT) { 791*6965eeceSOleksij Rempel if (b == l->count - 1) 792*6965eeceSOleksij Rempel return -EAGAIN; 793*6965eeceSOleksij Rempel } else if (action == ADS7846_FILTER_OK) { 794*6965eeceSOleksij Rempel ads7846_set_cmd_val(ts, cmd_idx, val); 795*6965eeceSOleksij Rempel break; 796*6965eeceSOleksij Rempel } else { 797*6965eeceSOleksij Rempel packet->ignore = true; 798*6965eeceSOleksij Rempel return 0; 799*6965eeceSOleksij Rempel } 800*6965eeceSOleksij Rempel } 801*6965eeceSOleksij Rempel } 802*6965eeceSOleksij Rempel 803*6965eeceSOleksij Rempel return 0; 8042991a1caSJason Wang } 8052991a1caSJason Wang 8062991a1caSJason Wang static void ads7846_read_state(struct ads7846 *ts) 8072991a1caSJason Wang { 808e8f462d2SDmitry Torokhov struct ads7846_packet *packet = ts->packet; 8092991a1caSJason Wang struct spi_message *m; 8102991a1caSJason Wang int msg_idx = 0; 8112991a1caSJason Wang int error; 8122991a1caSJason Wang 813*6965eeceSOleksij Rempel packet->last_cmd_idx = 0; 8142991a1caSJason Wang 815*6965eeceSOleksij Rempel while (true) { 8162991a1caSJason Wang ts->wait_for_sync(); 8172991a1caSJason Wang 8182991a1caSJason Wang m = &ts->msg[msg_idx]; 8192991a1caSJason Wang error = spi_sync(ts->spi, m); 8202991a1caSJason Wang if (error) { 821c8986208SMark Brown dev_err(&ts->spi->dev, "spi_sync --> %d\n", error); 822*6965eeceSOleksij Rempel packet->ignore = true; 8232991a1caSJason Wang return; 8242991a1caSJason Wang } 8252991a1caSJason Wang 826*6965eeceSOleksij Rempel error = ads7846_filter(ts); 827*6965eeceSOleksij Rempel if (error) 8282991a1caSJason Wang continue; 8292991a1caSJason Wang 830*6965eeceSOleksij Rempel return; 8312991a1caSJason Wang } 8322991a1caSJason Wang } 8332991a1caSJason Wang 8342991a1caSJason Wang static void ads7846_report_state(struct ads7846 *ts) 8352991a1caSJason Wang { 8362991a1caSJason Wang struct ads7846_packet *packet = ts->packet; 8372991a1caSJason Wang unsigned int Rt; 838ffa458c1SDavid Brownell u16 x, y, z1, z2; 839ffa458c1SDavid Brownell 840*6965eeceSOleksij Rempel x = packet->x; 841*6965eeceSOleksij Rempel y = packet->y; 8423eac5c7eSAnatolij Gustschin if (ts->model == 7845) { 8433eac5c7eSAnatolij Gustschin z1 = 0; 8443eac5c7eSAnatolij Gustschin z2 = 0; 8453eac5c7eSAnatolij Gustschin } else { 846*6965eeceSOleksij Rempel z1 = packet->z1; 847*6965eeceSOleksij Rempel z2 = packet->z2; 8483eac5c7eSAnatolij Gustschin } 849ffa458c1SDavid Brownell 850ffa458c1SDavid Brownell /* range filtering */ 851ffa458c1SDavid Brownell if (x == MAX_12BIT) 852ffa458c1SDavid Brownell x = 0; 853ffa458c1SDavid Brownell 8549460b652SHans-Christian Egtvedt if (ts->model == 7843) { 8559460b652SHans-Christian Egtvedt Rt = ts->pressure_max / 2; 8563eac5c7eSAnatolij Gustschin } else if (ts->model == 7845) { 8573eac5c7eSAnatolij Gustschin if (get_pendown_state(ts)) 8583eac5c7eSAnatolij Gustschin Rt = ts->pressure_max / 2; 8593eac5c7eSAnatolij Gustschin else 8603eac5c7eSAnatolij Gustschin Rt = 0; 8613eac5c7eSAnatolij Gustschin dev_vdbg(&ts->spi->dev, "x/y: %d/%d, PD %d\n", x, y, Rt); 8629460b652SHans-Christian Egtvedt } else if (likely(x && z1)) { 863ffa458c1SDavid Brownell /* compute touch pressure resistance using equation #2 */ 864ffa458c1SDavid Brownell Rt = z2; 865ffa458c1SDavid Brownell Rt -= z1; 866ffa458c1SDavid Brownell Rt *= ts->x_plate_ohms; 867820830ecSOleksij Rempel Rt = DIV_ROUND_CLOSEST(Rt, 16); 868820830ecSOleksij Rempel Rt *= x; 869ffa458c1SDavid Brownell Rt /= z1; 870820830ecSOleksij Rempel Rt = DIV_ROUND_CLOSEST(Rt, 256); 8719460b652SHans-Christian Egtvedt } else { 872ffa458c1SDavid Brownell Rt = 0; 8739460b652SHans-Christian Egtvedt } 874969111e9SNicolas Ferre 8752991a1caSJason Wang /* 8762991a1caSJason Wang * Sample found inconsistent by debouncing or pressure is beyond 877d5b415c9SImre Deak * the maximum. Don't report it to user space, repeat at least 8781936d590SImre Deak * once more the measurement 8791936d590SImre Deak */ 880*6965eeceSOleksij Rempel if (packet->ignore || Rt > ts->pressure_max) { 88152ce4eaaSPavel Machek dev_vdbg(&ts->spi->dev, "ignored %d pressure %d\n", 882*6965eeceSOleksij Rempel packet->ignore, Rt); 883d5b415c9SImre Deak return; 884d5b415c9SImre Deak } 885d5b415c9SImre Deak 8862991a1caSJason Wang /* 8872991a1caSJason Wang * Maybe check the pendown state before reporting. This discards 8881d25891fSSemih Hazar * false readings when the pen is lifted. 8891d25891fSSemih Hazar */ 8901d25891fSSemih Hazar if (ts->penirq_recheck_delay_usecs) { 8911d25891fSSemih Hazar udelay(ts->penirq_recheck_delay_usecs); 8924d5975e5SEric Miao if (!get_pendown_state(ts)) 8931d25891fSSemih Hazar Rt = 0; 8941d25891fSSemih Hazar } 8951d25891fSSemih Hazar 8962991a1caSJason Wang /* 8972991a1caSJason Wang * NOTE: We can't rely on the pressure to determine the pen down 89815e3589eSImre Deak * state, even this controller has a pressure sensor. The pressure 89915e3589eSImre Deak * value can fluctuate for quite a while after lifting the pen and 90015e3589eSImre Deak * in some cases may not even settle at the expected value. 901ffa458c1SDavid Brownell * 90215e3589eSImre Deak * The only safe way to check for the pen up condition is in the 90315e3589eSImre Deak * timer by reading the pen signal state (it's a GPIO _and_ IRQ). 904ffa458c1SDavid Brownell */ 905ffa458c1SDavid Brownell if (Rt) { 90615e3589eSImre Deak struct input_dev *input = ts->input; 907ae82d5abSImre Deak 9082991a1caSJason Wang if (!ts->pendown) { 9092991a1caSJason Wang input_report_key(input, BTN_TOUCH, 1); 9102991a1caSJason Wang ts->pendown = true; 9112991a1caSJason Wang dev_vdbg(&ts->spi->dev, "DOWN\n"); 9122991a1caSJason Wang } 9132991a1caSJason Wang 914a2f99330SMarco Felsch touchscreen_report_pos(input, &ts->core_prop, x, y, false); 91530ad7ba0SPavel Machek input_report_abs(input, ABS_PRESSURE, ts->pressure_max - Rt); 916ffa458c1SDavid Brownell 91715e3589eSImre Deak input_sync(input); 91852ce4eaaSPavel Machek dev_vdbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt); 91915e3589eSImre Deak } 920ffa458c1SDavid Brownell } 921ffa458c1SDavid Brownell 9222991a1caSJason Wang static irqreturn_t ads7846_hard_irq(int irq, void *handle) 923ffa458c1SDavid Brownell { 9242991a1caSJason Wang struct ads7846 *ts = handle; 925ffa458c1SDavid Brownell 9262991a1caSJason Wang return get_pendown_state(ts) ? IRQ_WAKE_THREAD : IRQ_HANDLED; 927da970e69SImre Deak } 928da970e69SImre Deak 9292991a1caSJason Wang 9302991a1caSJason Wang static irqreturn_t ads7846_irq(int irq, void *handle) 931da970e69SImre Deak { 9322991a1caSJason Wang struct ads7846 *ts = handle; 9332991a1caSJason Wang 9342991a1caSJason Wang /* Start with a small delay before checking pendown state */ 9352991a1caSJason Wang msleep(TS_POLL_DELAY); 9362991a1caSJason Wang 9372991a1caSJason Wang while (!ts->stopped && get_pendown_state(ts)) { 9382991a1caSJason Wang 9392991a1caSJason Wang /* pen is down, continue with the measurement */ 9402991a1caSJason Wang ads7846_read_state(ts); 9412991a1caSJason Wang 9422991a1caSJason Wang if (!ts->stopped) 9432991a1caSJason Wang ads7846_report_state(ts); 9442991a1caSJason Wang 9452991a1caSJason Wang wait_event_timeout(ts->wait, ts->stopped, 9462991a1caSJason Wang msecs_to_jiffies(TS_POLL_PERIOD)); 947da970e69SImre Deak } 948da970e69SImre Deak 949e52cd628SDavid Jander if (ts->pendown && !ts->stopped) 950e52cd628SDavid Jander ads7846_report_pen_up(ts); 95115e3589eSImre Deak 9527de90a8cSImre Deak return IRQ_HANDLED; 953ffa458c1SDavid Brownell } 954ffa458c1SDavid Brownell 95502b6a58bSJingoo Han static int __maybe_unused ads7846_suspend(struct device *dev) 9567de90a8cSImre Deak { 9573c36e719SMark Brown struct ads7846 *ts = dev_get_drvdata(dev); 9587de90a8cSImre Deak 9592991a1caSJason Wang mutex_lock(&ts->lock); 9607de90a8cSImre Deak 9612991a1caSJason Wang if (!ts->suspended) { 9627de90a8cSImre Deak 9632991a1caSJason Wang if (!ts->disabled) 9642991a1caSJason Wang __ads7846_disable(ts); 9657de90a8cSImre Deak 966fdba2bb1SRanjith Lohithakshan if (device_may_wakeup(&ts->spi->dev)) 967fdba2bb1SRanjith Lohithakshan enable_irq_wake(ts->spi->irq); 968fdba2bb1SRanjith Lohithakshan 9692991a1caSJason Wang ts->suspended = true; 9702991a1caSJason Wang } 9717de90a8cSImre Deak 9722991a1caSJason Wang mutex_unlock(&ts->lock); 9732991a1caSJason Wang 9742991a1caSJason Wang return 0; 975ffa458c1SDavid Brownell } 976ffa458c1SDavid Brownell 97702b6a58bSJingoo Han static int __maybe_unused ads7846_resume(struct device *dev) 978ffa458c1SDavid Brownell { 9793c36e719SMark Brown struct ads7846 *ts = dev_get_drvdata(dev); 980ffa458c1SDavid Brownell 9812991a1caSJason Wang mutex_lock(&ts->lock); 9822991a1caSJason Wang 9832991a1caSJason Wang if (ts->suspended) { 9842991a1caSJason Wang 9852991a1caSJason Wang ts->suspended = false; 9862991a1caSJason Wang 987fdba2bb1SRanjith Lohithakshan if (device_may_wakeup(&ts->spi->dev)) 988fdba2bb1SRanjith Lohithakshan disable_irq_wake(ts->spi->irq); 989fdba2bb1SRanjith Lohithakshan 9902991a1caSJason Wang if (!ts->disabled) 9912991a1caSJason Wang __ads7846_enable(ts); 9922991a1caSJason Wang } 9937de90a8cSImre Deak 9942991a1caSJason Wang mutex_unlock(&ts->lock); 9957de90a8cSImre Deak 996ffa458c1SDavid Brownell return 0; 997ffa458c1SDavid Brownell } 9983c36e719SMark Brown 9993c36e719SMark Brown static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume); 1000ffa458c1SDavid Brownell 10015298cc4cSBill Pemberton static int ads7846_setup_pendown(struct spi_device *spi, 100257691a1eSDmitry Torokhov struct ads7846 *ts, 100357691a1eSDmitry Torokhov const struct ads7846_platform_data *pdata) 10044d5975e5SEric Miao { 10054d5975e5SEric Miao int err; 10064d5975e5SEric Miao 10070fbc9fdbSDmitry Torokhov /* 10080fbc9fdbSDmitry Torokhov * REVISIT when the irq can be triggered active-low, or if for some 10094d5975e5SEric Miao * reason the touchscreen isn't hooked up, we don't need to access 10104d5975e5SEric Miao * the pendown state. 10114d5975e5SEric Miao */ 10124d5975e5SEric Miao 10134d5975e5SEric Miao if (pdata->get_pendown_state) { 10144d5975e5SEric Miao ts->get_pendown_state = pdata->get_pendown_state; 10150fbc9fdbSDmitry Torokhov } else if (gpio_is_valid(pdata->gpio_pendown)) { 10164d5975e5SEric Miao 101758c24400SIgor Grinberg err = gpio_request_one(pdata->gpio_pendown, GPIOF_IN, 101858c24400SIgor Grinberg "ads7846_pendown"); 10194d5975e5SEric Miao if (err) { 102058c24400SIgor Grinberg dev_err(&spi->dev, 102158c24400SIgor Grinberg "failed to request/setup pendown GPIO%d: %d\n", 102258c24400SIgor Grinberg pdata->gpio_pendown, err); 10231201e7e6SIgor Grinberg return err; 10241201e7e6SIgor Grinberg } 10254d5975e5SEric Miao 10264d5975e5SEric Miao ts->gpio_pendown = pdata->gpio_pendown; 10272991a1caSJason Wang 1028c4f49254SIgor Grinberg if (pdata->gpio_pendown_debounce) 1029c4f49254SIgor Grinberg gpio_set_debounce(pdata->gpio_pendown, 1030c4f49254SIgor Grinberg pdata->gpio_pendown_debounce); 10310fbc9fdbSDmitry Torokhov } else { 10320fbc9fdbSDmitry Torokhov dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); 10330fbc9fdbSDmitry Torokhov return -EINVAL; 10340fbc9fdbSDmitry Torokhov } 10350fbc9fdbSDmitry Torokhov 10364d5975e5SEric Miao return 0; 10374d5975e5SEric Miao } 10384d5975e5SEric Miao 10392991a1caSJason Wang /* 10402991a1caSJason Wang * Set up the transfers to read touchscreen state; this assumes we 10412991a1caSJason Wang * use formula #2 for pressure, not #3. 10422991a1caSJason Wang */ 1043*6965eeceSOleksij Rempel static int ads7846_setup_spi_msg(struct ads7846 *ts, 10442991a1caSJason Wang const struct ads7846_platform_data *pdata) 10452991a1caSJason Wang { 10462991a1caSJason Wang struct spi_message *m = &ts->msg[0]; 10472991a1caSJason Wang struct spi_transfer *x = ts->xfer; 10482991a1caSJason Wang struct ads7846_packet *packet = ts->packet; 10492991a1caSJason Wang int vref = pdata->keep_vref_on; 1050*6965eeceSOleksij Rempel unsigned int count, offset = 0; 1051*6965eeceSOleksij Rempel unsigned int cmd_idx, b; 1052*6965eeceSOleksij Rempel unsigned long time; 1053*6965eeceSOleksij Rempel size_t size = 0; 1054*6965eeceSOleksij Rempel 1055*6965eeceSOleksij Rempel /* time per bit */ 1056*6965eeceSOleksij Rempel time = NSEC_PER_SEC / ts->spi->max_speed_hz; 1057*6965eeceSOleksij Rempel 1058*6965eeceSOleksij Rempel count = pdata->settle_delay_usecs * NSEC_PER_USEC / time; 1059*6965eeceSOleksij Rempel packet->count_skip = DIV_ROUND_UP(count, 24); 1060*6965eeceSOleksij Rempel 1061*6965eeceSOleksij Rempel if (ts->debounce_max && ts->debounce_rep) 1062*6965eeceSOleksij Rempel /* ads7846_debounce_filter() is making ts->debounce_rep + 2 1063*6965eeceSOleksij Rempel * reads. So we need to get all samples for normal case. */ 1064*6965eeceSOleksij Rempel packet->count = ts->debounce_rep + 2; 1065*6965eeceSOleksij Rempel else 1066*6965eeceSOleksij Rempel packet->count = 1; 1067*6965eeceSOleksij Rempel 1068*6965eeceSOleksij Rempel if (ts->model == 7846) 1069*6965eeceSOleksij Rempel packet->cmds = 5; /* x, y, z1, z2, pwdown */ 1070*6965eeceSOleksij Rempel else 1071*6965eeceSOleksij Rempel packet->cmds = 3; /* x, y, pwdown */ 1072*6965eeceSOleksij Rempel 1073*6965eeceSOleksij Rempel for (cmd_idx = 0; cmd_idx < packet->cmds; cmd_idx++) { 1074*6965eeceSOleksij Rempel struct ads7846_buf_layout *l = &packet->l[cmd_idx]; 1075*6965eeceSOleksij Rempel unsigned int max_count; 1076*6965eeceSOleksij Rempel 1077*6965eeceSOleksij Rempel if (ads7846_cmd_need_settle(cmd_idx)) 1078*6965eeceSOleksij Rempel max_count = packet->count + packet->count_skip; 1079*6965eeceSOleksij Rempel else 1080*6965eeceSOleksij Rempel max_count = packet->count; 1081*6965eeceSOleksij Rempel 1082*6965eeceSOleksij Rempel l->offset = offset; 1083*6965eeceSOleksij Rempel offset += max_count; 1084*6965eeceSOleksij Rempel l->count = max_count; 1085*6965eeceSOleksij Rempel l->skip = packet->count_skip; 1086*6965eeceSOleksij Rempel size += sizeof(*packet->tx) * max_count; 1087*6965eeceSOleksij Rempel } 1088*6965eeceSOleksij Rempel 1089*6965eeceSOleksij Rempel packet->tx = devm_kzalloc(&ts->spi->dev, size, GFP_KERNEL); 1090*6965eeceSOleksij Rempel if (!packet->tx) 1091*6965eeceSOleksij Rempel return -ENOMEM; 1092*6965eeceSOleksij Rempel 1093*6965eeceSOleksij Rempel packet->rx = devm_kzalloc(&ts->spi->dev, size, GFP_KERNEL); 1094*6965eeceSOleksij Rempel if (!packet->rx) 1095*6965eeceSOleksij Rempel return -ENOMEM; 10962991a1caSJason Wang 10972991a1caSJason Wang if (ts->model == 7873) { 10982991a1caSJason Wang /* 10992991a1caSJason Wang * The AD7873 is almost identical to the ADS7846 11002991a1caSJason Wang * keep VREF off during differential/ratiometric 11012991a1caSJason Wang * conversion modes. 11022991a1caSJason Wang */ 11032991a1caSJason Wang ts->model = 7846; 11042991a1caSJason Wang vref = 0; 11052991a1caSJason Wang } 11062991a1caSJason Wang 11072991a1caSJason Wang ts->msg_count = 1; 11082991a1caSJason Wang spi_message_init(m); 11092991a1caSJason Wang m->context = ts; 11102991a1caSJason Wang 1111*6965eeceSOleksij Rempel for (cmd_idx = 0; cmd_idx < packet->cmds; cmd_idx++) { 1112*6965eeceSOleksij Rempel struct ads7846_buf_layout *l = &packet->l[cmd_idx]; 1113*6965eeceSOleksij Rempel u8 cmd = ads7846_get_cmd(cmd_idx, vref); 11142991a1caSJason Wang 1115*6965eeceSOleksij Rempel for (b = 0; b < l->count; b++) 1116*6965eeceSOleksij Rempel packet->tx[l->offset + b].cmd = cmd; 11172991a1caSJason Wang } 11182991a1caSJason Wang 1119*6965eeceSOleksij Rempel x->tx_buf = packet->tx; 1120*6965eeceSOleksij Rempel x->rx_buf = packet->rx; 1121*6965eeceSOleksij Rempel x->len = size; 11222991a1caSJason Wang spi_message_add_tail(x, m); 11232991a1caSJason Wang 1124*6965eeceSOleksij Rempel return 0; 11252991a1caSJason Wang } 11262991a1caSJason Wang 1127a608026eSDaniel Mack #ifdef CONFIG_OF 1128a608026eSDaniel Mack static const struct of_device_id ads7846_dt_ids[] = { 1129a608026eSDaniel Mack { .compatible = "ti,tsc2046", .data = (void *) 7846 }, 1130a608026eSDaniel Mack { .compatible = "ti,ads7843", .data = (void *) 7843 }, 1131a608026eSDaniel Mack { .compatible = "ti,ads7845", .data = (void *) 7845 }, 1132a608026eSDaniel Mack { .compatible = "ti,ads7846", .data = (void *) 7846 }, 1133a608026eSDaniel Mack { .compatible = "ti,ads7873", .data = (void *) 7873 }, 1134a608026eSDaniel Mack { } 1135a608026eSDaniel Mack }; 1136a608026eSDaniel Mack MODULE_DEVICE_TABLE(of, ads7846_dt_ids); 1137a608026eSDaniel Mack 1138a608026eSDaniel Mack static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) 1139a608026eSDaniel Mack { 1140a608026eSDaniel Mack struct ads7846_platform_data *pdata; 1141a608026eSDaniel Mack struct device_node *node = dev->of_node; 1142a608026eSDaniel Mack const struct of_device_id *match; 1143a2f99330SMarco Felsch u32 value; 1144a608026eSDaniel Mack 1145a608026eSDaniel Mack if (!node) { 1146a608026eSDaniel Mack dev_err(dev, "Device does not have associated DT data\n"); 1147a608026eSDaniel Mack return ERR_PTR(-EINVAL); 1148a608026eSDaniel Mack } 1149a608026eSDaniel Mack 1150a608026eSDaniel Mack match = of_match_device(ads7846_dt_ids, dev); 1151a608026eSDaniel Mack if (!match) { 1152a608026eSDaniel Mack dev_err(dev, "Unknown device model\n"); 1153a608026eSDaniel Mack return ERR_PTR(-EINVAL); 1154a608026eSDaniel Mack } 1155a608026eSDaniel Mack 1156a608026eSDaniel Mack pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 1157a608026eSDaniel Mack if (!pdata) 1158a608026eSDaniel Mack return ERR_PTR(-ENOMEM); 1159a608026eSDaniel Mack 1160a608026eSDaniel Mack pdata->model = (unsigned long)match->data; 1161a608026eSDaniel Mack 1162a608026eSDaniel Mack of_property_read_u16(node, "ti,vref-delay-usecs", 1163a608026eSDaniel Mack &pdata->vref_delay_usecs); 1164a608026eSDaniel Mack of_property_read_u16(node, "ti,vref-mv", &pdata->vref_mv); 1165a608026eSDaniel Mack pdata->keep_vref_on = of_property_read_bool(node, "ti,keep-vref-on"); 1166a608026eSDaniel Mack 1167a608026eSDaniel Mack pdata->swap_xy = of_property_read_bool(node, "ti,swap-xy"); 1168a608026eSDaniel Mack 1169a608026eSDaniel Mack of_property_read_u16(node, "ti,settle-delay-usec", 1170a608026eSDaniel Mack &pdata->settle_delay_usecs); 1171a608026eSDaniel Mack of_property_read_u16(node, "ti,penirq-recheck-delay-usecs", 1172a608026eSDaniel Mack &pdata->penirq_recheck_delay_usecs); 1173a608026eSDaniel Mack 1174a608026eSDaniel Mack of_property_read_u16(node, "ti,x-plate-ohms", &pdata->x_plate_ohms); 1175a608026eSDaniel Mack of_property_read_u16(node, "ti,y-plate-ohms", &pdata->y_plate_ohms); 1176a608026eSDaniel Mack 1177a608026eSDaniel Mack of_property_read_u16(node, "ti,x-min", &pdata->x_min); 1178a608026eSDaniel Mack of_property_read_u16(node, "ti,y-min", &pdata->y_min); 1179a608026eSDaniel Mack of_property_read_u16(node, "ti,x-max", &pdata->x_max); 1180a608026eSDaniel Mack of_property_read_u16(node, "ti,y-max", &pdata->y_max); 1181a608026eSDaniel Mack 1182a2f99330SMarco Felsch /* 1183a2f99330SMarco Felsch * touchscreen-max-pressure gets parsed during 1184a2f99330SMarco Felsch * touchscreen_parse_properties() 1185a2f99330SMarco Felsch */ 1186a608026eSDaniel Mack of_property_read_u16(node, "ti,pressure-min", &pdata->pressure_min); 1187a2f99330SMarco Felsch if (!of_property_read_u32(node, "touchscreen-min-pressure", &value)) 1188a2f99330SMarco Felsch pdata->pressure_min = (u16) value; 1189a608026eSDaniel Mack of_property_read_u16(node, "ti,pressure-max", &pdata->pressure_max); 1190a608026eSDaniel Mack 1191a608026eSDaniel Mack of_property_read_u16(node, "ti,debounce-max", &pdata->debounce_max); 1192a2f99330SMarco Felsch if (!of_property_read_u32(node, "touchscreen-average-samples", &value)) 1193a2f99330SMarco Felsch pdata->debounce_max = (u16) value; 1194a608026eSDaniel Mack of_property_read_u16(node, "ti,debounce-tol", &pdata->debounce_tol); 1195a608026eSDaniel Mack of_property_read_u16(node, "ti,debounce-rep", &pdata->debounce_rep); 1196a608026eSDaniel Mack 1197a608026eSDaniel Mack of_property_read_u32(node, "ti,pendown-gpio-debounce", 1198a608026eSDaniel Mack &pdata->gpio_pendown_debounce); 1199a608026eSDaniel Mack 1200abf77a32SDmitry Torokhov pdata->wakeup = of_property_read_bool(node, "wakeup-source") || 1201abf77a32SDmitry Torokhov of_property_read_bool(node, "linux,wakeup"); 1202a608026eSDaniel Mack 1203a608026eSDaniel Mack pdata->gpio_pendown = of_get_named_gpio(dev->of_node, "pendown-gpio", 0); 1204a608026eSDaniel Mack 1205a608026eSDaniel Mack return pdata; 1206a608026eSDaniel Mack } 1207a608026eSDaniel Mack #else 1208a608026eSDaniel Mack static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) 1209a608026eSDaniel Mack { 1210a608026eSDaniel Mack dev_err(dev, "no platform data defined\n"); 1211a608026eSDaniel Mack return ERR_PTR(-EINVAL); 1212a608026eSDaniel Mack } 1213a608026eSDaniel Mack #endif 1214a608026eSDaniel Mack 12155298cc4cSBill Pemberton static int ads7846_probe(struct spi_device *spi) 1216ffa458c1SDavid Brownell { 1217a608026eSDaniel Mack const struct ads7846_platform_data *pdata; 1218ffa458c1SDavid Brownell struct ads7846 *ts; 1219e8f462d2SDmitry Torokhov struct ads7846_packet *packet; 1220a90f7e98SDmitry Torokhov struct input_dev *input_dev; 12210f622bf4SDmitry Torokhov unsigned long irq_flags; 1222a90f7e98SDmitry Torokhov int err; 1223ffa458c1SDavid Brownell 1224ffa458c1SDavid Brownell if (!spi->irq) { 12252e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "no IRQ?\n"); 1226a608026eSDaniel Mack return -EINVAL; 1227ffa458c1SDavid Brownell } 1228ffa458c1SDavid Brownell 1229ffa458c1SDavid Brownell /* don't exceed max specified sample rate */ 1230d93f70b2SDavid Brownell if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { 1231a608026eSDaniel Mack dev_err(&spi->dev, "f(sample) %d KHz?\n", 1232d93f70b2SDavid Brownell (spi->max_speed_hz/SAMPLE_BITS)/1000); 1233ffa458c1SDavid Brownell return -EINVAL; 1234ffa458c1SDavid Brownell } 1235ffa458c1SDavid Brownell 1236a608026eSDaniel Mack /* 1237a608026eSDaniel Mack * We'd set TX word size 8 bits and RX word size to 13 bits ... except 12389084533eSDavid Brownell * that even if the hardware can do that, the SPI controller driver 12399084533eSDavid Brownell * may not. So we stick to very-portable 8 bit words, both RX and TX. 1240ffa458c1SDavid Brownell */ 12419084533eSDavid Brownell spi->bits_per_word = 8; 1242376ccca8SOleksij Rempel spi->mode &= ~SPI_MODE_X_MASK; 1243376ccca8SOleksij Rempel spi->mode |= SPI_MODE_0; 12447937e86aSImre Deak err = spi_setup(spi); 12457937e86aSImre Deak if (err < 0) 12467937e86aSImre Deak return err; 1247ffa458c1SDavid Brownell 1248a90f7e98SDmitry Torokhov ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); 1249e8f462d2SDmitry Torokhov packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL); 1250a90f7e98SDmitry Torokhov input_dev = input_allocate_device(); 1251e8f462d2SDmitry Torokhov if (!ts || !packet || !input_dev) { 1252a90f7e98SDmitry Torokhov err = -ENOMEM; 1253a90f7e98SDmitry Torokhov goto err_free_mem; 1254a90f7e98SDmitry Torokhov } 1255ffa458c1SDavid Brownell 1256c12454faSJingoo Han spi_set_drvdata(spi, ts); 1257ffa458c1SDavid Brownell 1258e8f462d2SDmitry Torokhov ts->packet = packet; 1259ffa458c1SDavid Brownell ts->spi = spi; 1260a90f7e98SDmitry Torokhov ts->input = input_dev; 1261ffa458c1SDavid Brownell 12622991a1caSJason Wang mutex_init(&ts->lock); 12632991a1caSJason Wang init_waitqueue_head(&ts->wait); 12647de90a8cSImre Deak 1265a608026eSDaniel Mack pdata = dev_get_platdata(&spi->dev); 1266a608026eSDaniel Mack if (!pdata) { 1267a608026eSDaniel Mack pdata = ads7846_probe_dt(&spi->dev); 1268a1cd3fd0SPramod Gurav if (IS_ERR(pdata)) { 1269a1cd3fd0SPramod Gurav err = PTR_ERR(pdata); 1270a1cd3fd0SPramod Gurav goto err_free_mem; 1271a1cd3fd0SPramod Gurav } 1272a608026eSDaniel Mack } 1273a608026eSDaniel Mack 1274ffa458c1SDavid Brownell ts->model = pdata->model ? : 7846; 1275ffa458c1SDavid Brownell ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; 1276ffa458c1SDavid Brownell ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; 1277a608026eSDaniel Mack ts->vref_mv = pdata->vref_mv; 1278a608026eSDaniel Mack 1279da970e69SImre Deak if (pdata->filter != NULL) { 1280da970e69SImre Deak if (pdata->filter_init != NULL) { 1281da970e69SImre Deak err = pdata->filter_init(pdata, &ts->filter_data); 1282da970e69SImre Deak if (err < 0) 1283da970e69SImre Deak goto err_free_mem; 1284da970e69SImre Deak } 1285da970e69SImre Deak ts->filter = pdata->filter; 1286da970e69SImre Deak ts->filter_cleanup = pdata->filter_cleanup; 1287da970e69SImre Deak } else if (pdata->debounce_max) { 1288d5b415c9SImre Deak ts->debounce_max = pdata->debounce_max; 1289da970e69SImre Deak if (ts->debounce_max < 2) 1290da970e69SImre Deak ts->debounce_max = 2; 1291d5b415c9SImre Deak ts->debounce_tol = pdata->debounce_tol; 1292d5b415c9SImre Deak ts->debounce_rep = pdata->debounce_rep; 12932991a1caSJason Wang ts->filter = ads7846_debounce_filter; 1294da970e69SImre Deak ts->filter_data = ts; 12952991a1caSJason Wang } else { 1296da970e69SImre Deak ts->filter = ads7846_no_filter; 12972991a1caSJason Wang } 12984d5975e5SEric Miao 129957691a1eSDmitry Torokhov err = ads7846_setup_pendown(spi, ts, pdata); 13004d5975e5SEric Miao if (err) 13014d5975e5SEric Miao goto err_cleanup_filter; 1302ffa458c1SDavid Brownell 13031d25891fSSemih Hazar if (pdata->penirq_recheck_delay_usecs) 13041d25891fSSemih Hazar ts->penirq_recheck_delay_usecs = 13051d25891fSSemih Hazar pdata->penirq_recheck_delay_usecs; 13061d25891fSSemih Hazar 1307fd746d54SEric Miao ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; 1308fd746d54SEric Miao 1309a6c2490fSKay Sievers snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); 1310b58895f8SMichael Roth snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model); 1311ffa458c1SDavid Brownell 1312b58895f8SMichael Roth input_dev->name = ts->name; 1313a90f7e98SDmitry Torokhov input_dev->phys = ts->phys; 1314a5394fb0SDmitry Torokhov input_dev->dev.parent = &spi->dev; 1315ffa458c1SDavid Brownell 13167b19ada2SJiri Slaby input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 13177b19ada2SJiri Slaby input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 1318a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_X, 1319ffa458c1SDavid Brownell pdata->x_min ? : 0, 1320ffa458c1SDavid Brownell pdata->x_max ? : MAX_12BIT, 1321ffa458c1SDavid Brownell 0, 0); 1322a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_Y, 1323ffa458c1SDavid Brownell pdata->y_min ? : 0, 1324ffa458c1SDavid Brownell pdata->y_max ? : MAX_12BIT, 1325ffa458c1SDavid Brownell 0, 0); 1326a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_PRESSURE, 1327ffa458c1SDavid Brownell pdata->pressure_min, pdata->pressure_max, 0, 0); 1328ffa458c1SDavid Brownell 1329a2f99330SMarco Felsch /* 1330a2f99330SMarco Felsch * Parse common framework properties. Must be done here to ensure the 1331a2f99330SMarco Felsch * correct behaviour in case of using the legacy vendor bindings. The 1332a2f99330SMarco Felsch * general binding value overrides the vendor specific one. 1333a2f99330SMarco Felsch */ 1334a2f99330SMarco Felsch touchscreen_parse_properties(ts->input, false, &ts->core_prop); 1335a2f99330SMarco Felsch ts->pressure_max = input_abs_get_max(input_dev, ABS_PRESSURE) ? : ~0; 1336a2f99330SMarco Felsch 1337a2f99330SMarco Felsch /* 1338a2f99330SMarco Felsch * Check if legacy ti,swap-xy binding is used instead of 1339a2f99330SMarco Felsch * touchscreen-swapped-x-y 1340a2f99330SMarco Felsch */ 1341a2f99330SMarco Felsch if (!ts->core_prop.swap_x_y && pdata->swap_xy) { 1342a2f99330SMarco Felsch swap(input_dev->absinfo[ABS_X], input_dev->absinfo[ABS_Y]); 1343a2f99330SMarco Felsch ts->core_prop.swap_x_y = true; 1344a2f99330SMarco Felsch } 1345a2f99330SMarco Felsch 13462991a1caSJason Wang ads7846_setup_spi_msg(ts, pdata); 1347d5b415c9SImre Deak 134891143379SGrazvydas Ignotas ts->reg = regulator_get(&spi->dev, "vcc"); 134991143379SGrazvydas Ignotas if (IS_ERR(ts->reg)) { 1350067fb2f6SKevin Hilman err = PTR_ERR(ts->reg); 135156960b36SDmitry Torokhov dev_err(&spi->dev, "unable to get regulator: %d\n", err); 135291143379SGrazvydas Ignotas goto err_free_gpio; 135391143379SGrazvydas Ignotas } 135491143379SGrazvydas Ignotas 135591143379SGrazvydas Ignotas err = regulator_enable(ts->reg); 135691143379SGrazvydas Ignotas if (err) { 135791143379SGrazvydas Ignotas dev_err(&spi->dev, "unable to enable regulator: %d\n", err); 135891143379SGrazvydas Ignotas goto err_put_regulator; 135991143379SGrazvydas Ignotas } 136091143379SGrazvydas Ignotas 13610f622bf4SDmitry Torokhov irq_flags = pdata->irq_flags ? : IRQF_TRIGGER_FALLING; 13622991a1caSJason Wang irq_flags |= IRQF_ONESHOT; 13637804302bSAnatolij Gustschin 13642991a1caSJason Wang err = request_threaded_irq(spi->irq, ads7846_hard_irq, ads7846_irq, 13652991a1caSJason Wang irq_flags, spi->dev.driver->name, ts); 13660f622bf4SDmitry Torokhov if (err && !pdata->irq_flags) { 1367c57c0a2aSMichael Roth dev_info(&spi->dev, 1368c57c0a2aSMichael Roth "trying pin change workaround on irq %d\n", spi->irq); 13692991a1caSJason Wang irq_flags |= IRQF_TRIGGER_RISING; 13702991a1caSJason Wang err = request_threaded_irq(spi->irq, 13712991a1caSJason Wang ads7846_hard_irq, ads7846_irq, 13722991a1caSJason Wang irq_flags, spi->dev.driver->name, ts); 13730f622bf4SDmitry Torokhov } 13740f622bf4SDmitry Torokhov 1375c57c0a2aSMichael Roth if (err) { 13762e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); 137791143379SGrazvydas Ignotas goto err_disable_regulator; 1378ffa458c1SDavid Brownell } 1379ffa458c1SDavid Brownell 13802c8dc071SDavid Brownell err = ads784x_hwmon_register(spi, ts); 13812c8dc071SDavid Brownell if (err) 13822c8dc071SDavid Brownell goto err_free_irq; 13832c8dc071SDavid Brownell 13842e5a7bd9SDavid Brownell dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); 1385ffa458c1SDavid Brownell 13862991a1caSJason Wang /* 13872991a1caSJason Wang * Take a first sample, leaving nPENIRQ active and vREF off; avoid 1388ffa458c1SDavid Brownell * the touchscreen, in case it's not connected. 1389ffa458c1SDavid Brownell */ 13903eac5c7eSAnatolij Gustschin if (ts->model == 7845) 13913eac5c7eSAnatolij Gustschin ads7845_read12_ser(&spi->dev, PWRDOWN); 13923eac5c7eSAnatolij Gustschin else 1393ebcaaad9SAlexander Stein (void) ads7846_read12_ser(&spi->dev, READ_12BIT_SER(vaux)); 1394ffa458c1SDavid Brownell 13952c8dc071SDavid Brownell err = sysfs_create_group(&spi->dev.kobj, &ads784x_attr_group); 13968dd51650SDmitry Torokhov if (err) 13972c8dc071SDavid Brownell goto err_remove_hwmon; 13987de90a8cSImre Deak 1399a90f7e98SDmitry Torokhov err = input_register_device(input_dev); 1400a90f7e98SDmitry Torokhov if (err) 14018dd51650SDmitry Torokhov goto err_remove_attr_group; 1402a90f7e98SDmitry Torokhov 1403fdba2bb1SRanjith Lohithakshan device_init_wakeup(&spi->dev, pdata->wakeup); 1404fdba2bb1SRanjith Lohithakshan 1405a608026eSDaniel Mack /* 1406a608026eSDaniel Mack * If device does not carry platform data we must have allocated it 1407a608026eSDaniel Mack * when parsing DT data. 1408a608026eSDaniel Mack */ 1409a608026eSDaniel Mack if (!dev_get_platdata(&spi->dev)) 1410a608026eSDaniel Mack devm_kfree(&spi->dev, (void *)pdata); 1411a608026eSDaniel Mack 1412ffa458c1SDavid Brownell return 0; 1413a90f7e98SDmitry Torokhov 14148dd51650SDmitry Torokhov err_remove_attr_group: 14152c8dc071SDavid Brownell sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group); 14162c8dc071SDavid Brownell err_remove_hwmon: 14172c8dc071SDavid Brownell ads784x_hwmon_unregister(spi, ts); 14188dd51650SDmitry Torokhov err_free_irq: 1419a90f7e98SDmitry Torokhov free_irq(spi->irq, ts); 142091143379SGrazvydas Ignotas err_disable_regulator: 142191143379SGrazvydas Ignotas regulator_disable(ts->reg); 142291143379SGrazvydas Ignotas err_put_regulator: 142391143379SGrazvydas Ignotas regulator_put(ts->reg); 14244d5975e5SEric Miao err_free_gpio: 14250fbc9fdbSDmitry Torokhov if (!ts->get_pendown_state) 14264d5975e5SEric Miao gpio_free(ts->gpio_pendown); 1427da970e69SImre Deak err_cleanup_filter: 1428da970e69SImre Deak if (ts->filter_cleanup) 1429da970e69SImre Deak ts->filter_cleanup(ts->filter_data); 1430a90f7e98SDmitry Torokhov err_free_mem: 1431a90f7e98SDmitry Torokhov input_free_device(input_dev); 1432e8f462d2SDmitry Torokhov kfree(packet); 1433a90f7e98SDmitry Torokhov kfree(ts); 1434a90f7e98SDmitry Torokhov return err; 1435ffa458c1SDavid Brownell } 1436ffa458c1SDavid Brownell 1437e2619cf7SBill Pemberton static int ads7846_remove(struct spi_device *spi) 1438ffa458c1SDavid Brownell { 1439c12454faSJingoo Han struct ads7846 *ts = spi_get_drvdata(spi); 1440ffa458c1SDavid Brownell 14412c8dc071SDavid Brownell sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group); 1442ffa458c1SDavid Brownell 14432991a1caSJason Wang ads7846_disable(ts); 14447de90a8cSImre Deak free_irq(ts->spi->irq, ts); 14452991a1caSJason Wang 14462991a1caSJason Wang input_unregister_device(ts->input); 14472991a1caSJason Wang 14482991a1caSJason Wang ads784x_hwmon_unregister(spi, ts); 14497de90a8cSImre Deak 145091143379SGrazvydas Ignotas regulator_put(ts->reg); 145191143379SGrazvydas Ignotas 14520fbc9fdbSDmitry Torokhov if (!ts->get_pendown_state) { 14530fbc9fdbSDmitry Torokhov /* 14540fbc9fdbSDmitry Torokhov * If we are not using specialized pendown method we must 14550fbc9fdbSDmitry Torokhov * have been relying on gpio we set up ourselves. 14560fbc9fdbSDmitry Torokhov */ 14574d5975e5SEric Miao gpio_free(ts->gpio_pendown); 14580fbc9fdbSDmitry Torokhov } 14594d5975e5SEric Miao 1460da970e69SImre Deak if (ts->filter_cleanup) 1461da970e69SImre Deak ts->filter_cleanup(ts->filter_data); 1462da970e69SImre Deak 1463e8f462d2SDmitry Torokhov kfree(ts->packet); 1464ffa458c1SDavid Brownell kfree(ts); 1465ffa458c1SDavid Brownell 14662e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "unregistered touchscreen\n"); 14672991a1caSJason Wang 1468ffa458c1SDavid Brownell return 0; 1469ffa458c1SDavid Brownell } 1470ffa458c1SDavid Brownell 14712e5a7bd9SDavid Brownell static struct spi_driver ads7846_driver = { 14722e5a7bd9SDavid Brownell .driver = { 1473ffa458c1SDavid Brownell .name = "ads7846", 14743c36e719SMark Brown .pm = &ads7846_pm, 1475a608026eSDaniel Mack .of_match_table = of_match_ptr(ads7846_dt_ids), 14762e5a7bd9SDavid Brownell }, 1477ffa458c1SDavid Brownell .probe = ads7846_probe, 14781cb0aa88SBill Pemberton .remove = ads7846_remove, 1479ffa458c1SDavid Brownell }; 1480ffa458c1SDavid Brownell 1481ca83922eSAxel Lin module_spi_driver(ads7846_driver); 1482ffa458c1SDavid Brownell 1483ffa458c1SDavid Brownell MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); 1484ffa458c1SDavid Brownell MODULE_LICENSE("GPL"); 1485e0626e38SAnton Vorontsov MODULE_ALIAS("spi:ads7846"); 1486