155c04de5SPatil, Rachna /* 255c04de5SPatil, Rachna * TI Touch Screen driver 355c04de5SPatil, Rachna * 455c04de5SPatil, Rachna * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ 555c04de5SPatil, Rachna * 655c04de5SPatil, Rachna * This program is free software; you can redistribute it and/or 755c04de5SPatil, Rachna * modify it under the terms of the GNU General Public License as 855c04de5SPatil, Rachna * published by the Free Software Foundation version 2. 955c04de5SPatil, Rachna * 1055c04de5SPatil, Rachna * This program is distributed "as is" WITHOUT ANY WARRANTY of any 1155c04de5SPatil, Rachna * kind, whether express or implied; without even the implied warranty 1255c04de5SPatil, Rachna * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1355c04de5SPatil, Rachna * GNU General Public License for more details. 1455c04de5SPatil, Rachna */ 1555c04de5SPatil, Rachna 1655c04de5SPatil, Rachna 1755c04de5SPatil, Rachna #include <linux/init.h> 1855c04de5SPatil, Rachna #include <linux/kernel.h> 1955c04de5SPatil, Rachna #include <linux/err.h> 2055c04de5SPatil, Rachna #include <linux/module.h> 2155c04de5SPatil, Rachna #include <linux/input.h> 2255c04de5SPatil, Rachna #include <linux/slab.h> 2355c04de5SPatil, Rachna #include <linux/interrupt.h> 2455c04de5SPatil, Rachna #include <linux/clk.h> 2555c04de5SPatil, Rachna #include <linux/platform_device.h> 2655c04de5SPatil, Rachna #include <linux/io.h> 2755c04de5SPatil, Rachna #include <linux/input/ti_am335x_tsc.h> 2855c04de5SPatil, Rachna #include <linux/delay.h> 2955c04de5SPatil, Rachna 302b99bafaSPatil, Rachna #include <linux/mfd/ti_am335x_tscadc.h> 3155c04de5SPatil, Rachna 3255c04de5SPatil, Rachna #define ADCFSM_STEPID 0x10 3355c04de5SPatil, Rachna #define SEQ_SETTLE 275 3455c04de5SPatil, Rachna #define MAX_12BIT ((1 << 12) - 1) 3555c04de5SPatil, Rachna 36*bb76dc09SPatil, Rachna static const int config_pins[] = { 37*bb76dc09SPatil, Rachna STEPCONFIG_XPP, 38*bb76dc09SPatil, Rachna STEPCONFIG_XNN, 39*bb76dc09SPatil, Rachna STEPCONFIG_YPP, 40*bb76dc09SPatil, Rachna STEPCONFIG_YNN, 41*bb76dc09SPatil, Rachna }; 42*bb76dc09SPatil, Rachna 4355c04de5SPatil, Rachna struct titsc { 4455c04de5SPatil, Rachna struct input_dev *input; 452b99bafaSPatil, Rachna struct ti_tscadc_dev *mfd_tscadc; 4655c04de5SPatil, Rachna unsigned int irq; 4755c04de5SPatil, Rachna unsigned int wires; 4855c04de5SPatil, Rachna unsigned int x_plate_resistance; 4955c04de5SPatil, Rachna bool pen_down; 5055c04de5SPatil, Rachna int steps_to_configure; 51*bb76dc09SPatil, Rachna u32 config_inp[4]; 52*bb76dc09SPatil, Rachna u32 bit_xp, bit_xn, bit_yp, bit_yn; 53*bb76dc09SPatil, Rachna u32 inp_xp, inp_xn, inp_yp, inp_yn; 5455c04de5SPatil, Rachna }; 5555c04de5SPatil, Rachna 5655c04de5SPatil, Rachna static unsigned int titsc_readl(struct titsc *ts, unsigned int reg) 5755c04de5SPatil, Rachna { 582b99bafaSPatil, Rachna return readl(ts->mfd_tscadc->tscadc_base + reg); 5955c04de5SPatil, Rachna } 6055c04de5SPatil, Rachna 6155c04de5SPatil, Rachna static void titsc_writel(struct titsc *tsc, unsigned int reg, 6255c04de5SPatil, Rachna unsigned int val) 6355c04de5SPatil, Rachna { 642b99bafaSPatil, Rachna writel(val, tsc->mfd_tscadc->tscadc_base + reg); 6555c04de5SPatil, Rachna } 6655c04de5SPatil, Rachna 67*bb76dc09SPatil, Rachna static int titsc_config_wires(struct titsc *ts_dev) 68*bb76dc09SPatil, Rachna { 69*bb76dc09SPatil, Rachna u32 analog_line[4]; 70*bb76dc09SPatil, Rachna u32 wire_order[4]; 71*bb76dc09SPatil, Rachna int i, bit_cfg; 72*bb76dc09SPatil, Rachna 73*bb76dc09SPatil, Rachna for (i = 0; i < 4; i++) { 74*bb76dc09SPatil, Rachna /* 75*bb76dc09SPatil, Rachna * Get the order in which TSC wires are attached 76*bb76dc09SPatil, Rachna * w.r.t. each of the analog input lines on the EVM. 77*bb76dc09SPatil, Rachna */ 78*bb76dc09SPatil, Rachna analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4; 79*bb76dc09SPatil, Rachna wire_order[i] = ts_dev->config_inp[i] & 0x0F; 80*bb76dc09SPatil, Rachna if (WARN_ON(analog_line[i] > 7)) 81*bb76dc09SPatil, Rachna return -EINVAL; 82*bb76dc09SPatil, Rachna if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins))) 83*bb76dc09SPatil, Rachna return -EINVAL; 84*bb76dc09SPatil, Rachna } 85*bb76dc09SPatil, Rachna 86*bb76dc09SPatil, Rachna for (i = 0; i < 4; i++) { 87*bb76dc09SPatil, Rachna int an_line; 88*bb76dc09SPatil, Rachna int wi_order; 89*bb76dc09SPatil, Rachna 90*bb76dc09SPatil, Rachna an_line = analog_line[i]; 91*bb76dc09SPatil, Rachna wi_order = wire_order[i]; 92*bb76dc09SPatil, Rachna bit_cfg = config_pins[wi_order]; 93*bb76dc09SPatil, Rachna if (bit_cfg == 0) 94*bb76dc09SPatil, Rachna return -EINVAL; 95*bb76dc09SPatil, Rachna switch (wi_order) { 96*bb76dc09SPatil, Rachna case 0: 97*bb76dc09SPatil, Rachna ts_dev->bit_xp = bit_cfg; 98*bb76dc09SPatil, Rachna ts_dev->inp_xp = an_line; 99*bb76dc09SPatil, Rachna break; 100*bb76dc09SPatil, Rachna 101*bb76dc09SPatil, Rachna case 1: 102*bb76dc09SPatil, Rachna ts_dev->bit_xn = bit_cfg; 103*bb76dc09SPatil, Rachna ts_dev->inp_xn = an_line; 104*bb76dc09SPatil, Rachna break; 105*bb76dc09SPatil, Rachna 106*bb76dc09SPatil, Rachna case 2: 107*bb76dc09SPatil, Rachna ts_dev->bit_yp = bit_cfg; 108*bb76dc09SPatil, Rachna ts_dev->inp_yp = an_line; 109*bb76dc09SPatil, Rachna break; 110*bb76dc09SPatil, Rachna case 3: 111*bb76dc09SPatil, Rachna ts_dev->bit_yn = bit_cfg; 112*bb76dc09SPatil, Rachna ts_dev->inp_yn = an_line; 113*bb76dc09SPatil, Rachna break; 114*bb76dc09SPatil, Rachna } 115*bb76dc09SPatil, Rachna } 116*bb76dc09SPatil, Rachna return 0; 117*bb76dc09SPatil, Rachna } 118*bb76dc09SPatil, Rachna 11955c04de5SPatil, Rachna static void titsc_step_config(struct titsc *ts_dev) 12055c04de5SPatil, Rachna { 12155c04de5SPatil, Rachna unsigned int config; 122abeccee4SPatil, Rachna unsigned int stepenable = 0; 12355c04de5SPatil, Rachna int i, total_steps; 12455c04de5SPatil, Rachna 12555c04de5SPatil, Rachna /* Configure the Step registers */ 12655c04de5SPatil, Rachna total_steps = 2 * ts_dev->steps_to_configure; 12755c04de5SPatil, Rachna 12855c04de5SPatil, Rachna config = STEPCONFIG_MODE_HWSYNC | 129*bb76dc09SPatil, Rachna STEPCONFIG_AVG_16 | ts_dev->bit_xp; 13055c04de5SPatil, Rachna switch (ts_dev->wires) { 13155c04de5SPatil, Rachna case 4: 132*bb76dc09SPatil, Rachna config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; 13355c04de5SPatil, Rachna break; 13455c04de5SPatil, Rachna case 5: 135*bb76dc09SPatil, Rachna config |= ts_dev->bit_yn | 136*bb76dc09SPatil, Rachna STEPCONFIG_INP_AN4 | ts_dev->bit_xn | 137*bb76dc09SPatil, Rachna ts_dev->bit_yp; 13855c04de5SPatil, Rachna break; 13955c04de5SPatil, Rachna case 8: 140*bb76dc09SPatil, Rachna config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; 14155c04de5SPatil, Rachna break; 14255c04de5SPatil, Rachna } 14355c04de5SPatil, Rachna 14455c04de5SPatil, Rachna for (i = 1; i <= ts_dev->steps_to_configure; i++) { 14555c04de5SPatil, Rachna titsc_writel(ts_dev, REG_STEPCONFIG(i), config); 14655c04de5SPatil, Rachna titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); 14755c04de5SPatil, Rachna } 14855c04de5SPatil, Rachna 14955c04de5SPatil, Rachna config = 0; 15055c04de5SPatil, Rachna config = STEPCONFIG_MODE_HWSYNC | 151*bb76dc09SPatil, Rachna STEPCONFIG_AVG_16 | ts_dev->bit_yn | 15255c04de5SPatil, Rachna STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1; 15355c04de5SPatil, Rachna switch (ts_dev->wires) { 15455c04de5SPatil, Rachna case 4: 155*bb76dc09SPatil, Rachna config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); 15655c04de5SPatil, Rachna break; 15755c04de5SPatil, Rachna case 5: 158*bb76dc09SPatil, Rachna config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 | 159*bb76dc09SPatil, Rachna ts_dev->bit_xn | ts_dev->bit_yp; 16055c04de5SPatil, Rachna break; 16155c04de5SPatil, Rachna case 8: 162*bb76dc09SPatil, Rachna config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); 16355c04de5SPatil, Rachna break; 16455c04de5SPatil, Rachna } 16555c04de5SPatil, Rachna 16655c04de5SPatil, Rachna for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) { 16755c04de5SPatil, Rachna titsc_writel(ts_dev, REG_STEPCONFIG(i), config); 16855c04de5SPatil, Rachna titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); 16955c04de5SPatil, Rachna } 17055c04de5SPatil, Rachna 17155c04de5SPatil, Rachna config = 0; 17255c04de5SPatil, Rachna /* Charge step configuration */ 173*bb76dc09SPatil, Rachna config = ts_dev->bit_xp | ts_dev->bit_yn | 17455c04de5SPatil, Rachna STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | 175*bb76dc09SPatil, Rachna STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp); 17655c04de5SPatil, Rachna 17755c04de5SPatil, Rachna titsc_writel(ts_dev, REG_CHARGECONFIG, config); 17855c04de5SPatil, Rachna titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); 17955c04de5SPatil, Rachna 18055c04de5SPatil, Rachna config = 0; 18155c04de5SPatil, Rachna /* Configure to calculate pressure */ 18255c04de5SPatil, Rachna config = STEPCONFIG_MODE_HWSYNC | 183*bb76dc09SPatil, Rachna STEPCONFIG_AVG_16 | ts_dev->bit_yp | 184*bb76dc09SPatil, Rachna ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM | 185*bb76dc09SPatil, Rachna STEPCONFIG_INP(ts_dev->inp_xp); 18655c04de5SPatil, Rachna titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config); 18755c04de5SPatil, Rachna titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1), 18855c04de5SPatil, Rachna STEPCONFIG_OPENDLY); 18955c04de5SPatil, Rachna 190*bb76dc09SPatil, Rachna config |= STEPCONFIG_INP(ts_dev->inp_yn) | STEPCONFIG_FIFO1; 19155c04de5SPatil, Rachna titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config); 19255c04de5SPatil, Rachna titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), 19355c04de5SPatil, Rachna STEPCONFIG_OPENDLY); 19455c04de5SPatil, Rachna 195abeccee4SPatil, Rachna /* The steps1 … end and bit 0 for TS_Charge */ 196abeccee4SPatil, Rachna stepenable = (1 << (total_steps + 2)) - 1; 197abeccee4SPatil, Rachna am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable); 19855c04de5SPatil, Rachna } 19955c04de5SPatil, Rachna 20055c04de5SPatil, Rachna static void titsc_read_coordinates(struct titsc *ts_dev, 20155c04de5SPatil, Rachna unsigned int *x, unsigned int *y) 20255c04de5SPatil, Rachna { 20355c04de5SPatil, Rachna unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT); 20455c04de5SPatil, Rachna unsigned int prev_val_x = ~0, prev_val_y = ~0; 20555c04de5SPatil, Rachna unsigned int prev_diff_x = ~0, prev_diff_y = ~0; 20655c04de5SPatil, Rachna unsigned int read, diff; 2072b99bafaSPatil, Rachna unsigned int i, channel; 20855c04de5SPatil, Rachna 20955c04de5SPatil, Rachna /* 21055c04de5SPatil, Rachna * Delta filter is used to remove large variations in sampled 21155c04de5SPatil, Rachna * values from ADC. The filter tries to predict where the next 21255c04de5SPatil, Rachna * coordinate could be. This is done by taking a previous 21355c04de5SPatil, Rachna * coordinate and subtracting it form current one. Further the 21455c04de5SPatil, Rachna * algorithm compares the difference with that of a present value, 21555c04de5SPatil, Rachna * if true the value is reported to the sub system. 21655c04de5SPatil, Rachna */ 21755c04de5SPatil, Rachna for (i = 0; i < fifocount - 1; i++) { 2182b99bafaSPatil, Rachna read = titsc_readl(ts_dev, REG_FIFO0); 2192b99bafaSPatil, Rachna channel = read & 0xf0000; 2202b99bafaSPatil, Rachna channel = channel >> 0x10; 2212b99bafaSPatil, Rachna if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) { 2222b99bafaSPatil, Rachna read &= 0xfff; 22355c04de5SPatil, Rachna diff = abs(read - prev_val_x); 22455c04de5SPatil, Rachna if (diff < prev_diff_x) { 22555c04de5SPatil, Rachna prev_diff_x = diff; 22655c04de5SPatil, Rachna *x = read; 22755c04de5SPatil, Rachna } 22855c04de5SPatil, Rachna prev_val_x = read; 2292b99bafaSPatil, Rachna } 23055c04de5SPatil, Rachna 2312b99bafaSPatil, Rachna read = titsc_readl(ts_dev, REG_FIFO1); 2322b99bafaSPatil, Rachna channel = read & 0xf0000; 2332b99bafaSPatil, Rachna channel = channel >> 0x10; 2342b99bafaSPatil, Rachna if ((channel >= ts_dev->steps_to_configure) && 2352b99bafaSPatil, Rachna (channel < (2 * ts_dev->steps_to_configure - 1))) { 2362b99bafaSPatil, Rachna read &= 0xfff; 23755c04de5SPatil, Rachna diff = abs(read - prev_val_y); 23855c04de5SPatil, Rachna if (diff < prev_diff_y) { 23955c04de5SPatil, Rachna prev_diff_y = diff; 24055c04de5SPatil, Rachna *y = read; 24155c04de5SPatil, Rachna } 24255c04de5SPatil, Rachna prev_val_y = read; 24355c04de5SPatil, Rachna } 24455c04de5SPatil, Rachna } 2452b99bafaSPatil, Rachna } 24655c04de5SPatil, Rachna 24755c04de5SPatil, Rachna static irqreturn_t titsc_irq(int irq, void *dev) 24855c04de5SPatil, Rachna { 24955c04de5SPatil, Rachna struct titsc *ts_dev = dev; 25055c04de5SPatil, Rachna struct input_dev *input_dev = ts_dev->input; 25155c04de5SPatil, Rachna unsigned int status, irqclr = 0; 25255c04de5SPatil, Rachna unsigned int x = 0, y = 0; 25355c04de5SPatil, Rachna unsigned int z1, z2, z; 25455c04de5SPatil, Rachna unsigned int fsm; 2552b99bafaSPatil, Rachna unsigned int fifo1count, fifo0count; 2562b99bafaSPatil, Rachna int i; 25755c04de5SPatil, Rachna 25855c04de5SPatil, Rachna status = titsc_readl(ts_dev, REG_IRQSTATUS); 25955c04de5SPatil, Rachna if (status & IRQENB_FIFO0THRES) { 26055c04de5SPatil, Rachna titsc_read_coordinates(ts_dev, &x, &y); 26155c04de5SPatil, Rachna 26255c04de5SPatil, Rachna z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff; 26355c04de5SPatil, Rachna z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff; 26455c04de5SPatil, Rachna 2652b99bafaSPatil, Rachna fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT); 2662b99bafaSPatil, Rachna for (i = 0; i < fifo1count; i++) 2672b99bafaSPatil, Rachna titsc_readl(ts_dev, REG_FIFO1); 2682b99bafaSPatil, Rachna 2692b99bafaSPatil, Rachna fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT); 2702b99bafaSPatil, Rachna for (i = 0; i < fifo0count; i++) 2712b99bafaSPatil, Rachna titsc_readl(ts_dev, REG_FIFO0); 2722b99bafaSPatil, Rachna 27355c04de5SPatil, Rachna if (ts_dev->pen_down && z1 != 0 && z2 != 0) { 27455c04de5SPatil, Rachna /* 27555c04de5SPatil, Rachna * Calculate pressure using formula 27655c04de5SPatil, Rachna * Resistance(touch) = x plate resistance * 27755c04de5SPatil, Rachna * x postion/4096 * ((z2 / z1) - 1) 27855c04de5SPatil, Rachna */ 27955c04de5SPatil, Rachna z = z2 - z1; 28055c04de5SPatil, Rachna z *= x; 28155c04de5SPatil, Rachna z *= ts_dev->x_plate_resistance; 28255c04de5SPatil, Rachna z /= z1; 28355c04de5SPatil, Rachna z = (z + 2047) >> 12; 28455c04de5SPatil, Rachna 28555c04de5SPatil, Rachna if (z <= MAX_12BIT) { 28655c04de5SPatil, Rachna input_report_abs(input_dev, ABS_X, x); 28755c04de5SPatil, Rachna input_report_abs(input_dev, ABS_Y, y); 28855c04de5SPatil, Rachna input_report_abs(input_dev, ABS_PRESSURE, z); 28955c04de5SPatil, Rachna input_report_key(input_dev, BTN_TOUCH, 1); 29055c04de5SPatil, Rachna input_sync(input_dev); 29155c04de5SPatil, Rachna } 29255c04de5SPatil, Rachna } 29355c04de5SPatil, Rachna irqclr |= IRQENB_FIFO0THRES; 29455c04de5SPatil, Rachna } 29555c04de5SPatil, Rachna 29655c04de5SPatil, Rachna /* 29755c04de5SPatil, Rachna * Time for sequencer to settle, to read 29855c04de5SPatil, Rachna * correct state of the sequencer. 29955c04de5SPatil, Rachna */ 30055c04de5SPatil, Rachna udelay(SEQ_SETTLE); 30155c04de5SPatil, Rachna 30255c04de5SPatil, Rachna status = titsc_readl(ts_dev, REG_RAWIRQSTATUS); 30355c04de5SPatil, Rachna if (status & IRQENB_PENUP) { 30455c04de5SPatil, Rachna /* Pen up event */ 30555c04de5SPatil, Rachna fsm = titsc_readl(ts_dev, REG_ADCFSM); 30655c04de5SPatil, Rachna if (fsm == ADCFSM_STEPID) { 30755c04de5SPatil, Rachna ts_dev->pen_down = false; 30855c04de5SPatil, Rachna input_report_key(input_dev, BTN_TOUCH, 0); 30955c04de5SPatil, Rachna input_report_abs(input_dev, ABS_PRESSURE, 0); 31055c04de5SPatil, Rachna input_sync(input_dev); 31155c04de5SPatil, Rachna } else { 31255c04de5SPatil, Rachna ts_dev->pen_down = true; 31355c04de5SPatil, Rachna } 31455c04de5SPatil, Rachna irqclr |= IRQENB_PENUP; 31555c04de5SPatil, Rachna } 31655c04de5SPatil, Rachna 31755c04de5SPatil, Rachna titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); 31855c04de5SPatil, Rachna 319abeccee4SPatil, Rachna am335x_tsc_se_update(ts_dev->mfd_tscadc); 32055c04de5SPatil, Rachna return IRQ_HANDLED; 32155c04de5SPatil, Rachna } 32255c04de5SPatil, Rachna 32355c04de5SPatil, Rachna /* 32455c04de5SPatil, Rachna * The functions for inserting/removing driver as a module. 32555c04de5SPatil, Rachna */ 32655c04de5SPatil, Rachna 32731564cbdSLinus Torvalds static int titsc_probe(struct platform_device *pdev) 32855c04de5SPatil, Rachna { 32955c04de5SPatil, Rachna struct titsc *ts_dev; 33055c04de5SPatil, Rachna struct input_dev *input_dev; 331a9bce1b0SSebastian Andrzej Siewior struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); 3322b99bafaSPatil, Rachna struct mfd_tscadc_board *pdata; 33355c04de5SPatil, Rachna int err; 3342b99bafaSPatil, Rachna 3352b99bafaSPatil, Rachna pdata = tscadc_dev->dev->platform_data; 33655c04de5SPatil, Rachna 33755c04de5SPatil, Rachna if (!pdata) { 3382b99bafaSPatil, Rachna dev_err(&pdev->dev, "Could not find platform data\n"); 33955c04de5SPatil, Rachna return -EINVAL; 34055c04de5SPatil, Rachna } 34155c04de5SPatil, Rachna 34255c04de5SPatil, Rachna /* Allocate memory for device */ 34355c04de5SPatil, Rachna ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL); 34455c04de5SPatil, Rachna input_dev = input_allocate_device(); 34555c04de5SPatil, Rachna if (!ts_dev || !input_dev) { 34655c04de5SPatil, Rachna dev_err(&pdev->dev, "failed to allocate memory.\n"); 34755c04de5SPatil, Rachna err = -ENOMEM; 34855c04de5SPatil, Rachna goto err_free_mem; 34955c04de5SPatil, Rachna } 35055c04de5SPatil, Rachna 3512b99bafaSPatil, Rachna tscadc_dev->tsc = ts_dev; 3522b99bafaSPatil, Rachna ts_dev->mfd_tscadc = tscadc_dev; 35355c04de5SPatil, Rachna ts_dev->input = input_dev; 3542b99bafaSPatil, Rachna ts_dev->irq = tscadc_dev->irq; 3552b99bafaSPatil, Rachna ts_dev->wires = pdata->tsc_init->wires; 3562b99bafaSPatil, Rachna ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance; 3572b99bafaSPatil, Rachna ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure; 358*bb76dc09SPatil, Rachna memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config, 359*bb76dc09SPatil, Rachna sizeof(pdata->tsc_init->wire_config)); 36055c04de5SPatil, Rachna 36155c04de5SPatil, Rachna err = request_irq(ts_dev->irq, titsc_irq, 36255c04de5SPatil, Rachna 0, pdev->dev.driver->name, ts_dev); 36355c04de5SPatil, Rachna if (err) { 36455c04de5SPatil, Rachna dev_err(&pdev->dev, "failed to allocate irq.\n"); 3652b99bafaSPatil, Rachna goto err_free_mem; 36655c04de5SPatil, Rachna } 36755c04de5SPatil, Rachna 36855c04de5SPatil, Rachna titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); 369*bb76dc09SPatil, Rachna err = titsc_config_wires(ts_dev); 370*bb76dc09SPatil, Rachna if (err) { 371*bb76dc09SPatil, Rachna dev_err(&pdev->dev, "wrong i/p wire configuration\n"); 372*bb76dc09SPatil, Rachna goto err_free_irq; 373*bb76dc09SPatil, Rachna } 37455c04de5SPatil, Rachna titsc_step_config(ts_dev); 37555c04de5SPatil, Rachna titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure); 37655c04de5SPatil, Rachna 3772b99bafaSPatil, Rachna input_dev->name = "ti-tsc"; 37855c04de5SPatil, Rachna input_dev->dev.parent = &pdev->dev; 37955c04de5SPatil, Rachna 38055c04de5SPatil, Rachna input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 38155c04de5SPatil, Rachna input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 38255c04de5SPatil, Rachna 38355c04de5SPatil, Rachna input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); 38455c04de5SPatil, Rachna input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); 38555c04de5SPatil, Rachna input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); 38655c04de5SPatil, Rachna 38755c04de5SPatil, Rachna /* register to the input system */ 38855c04de5SPatil, Rachna err = input_register_device(input_dev); 38955c04de5SPatil, Rachna if (err) 3902b99bafaSPatil, Rachna goto err_free_irq; 39155c04de5SPatil, Rachna 39255c04de5SPatil, Rachna platform_set_drvdata(pdev, ts_dev); 39355c04de5SPatil, Rachna return 0; 39455c04de5SPatil, Rachna 39555c04de5SPatil, Rachna err_free_irq: 39655c04de5SPatil, Rachna free_irq(ts_dev->irq, ts_dev); 39755c04de5SPatil, Rachna err_free_mem: 39855c04de5SPatil, Rachna input_free_device(input_dev); 39955c04de5SPatil, Rachna kfree(ts_dev); 40055c04de5SPatil, Rachna return err; 40155c04de5SPatil, Rachna } 40255c04de5SPatil, Rachna 40331564cbdSLinus Torvalds static int titsc_remove(struct platform_device *pdev) 40455c04de5SPatil, Rachna { 405a9bce1b0SSebastian Andrzej Siewior struct titsc *ts_dev = platform_get_drvdata(pdev); 406a9bce1b0SSebastian Andrzej Siewior u32 steps; 40755c04de5SPatil, Rachna 40855c04de5SPatil, Rachna free_irq(ts_dev->irq, ts_dev); 40955c04de5SPatil, Rachna 410abeccee4SPatil, Rachna /* total steps followed by the enable mask */ 411abeccee4SPatil, Rachna steps = 2 * ts_dev->steps_to_configure + 2; 412abeccee4SPatil, Rachna steps = (1 << steps) - 1; 413abeccee4SPatil, Rachna am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps); 414abeccee4SPatil, Rachna 41555c04de5SPatil, Rachna input_unregister_device(ts_dev->input); 41655c04de5SPatil, Rachna 41755c04de5SPatil, Rachna platform_set_drvdata(pdev, NULL); 4182b99bafaSPatil, Rachna kfree(ts_dev); 41955c04de5SPatil, Rachna return 0; 42055c04de5SPatil, Rachna } 42155c04de5SPatil, Rachna 4222b99bafaSPatil, Rachna #ifdef CONFIG_PM 4232b99bafaSPatil, Rachna static int titsc_suspend(struct device *dev) 4242b99bafaSPatil, Rachna { 425a9bce1b0SSebastian Andrzej Siewior struct titsc *ts_dev = dev_get_drvdata(dev); 426a9bce1b0SSebastian Andrzej Siewior struct ti_tscadc_dev *tscadc_dev; 4272b99bafaSPatil, Rachna unsigned int idle; 4282b99bafaSPatil, Rachna 429a9bce1b0SSebastian Andrzej Siewior tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); 4302b99bafaSPatil, Rachna if (device_may_wakeup(tscadc_dev->dev)) { 4312b99bafaSPatil, Rachna idle = titsc_readl(ts_dev, REG_IRQENABLE); 4322b99bafaSPatil, Rachna titsc_writel(ts_dev, REG_IRQENABLE, 4332b99bafaSPatil, Rachna (idle | IRQENB_HW_PEN)); 4342b99bafaSPatil, Rachna titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB); 4352b99bafaSPatil, Rachna } 4362b99bafaSPatil, Rachna return 0; 4372b99bafaSPatil, Rachna } 4382b99bafaSPatil, Rachna 4392b99bafaSPatil, Rachna static int titsc_resume(struct device *dev) 4402b99bafaSPatil, Rachna { 441a9bce1b0SSebastian Andrzej Siewior struct titsc *ts_dev = dev_get_drvdata(dev); 442a9bce1b0SSebastian Andrzej Siewior struct ti_tscadc_dev *tscadc_dev; 4432b99bafaSPatil, Rachna 444a9bce1b0SSebastian Andrzej Siewior tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); 4452b99bafaSPatil, Rachna if (device_may_wakeup(tscadc_dev->dev)) { 4462b99bafaSPatil, Rachna titsc_writel(ts_dev, REG_IRQWAKEUP, 4472b99bafaSPatil, Rachna 0x00); 4482b99bafaSPatil, Rachna titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN); 4492b99bafaSPatil, Rachna } 4502b99bafaSPatil, Rachna titsc_step_config(ts_dev); 4512b99bafaSPatil, Rachna titsc_writel(ts_dev, REG_FIFO0THR, 4522b99bafaSPatil, Rachna ts_dev->steps_to_configure); 4532b99bafaSPatil, Rachna return 0; 4542b99bafaSPatil, Rachna } 4552b99bafaSPatil, Rachna 4562b99bafaSPatil, Rachna static const struct dev_pm_ops titsc_pm_ops = { 4572b99bafaSPatil, Rachna .suspend = titsc_suspend, 4582b99bafaSPatil, Rachna .resume = titsc_resume, 4592b99bafaSPatil, Rachna }; 4602b99bafaSPatil, Rachna #define TITSC_PM_OPS (&titsc_pm_ops) 4612b99bafaSPatil, Rachna #else 4622b99bafaSPatil, Rachna #define TITSC_PM_OPS NULL 4632b99bafaSPatil, Rachna #endif 4642b99bafaSPatil, Rachna 46555c04de5SPatil, Rachna static struct platform_driver ti_tsc_driver = { 46655c04de5SPatil, Rachna .probe = titsc_probe, 46731564cbdSLinus Torvalds .remove = titsc_remove, 46855c04de5SPatil, Rachna .driver = { 46955c04de5SPatil, Rachna .name = "tsc", 47055c04de5SPatil, Rachna .owner = THIS_MODULE, 4712b99bafaSPatil, Rachna .pm = TITSC_PM_OPS, 47255c04de5SPatil, Rachna }, 47355c04de5SPatil, Rachna }; 47455c04de5SPatil, Rachna module_platform_driver(ti_tsc_driver); 47555c04de5SPatil, Rachna 47655c04de5SPatil, Rachna MODULE_DESCRIPTION("TI touchscreen controller driver"); 47755c04de5SPatil, Rachna MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); 47855c04de5SPatil, Rachna MODULE_LICENSE("GPL"); 479