diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt index 801d58cb6d4d..46882058b59b 100644 --- a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt +++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt @@ -5,6 +5,12 @@ Required properties: - reg: Address and length of the register set for the device - interrupts: Should contain the LRADC interrupts +Optional properties: +- fsl,lradc-touchscreen-wires: Number of wires used to connect the touchscreen + to LRADC. Valid value is either 4 or 5. If this + property is not present, then the touchscreen is + disabled. + Examples: lradc@80050000 { diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index eca07045f4de..e4728712a1ad 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include @@ -59,6 +61,21 @@ #define LRADC_DELAY_TIMER_PER 200 #define LRADC_DELAY_TIMER_LOOP 5 +/* + * Once the pen touches the touchscreen, the touchscreen switches from + * IRQ-driven mode to polling mode to prevent interrupt storm. The polling + * is realized by worker thread, which is called every 20 or so milliseconds. + * This gives the touchscreen enough fluence and does not strain the system + * too much. + */ +#define LRADC_TS_SAMPLE_DELAY_MS 5 + +/* + * The LRADC reads the following amount of samples from each touchscreen + * channel and the driver then computes avarage of these. + */ +#define LRADC_TS_SAMPLE_AMOUNT 4 + static const char * const mxs_lradc_irq_name[] = { "mxs-lradc-touchscreen", "mxs-lradc-thresh0", @@ -75,6 +92,12 @@ static const char * const mxs_lradc_irq_name[] = { "mxs-lradc-button1", }; +enum mxs_lradc_ts { + MXS_LRADC_TOUCHSCREEN_NONE = 0, + MXS_LRADC_TOUCHSCREEN_4WIRE, + MXS_LRADC_TOUCHSCREEN_5WIRE, +}; + struct mxs_lradc { struct device *dev; void __iomem *base; @@ -86,21 +109,69 @@ struct mxs_lradc { struct mutex lock; struct completion completion; + + /* + * Touchscreen LRADC channels receives a private slot in the CTRL4 + * register, the slot #7. Therefore only 7 slots instead of 8 in the + * CTRL4 register can be mapped to LRADC channels when using the + * touchscreen. + * + * Furthermore, certain LRADC channels are shared between touchscreen + * and/or touch-buttons and generic LRADC block. Therefore when using + * either of these, these channels are not available for the regular + * sampling. The shared channels are as follows: + * + * CH0 -- Touch button #0 + * CH1 -- Touch button #1 + * CH2 -- Touch screen XPUL + * CH3 -- Touch screen YPLL + * CH4 -- Touch screen XNUL + * CH5 -- Touch screen YNLR + * CH6 -- Touch screen WIPER (5-wire only) + * + * The bitfields below represents which parts of the LRADC block are + * switched into special mode of operation. These channels can not + * be sampled as regular LRADC channels. The driver will refuse any + * attempt to sample these channels. + */ +#define CHAN_MASK_TOUCHBUTTON (0x3 << 0) +#define CHAN_MASK_TOUCHSCREEN_4WIRE (0xf << 2) +#define CHAN_MASK_TOUCHSCREEN_5WIRE (0x1f << 2) + enum mxs_lradc_ts use_touchscreen; + bool stop_touchscreen; + bool use_touchbutton; + + struct input_dev *ts_input; + struct work_struct ts_work; }; #define LRADC_CTRL0 0x00 -#define LRADC_CTRL0_TOUCH_DETECT_ENABLE (1 << 23) -#define LRADC_CTRL0_TOUCH_SCREEN_TYPE (1 << 22) +#define LRADC_CTRL0_TOUCH_DETECT_ENABLE (1 << 23) +#define LRADC_CTRL0_TOUCH_SCREEN_TYPE (1 << 22) +#define LRADC_CTRL0_YNNSW /* YM */ (1 << 21) +#define LRADC_CTRL0_YPNSW /* YP */ (1 << 20) +#define LRADC_CTRL0_YPPSW /* YP */ (1 << 19) +#define LRADC_CTRL0_XNNSW /* XM */ (1 << 18) +#define LRADC_CTRL0_XNPSW /* XM */ (1 << 17) +#define LRADC_CTRL0_XPPSW /* XP */ (1 << 16) +#define LRADC_CTRL0_PLATE_MASK (0x3f << 16) #define LRADC_CTRL1 0x10 -#define LRADC_CTRL1_LRADC_IRQ(n) (1 << (n)) -#define LRADC_CTRL1_LRADC_IRQ_MASK 0x1fff +#define LRADC_CTRL1_TOUCH_DETECT_IRQ_EN (1 << 24) #define LRADC_CTRL1_LRADC_IRQ_EN(n) (1 << ((n) + 16)) #define LRADC_CTRL1_LRADC_IRQ_EN_MASK (0x1fff << 16) +#define LRADC_CTRL1_LRADC_IRQ_EN_OFFSET 16 +#define LRADC_CTRL1_TOUCH_DETECT_IRQ (1 << 8) +#define LRADC_CTRL1_LRADC_IRQ(n) (1 << (n)) +#define LRADC_CTRL1_LRADC_IRQ_MASK 0x1fff +#define LRADC_CTRL1_LRADC_IRQ_OFFSET 0 #define LRADC_CTRL2 0x20 #define LRADC_CTRL2_TEMPSENSE_PWD (1 << 15) +#define LRADC_STATUS 0x40 +#define LRADC_STATUS_TOUCH_DETECT_RAW (1 << 0) + #define LRADC_CH(n) (0x50 + (0x10 * (n))) #define LRADC_CH_ACCUMULATE (1 << 29) #define LRADC_CH_NUM_SAMPLES_MASK (0x1f << 24) @@ -132,6 +203,7 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev, { struct mxs_lradc *lradc = iio_priv(iio_dev); int ret; + unsigned long mask; if (m != IIO_CHAN_INFO_RAW) return -EINVAL; @@ -140,6 +212,12 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev, if (chan->channel > LRADC_MAX_TOTAL_CHANS) return -EINVAL; + /* Validate the channel if it doesn't intersect with reserved chans. */ + bitmap_set(&mask, chan->channel, 1); + ret = iio_validate_scan_mask_onehot(iio_dev, &mask); + if (ret) + return -EINVAL; + /* * See if there is no buffered operation in progess. If there is, simply * bail out. This can be improved to support both buffered and raw IO at @@ -161,7 +239,11 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); - writel(chan->channel, lradc->base + LRADC_CTRL4); + /* Clean the slot's previous content, then set new one. */ + writel(LRADC_CTRL4_LRADCSELECT_MASK(0), + lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR); + writel(chan->channel, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET); + writel(0, lradc->base + LRADC_CH(0)); /* Enable the IRQ and start sampling the channel. */ @@ -194,6 +276,269 @@ static const struct iio_info mxs_lradc_iio_info = { .read_raw = mxs_lradc_read_raw, }; +/* + * Touchscreen handling + */ +enum lradc_ts_plate { + LRADC_SAMPLE_X, + LRADC_SAMPLE_Y, + LRADC_SAMPLE_PRESSURE, +}; + +static int mxs_lradc_ts_touched(struct mxs_lradc *lradc) +{ + uint32_t reg; + + /* Enable touch detection. */ + writel(LRADC_CTRL0_PLATE_MASK, + lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); + writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE, + lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); + + msleep(LRADC_TS_SAMPLE_DELAY_MS); + + reg = readl(lradc->base + LRADC_STATUS); + + return reg & LRADC_STATUS_TOUCH_DETECT_RAW; +} + +static int32_t mxs_lradc_ts_sample(struct mxs_lradc *lradc, + enum lradc_ts_plate plate, int change) +{ + unsigned long delay, jiff; + uint32_t reg, ctrl0 = 0, chan = 0; + /* The touchscreen always uses CTRL4 slot #7. */ + const uint8_t slot = 7; + uint32_t val; + + /* + * There are three correct configurations of the controller sampling + * the touchscreen, each of these configuration provides different + * information from the touchscreen. + * + * The following table describes the sampling configurations: + * +-------------+-------+-------+-------+ + * | Wire \ Axis | X | Y | Z | + * +---------------------+-------+-------+ + * | X+ (CH2) | HI | TS | TS | + * +-------------+-------+-------+-------+ + * | X- (CH4) | LO | SH | HI | + * +-------------+-------+-------+-------+ + * | Y+ (CH3) | SH | HI | HI | + * +-------------+-------+-------+-------+ + * | Y- (CH5) | TS | LO | SH | + * +-------------+-------+-------+-------+ + * + * HI ... strong '1' ; LO ... strong '0' + * SH ... sample here ; TS ... tri-state + * + * There are a few other ways of obtaining the Z coordinate + * (aka. pressure), but the one in the table seems to be the + * most reliable one. + */ + switch (plate) { + case LRADC_SAMPLE_X: + ctrl0 = LRADC_CTRL0_XPPSW | LRADC_CTRL0_XNNSW; + chan = 3; + break; + case LRADC_SAMPLE_Y: + ctrl0 = LRADC_CTRL0_YPPSW | LRADC_CTRL0_YNNSW; + chan = 4; + break; + case LRADC_SAMPLE_PRESSURE: + ctrl0 = LRADC_CTRL0_YPPSW | LRADC_CTRL0_XNNSW; + chan = 5; + break; + } + + if (change) { + writel(LRADC_CTRL0_PLATE_MASK, + lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); + writel(ctrl0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); + + writel(LRADC_CTRL4_LRADCSELECT_MASK(slot), + lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR); + writel(chan << LRADC_CTRL4_LRADCSELECT_OFFSET(slot), + lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET); + } + + writel(0xffffffff, lradc->base + LRADC_CH(slot) + STMP_OFFSET_REG_CLR); + writel(1 << slot, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); + + delay = jiffies + msecs_to_jiffies(LRADC_TS_SAMPLE_DELAY_MS); + do { + jiff = jiffies; + reg = readl_relaxed(lradc->base + LRADC_CTRL1); + if (reg & LRADC_CTRL1_LRADC_IRQ(slot)) + break; + } while (time_before(jiff, delay)); + + writel(LRADC_CTRL1_LRADC_IRQ(slot), + lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); + + if (time_after_eq(jiff, delay)) + return -ETIMEDOUT; + + val = readl(lradc->base + LRADC_CH(slot)); + val &= LRADC_CH_VALUE_MASK; + + return val; +} + +static int32_t mxs_lradc_ts_sample_filter(struct mxs_lradc *lradc, + enum lradc_ts_plate plate) +{ + int32_t val, tot = 0; + int i; + + val = mxs_lradc_ts_sample(lradc, plate, 1); + + /* Delay a bit so the touchscreen is stable. */ + mdelay(2); + + for (i = 0; i < LRADC_TS_SAMPLE_AMOUNT; i++) { + val = mxs_lradc_ts_sample(lradc, plate, 0); + tot += val; + } + + return tot / LRADC_TS_SAMPLE_AMOUNT; +} + +static void mxs_lradc_ts_work(struct work_struct *ts_work) +{ + struct mxs_lradc *lradc = container_of(ts_work, + struct mxs_lradc, ts_work); + int val_x, val_y, val_p; + bool valid = false; + + while (mxs_lradc_ts_touched(lradc)) { + /* Disable touch detector so we can sample the touchscreen. */ + writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE, + lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); + + if (likely(valid)) { + input_report_abs(lradc->ts_input, ABS_X, val_x); + input_report_abs(lradc->ts_input, ABS_Y, val_y); + input_report_abs(lradc->ts_input, ABS_PRESSURE, val_p); + input_report_key(lradc->ts_input, BTN_TOUCH, 1); + input_sync(lradc->ts_input); + } + + valid = false; + + val_x = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_X); + if (val_x < 0) + continue; + val_y = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_Y); + if (val_y < 0) + continue; + val_p = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_PRESSURE); + if (val_p < 0) + continue; + + valid = true; + } + + input_report_abs(lradc->ts_input, ABS_PRESSURE, 0); + input_report_key(lradc->ts_input, BTN_TOUCH, 0); + input_sync(lradc->ts_input); + + /* Do not restart the TS IRQ if the driver is shutting down. */ + if (lradc->stop_touchscreen) + return; + + /* Restart the touchscreen interrupts. */ + writel(LRADC_CTRL1_TOUCH_DETECT_IRQ, + lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); + writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, + lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET); +} + +static int mxs_lradc_ts_open(struct input_dev *dev) +{ + struct mxs_lradc *lradc = input_get_drvdata(dev); + + /* The touchscreen is starting. */ + lradc->stop_touchscreen = false; + + /* Enable the touch-detect circuitry. */ + writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE, + lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); + + /* Enable the touch-detect IRQ. */ + writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, + lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET); + + return 0; +} + +static void mxs_lradc_ts_close(struct input_dev *dev) +{ + struct mxs_lradc *lradc = input_get_drvdata(dev); + + /* Indicate the touchscreen is stopping. */ + lradc->stop_touchscreen = true; + mb(); + + /* Wait until touchscreen thread finishes any possible remnants. */ + cancel_work_sync(&lradc->ts_work); + + /* Disable touchscreen touch-detect IRQ. */ + writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, + lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); + + /* Power-down touchscreen touch-detect circuitry. */ + writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE, + lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); +} + +static int mxs_lradc_ts_register(struct mxs_lradc *lradc) +{ + struct input_dev *input; + struct device *dev = lradc->dev; + int ret; + + if (!lradc->use_touchscreen) + return 0; + + input = input_allocate_device(); + if (!input) { + dev_err(dev, "Failed to allocate TS device!\n"); + return -ENOMEM; + } + + input->name = DRIVER_NAME; + input->id.bustype = BUS_HOST; + input->dev.parent = dev; + input->open = mxs_lradc_ts_open; + input->close = mxs_lradc_ts_close; + + __set_bit(EV_ABS, input->evbit); + __set_bit(EV_KEY, input->evbit); + __set_bit(BTN_TOUCH, input->keybit); + input_set_abs_params(input, ABS_X, 0, LRADC_CH_VALUE_MASK, 0, 0); + input_set_abs_params(input, ABS_Y, 0, LRADC_CH_VALUE_MASK, 0, 0); + input_set_abs_params(input, ABS_PRESSURE, 0, LRADC_CH_VALUE_MASK, 0, 0); + + lradc->ts_input = input; + input_set_drvdata(input, lradc); + ret = input_register_device(input); + if (ret) + input_free_device(lradc->ts_input); + + return ret; +} + +static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc) +{ + if (!lradc->use_touchscreen) + return; + + cancel_work_sync(&lradc->ts_work); + + input_unregister_device(lradc->ts_input); +} + /* * IRQ Handling */ @@ -202,14 +547,24 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) struct iio_dev *iio = data; struct mxs_lradc *lradc = iio_priv(iio); unsigned long reg = readl(lradc->base + LRADC_CTRL1); + const uint32_t ts_irq_mask = + LRADC_CTRL1_TOUCH_DETECT_IRQ_EN | + LRADC_CTRL1_TOUCH_DETECT_IRQ; if (!(reg & LRADC_CTRL1_LRADC_IRQ_MASK)) return IRQ_NONE; /* - * Touchscreen IRQ handling code shall probably have priority - * and therefore shall be placed here. + * Touchscreen IRQ handling code has priority and therefore + * is placed here. In case touchscreen IRQ arrives, disable + * it ASAP */ + if (reg & LRADC_CTRL1_TOUCH_DETECT_IRQ) { + writel(ts_irq_mask, + lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); + if (!lradc->stop_touchscreen) + schedule_work(&lradc->ts_work); + } if (iio_buffer_enabled(iio)) iio_trigger_poll(iio->trig, iio_get_time_ns()); @@ -305,8 +660,10 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio) { struct mxs_lradc *lradc = iio_priv(iio); struct iio_buffer *buffer = iio->buffer; - int ret = 0, chan, ofs = 0, enable = 0; - uint32_t ctrl4 = 0; + int ret = 0, chan, ofs = 0; + unsigned long enable = 0; + uint32_t ctrl4_set = 0; + uint32_t ctrl4_clr = 0; uint32_t ctrl1_irq = 0; const uint32_t chan_value = LRADC_CH_ACCUMULATE | ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); @@ -338,17 +695,20 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio) writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); for_each_set_bit(chan, buffer->scan_mask, LRADC_MAX_TOTAL_CHANS) { - ctrl4 |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs); + ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs); + ctrl4_clr |= LRADC_CTRL4_LRADCSELECT_MASK(ofs); ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs); writel(chan_value, lradc->base + LRADC_CH(ofs)); - enable |= 1 << ofs; + bitmap_set(&enable, ofs, 1); ofs++; } writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK, lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR); - writel(ctrl4, lradc->base + LRADC_CTRL4); + writel(ctrl4_clr, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR); + writel(ctrl4_set, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET); + writel(ctrl1_irq, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET); writel(enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET, @@ -383,9 +743,33 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio) static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio, const unsigned long *mask) { - const int mw = bitmap_weight(mask, iio->masklength); + struct mxs_lradc *lradc = iio_priv(iio); + const int len = iio->masklength; + const int map_chans = bitmap_weight(mask, len); + int rsvd_chans = 0; + unsigned long rsvd_mask = 0; - return mw <= LRADC_MAX_MAPPED_CHANS; + if (lradc->use_touchbutton) + rsvd_mask |= CHAN_MASK_TOUCHBUTTON; + if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_4WIRE) + rsvd_mask |= CHAN_MASK_TOUCHSCREEN_4WIRE; + if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) + rsvd_mask |= CHAN_MASK_TOUCHSCREEN_5WIRE; + + if (lradc->use_touchbutton) + rsvd_chans++; + if (lradc->use_touchscreen) + rsvd_chans++; + + /* Test for attempts to map channels with special mode of operation. */ + if (bitmap_intersects(mask, &rsvd_mask, len)) + return false; + + /* Test for attempts to map more channels then available slots. */ + if (map_chans + rsvd_chans > LRADC_MAX_MAPPED_CHANS) + return false; + + return true; } static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = { @@ -434,15 +818,29 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = { static void mxs_lradc_hw_init(struct mxs_lradc *lradc) { - int i; - const uint32_t cfg = + /* The ADC always uses DELAY CHANNEL 0. */ + const uint32_t adc_cfg = + (1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + 0)) | (LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET); stmp_reset_block(lradc->base); - for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) - writel(cfg | (1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + i)), - lradc->base + LRADC_DELAY(i)); + /* Configure DELAY CHANNEL 0 for generic ADC sampling. */ + writel(adc_cfg, lradc->base + LRADC_DELAY(0)); + + /* Disable remaining DELAY CHANNELs */ + writel(0, lradc->base + LRADC_DELAY(1)); + writel(0, lradc->base + LRADC_DELAY(2)); + writel(0, lradc->base + LRADC_DELAY(3)); + + /* Configure the touchscreen type */ + writel(LRADC_CTRL0_TOUCH_SCREEN_TYPE, + lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); + + if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) { + writel(LRADC_CTRL0_TOUCH_SCREEN_TYPE, + lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); + } /* Start internal temperature sensing. */ writel(0, lradc->base + LRADC_CTRL2); @@ -462,9 +860,11 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) static int mxs_lradc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; struct mxs_lradc *lradc; struct iio_dev *iio; struct resource *iores; + uint32_t ts_wires = 0; int ret = 0; int i; @@ -486,6 +886,21 @@ static int mxs_lradc_probe(struct platform_device *pdev) goto err_addr; } + INIT_WORK(&lradc->ts_work, mxs_lradc_ts_work); + + /* Check if touchscreen is enabled in DT. */ + ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires", + &ts_wires); + if (ret) + dev_info(dev, "Touchscreen not enabled.\n"); + else if (ts_wires == 4) + lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE; + else if (ts_wires == 5) + lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE; + else + dev_warn(dev, "Unsupported number of touchscreen wires (%d)\n", + ts_wires); + /* Grab all IRQ sources */ for (i = 0; i < 13; i++) { lradc->irq[i] = platform_get_irq(pdev, i); @@ -523,11 +938,16 @@ static int mxs_lradc_probe(struct platform_device *pdev) if (ret) goto err_trig; + /* Register the touchscreen input device. */ + ret = mxs_lradc_ts_register(lradc); + if (ret) + goto err_dev; + /* Register IIO device. */ ret = iio_device_register(iio); if (ret) { dev_err(dev, "Failed to register IIO device\n"); - goto err_dev; + goto err_ts; } /* Configure the hardware. */ @@ -535,6 +955,8 @@ static int mxs_lradc_probe(struct platform_device *pdev) return 0; +err_ts: + mxs_lradc_ts_unregister(lradc); err_dev: mxs_lradc_trigger_remove(iio); err_trig: @@ -549,6 +971,8 @@ static int mxs_lradc_remove(struct platform_device *pdev) struct iio_dev *iio = platform_get_drvdata(pdev); struct mxs_lradc *lradc = iio_priv(iio); + mxs_lradc_ts_unregister(lradc); + mxs_lradc_hw_stop(lradc); iio_device_unregister(iio);