cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mxs-lradc-ts.c (19533B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Freescale MXS LRADC touchscreen driver
      4 *
      5 * Copyright (c) 2012 DENX Software Engineering, GmbH.
      6 * Copyright (c) 2017 Ksenija Stanojevic <ksenija.stanojevic@gmail.com>
      7 *
      8 * Authors:
      9 *  Marek Vasut <marex@denx.de>
     10 *  Ksenija Stanojevic <ksenija.stanojevic@gmail.com>
     11 */
     12
     13#include <linux/device.h>
     14#include <linux/err.h>
     15#include <linux/input.h>
     16#include <linux/interrupt.h>
     17#include <linux/module.h>
     18#include <linux/mfd/core.h>
     19#include <linux/mfd/mxs-lradc.h>
     20#include <linux/of.h>
     21#include <linux/of_irq.h>
     22#include <linux/platform_device.h>
     23
     24static const char * const mxs_lradc_ts_irq_names[] = {
     25	"mxs-lradc-touchscreen",
     26	"mxs-lradc-channel6",
     27	"mxs-lradc-channel7",
     28};
     29
     30/*
     31 * Touchscreen handling
     32 */
     33enum mxs_lradc_ts_plate {
     34	LRADC_TOUCH = 0,
     35	LRADC_SAMPLE_X,
     36	LRADC_SAMPLE_Y,
     37	LRADC_SAMPLE_PRESSURE,
     38	LRADC_SAMPLE_VALID,
     39};
     40
     41struct mxs_lradc_ts {
     42	struct mxs_lradc	*lradc;
     43	struct device		*dev;
     44
     45	void __iomem		*base;
     46	/*
     47	 * When the touchscreen is enabled, we give it two private virtual
     48	 * channels: #6 and #7. This means that only 6 virtual channels (instead
     49	 * of 8) will be available for buffered capture.
     50	 */
     51#define TOUCHSCREEN_VCHANNEL1		7
     52#define TOUCHSCREEN_VCHANNEL2		6
     53
     54	struct input_dev	*ts_input;
     55
     56	enum mxs_lradc_ts_plate	cur_plate; /* state machine */
     57	bool			ts_valid;
     58	unsigned int		ts_x_pos;
     59	unsigned int		ts_y_pos;
     60	unsigned int		ts_pressure;
     61
     62	/* handle touchscreen's physical behaviour */
     63	/* samples per coordinate */
     64	unsigned int		over_sample_cnt;
     65	/* time clocks between samples */
     66	unsigned int		over_sample_delay;
     67	/* time in clocks to wait after the plates where switched */
     68	unsigned int		settling_delay;
     69	spinlock_t		lock;
     70};
     71
     72struct state_info {
     73	u32		mask;
     74	u32		bit;
     75	u32		x_plate;
     76	u32		y_plate;
     77	u32		pressure;
     78};
     79
     80static struct state_info info[] = {
     81	{LRADC_CTRL0_MX23_PLATE_MASK, LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE,
     82	 LRADC_CTRL0_MX23_XP | LRADC_CTRL0_MX23_XM,
     83	 LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_YM,
     84	 LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XM},
     85	{LRADC_CTRL0_MX28_PLATE_MASK, LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE,
     86	 LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW,
     87	 LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW,
     88	 LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW}
     89};
     90
     91static bool mxs_lradc_check_touch_event(struct mxs_lradc_ts *ts)
     92{
     93	return !!(readl(ts->base + LRADC_STATUS) &
     94					LRADC_STATUS_TOUCH_DETECT_RAW);
     95}
     96
     97static void mxs_lradc_map_ts_channel(struct mxs_lradc_ts *ts, unsigned int vch,
     98				     unsigned int ch)
     99{
    100	writel(LRADC_CTRL4_LRADCSELECT_MASK(vch),
    101	       ts->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR);
    102	writel(LRADC_CTRL4_LRADCSELECT(vch, ch),
    103	       ts->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET);
    104}
    105
    106static void mxs_lradc_setup_ts_channel(struct mxs_lradc_ts *ts, unsigned int ch)
    107{
    108	/*
    109	 * prepare for oversampling conversion
    110	 *
    111	 * from the datasheet:
    112	 * "The ACCUMULATE bit in the appropriate channel register
    113	 * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0;
    114	 * otherwise, the IRQs will not fire."
    115	 */
    116	writel(LRADC_CH_ACCUMULATE |
    117	       LRADC_CH_NUM_SAMPLES(ts->over_sample_cnt - 1),
    118	       ts->base + LRADC_CH(ch));
    119
    120	/* from the datasheet:
    121	 * "Software must clear this register in preparation for a
    122	 * multi-cycle accumulation.
    123	 */
    124	writel(LRADC_CH_VALUE_MASK,
    125	       ts->base + LRADC_CH(ch) + STMP_OFFSET_REG_CLR);
    126
    127	/*
    128	 * prepare the delay/loop unit according to the oversampling count
    129	 *
    130	 * from the datasheet:
    131	 * "The DELAY fields in HW_LRADC_DELAY0, HW_LRADC_DELAY1,
    132	 * HW_LRADC_DELAY2, and HW_LRADC_DELAY3 must be non-zero; otherwise,
    133	 * the LRADC will not trigger the delay group."
    134	 */
    135	writel(LRADC_DELAY_TRIGGER(1 << ch) | LRADC_DELAY_TRIGGER_DELAYS(0) |
    136	       LRADC_DELAY_LOOP(ts->over_sample_cnt - 1) |
    137	       LRADC_DELAY_DELAY(ts->over_sample_delay - 1),
    138	       ts->base + LRADC_DELAY(3));
    139
    140	writel(LRADC_CTRL1_LRADC_IRQ(ch),
    141	       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
    142
    143	/*
    144	 * after changing the touchscreen plates setting
    145	 * the signals need some initial time to settle. Start the
    146	 * SoC's delay unit and start the conversion later
    147	 * and automatically.
    148	 */
    149	writel(LRADC_DELAY_TRIGGER(0) | LRADC_DELAY_TRIGGER_DELAYS(BIT(3)) |
    150	       LRADC_DELAY_KICK | LRADC_DELAY_DELAY(ts->settling_delay),
    151	       ts->base + LRADC_DELAY(2));
    152}
    153
    154/*
    155 * Pressure detection is special:
    156 * We want to do both required measurements for the pressure detection in
    157 * one turn. Use the hardware features to chain both conversions and let the
    158 * hardware report one interrupt if both conversions are done
    159 */
    160static void mxs_lradc_setup_ts_pressure(struct mxs_lradc_ts *ts,
    161					unsigned int ch1, unsigned int ch2)
    162{
    163	u32 reg;
    164
    165	/*
    166	 * prepare for oversampling conversion
    167	 *
    168	 * from the datasheet:
    169	 * "The ACCUMULATE bit in the appropriate channel register
    170	 * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0;
    171	 * otherwise, the IRQs will not fire."
    172	 */
    173	reg = LRADC_CH_ACCUMULATE |
    174		LRADC_CH_NUM_SAMPLES(ts->over_sample_cnt - 1);
    175	writel(reg, ts->base + LRADC_CH(ch1));
    176	writel(reg, ts->base + LRADC_CH(ch2));
    177
    178	/* from the datasheet:
    179	 * "Software must clear this register in preparation for a
    180	 * multi-cycle accumulation.
    181	 */
    182	writel(LRADC_CH_VALUE_MASK,
    183	       ts->base + LRADC_CH(ch1) + STMP_OFFSET_REG_CLR);
    184	writel(LRADC_CH_VALUE_MASK,
    185	       ts->base + LRADC_CH(ch2) + STMP_OFFSET_REG_CLR);
    186
    187	/* prepare the delay/loop unit according to the oversampling count */
    188	writel(LRADC_DELAY_TRIGGER(1 << ch1) | LRADC_DELAY_TRIGGER(1 << ch2) |
    189	       LRADC_DELAY_TRIGGER_DELAYS(0) |
    190	       LRADC_DELAY_LOOP(ts->over_sample_cnt - 1) |
    191	       LRADC_DELAY_DELAY(ts->over_sample_delay - 1),
    192	       ts->base + LRADC_DELAY(3));
    193
    194	writel(LRADC_CTRL1_LRADC_IRQ(ch2),
    195	       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
    196
    197	/*
    198	 * after changing the touchscreen plates setting
    199	 * the signals need some initial time to settle. Start the
    200	 * SoC's delay unit and start the conversion later
    201	 * and automatically.
    202	 */
    203	writel(LRADC_DELAY_TRIGGER(0) | LRADC_DELAY_TRIGGER_DELAYS(BIT(3)) |
    204	       LRADC_DELAY_KICK | LRADC_DELAY_DELAY(ts->settling_delay),
    205	       ts->base + LRADC_DELAY(2));
    206}
    207
    208static unsigned int mxs_lradc_ts_read_raw_channel(struct mxs_lradc_ts *ts,
    209						  unsigned int channel)
    210{
    211	u32 reg;
    212	unsigned int num_samples, val;
    213
    214	reg = readl(ts->base + LRADC_CH(channel));
    215	if (reg & LRADC_CH_ACCUMULATE)
    216		num_samples = ts->over_sample_cnt;
    217	else
    218		num_samples = 1;
    219
    220	val = (reg & LRADC_CH_VALUE_MASK) >> LRADC_CH_VALUE_OFFSET;
    221	return val / num_samples;
    222}
    223
    224static unsigned int mxs_lradc_read_ts_pressure(struct mxs_lradc_ts *ts,
    225					unsigned int ch1, unsigned int ch2)
    226{
    227	u32 reg, mask;
    228	unsigned int pressure, m1, m2;
    229
    230	mask = LRADC_CTRL1_LRADC_IRQ(ch1) | LRADC_CTRL1_LRADC_IRQ(ch2);
    231	reg = readl(ts->base + LRADC_CTRL1) & mask;
    232
    233	while (reg != mask) {
    234		reg = readl(ts->base + LRADC_CTRL1) & mask;
    235		dev_dbg(ts->dev, "One channel is still busy: %X\n", reg);
    236	}
    237
    238	m1 = mxs_lradc_ts_read_raw_channel(ts, ch1);
    239	m2 = mxs_lradc_ts_read_raw_channel(ts, ch2);
    240
    241	if (m2 == 0) {
    242		dev_warn(ts->dev, "Cannot calculate pressure\n");
    243		return 1 << (LRADC_RESOLUTION - 1);
    244	}
    245
    246	/* simply scale the value from 0 ... max ADC resolution */
    247	pressure = m1;
    248	pressure *= (1 << LRADC_RESOLUTION);
    249	pressure /= m2;
    250
    251	dev_dbg(ts->dev, "Pressure = %u\n", pressure);
    252	return pressure;
    253}
    254
    255#define TS_CH_XP 2
    256#define TS_CH_YP 3
    257#define TS_CH_XM 4
    258#define TS_CH_YM 5
    259
    260/*
    261 * YP(open)--+-------------+
    262 *	     |		   |--+
    263 *	     |		   |  |
    264 *    YM(-)--+-------------+  |
    265 *	       +--------------+
    266 *	       |	      |
    267 *	   XP(weak+)	    XM(open)
    268 *
    269 * "weak+" means 200k Ohm VDDIO
    270 * (-) means GND
    271 */
    272static void mxs_lradc_setup_touch_detection(struct mxs_lradc_ts *ts)
    273{
    274	struct mxs_lradc *lradc = ts->lradc;
    275
    276	/*
    277	 * In order to detect a touch event the 'touch detect enable' bit
    278	 * enables:
    279	 *  - a weak pullup to the X+ connector
    280	 *  - a strong ground at the Y- connector
    281	 */
    282	writel(info[lradc->soc].mask,
    283	       ts->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
    284	writel(info[lradc->soc].bit,
    285	       ts->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
    286}
    287
    288/*
    289 * YP(meas)--+-------------+
    290 *	     |		   |--+
    291 *	     |		   |  |
    292 * YM(open)--+-------------+  |
    293 *	       +--------------+
    294 *	       |	      |
    295 *	     XP(+)	    XM(-)
    296 *
    297 * (+) means here 1.85 V
    298 * (-) means here GND
    299 */
    300static void mxs_lradc_prepare_x_pos(struct mxs_lradc_ts *ts)
    301{
    302	struct mxs_lradc *lradc = ts->lradc;
    303
    304	writel(info[lradc->soc].mask,
    305	       ts->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
    306	writel(info[lradc->soc].x_plate,
    307	       ts->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
    308
    309	ts->cur_plate = LRADC_SAMPLE_X;
    310	mxs_lradc_map_ts_channel(ts, TOUCHSCREEN_VCHANNEL1, TS_CH_YP);
    311	mxs_lradc_setup_ts_channel(ts, TOUCHSCREEN_VCHANNEL1);
    312}
    313
    314/*
    315 *   YP(+)--+-------------+
    316 *	    |		  |--+
    317 *	    |		  |  |
    318 *   YM(-)--+-------------+  |
    319 *	      +--------------+
    320 *	      |		     |
    321 *	   XP(open)	   XM(meas)
    322 *
    323 * (+) means here 1.85 V
    324 * (-) means here GND
    325 */
    326static void mxs_lradc_prepare_y_pos(struct mxs_lradc_ts *ts)
    327{
    328	struct mxs_lradc *lradc = ts->lradc;
    329
    330	writel(info[lradc->soc].mask,
    331	       ts->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
    332	writel(info[lradc->soc].y_plate,
    333	       ts->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
    334
    335	ts->cur_plate = LRADC_SAMPLE_Y;
    336	mxs_lradc_map_ts_channel(ts, TOUCHSCREEN_VCHANNEL1, TS_CH_XM);
    337	mxs_lradc_setup_ts_channel(ts, TOUCHSCREEN_VCHANNEL1);
    338}
    339
    340/*
    341 *    YP(+)--+-------------+
    342 *	     |		   |--+
    343 *	     |		   |  |
    344 * YM(meas)--+-------------+  |
    345 *	       +--------------+
    346 *	       |	      |
    347 *	    XP(meas)	    XM(-)
    348 *
    349 * (+) means here 1.85 V
    350 * (-) means here GND
    351 */
    352static void mxs_lradc_prepare_pressure(struct mxs_lradc_ts *ts)
    353{
    354	struct mxs_lradc *lradc = ts->lradc;
    355
    356	writel(info[lradc->soc].mask,
    357	       ts->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
    358	writel(info[lradc->soc].pressure,
    359	       ts->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
    360
    361	ts->cur_plate = LRADC_SAMPLE_PRESSURE;
    362	mxs_lradc_map_ts_channel(ts, TOUCHSCREEN_VCHANNEL1, TS_CH_YM);
    363	mxs_lradc_map_ts_channel(ts, TOUCHSCREEN_VCHANNEL2, TS_CH_XP);
    364	mxs_lradc_setup_ts_pressure(ts, TOUCHSCREEN_VCHANNEL2,
    365				    TOUCHSCREEN_VCHANNEL1);
    366}
    367
    368static void mxs_lradc_enable_touch_detection(struct mxs_lradc_ts *ts)
    369{
    370	mxs_lradc_setup_touch_detection(ts);
    371
    372	ts->cur_plate = LRADC_TOUCH;
    373	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ | LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
    374	       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
    375	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
    376	       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
    377}
    378
    379static void mxs_lradc_start_touch_event(struct mxs_lradc_ts *ts)
    380{
    381	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
    382	       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
    383	writel(LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1),
    384	       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
    385	/*
    386	 * start with the Y-pos, because it uses nearly the same plate
    387	 * settings like the touch detection
    388	 */
    389	mxs_lradc_prepare_y_pos(ts);
    390}
    391
    392static void mxs_lradc_report_ts_event(struct mxs_lradc_ts *ts)
    393{
    394	input_report_abs(ts->ts_input, ABS_X, ts->ts_x_pos);
    395	input_report_abs(ts->ts_input, ABS_Y, ts->ts_y_pos);
    396	input_report_abs(ts->ts_input, ABS_PRESSURE, ts->ts_pressure);
    397	input_report_key(ts->ts_input, BTN_TOUCH, 1);
    398	input_sync(ts->ts_input);
    399}
    400
    401static void mxs_lradc_complete_touch_event(struct mxs_lradc_ts *ts)
    402{
    403	mxs_lradc_setup_touch_detection(ts);
    404	ts->cur_plate = LRADC_SAMPLE_VALID;
    405	/*
    406	 * start a dummy conversion to burn time to settle the signals
    407	 * note: we are not interested in the conversion's value
    408	 */
    409	writel(0, ts->base + LRADC_CH(TOUCHSCREEN_VCHANNEL1));
    410	writel(LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
    411	       LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2),
    412	       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
    413	writel(LRADC_DELAY_TRIGGER(1 << TOUCHSCREEN_VCHANNEL1) |
    414	       LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10),
    415	       ts->base + LRADC_DELAY(2));
    416}
    417
    418/*
    419 * in order to avoid false measurements, report only samples where
    420 * the surface is still touched after the position measurement
    421 */
    422static void mxs_lradc_finish_touch_event(struct mxs_lradc_ts *ts, bool valid)
    423{
    424	/* if it is still touched, report the sample */
    425	if (valid && mxs_lradc_check_touch_event(ts)) {
    426		ts->ts_valid = true;
    427		mxs_lradc_report_ts_event(ts);
    428	}
    429
    430	/* if it is even still touched, continue with the next measurement */
    431	if (mxs_lradc_check_touch_event(ts)) {
    432		mxs_lradc_prepare_y_pos(ts);
    433		return;
    434	}
    435
    436	if (ts->ts_valid) {
    437		/* signal the release */
    438		ts->ts_valid = false;
    439		input_report_key(ts->ts_input, BTN_TOUCH, 0);
    440		input_sync(ts->ts_input);
    441	}
    442
    443	/* if it is released, wait for the next touch via IRQ */
    444	ts->cur_plate = LRADC_TOUCH;
    445	writel(0, ts->base + LRADC_DELAY(2));
    446	writel(0, ts->base + LRADC_DELAY(3));
    447	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ |
    448	       LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) |
    449	       LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1),
    450	       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
    451	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
    452	       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
    453}
    454
    455/* touchscreen's state machine */
    456static void mxs_lradc_handle_touch(struct mxs_lradc_ts *ts)
    457{
    458	switch (ts->cur_plate) {
    459	case LRADC_TOUCH:
    460		if (mxs_lradc_check_touch_event(ts))
    461			mxs_lradc_start_touch_event(ts);
    462		writel(LRADC_CTRL1_TOUCH_DETECT_IRQ,
    463		       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
    464		return;
    465
    466	case LRADC_SAMPLE_Y:
    467		ts->ts_y_pos =
    468		    mxs_lradc_ts_read_raw_channel(ts, TOUCHSCREEN_VCHANNEL1);
    469		mxs_lradc_prepare_x_pos(ts);
    470		return;
    471
    472	case LRADC_SAMPLE_X:
    473		ts->ts_x_pos =
    474		    mxs_lradc_ts_read_raw_channel(ts, TOUCHSCREEN_VCHANNEL1);
    475		mxs_lradc_prepare_pressure(ts);
    476		return;
    477
    478	case LRADC_SAMPLE_PRESSURE:
    479		ts->ts_pressure =
    480		    mxs_lradc_read_ts_pressure(ts,
    481					       TOUCHSCREEN_VCHANNEL2,
    482					       TOUCHSCREEN_VCHANNEL1);
    483		mxs_lradc_complete_touch_event(ts);
    484		return;
    485
    486	case LRADC_SAMPLE_VALID:
    487		mxs_lradc_finish_touch_event(ts, 1);
    488		break;
    489	}
    490}
    491
    492/* IRQ Handling */
    493static irqreturn_t mxs_lradc_ts_handle_irq(int irq, void *data)
    494{
    495	struct mxs_lradc_ts *ts = data;
    496	struct mxs_lradc *lradc = ts->lradc;
    497	unsigned long reg = readl(ts->base + LRADC_CTRL1);
    498	u32 clr_irq = mxs_lradc_irq_mask(lradc);
    499	const u32 ts_irq_mask =
    500		LRADC_CTRL1_TOUCH_DETECT_IRQ |
    501		LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
    502		LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2);
    503	unsigned long flags;
    504
    505	if (!(reg & mxs_lradc_irq_mask(lradc)))
    506		return IRQ_NONE;
    507
    508	if (reg & ts_irq_mask) {
    509		spin_lock_irqsave(&ts->lock, flags);
    510		mxs_lradc_handle_touch(ts);
    511		spin_unlock_irqrestore(&ts->lock, flags);
    512		/* Make sure we don't clear the next conversion's interrupt. */
    513		clr_irq &= ~(LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
    514				LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2));
    515		writel(reg & clr_irq,
    516		       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
    517	}
    518
    519	return IRQ_HANDLED;
    520}
    521
    522static int mxs_lradc_ts_open(struct input_dev *dev)
    523{
    524	struct mxs_lradc_ts *ts = input_get_drvdata(dev);
    525
    526	/* Enable the touch-detect circuitry. */
    527	mxs_lradc_enable_touch_detection(ts);
    528
    529	return 0;
    530}
    531
    532static void mxs_lradc_ts_stop(struct mxs_lradc_ts *ts)
    533{
    534	int i;
    535	struct mxs_lradc *lradc = ts->lradc;
    536
    537	/* stop all interrupts from firing */
    538	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
    539	       LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) |
    540	       LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL2),
    541	       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
    542
    543	/* Power-down touchscreen touch-detect circuitry. */
    544	writel(info[lradc->soc].mask,
    545	       ts->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
    546
    547	writel(lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET,
    548	       ts->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
    549
    550	for (i = 1; i < LRADC_MAX_DELAY_CHANS; i++)
    551		writel(0, ts->base + LRADC_DELAY(i));
    552}
    553
    554static void mxs_lradc_ts_close(struct input_dev *dev)
    555{
    556	struct mxs_lradc_ts *ts = input_get_drvdata(dev);
    557
    558	mxs_lradc_ts_stop(ts);
    559}
    560
    561static void mxs_lradc_ts_hw_init(struct mxs_lradc_ts *ts)
    562{
    563	struct mxs_lradc *lradc = ts->lradc;
    564
    565	/* Configure the touchscreen type */
    566	if (lradc->soc == IMX28_LRADC) {
    567		writel(LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
    568		       ts->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
    569
    570		if (lradc->touchscreen_wire == MXS_LRADC_TOUCHSCREEN_5WIRE)
    571			writel(LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
    572			       ts->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
    573	}
    574}
    575
    576static int mxs_lradc_ts_register(struct mxs_lradc_ts *ts)
    577{
    578	struct input_dev *input;
    579	struct device *dev = ts->dev;
    580
    581	input = devm_input_allocate_device(dev);
    582	if (!input)
    583		return -ENOMEM;
    584
    585	input->name = "mxs-lradc-ts";
    586	input->id.bustype = BUS_HOST;
    587	input->open = mxs_lradc_ts_open;
    588	input->close = mxs_lradc_ts_close;
    589
    590	__set_bit(INPUT_PROP_DIRECT, input->propbit);
    591	input_set_capability(input, EV_KEY, BTN_TOUCH);
    592	input_set_abs_params(input, ABS_X, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0);
    593	input_set_abs_params(input, ABS_Y, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0);
    594	input_set_abs_params(input, ABS_PRESSURE, 0, LRADC_SINGLE_SAMPLE_MASK,
    595			     0, 0);
    596
    597	ts->ts_input = input;
    598	input_set_drvdata(input, ts);
    599
    600	return input_register_device(input);
    601}
    602
    603static int mxs_lradc_ts_probe(struct platform_device *pdev)
    604{
    605	struct device *dev = &pdev->dev;
    606	struct device_node *node = dev->parent->of_node;
    607	struct mxs_lradc *lradc = dev_get_drvdata(dev->parent);
    608	struct mxs_lradc_ts *ts;
    609	int ret, irq, virq, i;
    610	u32 ts_wires = 0, adapt;
    611
    612	ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
    613	if (!ts)
    614		return -ENOMEM;
    615
    616	platform_set_drvdata(pdev, ts);
    617
    618	ts->lradc = lradc;
    619	ts->dev = dev;
    620	spin_lock_init(&ts->lock);
    621
    622	ts->base = devm_platform_ioremap_resource(pdev, 0);
    623	if (IS_ERR(ts->base))
    624		return PTR_ERR(ts->base);
    625
    626	ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires",
    627				   &ts_wires);
    628	if (ret)
    629		return ret;
    630
    631	if (of_property_read_u32(node, "fsl,ave-ctrl", &adapt)) {
    632		ts->over_sample_cnt = 4;
    633	} else {
    634		if (adapt >= 1 && adapt <= 32) {
    635			ts->over_sample_cnt = adapt;
    636		} else {
    637			dev_err(ts->dev, "Invalid sample count (%u)\n",
    638				adapt);
    639			return -EINVAL;
    640		}
    641	}
    642
    643	if (of_property_read_u32(node, "fsl,ave-delay", &adapt)) {
    644		ts->over_sample_delay = 2;
    645	} else {
    646		if (adapt >= 2 && adapt <= LRADC_DELAY_DELAY_MASK + 1) {
    647			ts->over_sample_delay = adapt;
    648		} else {
    649			dev_err(ts->dev, "Invalid sample delay (%u)\n",
    650				adapt);
    651			return -EINVAL;
    652		}
    653	}
    654
    655	if (of_property_read_u32(node, "fsl,settling", &adapt)) {
    656		ts->settling_delay = 10;
    657	} else {
    658		if (adapt >= 1 && adapt <= LRADC_DELAY_DELAY_MASK) {
    659			ts->settling_delay = adapt;
    660		} else {
    661			dev_err(ts->dev, "Invalid settling delay (%u)\n",
    662				adapt);
    663			return -EINVAL;
    664		}
    665	}
    666
    667	ret = stmp_reset_block(ts->base);
    668	if (ret)
    669		return ret;
    670
    671	mxs_lradc_ts_hw_init(ts);
    672
    673	for (i = 0; i < 3; i++) {
    674		irq = platform_get_irq_byname(pdev, mxs_lradc_ts_irq_names[i]);
    675		if (irq < 0)
    676			return irq;
    677
    678		virq = irq_of_parse_and_map(node, irq);
    679
    680		mxs_lradc_ts_stop(ts);
    681
    682		ret = devm_request_irq(dev, virq,
    683				       mxs_lradc_ts_handle_irq,
    684				       0, mxs_lradc_ts_irq_names[i], ts);
    685		if (ret)
    686			return ret;
    687	}
    688
    689	return mxs_lradc_ts_register(ts);
    690}
    691
    692static struct platform_driver mxs_lradc_ts_driver = {
    693	.driver	= {
    694		.name = "mxs-lradc-ts",
    695	},
    696	.probe	= mxs_lradc_ts_probe,
    697};
    698module_platform_driver(mxs_lradc_ts_driver);
    699
    700MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
    701MODULE_DESCRIPTION("Freescale MXS LRADC touchscreen driver");
    702MODULE_LICENSE("GPL");
    703MODULE_ALIAS("platform:mxs-lradc-ts");