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>
27767d8336SLinus Walleij #include <linux/property.h>
280e685c3eSArnd Bergmann #include <linux/gpio/consumer.h>
29ffa458c1SDavid Brownell #include <linux/spi/spi.h>
30ffa458c1SDavid Brownell #include <linux/spi/ads7846.h>
3191143379SGrazvydas Ignotas #include <linux/regulator/consumer.h>
32d2d8442dSPaul Gortmaker #include <linux/module.h>
3303e2c9c7SDmitry Torokhov #include <asm/unaligned.h>
34ffa458c1SDavid Brownell 
35ffa458c1SDavid Brownell /*
369084533eSDavid Brownell  * This code has been heavily tested on a Nokia 770, and lightly
3752ce4eaaSPavel Machek  * tested on other ads7846 devices (OSK/Mistral, Lubbock, Spitz).
38bff0de5fSDavid Brownell  * TSC2046 is just newer ads7846 silicon.
39969111e9SNicolas Ferre  * Support for ads7843 tested on Atmel at91sam926x-EK.
40969111e9SNicolas Ferre  * Support for ads7845 has only been stubbed in.
4106a09124SMichael Hennerich  * Support for Analog Devices AD7873 and AD7843 tested.
42ffa458c1SDavid Brownell  *
437de90a8cSImre Deak  * IRQ handling needs a workaround because of a shortcoming in handling
447de90a8cSImre Deak  * edge triggered IRQs on some platforms like the OMAP1/2. These
457de90a8cSImre Deak  * platforms don't handle the ARM lazy IRQ disabling properly, thus we
467de90a8cSImre Deak  * have to maintain our own SW IRQ disabled status. This should be
477de90a8cSImre Deak  * removed as soon as the affected platform's IRQ handling is fixed.
487de90a8cSImre Deak  *
4952ce4eaaSPavel Machek  * App note sbaa036 talks in more detail about accurate sampling...
50ffa458c1SDavid Brownell  * that ought to help in situations like LCDs inducing noise (which
51ffa458c1SDavid Brownell  * can also be helped by using synch signals) and more generally.
527de90a8cSImre Deak  * This driver tries to utilize the measures described in the app
537de90a8cSImre Deak  * note. The strength of filtering can be set in the board-* specific
547de90a8cSImre Deak  * files.
55ffa458c1SDavid Brownell  */
56ffa458c1SDavid Brownell 
572991a1caSJason Wang #define TS_POLL_DELAY	1	/* ms delay before the first sample */
582991a1caSJason Wang #define TS_POLL_PERIOD	5	/* ms delay between samples */
59ffa458c1SDavid Brownell 
60d93f70b2SDavid Brownell /* this driver doesn't aim at the peak continuous sample rate */
61d93f70b2SDavid Brownell #define	SAMPLE_BITS	(8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */)
62d93f70b2SDavid Brownell 
639c950971SOleksij Rempel struct ads7846_buf {
649c950971SOleksij Rempel 	u8 cmd;
656965eeceSOleksij Rempel 	__be16 data;
669c950971SOleksij Rempel } __packed;
679c950971SOleksij Rempel 
686965eeceSOleksij Rempel struct ads7846_buf_layout {
696965eeceSOleksij Rempel 	unsigned int offset;
706965eeceSOleksij Rempel 	unsigned int count;
716965eeceSOleksij Rempel 	unsigned int skip;
72ffa458c1SDavid Brownell };
73ffa458c1SDavid Brownell 
74e8f462d2SDmitry Torokhov /*
75e8f462d2SDmitry Torokhov  * We allocate this separately to avoid cache line sharing issues when
76e8f462d2SDmitry Torokhov  * driver is used with DMA-based SPI controllers (like atmel_spi) on
77e8f462d2SDmitry Torokhov  * systems where main memory is not DMA-coherent (most non-x86 boards).
78e8f462d2SDmitry Torokhov  */
79e8f462d2SDmitry Torokhov struct ads7846_packet {
806965eeceSOleksij Rempel 	unsigned int count;
816965eeceSOleksij Rempel 	unsigned int count_skip;
826965eeceSOleksij Rempel 	unsigned int cmds;
836965eeceSOleksij Rempel 	unsigned int last_cmd_idx;
846965eeceSOleksij Rempel 	struct ads7846_buf_layout l[5];
856965eeceSOleksij Rempel 	struct ads7846_buf *rx;
866965eeceSOleksij Rempel 	struct ads7846_buf *tx;
876965eeceSOleksij Rempel 
889c950971SOleksij Rempel 	struct ads7846_buf pwrdown_cmd;
896965eeceSOleksij Rempel 
906965eeceSOleksij Rempel 	bool ignore;
916965eeceSOleksij Rempel 	u16 x, y, z1, z2;
92e8f462d2SDmitry Torokhov };
93e8f462d2SDmitry Torokhov 
94ffa458c1SDavid Brownell struct ads7846 {
95a90f7e98SDmitry Torokhov 	struct input_dev	*input;
96ffa458c1SDavid Brownell 	char			phys[32];
97b58895f8SMichael Roth 	char			name[32];
98ffa458c1SDavid Brownell 
99ffa458c1SDavid Brownell 	struct spi_device	*spi;
10091143379SGrazvydas Ignotas 	struct regulator	*reg;
1012c8dc071SDavid Brownell 
102ffa458c1SDavid Brownell 	u16			model;
1037c6d0ee1SDavid Brownell 	u16			vref_mv;
104ffa458c1SDavid Brownell 	u16			vref_delay_usecs;
105ffa458c1SDavid Brownell 	u16			x_plate_ohms;
106d5b415c9SImre Deak 	u16			pressure_max;
107ffa458c1SDavid Brownell 
10886579a4cSMichael Roth 	bool			swap_xy;
109ebcaaad9SAlexander Stein 	bool			use_internal;
11086579a4cSMichael Roth 
111e8f462d2SDmitry Torokhov 	struct ads7846_packet	*packet;
112ffa458c1SDavid Brownell 
113e4f48861SSemih Hazar 	struct spi_transfer	xfer[18];
1140b7018aaSImre Deak 	struct spi_message	msg[5];
1152991a1caSJason Wang 	int			msg_count;
1162991a1caSJason Wang 	wait_queue_head_t	wait;
1172991a1caSJason Wang 
1182991a1caSJason Wang 	bool			pendown;
1192991a1caSJason Wang 
1200b7018aaSImre Deak 	int			read_cnt;
121d5b415c9SImre Deak 	int			read_rep;
1220b7018aaSImre Deak 	int			last_read;
1230b7018aaSImre Deak 
1240b7018aaSImre Deak 	u16			debounce_max;
1250b7018aaSImre Deak 	u16			debounce_tol;
126d5b415c9SImre Deak 	u16			debounce_rep;
127ffa458c1SDavid Brownell 
1281d25891fSSemih Hazar 	u16			penirq_recheck_delay_usecs;
1291d25891fSSemih Hazar 
130a2f99330SMarco Felsch 	struct touchscreen_properties core_prop;
131a2f99330SMarco Felsch 
1322991a1caSJason Wang 	struct mutex		lock;
1332991a1caSJason Wang 	bool			stopped;	/* P: lock */
1342991a1caSJason Wang 	bool			disabled;	/* P: lock */
1352991a1caSJason Wang 	bool			suspended;	/* P: lock */
136c9e617a5SImre Deak 
137da970e69SImre Deak 	int			(*filter)(void *data, int data_idx, int *val);
138da970e69SImre Deak 	void			*filter_data;
139c9e617a5SImre Deak 	int			(*get_pendown_state)(void);
140767d8336SLinus Walleij 	struct gpio_desc	*gpio_pendown;
141fd746d54SEric Miao 
142fd746d54SEric Miao 	void			(*wait_for_sync)(void);
143ffa458c1SDavid Brownell };
144ffa458c1SDavid Brownell 
145937f5d5eSDaniel Mack enum ads7846_filter {
146937f5d5eSDaniel Mack 	ADS7846_FILTER_OK,
147937f5d5eSDaniel Mack 	ADS7846_FILTER_REPEAT,
148937f5d5eSDaniel Mack 	ADS7846_FILTER_IGNORE,
149937f5d5eSDaniel Mack };
150937f5d5eSDaniel Mack 
151ffa458c1SDavid Brownell /* leave chip selected when we're done, for quicker re-select? */
152ffa458c1SDavid Brownell #if	0
153ffa458c1SDavid Brownell #define	CS_CHANGE(xfer)	((xfer).cs_change = 1)
154ffa458c1SDavid Brownell #else
155ffa458c1SDavid Brownell #define	CS_CHANGE(xfer)	((xfer).cs_change = 0)
156ffa458c1SDavid Brownell #endif
157ffa458c1SDavid Brownell 
158ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/
159ffa458c1SDavid Brownell 
160ffa458c1SDavid Brownell /* The ADS7846 has touchscreen and other sensors.
161ffa458c1SDavid Brownell  * Earlier ads784x chips are somewhat compatible.
162ffa458c1SDavid Brownell  */
163ffa458c1SDavid Brownell #define	ADS_START		(1 << 7)
164ffa458c1SDavid Brownell #define	ADS_A2A1A0_d_y		(1 << 4)	/* differential */
165ffa458c1SDavid Brownell #define	ADS_A2A1A0_d_z1		(3 << 4)	/* differential */
166ffa458c1SDavid Brownell #define	ADS_A2A1A0_d_z2		(4 << 4)	/* differential */
167ffa458c1SDavid Brownell #define	ADS_A2A1A0_d_x		(5 << 4)	/* differential */
168ffa458c1SDavid Brownell #define	ADS_A2A1A0_temp0	(0 << 4)	/* non-differential */
169ffa458c1SDavid Brownell #define	ADS_A2A1A0_vbatt	(2 << 4)	/* non-differential */
170ffa458c1SDavid Brownell #define	ADS_A2A1A0_vaux		(6 << 4)	/* non-differential */
171ffa458c1SDavid Brownell #define	ADS_A2A1A0_temp1	(7 << 4)	/* non-differential */
172ffa458c1SDavid Brownell #define	ADS_8_BIT		(1 << 3)
173ffa458c1SDavid Brownell #define	ADS_12_BIT		(0 << 3)
174ffa458c1SDavid Brownell #define	ADS_SER			(1 << 2)	/* non-differential */
175ffa458c1SDavid Brownell #define	ADS_DFR			(0 << 2)	/* differential */
176ffa458c1SDavid Brownell #define	ADS_PD10_PDOWN		(0 << 0)	/* low power mode + penirq */
177ffa458c1SDavid Brownell #define	ADS_PD10_ADC_ON		(1 << 0)	/* ADC on */
178ffa458c1SDavid Brownell #define	ADS_PD10_REF_ON		(2 << 0)	/* vREF on + penirq */
179ffa458c1SDavid Brownell #define	ADS_PD10_ALL_ON		(3 << 0)	/* ADC + vREF on */
180ffa458c1SDavid Brownell 
181ffa458c1SDavid Brownell #define	MAX_12BIT	((1<<12)-1)
182ffa458c1SDavid Brownell 
183ffa458c1SDavid Brownell /* leave ADC powered up (disables penirq) between differential samples */
184de2defd9SImre Deak #define	READ_12BIT_DFR(x, adc, vref) (ADS_START | ADS_A2A1A0_d_ ## x \
185de2defd9SImre Deak 	| ADS_12_BIT | ADS_DFR | \
186de2defd9SImre Deak 	(adc ? ADS_PD10_ADC_ON : 0) | (vref ? ADS_PD10_REF_ON : 0))
187ffa458c1SDavid Brownell 
188de2defd9SImre Deak #define	READ_Y(vref)	(READ_12BIT_DFR(y,  1, vref))
189de2defd9SImre Deak #define	READ_Z1(vref)	(READ_12BIT_DFR(z1, 1, vref))
190de2defd9SImre Deak #define	READ_Z2(vref)	(READ_12BIT_DFR(z2, 1, vref))
191de2defd9SImre Deak #define	READ_X(vref)	(READ_12BIT_DFR(x,  1, vref))
192de2defd9SImre Deak #define	PWRDOWN		(READ_12BIT_DFR(y,  0, 0))	/* LAST */
193ffa458c1SDavid Brownell 
194ffa458c1SDavid Brownell /* single-ended samples need to first power up reference voltage;
195ffa458c1SDavid Brownell  * we leave both ADC and VREF powered
196ffa458c1SDavid Brownell  */
197ffa458c1SDavid Brownell #define	READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \
198ffa458c1SDavid Brownell 	| ADS_12_BIT | ADS_SER)
199ffa458c1SDavid Brownell 
200de2defd9SImre Deak #define	REF_ON	(READ_12BIT_DFR(x, 1, 1))
201de2defd9SImre Deak #define	REF_OFF	(READ_12BIT_DFR(y, 0, 0))
202ffa458c1SDavid Brownell 
2036965eeceSOleksij Rempel /* Order commands in the most optimal way to reduce Vref switching and
2046965eeceSOleksij Rempel  * settling time:
2056965eeceSOleksij Rempel  * Measure:  X; Vref: X+, X-; IN: Y+
2066965eeceSOleksij Rempel  * Measure:  Y; Vref: Y+, Y-; IN: X+
2076965eeceSOleksij Rempel  * Measure: Z1; Vref: Y+, X-; IN: X+
2086965eeceSOleksij Rempel  * Measure: Z2; Vref: Y+, X-; IN: Y-
2096965eeceSOleksij Rempel  */
2106965eeceSOleksij Rempel enum ads7846_cmds {
2116965eeceSOleksij Rempel 	ADS7846_X,
2126965eeceSOleksij Rempel 	ADS7846_Y,
2136965eeceSOleksij Rempel 	ADS7846_Z1,
2146965eeceSOleksij Rempel 	ADS7846_Z2,
2156965eeceSOleksij Rempel 	ADS7846_PWDOWN,
2166965eeceSOleksij Rempel };
2176965eeceSOleksij Rempel 
get_pendown_state(struct ads7846 * ts)218e52cd628SDavid Jander static int get_pendown_state(struct ads7846 *ts)
219e52cd628SDavid Jander {
220e52cd628SDavid Jander 	if (ts->get_pendown_state)
221e52cd628SDavid Jander 		return ts->get_pendown_state();
222e52cd628SDavid Jander 
223767d8336SLinus Walleij 	return gpiod_get_value(ts->gpio_pendown);
224e52cd628SDavid Jander }
225e52cd628SDavid Jander 
ads7846_report_pen_up(struct ads7846 * ts)226e52cd628SDavid Jander static void ads7846_report_pen_up(struct ads7846 *ts)
227e52cd628SDavid Jander {
228e52cd628SDavid Jander 	struct input_dev *input = ts->input;
229e52cd628SDavid Jander 
230e52cd628SDavid Jander 	input_report_key(input, BTN_TOUCH, 0);
231e52cd628SDavid Jander 	input_report_abs(input, ABS_PRESSURE, 0);
232e52cd628SDavid Jander 	input_sync(input);
233e52cd628SDavid Jander 
234e52cd628SDavid Jander 	ts->pendown = false;
235e52cd628SDavid Jander 	dev_vdbg(&ts->spi->dev, "UP\n");
236e52cd628SDavid Jander }
237e52cd628SDavid Jander 
2382991a1caSJason Wang /* Must be called with ts->lock held */
ads7846_stop(struct ads7846 * ts)2392991a1caSJason Wang static void ads7846_stop(struct ads7846 *ts)
2402991a1caSJason Wang {
2412991a1caSJason Wang 	if (!ts->disabled && !ts->suspended) {
2422991a1caSJason Wang 		/* Signal IRQ thread to stop polling and disable the handler. */
2432991a1caSJason Wang 		ts->stopped = true;
2442991a1caSJason Wang 		mb();
2452991a1caSJason Wang 		wake_up(&ts->wait);
2462991a1caSJason Wang 		disable_irq(ts->spi->irq);
2472991a1caSJason Wang 	}
2482991a1caSJason Wang }
2492991a1caSJason Wang 
2502991a1caSJason Wang /* Must be called with ts->lock held */
ads7846_restart(struct ads7846 * ts)2512991a1caSJason Wang static void ads7846_restart(struct ads7846 *ts)
2522991a1caSJason Wang {
2532991a1caSJason Wang 	if (!ts->disabled && !ts->suspended) {
254e52cd628SDavid Jander 		/* Check if pen was released since last stop */
255e52cd628SDavid Jander 		if (ts->pendown && !get_pendown_state(ts))
256e52cd628SDavid Jander 			ads7846_report_pen_up(ts);
257e52cd628SDavid Jander 
2582991a1caSJason Wang 		/* Tell IRQ thread that it may poll the device. */
2592991a1caSJason Wang 		ts->stopped = false;
2602991a1caSJason Wang 		mb();
2612991a1caSJason Wang 		enable_irq(ts->spi->irq);
2622991a1caSJason Wang 	}
2632991a1caSJason Wang }
2642991a1caSJason Wang 
2652991a1caSJason Wang /* Must be called with ts->lock held */
__ads7846_disable(struct ads7846 * ts)2662991a1caSJason Wang static void __ads7846_disable(struct ads7846 *ts)
2672991a1caSJason Wang {
2682991a1caSJason Wang 	ads7846_stop(ts);
2692991a1caSJason Wang 	regulator_disable(ts->reg);
2702991a1caSJason Wang 
2712991a1caSJason Wang 	/*
2722991a1caSJason Wang 	 * We know the chip's in low power mode since we always
2732991a1caSJason Wang 	 * leave it that way after every request
2742991a1caSJason Wang 	 */
2752991a1caSJason Wang }
2762991a1caSJason Wang 
2772991a1caSJason Wang /* Must be called with ts->lock held */
__ads7846_enable(struct ads7846 * ts)2782991a1caSJason Wang static void __ads7846_enable(struct ads7846 *ts)
2792991a1caSJason Wang {
280f94352f8SMark Brown 	int error;
281f94352f8SMark Brown 
282f94352f8SMark Brown 	error = regulator_enable(ts->reg);
283f94352f8SMark Brown 	if (error != 0)
284f94352f8SMark Brown 		dev_err(&ts->spi->dev, "Failed to enable supply: %d\n", error);
285f94352f8SMark Brown 
2862991a1caSJason Wang 	ads7846_restart(ts);
2872991a1caSJason Wang }
2882991a1caSJason Wang 
ads7846_disable(struct ads7846 * ts)2892991a1caSJason Wang static void ads7846_disable(struct ads7846 *ts)
2902991a1caSJason Wang {
2912991a1caSJason Wang 	mutex_lock(&ts->lock);
2922991a1caSJason Wang 
2932991a1caSJason Wang 	if (!ts->disabled) {
2942991a1caSJason Wang 
2952991a1caSJason Wang 		if  (!ts->suspended)
2962991a1caSJason Wang 			__ads7846_disable(ts);
2972991a1caSJason Wang 
2982991a1caSJason Wang 		ts->disabled = true;
2992991a1caSJason Wang 	}
3002991a1caSJason Wang 
3012991a1caSJason Wang 	mutex_unlock(&ts->lock);
3022991a1caSJason Wang }
3032991a1caSJason Wang 
ads7846_enable(struct ads7846 * ts)3042991a1caSJason Wang static void ads7846_enable(struct ads7846 *ts)
3052991a1caSJason Wang {
3062991a1caSJason Wang 	mutex_lock(&ts->lock);
3072991a1caSJason Wang 
3082991a1caSJason Wang 	if (ts->disabled) {
3092991a1caSJason Wang 
3102991a1caSJason Wang 		ts->disabled = false;
3112991a1caSJason Wang 
3122991a1caSJason Wang 		if (!ts->suspended)
3132991a1caSJason Wang 			__ads7846_enable(ts);
3142991a1caSJason Wang 	}
3152991a1caSJason Wang 
3162991a1caSJason Wang 	mutex_unlock(&ts->lock);
3172991a1caSJason Wang }
3182991a1caSJason Wang 
319ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/
320ffa458c1SDavid Brownell 
321ffa458c1SDavid Brownell /*
322ffa458c1SDavid Brownell  * Non-touchscreen sensors only use single-ended conversions.
3232c8dc071SDavid Brownell  * The range is GND..vREF. The ads7843 and ads7835 must use external vREF;
3242c8dc071SDavid Brownell  * ads7846 lets that pin be unconnected, to use internal vREF.
325ffa458c1SDavid Brownell  */
326ffa458c1SDavid Brownell 
327ffa458c1SDavid Brownell struct ser_req {
328d93f70b2SDavid Brownell 	u8			ref_on;
329ffa458c1SDavid Brownell 	u8			command;
330d93f70b2SDavid Brownell 	u8			ref_off;
331ffa458c1SDavid Brownell 	u16			scratch;
332ffa458c1SDavid Brownell 	struct spi_message	msg;
333ffa458c1SDavid Brownell 	struct spi_transfer	xfer[6];
3341dbe7dadSAlexander Stein 	/*
3351dbe7dadSAlexander Stein 	 * DMA (thus cache coherency maintenance) requires the
3361dbe7dadSAlexander Stein 	 * transfer buffers to live in their own cache lines.
3371dbe7dadSAlexander Stein 	 */
3381dbe7dadSAlexander Stein 	__be16 sample ____cacheline_aligned;
339ffa458c1SDavid Brownell };
340ffa458c1SDavid Brownell 
3413eac5c7eSAnatolij Gustschin struct ads7845_ser_req {
3423eac5c7eSAnatolij Gustschin 	u8			command[3];
3433eac5c7eSAnatolij Gustschin 	struct spi_message	msg;
3443eac5c7eSAnatolij Gustschin 	struct spi_transfer	xfer[2];
3451dbe7dadSAlexander Stein 	/*
3461dbe7dadSAlexander Stein 	 * DMA (thus cache coherency maintenance) requires the
3471dbe7dadSAlexander Stein 	 * transfer buffers to live in their own cache lines.
3481dbe7dadSAlexander Stein 	 */
3491dbe7dadSAlexander Stein 	u8 sample[3] ____cacheline_aligned;
3503eac5c7eSAnatolij Gustschin };
3513eac5c7eSAnatolij Gustschin 
ads7846_read12_ser(struct device * dev,unsigned command)352ffa458c1SDavid Brownell static int ads7846_read12_ser(struct device *dev, unsigned command)
353ffa458c1SDavid Brownell {
354ffa458c1SDavid Brownell 	struct spi_device *spi = to_spi_device(dev);
355ffa458c1SDavid Brownell 	struct ads7846 *ts = dev_get_drvdata(dev);
3562991a1caSJason Wang 	struct ser_req *req;
357ffa458c1SDavid Brownell 	int status;
358ffa458c1SDavid Brownell 
3592991a1caSJason Wang 	req = kzalloc(sizeof *req, GFP_KERNEL);
360ffa458c1SDavid Brownell 	if (!req)
361ffa458c1SDavid Brownell 		return -ENOMEM;
362ffa458c1SDavid Brownell 
3630b7018aaSImre Deak 	spi_message_init(&req->msg);
3648275c642SVitaly Wool 
3652c8dc071SDavid Brownell 	/* maybe turn on internal vREF, and let it settle */
366ebcaaad9SAlexander Stein 	if (ts->use_internal) {
367d93f70b2SDavid Brownell 		req->ref_on = REF_ON;
368d93f70b2SDavid Brownell 		req->xfer[0].tx_buf = &req->ref_on;
369ffa458c1SDavid Brownell 		req->xfer[0].len = 1;
3702c8dc071SDavid Brownell 		spi_message_add_tail(&req->xfer[0], &req->msg);
3712c8dc071SDavid Brownell 
372ffa458c1SDavid Brownell 		req->xfer[1].rx_buf = &req->scratch;
373ffa458c1SDavid Brownell 		req->xfer[1].len = 2;
374ffa458c1SDavid Brownell 
3752c8dc071SDavid Brownell 		/* for 1uF, settle for 800 usec; no cap, 100 usec.  */
3760dfed6dcSAlexandru Ardelean 		req->xfer[1].delay.value = ts->vref_delay_usecs;
3770dfed6dcSAlexandru Ardelean 		req->xfer[1].delay.unit = SPI_DELAY_UNIT_USECS;
3782c8dc071SDavid Brownell 		spi_message_add_tail(&req->xfer[1], &req->msg);
379ebcaaad9SAlexander Stein 
380ebcaaad9SAlexander Stein 		/* Enable reference voltage */
381ebcaaad9SAlexander Stein 		command |= ADS_PD10_REF_ON;
3822c8dc071SDavid Brownell 	}
383ffa458c1SDavid Brownell 
384ebcaaad9SAlexander Stein 	/* Enable ADC in every case */
385ebcaaad9SAlexander Stein 	command |= ADS_PD10_ADC_ON;
386ebcaaad9SAlexander Stein 
387ffa458c1SDavid Brownell 	/* take sample */
388ffa458c1SDavid Brownell 	req->command = (u8) command;
389ffa458c1SDavid Brownell 	req->xfer[2].tx_buf = &req->command;
390ffa458c1SDavid Brownell 	req->xfer[2].len = 1;
3912c8dc071SDavid Brownell 	spi_message_add_tail(&req->xfer[2], &req->msg);
3922c8dc071SDavid Brownell 
393ffa458c1SDavid Brownell 	req->xfer[3].rx_buf = &req->sample;
394ffa458c1SDavid Brownell 	req->xfer[3].len = 2;
3952c8dc071SDavid Brownell 	spi_message_add_tail(&req->xfer[3], &req->msg);
396ffa458c1SDavid Brownell 
397ffa458c1SDavid Brownell 	/* REVISIT:  take a few more samples, and compare ... */
398ffa458c1SDavid Brownell 
399969111e9SNicolas Ferre 	/* converter in low power mode & enable PENIRQ */
400969111e9SNicolas Ferre 	req->ref_off = PWRDOWN;
401d93f70b2SDavid Brownell 	req->xfer[4].tx_buf = &req->ref_off;
402ffa458c1SDavid Brownell 	req->xfer[4].len = 1;
4032c8dc071SDavid Brownell 	spi_message_add_tail(&req->xfer[4], &req->msg);
4042c8dc071SDavid Brownell 
405ffa458c1SDavid Brownell 	req->xfer[5].rx_buf = &req->scratch;
406ffa458c1SDavid Brownell 	req->xfer[5].len = 2;
407ffa458c1SDavid Brownell 	CS_CHANGE(req->xfer[5]);
4082c8dc071SDavid Brownell 	spi_message_add_tail(&req->xfer[5], &req->msg);
409ffa458c1SDavid Brownell 
4102991a1caSJason Wang 	mutex_lock(&ts->lock);
4112991a1caSJason Wang 	ads7846_stop(ts);
412ffa458c1SDavid Brownell 	status = spi_sync(spi, &req->msg);
4132991a1caSJason Wang 	ads7846_restart(ts);
4142991a1caSJason Wang 	mutex_unlock(&ts->lock);
415ffa458c1SDavid Brownell 
416c24b2602SMarc Pignat 	if (status == 0) {
4179084533eSDavid Brownell 		/* on-wire is a must-ignore bit, a BE12 value, then padding */
4187c6d0ee1SDavid Brownell 		status = be16_to_cpu(req->sample);
4197c6d0ee1SDavid Brownell 		status = status >> 3;
4207c6d0ee1SDavid Brownell 		status &= 0x0fff;
421c24b2602SMarc Pignat 	}
4229084533eSDavid Brownell 
4239084533eSDavid Brownell 	kfree(req);
4247c6d0ee1SDavid Brownell 	return status;
425ffa458c1SDavid Brownell }
426ffa458c1SDavid Brownell 
ads7845_read12_ser(struct device * dev,unsigned command)4273eac5c7eSAnatolij Gustschin static int ads7845_read12_ser(struct device *dev, unsigned command)
4283eac5c7eSAnatolij Gustschin {
4293eac5c7eSAnatolij Gustschin 	struct spi_device *spi = to_spi_device(dev);
4303eac5c7eSAnatolij Gustschin 	struct ads7846 *ts = dev_get_drvdata(dev);
4312991a1caSJason Wang 	struct ads7845_ser_req *req;
4323eac5c7eSAnatolij Gustschin 	int status;
4333eac5c7eSAnatolij Gustschin 
4342991a1caSJason Wang 	req = kzalloc(sizeof *req, GFP_KERNEL);
4353eac5c7eSAnatolij Gustschin 	if (!req)
4363eac5c7eSAnatolij Gustschin 		return -ENOMEM;
4373eac5c7eSAnatolij Gustschin 
4383eac5c7eSAnatolij Gustschin 	spi_message_init(&req->msg);
4393eac5c7eSAnatolij Gustschin 
4403eac5c7eSAnatolij Gustschin 	req->command[0] = (u8) command;
4413eac5c7eSAnatolij Gustschin 	req->xfer[0].tx_buf = req->command;
4423eac5c7eSAnatolij Gustschin 	req->xfer[0].rx_buf = req->sample;
4433eac5c7eSAnatolij Gustschin 	req->xfer[0].len = 3;
4443eac5c7eSAnatolij Gustschin 	spi_message_add_tail(&req->xfer[0], &req->msg);
4453eac5c7eSAnatolij Gustschin 
4462991a1caSJason Wang 	mutex_lock(&ts->lock);
4472991a1caSJason Wang 	ads7846_stop(ts);
4483eac5c7eSAnatolij Gustschin 	status = spi_sync(spi, &req->msg);
4492991a1caSJason Wang 	ads7846_restart(ts);
4502991a1caSJason Wang 	mutex_unlock(&ts->lock);
4513eac5c7eSAnatolij Gustschin 
4523eac5c7eSAnatolij Gustschin 	if (status == 0) {
4533eac5c7eSAnatolij Gustschin 		/* BE12 value, then padding */
45403e2c9c7SDmitry Torokhov 		status = get_unaligned_be16(&req->sample[1]);
4553eac5c7eSAnatolij Gustschin 		status = status >> 3;
4563eac5c7eSAnatolij Gustschin 		status &= 0x0fff;
4573eac5c7eSAnatolij Gustschin 	}
4583eac5c7eSAnatolij Gustschin 
4593eac5c7eSAnatolij Gustschin 	kfree(req);
4603eac5c7eSAnatolij Gustschin 	return status;
4613eac5c7eSAnatolij Gustschin }
4623eac5c7eSAnatolij Gustschin 
463c52b4fc7SFabio Estevam #if IS_ENABLED(CONFIG_HWMON)
4642c8dc071SDavid Brownell 
4652c8dc071SDavid Brownell #define SHOW(name, var, adjust) static ssize_t \
466ffa458c1SDavid Brownell name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
467ffa458c1SDavid Brownell { \
4682c8dc071SDavid Brownell 	struct ads7846 *ts = dev_get_drvdata(dev); \
4692fdf4cd9SAlexander Stein 	ssize_t v = ads7846_read12_ser(&ts->spi->dev, \
470ebcaaad9SAlexander Stein 			READ_12BIT_SER(var)); \
471ffa458c1SDavid Brownell 	if (v < 0) \
472ffa458c1SDavid Brownell 		return v; \
4732c8dc071SDavid Brownell 	return sprintf(buf, "%u\n", adjust(ts, v)); \
474ffa458c1SDavid Brownell } \
475ffa458c1SDavid Brownell static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL);
476ffa458c1SDavid Brownell 
4772c8dc071SDavid Brownell 
478b731d7b6SAdam Buchbinder /* Sysfs conventions report temperatures in millidegrees Celsius.
4792c8dc071SDavid Brownell  * ADS7846 could use the low-accuracy two-sample scheme, but can't do the high
4802c8dc071SDavid Brownell  * accuracy scheme without calibration data.  For now we won't try either;
4812c8dc071SDavid Brownell  * userspace sees raw sensor values, and must scale/calibrate appropriately.
4822c8dc071SDavid Brownell  */
null_adjust(struct ads7846 * ts,ssize_t v)4832c8dc071SDavid Brownell static inline unsigned null_adjust(struct ads7846 *ts, ssize_t v)
4842c8dc071SDavid Brownell {
4852c8dc071SDavid Brownell 	return v;
4862c8dc071SDavid Brownell }
4872c8dc071SDavid Brownell 
SHOW(temp0,temp0,null_adjust)4882c8dc071SDavid Brownell SHOW(temp0, temp0, null_adjust)		/* temp1_input */
4892c8dc071SDavid Brownell SHOW(temp1, temp1, null_adjust)		/* temp2_input */
4902c8dc071SDavid Brownell 
4912c8dc071SDavid Brownell 
4922c8dc071SDavid Brownell /* sysfs conventions report voltages in millivolts.  We can convert voltages
4932c8dc071SDavid Brownell  * if we know vREF.  userspace may need to scale vAUX to match the board's
4942c8dc071SDavid Brownell  * external resistors; we assume that vBATT only uses the internal ones.
4952c8dc071SDavid Brownell  */
4962c8dc071SDavid Brownell static inline unsigned vaux_adjust(struct ads7846 *ts, ssize_t v)
4972c8dc071SDavid Brownell {
4982c8dc071SDavid Brownell 	unsigned retval = v;
4992c8dc071SDavid Brownell 
5002c8dc071SDavid Brownell 	/* external resistors may scale vAUX into 0..vREF */
5017c6d0ee1SDavid Brownell 	retval *= ts->vref_mv;
5022c8dc071SDavid Brownell 	retval = retval >> 12;
5032991a1caSJason Wang 
5042c8dc071SDavid Brownell 	return retval;
5052c8dc071SDavid Brownell }
5062c8dc071SDavid Brownell 
vbatt_adjust(struct ads7846 * ts,ssize_t v)5072c8dc071SDavid Brownell static inline unsigned vbatt_adjust(struct ads7846 *ts, ssize_t v)
5082c8dc071SDavid Brownell {
5092c8dc071SDavid Brownell 	unsigned retval = vaux_adjust(ts, v);
5102c8dc071SDavid Brownell 
5112c8dc071SDavid Brownell 	/* ads7846 has a resistor ladder to scale this signal down */
5122c8dc071SDavid Brownell 	if (ts->model == 7846)
5132c8dc071SDavid Brownell 		retval *= 4;
5142991a1caSJason Wang 
5152c8dc071SDavid Brownell 	return retval;
5162c8dc071SDavid Brownell }
5172c8dc071SDavid Brownell 
SHOW(in0_input,vaux,vaux_adjust)5182c8dc071SDavid Brownell SHOW(in0_input, vaux, vaux_adjust)
5192c8dc071SDavid Brownell SHOW(in1_input, vbatt, vbatt_adjust)
5202c8dc071SDavid Brownell 
521e585c40bSGuenter Roeck static umode_t ads7846_is_visible(struct kobject *kobj, struct attribute *attr,
522e585c40bSGuenter Roeck 				  int index)
523e585c40bSGuenter Roeck {
5243fe781f4SWang Qing 	struct device *dev = kobj_to_dev(kobj);
525e585c40bSGuenter Roeck 	struct ads7846 *ts = dev_get_drvdata(dev);
526e585c40bSGuenter Roeck 
527e585c40bSGuenter Roeck 	if (ts->model == 7843 && index < 2)	/* in0, in1 */
528e585c40bSGuenter Roeck 		return 0;
529e585c40bSGuenter Roeck 	if (ts->model == 7845 && index != 2)	/* in0 */
530e585c40bSGuenter Roeck 		return 0;
531e585c40bSGuenter Roeck 
532e585c40bSGuenter Roeck 	return attr->mode;
533e585c40bSGuenter Roeck }
534e585c40bSGuenter Roeck 
5352c8dc071SDavid Brownell static struct attribute *ads7846_attributes[] = {
536e585c40bSGuenter Roeck 	&dev_attr_temp0.attr,		/* 0 */
537e585c40bSGuenter Roeck 	&dev_attr_temp1.attr,		/* 1 */
538e585c40bSGuenter Roeck 	&dev_attr_in0_input.attr,	/* 2 */
539e585c40bSGuenter Roeck 	&dev_attr_in1_input.attr,	/* 3 */
5402c8dc071SDavid Brownell 	NULL,
5412c8dc071SDavid Brownell };
5422c8dc071SDavid Brownell 
5439e938decSArvind Yadav static const struct attribute_group ads7846_attr_group = {
5442c8dc071SDavid Brownell 	.attrs = ads7846_attributes,
545e585c40bSGuenter Roeck 	.is_visible = ads7846_is_visible,
5462c8dc071SDavid Brownell };
547e585c40bSGuenter Roeck __ATTRIBUTE_GROUPS(ads7846_attr);
5482c8dc071SDavid Brownell 
ads784x_hwmon_register(struct spi_device * spi,struct ads7846 * ts)5492c8dc071SDavid Brownell static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
5502c8dc071SDavid Brownell {
551845ef3a7SDaniel Mack 	struct device *hwmon;
552845ef3a7SDaniel Mack 
5532c8dc071SDavid Brownell 	/* hwmon sensors need a reference voltage */
5542c8dc071SDavid Brownell 	switch (ts->model) {
5552c8dc071SDavid Brownell 	case 7846:
5567c6d0ee1SDavid Brownell 		if (!ts->vref_mv) {
5572c8dc071SDavid Brownell 			dev_dbg(&spi->dev, "assuming 2.5V internal vREF\n");
5587c6d0ee1SDavid Brownell 			ts->vref_mv = 2500;
559ebcaaad9SAlexander Stein 			ts->use_internal = true;
5602c8dc071SDavid Brownell 		}
5612c8dc071SDavid Brownell 		break;
5622c8dc071SDavid Brownell 	case 7845:
5632c8dc071SDavid Brownell 	case 7843:
5647c6d0ee1SDavid Brownell 		if (!ts->vref_mv) {
5652c8dc071SDavid Brownell 			dev_warn(&spi->dev,
5662c8dc071SDavid Brownell 				"external vREF for ADS%d not specified\n",
5672c8dc071SDavid Brownell 				ts->model);
5682c8dc071SDavid Brownell 			return 0;
5692c8dc071SDavid Brownell 		}
5702c8dc071SDavid Brownell 		break;
5712c8dc071SDavid Brownell 	}
5722c8dc071SDavid Brownell 
573845ef3a7SDaniel Mack 	hwmon = devm_hwmon_device_register_with_groups(&spi->dev,
574845ef3a7SDaniel Mack 						       spi->modalias, ts,
575845ef3a7SDaniel Mack 						       ads7846_attr_groups);
5762c8dc071SDavid Brownell 
577845ef3a7SDaniel Mack 	return PTR_ERR_OR_ZERO(hwmon);
5782c8dc071SDavid Brownell }
5792c8dc071SDavid Brownell 
5802c8dc071SDavid Brownell #else
ads784x_hwmon_register(struct spi_device * spi,struct ads7846 * ts)5812c8dc071SDavid Brownell static inline int ads784x_hwmon_register(struct spi_device *spi,
5822c8dc071SDavid Brownell 					 struct ads7846 *ts)
5832c8dc071SDavid Brownell {
5842c8dc071SDavid Brownell 	return 0;
5852c8dc071SDavid Brownell }
5862c8dc071SDavid Brownell #endif
587ffa458c1SDavid Brownell 
ads7846_pen_down_show(struct device * dev,struct device_attribute * attr,char * buf)588438f2a74SImre Deak static ssize_t ads7846_pen_down_show(struct device *dev,
589438f2a74SImre Deak 				     struct device_attribute *attr, char *buf)
590438f2a74SImre Deak {
5912991a1caSJason Wang 	struct ads7846 *ts = dev_get_drvdata(dev);
5922991a1caSJason Wang 
5932991a1caSJason Wang 	return sprintf(buf, "%u\n", ts->pendown);
594438f2a74SImre Deak }
595438f2a74SImre Deak 
596438f2a74SImre Deak static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
597438f2a74SImre Deak 
ads7846_disable_show(struct device * dev,struct device_attribute * attr,char * buf)5987de90a8cSImre Deak static ssize_t ads7846_disable_show(struct device *dev,
5997de90a8cSImre Deak 				     struct device_attribute *attr, char *buf)
6007de90a8cSImre Deak {
6017de90a8cSImre Deak 	struct ads7846 *ts = dev_get_drvdata(dev);
6027de90a8cSImre Deak 
6037de90a8cSImre Deak 	return sprintf(buf, "%u\n", ts->disabled);
6047de90a8cSImre Deak }
6057de90a8cSImre Deak 
ads7846_disable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)6067de90a8cSImre Deak static ssize_t ads7846_disable_store(struct device *dev,
6077de90a8cSImre Deak 				     struct device_attribute *attr,
6087de90a8cSImre Deak 				     const char *buf, size_t count)
6097de90a8cSImre Deak {
6107de90a8cSImre Deak 	struct ads7846 *ts = dev_get_drvdata(dev);
61176496e7aSJJ Ding 	unsigned int i;
61276496e7aSJJ Ding 	int err;
6137de90a8cSImre Deak 
61476496e7aSJJ Ding 	err = kstrtouint(buf, 10, &i);
61576496e7aSJJ Ding 	if (err)
61676496e7aSJJ Ding 		return err;
617160f1fefSJoe Rouvier 
6187de90a8cSImre Deak 	if (i)
6197de90a8cSImre Deak 		ads7846_disable(ts);
6207de90a8cSImre Deak 	else
6217de90a8cSImre Deak 		ads7846_enable(ts);
6227de90a8cSImre Deak 
6237de90a8cSImre Deak 	return count;
6247de90a8cSImre Deak }
6257de90a8cSImre Deak 
6267de90a8cSImre Deak static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
6277de90a8cSImre Deak 
6282c8dc071SDavid Brownell static struct attribute *ads784x_attributes[] = {
6298dd51650SDmitry Torokhov 	&dev_attr_pen_down.attr,
6308dd51650SDmitry Torokhov 	&dev_attr_disable.attr,
6318dd51650SDmitry Torokhov 	NULL,
6328dd51650SDmitry Torokhov };
6338dd51650SDmitry Torokhov 
6349e938decSArvind Yadav static const struct attribute_group ads784x_attr_group = {
6352c8dc071SDavid Brownell 	.attrs = ads784x_attributes,
6368dd51650SDmitry Torokhov };
6378dd51650SDmitry Torokhov 
638ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/
639ffa458c1SDavid Brownell 
null_wait_for_sync(void)640fd746d54SEric Miao static void null_wait_for_sync(void)
641fd746d54SEric Miao {
642fd746d54SEric Miao }
643fd746d54SEric Miao 
ads7846_debounce_filter(void * ads,int data_idx,int * val)6442991a1caSJason Wang static int ads7846_debounce_filter(void *ads, int data_idx, int *val)
645ffa458c1SDavid Brownell {
646ffa458c1SDavid Brownell 	struct ads7846 *ts = ads;
6472991a1caSJason Wang 
6482991a1caSJason Wang 	if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) {
6492991a1caSJason Wang 		/* Start over collecting consistent readings. */
6502991a1caSJason Wang 		ts->read_rep = 0;
6512991a1caSJason Wang 		/*
6522991a1caSJason Wang 		 * Repeat it, if this was the first read or the read
6532991a1caSJason Wang 		 * wasn't consistent enough.
6542991a1caSJason Wang 		 */
6552991a1caSJason Wang 		if (ts->read_cnt < ts->debounce_max) {
6562991a1caSJason Wang 			ts->last_read = *val;
6572991a1caSJason Wang 			ts->read_cnt++;
6582991a1caSJason Wang 			return ADS7846_FILTER_REPEAT;
6592991a1caSJason Wang 		} else {
6602991a1caSJason Wang 			/*
6612991a1caSJason Wang 			 * Maximum number of debouncing reached and still
6622991a1caSJason Wang 			 * not enough number of consistent readings. Abort
6632991a1caSJason Wang 			 * the whole sample, repeat it in the next sampling
6642991a1caSJason Wang 			 * period.
6652991a1caSJason Wang 			 */
6662991a1caSJason Wang 			ts->read_cnt = 0;
6672991a1caSJason Wang 			return ADS7846_FILTER_IGNORE;
6682991a1caSJason Wang 		}
6692991a1caSJason Wang 	} else {
6702991a1caSJason Wang 		if (++ts->read_rep > ts->debounce_rep) {
6712991a1caSJason Wang 			/*
6722991a1caSJason Wang 			 * Got a good reading for this coordinate,
6732991a1caSJason Wang 			 * go for the next one.
6742991a1caSJason Wang 			 */
6752991a1caSJason Wang 			ts->read_cnt = 0;
6762991a1caSJason Wang 			ts->read_rep = 0;
6772991a1caSJason Wang 			return ADS7846_FILTER_OK;
6782991a1caSJason Wang 		} else {
6792991a1caSJason Wang 			/* Read more values that are consistent. */
6802991a1caSJason Wang 			ts->read_cnt++;
6812991a1caSJason Wang 			return ADS7846_FILTER_REPEAT;
6822991a1caSJason Wang 		}
6832991a1caSJason Wang 	}
6842991a1caSJason Wang }
6852991a1caSJason Wang 
ads7846_no_filter(void * ads,int data_idx,int * val)6862991a1caSJason Wang static int ads7846_no_filter(void *ads, int data_idx, int *val)
6872991a1caSJason Wang {
6882991a1caSJason Wang 	return ADS7846_FILTER_OK;
6892991a1caSJason Wang }
6902991a1caSJason Wang 
ads7846_get_value(struct ads7846_buf * buf)6916965eeceSOleksij Rempel static int ads7846_get_value(struct ads7846_buf *buf)
6922991a1caSJason Wang {
693879f2feaSAndrey Gelman 	int value;
6942991a1caSJason Wang 
6956965eeceSOleksij Rempel 	value = be16_to_cpup(&buf->data);
696879f2feaSAndrey Gelman 
697879f2feaSAndrey Gelman 	/* enforce ADC output is 12 bits width */
698879f2feaSAndrey Gelman 	return (value >> 3) & 0xfff;
6992991a1caSJason Wang }
7002991a1caSJason Wang 
ads7846_set_cmd_val(struct ads7846 * ts,enum ads7846_cmds cmd_idx,u16 val)7016965eeceSOleksij Rempel static void ads7846_set_cmd_val(struct ads7846 *ts, enum ads7846_cmds cmd_idx,
7026965eeceSOleksij Rempel 				u16 val)
7032991a1caSJason Wang {
7046965eeceSOleksij Rempel 	struct ads7846_packet *packet = ts->packet;
7052991a1caSJason Wang 
7066965eeceSOleksij Rempel 	switch (cmd_idx) {
7076965eeceSOleksij Rempel 	case ADS7846_Y:
7086965eeceSOleksij Rempel 		packet->y = val;
7096965eeceSOleksij Rempel 		break;
7106965eeceSOleksij Rempel 	case ADS7846_X:
7116965eeceSOleksij Rempel 		packet->x = val;
7126965eeceSOleksij Rempel 		break;
7136965eeceSOleksij Rempel 	case ADS7846_Z1:
7146965eeceSOleksij Rempel 		packet->z1 = val;
7156965eeceSOleksij Rempel 		break;
7166965eeceSOleksij Rempel 	case ADS7846_Z2:
7176965eeceSOleksij Rempel 		packet->z2 = val;
7186965eeceSOleksij Rempel 		break;
7196965eeceSOleksij Rempel 	default:
7206965eeceSOleksij Rempel 		WARN_ON_ONCE(1);
7216965eeceSOleksij Rempel 	}
7226965eeceSOleksij Rempel }
7236965eeceSOleksij Rempel 
ads7846_get_cmd(enum ads7846_cmds cmd_idx,int vref)7246965eeceSOleksij Rempel static u8 ads7846_get_cmd(enum ads7846_cmds cmd_idx, int vref)
7256965eeceSOleksij Rempel {
7266965eeceSOleksij Rempel 	switch (cmd_idx) {
7276965eeceSOleksij Rempel 	case ADS7846_Y:
7286965eeceSOleksij Rempel 		return READ_Y(vref);
7296965eeceSOleksij Rempel 	case ADS7846_X:
7306965eeceSOleksij Rempel 		return READ_X(vref);
7316965eeceSOleksij Rempel 
7326965eeceSOleksij Rempel 	/* 7846 specific commands  */
7336965eeceSOleksij Rempel 	case ADS7846_Z1:
7346965eeceSOleksij Rempel 		return READ_Z1(vref);
7356965eeceSOleksij Rempel 	case ADS7846_Z2:
7366965eeceSOleksij Rempel 		return READ_Z2(vref);
7376965eeceSOleksij Rempel 	case ADS7846_PWDOWN:
7386965eeceSOleksij Rempel 		return PWRDOWN;
7396965eeceSOleksij Rempel 	default:
7406965eeceSOleksij Rempel 		WARN_ON_ONCE(1);
7416965eeceSOleksij Rempel 	}
7426965eeceSOleksij Rempel 
7436965eeceSOleksij Rempel 	return 0;
7446965eeceSOleksij Rempel }
7456965eeceSOleksij Rempel 
ads7846_cmd_need_settle(enum ads7846_cmds cmd_idx)7466965eeceSOleksij Rempel static bool ads7846_cmd_need_settle(enum ads7846_cmds cmd_idx)
7476965eeceSOleksij Rempel {
7486965eeceSOleksij Rempel 	switch (cmd_idx) {
7496965eeceSOleksij Rempel 	case ADS7846_X:
7506965eeceSOleksij Rempel 	case ADS7846_Y:
7516965eeceSOleksij Rempel 	case ADS7846_Z1:
7526965eeceSOleksij Rempel 	case ADS7846_Z2:
7536965eeceSOleksij Rempel 		return true;
7546965eeceSOleksij Rempel 	case ADS7846_PWDOWN:
7556965eeceSOleksij Rempel 		return false;
7566965eeceSOleksij Rempel 	default:
7576965eeceSOleksij Rempel 		WARN_ON_ONCE(1);
7586965eeceSOleksij Rempel 	}
7596965eeceSOleksij Rempel 
7606965eeceSOleksij Rempel 	return false;
7616965eeceSOleksij Rempel }
7626965eeceSOleksij Rempel 
ads7846_filter(struct ads7846 * ts)7636965eeceSOleksij Rempel static int ads7846_filter(struct ads7846 *ts)
7646965eeceSOleksij Rempel {
7656965eeceSOleksij Rempel 	struct ads7846_packet *packet = ts->packet;
7666965eeceSOleksij Rempel 	int action;
7676965eeceSOleksij Rempel 	int val;
7686965eeceSOleksij Rempel 	unsigned int cmd_idx, b;
7696965eeceSOleksij Rempel 
7706965eeceSOleksij Rempel 	packet->ignore = false;
7716965eeceSOleksij Rempel 	for (cmd_idx = packet->last_cmd_idx; cmd_idx < packet->cmds - 1; cmd_idx++) {
7726965eeceSOleksij Rempel 		struct ads7846_buf_layout *l = &packet->l[cmd_idx];
7736965eeceSOleksij Rempel 
7746965eeceSOleksij Rempel 		packet->last_cmd_idx = cmd_idx;
7756965eeceSOleksij Rempel 
7766965eeceSOleksij Rempel 		for (b = l->skip; b < l->count; b++) {
7776965eeceSOleksij Rempel 			val = ads7846_get_value(&packet->rx[l->offset + b]);
7786965eeceSOleksij Rempel 
7796965eeceSOleksij Rempel 			action = ts->filter(ts->filter_data, cmd_idx, &val);
7806965eeceSOleksij Rempel 			if (action == ADS7846_FILTER_REPEAT) {
7816965eeceSOleksij Rempel 				if (b == l->count - 1)
7826965eeceSOleksij Rempel 					return -EAGAIN;
7836965eeceSOleksij Rempel 			} else if (action == ADS7846_FILTER_OK) {
7846965eeceSOleksij Rempel 				ads7846_set_cmd_val(ts, cmd_idx, val);
7856965eeceSOleksij Rempel 				break;
7866965eeceSOleksij Rempel 			} else {
7876965eeceSOleksij Rempel 				packet->ignore = true;
7886965eeceSOleksij Rempel 				return 0;
7896965eeceSOleksij Rempel 			}
7906965eeceSOleksij Rempel 		}
7916965eeceSOleksij Rempel 	}
7926965eeceSOleksij Rempel 
7936965eeceSOleksij Rempel 	return 0;
7942991a1caSJason Wang }
7952991a1caSJason Wang 
ads7846_read_state(struct ads7846 * ts)7962991a1caSJason Wang static void ads7846_read_state(struct ads7846 *ts)
7972991a1caSJason Wang {
798e8f462d2SDmitry Torokhov 	struct ads7846_packet *packet = ts->packet;
7992991a1caSJason Wang 	struct spi_message *m;
8002991a1caSJason Wang 	int msg_idx = 0;
8012991a1caSJason Wang 	int error;
8022991a1caSJason Wang 
8036965eeceSOleksij Rempel 	packet->last_cmd_idx = 0;
8042991a1caSJason Wang 
8056965eeceSOleksij Rempel 	while (true) {
8062991a1caSJason Wang 		ts->wait_for_sync();
8072991a1caSJason Wang 
8082991a1caSJason Wang 		m = &ts->msg[msg_idx];
8092991a1caSJason Wang 		error = spi_sync(ts->spi, m);
8102991a1caSJason Wang 		if (error) {
811c8986208SMark Brown 			dev_err(&ts->spi->dev, "spi_sync --> %d\n", error);
8126965eeceSOleksij Rempel 			packet->ignore = true;
8132991a1caSJason Wang 			return;
8142991a1caSJason Wang 		}
8152991a1caSJason Wang 
8166965eeceSOleksij Rempel 		error = ads7846_filter(ts);
8176965eeceSOleksij Rempel 		if (error)
8182991a1caSJason Wang 			continue;
8192991a1caSJason Wang 
8206965eeceSOleksij Rempel 		return;
8212991a1caSJason Wang 	}
8222991a1caSJason Wang }
8232991a1caSJason Wang 
ads7846_report_state(struct ads7846 * ts)8242991a1caSJason Wang static void ads7846_report_state(struct ads7846 *ts)
8252991a1caSJason Wang {
8262991a1caSJason Wang 	struct ads7846_packet *packet = ts->packet;
8272991a1caSJason Wang 	unsigned int Rt;
828ffa458c1SDavid Brownell 	u16 x, y, z1, z2;
829ffa458c1SDavid Brownell 
8306965eeceSOleksij Rempel 	x = packet->x;
8316965eeceSOleksij Rempel 	y = packet->y;
8323eac5c7eSAnatolij Gustschin 	if (ts->model == 7845) {
8333eac5c7eSAnatolij Gustschin 		z1 = 0;
8343eac5c7eSAnatolij Gustschin 		z2 = 0;
8353eac5c7eSAnatolij Gustschin 	} else {
8366965eeceSOleksij Rempel 		z1 = packet->z1;
8376965eeceSOleksij Rempel 		z2 = packet->z2;
8383eac5c7eSAnatolij Gustschin 	}
839ffa458c1SDavid Brownell 
840ffa458c1SDavid Brownell 	/* range filtering */
841ffa458c1SDavid Brownell 	if (x == MAX_12BIT)
842ffa458c1SDavid Brownell 		x = 0;
843ffa458c1SDavid Brownell 
844fa9f4275SLuca Ellero 	if (ts->model == 7843 || ts->model == 7845) {
8459460b652SHans-Christian Egtvedt 		Rt = ts->pressure_max / 2;
8469460b652SHans-Christian Egtvedt 	} else if (likely(x && z1)) {
847ffa458c1SDavid Brownell 		/* compute touch pressure resistance using equation #2 */
848ffa458c1SDavid Brownell 		Rt = z2;
849ffa458c1SDavid Brownell 		Rt -= z1;
850ffa458c1SDavid Brownell 		Rt *= ts->x_plate_ohms;
851820830ecSOleksij Rempel 		Rt = DIV_ROUND_CLOSEST(Rt, 16);
852820830ecSOleksij Rempel 		Rt *= x;
853ffa458c1SDavid Brownell 		Rt /= z1;
854820830ecSOleksij Rempel 		Rt = DIV_ROUND_CLOSEST(Rt, 256);
8559460b652SHans-Christian Egtvedt 	} else {
856ffa458c1SDavid Brownell 		Rt = 0;
8579460b652SHans-Christian Egtvedt 	}
858969111e9SNicolas Ferre 
8592991a1caSJason Wang 	/*
8602991a1caSJason Wang 	 * Sample found inconsistent by debouncing or pressure is beyond
861d5b415c9SImre Deak 	 * the maximum. Don't report it to user space, repeat at least
8621936d590SImre Deak 	 * once more the measurement
8631936d590SImre Deak 	 */
8646965eeceSOleksij Rempel 	if (packet->ignore || Rt > ts->pressure_max) {
86552ce4eaaSPavel Machek 		dev_vdbg(&ts->spi->dev, "ignored %d pressure %d\n",
8666965eeceSOleksij Rempel 			 packet->ignore, Rt);
867d5b415c9SImre Deak 		return;
868d5b415c9SImre Deak 	}
869d5b415c9SImre Deak 
8702991a1caSJason Wang 	/*
8712991a1caSJason Wang 	 * Maybe check the pendown state before reporting. This discards
8721d25891fSSemih Hazar 	 * false readings when the pen is lifted.
8731d25891fSSemih Hazar 	 */
8741d25891fSSemih Hazar 	if (ts->penirq_recheck_delay_usecs) {
8751d25891fSSemih Hazar 		udelay(ts->penirq_recheck_delay_usecs);
8764d5975e5SEric Miao 		if (!get_pendown_state(ts))
8771d25891fSSemih Hazar 			Rt = 0;
8781d25891fSSemih Hazar 	}
8791d25891fSSemih Hazar 
8802991a1caSJason Wang 	/*
8812991a1caSJason Wang 	 * NOTE: We can't rely on the pressure to determine the pen down
88215e3589eSImre Deak 	 * state, even this controller has a pressure sensor. The pressure
88315e3589eSImre Deak 	 * value can fluctuate for quite a while after lifting the pen and
88415e3589eSImre Deak 	 * in some cases may not even settle at the expected value.
885ffa458c1SDavid Brownell 	 *
88615e3589eSImre Deak 	 * The only safe way to check for the pen up condition is in the
88715e3589eSImre Deak 	 * timer by reading the pen signal state (it's a GPIO _and_ IRQ).
888ffa458c1SDavid Brownell 	 */
889ffa458c1SDavid Brownell 	if (Rt) {
89015e3589eSImre Deak 		struct input_dev *input = ts->input;
891ae82d5abSImre Deak 
8922991a1caSJason Wang 		if (!ts->pendown) {
8932991a1caSJason Wang 			input_report_key(input, BTN_TOUCH, 1);
8942991a1caSJason Wang 			ts->pendown = true;
8952991a1caSJason Wang 			dev_vdbg(&ts->spi->dev, "DOWN\n");
8962991a1caSJason Wang 		}
8972991a1caSJason Wang 
898a2f99330SMarco Felsch 		touchscreen_report_pos(input, &ts->core_prop, x, y, false);
89930ad7ba0SPavel Machek 		input_report_abs(input, ABS_PRESSURE, ts->pressure_max - Rt);
900ffa458c1SDavid Brownell 
90115e3589eSImre Deak 		input_sync(input);
90252ce4eaaSPavel Machek 		dev_vdbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt);
90315e3589eSImre Deak 	}
904ffa458c1SDavid Brownell }
905ffa458c1SDavid Brownell 
ads7846_hard_irq(int irq,void * handle)9062991a1caSJason Wang static irqreturn_t ads7846_hard_irq(int irq, void *handle)
907ffa458c1SDavid Brownell {
9082991a1caSJason Wang 	struct ads7846 *ts = handle;
909ffa458c1SDavid Brownell 
9102991a1caSJason Wang 	return get_pendown_state(ts) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
911da970e69SImre Deak }
912da970e69SImre Deak 
9132991a1caSJason Wang 
ads7846_irq(int irq,void * handle)9142991a1caSJason Wang static irqreturn_t ads7846_irq(int irq, void *handle)
915da970e69SImre Deak {
9162991a1caSJason Wang 	struct ads7846 *ts = handle;
9172991a1caSJason Wang 
9182991a1caSJason Wang 	/* Start with a small delay before checking pendown state */
9192991a1caSJason Wang 	msleep(TS_POLL_DELAY);
9202991a1caSJason Wang 
9212991a1caSJason Wang 	while (!ts->stopped && get_pendown_state(ts)) {
9222991a1caSJason Wang 
9232991a1caSJason Wang 		/* pen is down, continue with the measurement */
9242991a1caSJason Wang 		ads7846_read_state(ts);
9252991a1caSJason Wang 
9262991a1caSJason Wang 		if (!ts->stopped)
9272991a1caSJason Wang 			ads7846_report_state(ts);
9282991a1caSJason Wang 
9292991a1caSJason Wang 		wait_event_timeout(ts->wait, ts->stopped,
9302991a1caSJason Wang 				   msecs_to_jiffies(TS_POLL_PERIOD));
931da970e69SImre Deak 	}
932da970e69SImre Deak 
933e52cd628SDavid Jander 	if (ts->pendown && !ts->stopped)
934e52cd628SDavid Jander 		ads7846_report_pen_up(ts);
93515e3589eSImre Deak 
9367de90a8cSImre Deak 	return IRQ_HANDLED;
937ffa458c1SDavid Brownell }
938ffa458c1SDavid Brownell 
ads7846_suspend(struct device * dev)939f8909d9aSJonathan Cameron static int ads7846_suspend(struct device *dev)
9407de90a8cSImre Deak {
9413c36e719SMark Brown 	struct ads7846 *ts = dev_get_drvdata(dev);
9427de90a8cSImre Deak 
9432991a1caSJason Wang 	mutex_lock(&ts->lock);
9447de90a8cSImre Deak 
9452991a1caSJason Wang 	if (!ts->suspended) {
9467de90a8cSImre Deak 
9472991a1caSJason Wang 		if (!ts->disabled)
9482991a1caSJason Wang 			__ads7846_disable(ts);
9497de90a8cSImre Deak 
950fdba2bb1SRanjith Lohithakshan 		if (device_may_wakeup(&ts->spi->dev))
951fdba2bb1SRanjith Lohithakshan 			enable_irq_wake(ts->spi->irq);
952fdba2bb1SRanjith Lohithakshan 
9532991a1caSJason Wang 		ts->suspended = true;
9542991a1caSJason Wang 	}
9557de90a8cSImre Deak 
9562991a1caSJason Wang 	mutex_unlock(&ts->lock);
9572991a1caSJason Wang 
9582991a1caSJason Wang 	return 0;
959ffa458c1SDavid Brownell }
960ffa458c1SDavid Brownell 
ads7846_resume(struct device * dev)961f8909d9aSJonathan Cameron static int ads7846_resume(struct device *dev)
962ffa458c1SDavid Brownell {
9633c36e719SMark Brown 	struct ads7846 *ts = dev_get_drvdata(dev);
964ffa458c1SDavid Brownell 
9652991a1caSJason Wang 	mutex_lock(&ts->lock);
9662991a1caSJason Wang 
9672991a1caSJason Wang 	if (ts->suspended) {
9682991a1caSJason Wang 
9692991a1caSJason Wang 		ts->suspended = false;
9702991a1caSJason Wang 
971fdba2bb1SRanjith Lohithakshan 		if (device_may_wakeup(&ts->spi->dev))
972fdba2bb1SRanjith Lohithakshan 			disable_irq_wake(ts->spi->irq);
973fdba2bb1SRanjith Lohithakshan 
9742991a1caSJason Wang 		if (!ts->disabled)
9752991a1caSJason Wang 			__ads7846_enable(ts);
9762991a1caSJason Wang 	}
9777de90a8cSImre Deak 
9782991a1caSJason Wang 	mutex_unlock(&ts->lock);
9797de90a8cSImre Deak 
980ffa458c1SDavid Brownell 	return 0;
981ffa458c1SDavid Brownell }
9823c36e719SMark Brown 
983f8909d9aSJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
984ffa458c1SDavid Brownell 
ads7846_setup_pendown(struct spi_device * spi,struct ads7846 * ts,const struct ads7846_platform_data * pdata)9855298cc4cSBill Pemberton static int ads7846_setup_pendown(struct spi_device *spi,
98657691a1eSDmitry Torokhov 				 struct ads7846 *ts,
98757691a1eSDmitry Torokhov 				 const struct ads7846_platform_data *pdata)
9884d5975e5SEric Miao {
9890fbc9fdbSDmitry Torokhov 	/*
9900fbc9fdbSDmitry Torokhov 	 * REVISIT when the irq can be triggered active-low, or if for some
9914d5975e5SEric Miao 	 * reason the touchscreen isn't hooked up, we don't need to access
9924d5975e5SEric Miao 	 * the pendown state.
9934d5975e5SEric Miao 	 */
9944d5975e5SEric Miao 
9954d5975e5SEric Miao 	if (pdata->get_pendown_state) {
9964d5975e5SEric Miao 		ts->get_pendown_state = pdata->get_pendown_state;
9970fbc9fdbSDmitry Torokhov 	} else {
998767d8336SLinus Walleij 		ts->gpio_pendown = gpiod_get(&spi->dev, "pendown", GPIOD_IN);
999767d8336SLinus Walleij 		if (IS_ERR(ts->gpio_pendown)) {
1000767d8336SLinus Walleij 			dev_err(&spi->dev, "failed to request pendown GPIO\n");
1001767d8336SLinus Walleij 			return PTR_ERR(ts->gpio_pendown);
1002767d8336SLinus Walleij 		}
1003767d8336SLinus Walleij 		if (pdata->gpio_pendown_debounce)
1004767d8336SLinus Walleij 			gpiod_set_debounce(ts->gpio_pendown,
1005767d8336SLinus Walleij 					   pdata->gpio_pendown_debounce);
10060fbc9fdbSDmitry Torokhov 	}
10070fbc9fdbSDmitry Torokhov 
10084d5975e5SEric Miao 	return 0;
10094d5975e5SEric Miao }
10104d5975e5SEric Miao 
10112991a1caSJason Wang /*
10122991a1caSJason Wang  * Set up the transfers to read touchscreen state; this assumes we
10132991a1caSJason Wang  * use formula #2 for pressure, not #3.
10142991a1caSJason Wang  */
ads7846_setup_spi_msg(struct ads7846 * ts,const struct ads7846_platform_data * pdata)10156965eeceSOleksij Rempel static int ads7846_setup_spi_msg(struct ads7846 *ts,
10162991a1caSJason Wang 				  const struct ads7846_platform_data *pdata)
10172991a1caSJason Wang {
10182991a1caSJason Wang 	struct spi_message *m = &ts->msg[0];
10192991a1caSJason Wang 	struct spi_transfer *x = ts->xfer;
10202991a1caSJason Wang 	struct ads7846_packet *packet = ts->packet;
10212991a1caSJason Wang 	int vref = pdata->keep_vref_on;
10226965eeceSOleksij Rempel 	unsigned int count, offset = 0;
10236965eeceSOleksij Rempel 	unsigned int cmd_idx, b;
10246965eeceSOleksij Rempel 	unsigned long time;
10256965eeceSOleksij Rempel 	size_t size = 0;
10266965eeceSOleksij Rempel 
10276965eeceSOleksij Rempel 	/* time per bit */
10286965eeceSOleksij Rempel 	time = NSEC_PER_SEC / ts->spi->max_speed_hz;
10296965eeceSOleksij Rempel 
10306965eeceSOleksij Rempel 	count = pdata->settle_delay_usecs * NSEC_PER_USEC / time;
10316965eeceSOleksij Rempel 	packet->count_skip = DIV_ROUND_UP(count, 24);
10326965eeceSOleksij Rempel 
10336965eeceSOleksij Rempel 	if (ts->debounce_max && ts->debounce_rep)
10346965eeceSOleksij Rempel 		/* ads7846_debounce_filter() is making ts->debounce_rep + 2
10356965eeceSOleksij Rempel 		 * reads. So we need to get all samples for normal case. */
10366965eeceSOleksij Rempel 		packet->count = ts->debounce_rep + 2;
10376965eeceSOleksij Rempel 	else
10386965eeceSOleksij Rempel 		packet->count = 1;
10396965eeceSOleksij Rempel 
10406965eeceSOleksij Rempel 	if (ts->model == 7846)
10416965eeceSOleksij Rempel 		packet->cmds = 5; /* x, y, z1, z2, pwdown */
10426965eeceSOleksij Rempel 	else
10436965eeceSOleksij Rempel 		packet->cmds = 3; /* x, y, pwdown */
10446965eeceSOleksij Rempel 
10456965eeceSOleksij Rempel 	for (cmd_idx = 0; cmd_idx < packet->cmds; cmd_idx++) {
10466965eeceSOleksij Rempel 		struct ads7846_buf_layout *l = &packet->l[cmd_idx];
10476965eeceSOleksij Rempel 		unsigned int max_count;
10486965eeceSOleksij Rempel 
104913f82ca3SLuca Ellero 		if (cmd_idx == packet->cmds - 1)
105013f82ca3SLuca Ellero 			cmd_idx = ADS7846_PWDOWN;
105113f82ca3SLuca Ellero 
10526965eeceSOleksij Rempel 		if (ads7846_cmd_need_settle(cmd_idx))
10536965eeceSOleksij Rempel 			max_count = packet->count + packet->count_skip;
10546965eeceSOleksij Rempel 		else
10556965eeceSOleksij Rempel 			max_count = packet->count;
10566965eeceSOleksij Rempel 
10576965eeceSOleksij Rempel 		l->offset = offset;
10586965eeceSOleksij Rempel 		offset += max_count;
10596965eeceSOleksij Rempel 		l->count = max_count;
10606965eeceSOleksij Rempel 		l->skip = packet->count_skip;
10616965eeceSOleksij Rempel 		size += sizeof(*packet->tx) * max_count;
10626965eeceSOleksij Rempel 	}
10636965eeceSOleksij Rempel 
10646965eeceSOleksij Rempel 	packet->tx = devm_kzalloc(&ts->spi->dev, size, GFP_KERNEL);
10656965eeceSOleksij Rempel 	if (!packet->tx)
10666965eeceSOleksij Rempel 		return -ENOMEM;
10676965eeceSOleksij Rempel 
10686965eeceSOleksij Rempel 	packet->rx = devm_kzalloc(&ts->spi->dev, size, GFP_KERNEL);
10696965eeceSOleksij Rempel 	if (!packet->rx)
10706965eeceSOleksij Rempel 		return -ENOMEM;
10712991a1caSJason Wang 
10722991a1caSJason Wang 	if (ts->model == 7873) {
10732991a1caSJason Wang 		/*
10742991a1caSJason Wang 		 * The AD7873 is almost identical to the ADS7846
10752991a1caSJason Wang 		 * keep VREF off during differential/ratiometric
10762991a1caSJason Wang 		 * conversion modes.
10772991a1caSJason Wang 		 */
10782991a1caSJason Wang 		ts->model = 7846;
10792991a1caSJason Wang 		vref = 0;
10802991a1caSJason Wang 	}
10812991a1caSJason Wang 
10822991a1caSJason Wang 	ts->msg_count = 1;
10832991a1caSJason Wang 	spi_message_init(m);
10842991a1caSJason Wang 	m->context = ts;
10852991a1caSJason Wang 
10866965eeceSOleksij Rempel 	for (cmd_idx = 0; cmd_idx < packet->cmds; cmd_idx++) {
10876965eeceSOleksij Rempel 		struct ads7846_buf_layout *l = &packet->l[cmd_idx];
108813f82ca3SLuca Ellero 		u8 cmd;
108913f82ca3SLuca Ellero 
109013f82ca3SLuca Ellero 		if (cmd_idx == packet->cmds - 1)
109113f82ca3SLuca Ellero 			cmd_idx = ADS7846_PWDOWN;
109213f82ca3SLuca Ellero 
109313f82ca3SLuca Ellero 		cmd = ads7846_get_cmd(cmd_idx, vref);
10942991a1caSJason Wang 
10956965eeceSOleksij Rempel 		for (b = 0; b < l->count; b++)
10966965eeceSOleksij Rempel 			packet->tx[l->offset + b].cmd = cmd;
10972991a1caSJason Wang 	}
10982991a1caSJason Wang 
10996965eeceSOleksij Rempel 	x->tx_buf = packet->tx;
11006965eeceSOleksij Rempel 	x->rx_buf = packet->rx;
11016965eeceSOleksij Rempel 	x->len = size;
11022991a1caSJason Wang 	spi_message_add_tail(x, m);
11032991a1caSJason Wang 
11046965eeceSOleksij Rempel 	return 0;
11052991a1caSJason Wang }
11062991a1caSJason Wang 
1107a608026eSDaniel Mack static const struct of_device_id ads7846_dt_ids[] = {
1108a608026eSDaniel Mack 	{ .compatible = "ti,tsc2046",	.data = (void *) 7846 },
1109a608026eSDaniel Mack 	{ .compatible = "ti,ads7843",	.data = (void *) 7843 },
1110a608026eSDaniel Mack 	{ .compatible = "ti,ads7845",	.data = (void *) 7845 },
1111a608026eSDaniel Mack 	{ .compatible = "ti,ads7846",	.data = (void *) 7846 },
1112a608026eSDaniel Mack 	{ .compatible = "ti,ads7873",	.data = (void *) 7873 },
1113a608026eSDaniel Mack 	{ }
1114a608026eSDaniel Mack };
1115a608026eSDaniel Mack MODULE_DEVICE_TABLE(of, ads7846_dt_ids);
1116a608026eSDaniel Mack 
ads7846_get_props(struct device * dev)1117767d8336SLinus Walleij static const struct ads7846_platform_data *ads7846_get_props(struct device *dev)
1118a608026eSDaniel Mack {
1119a608026eSDaniel Mack 	struct ads7846_platform_data *pdata;
1120a2f99330SMarco Felsch 	u32 value;
1121a608026eSDaniel Mack 
1122a608026eSDaniel Mack 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1123a608026eSDaniel Mack 	if (!pdata)
1124a608026eSDaniel Mack 		return ERR_PTR(-ENOMEM);
1125a608026eSDaniel Mack 
1126*11ca6056SArnd Bergmann 	pdata->model = (uintptr_t)device_get_match_data(dev);
1127a608026eSDaniel Mack 
1128767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,vref-delay-usecs",
1129a608026eSDaniel Mack 				 &pdata->vref_delay_usecs);
1130767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,vref-mv", &pdata->vref_mv);
1131767d8336SLinus Walleij 	pdata->keep_vref_on = device_property_read_bool(dev, "ti,keep-vref-on");
1132a608026eSDaniel Mack 
1133767d8336SLinus Walleij 	pdata->swap_xy = device_property_read_bool(dev, "ti,swap-xy");
1134a608026eSDaniel Mack 
1135767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,settle-delay-usec",
1136a608026eSDaniel Mack 				 &pdata->settle_delay_usecs);
1137767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,penirq-recheck-delay-usecs",
1138a608026eSDaniel Mack 				 &pdata->penirq_recheck_delay_usecs);
1139a608026eSDaniel Mack 
1140767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,x-plate-ohms", &pdata->x_plate_ohms);
1141767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,y-plate-ohms", &pdata->y_plate_ohms);
1142a608026eSDaniel Mack 
1143767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,x-min", &pdata->x_min);
1144767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,y-min", &pdata->y_min);
1145767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,x-max", &pdata->x_max);
1146767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,y-max", &pdata->y_max);
1147a608026eSDaniel Mack 
1148a2f99330SMarco Felsch 	/*
1149a2f99330SMarco Felsch 	 * touchscreen-max-pressure gets parsed during
1150a2f99330SMarco Felsch 	 * touchscreen_parse_properties()
1151a2f99330SMarco Felsch 	 */
1152767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,pressure-min", &pdata->pressure_min);
1153767d8336SLinus Walleij 	if (!device_property_read_u32(dev, "touchscreen-min-pressure", &value))
1154a2f99330SMarco Felsch 		pdata->pressure_min = (u16) value;
1155767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,pressure-max", &pdata->pressure_max);
1156a608026eSDaniel Mack 
1157767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,debounce-max", &pdata->debounce_max);
1158767d8336SLinus Walleij 	if (!device_property_read_u32(dev, "touchscreen-average-samples", &value))
1159a2f99330SMarco Felsch 		pdata->debounce_max = (u16) value;
1160767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,debounce-tol", &pdata->debounce_tol);
1161767d8336SLinus Walleij 	device_property_read_u16(dev, "ti,debounce-rep", &pdata->debounce_rep);
1162a608026eSDaniel Mack 
1163767d8336SLinus Walleij 	device_property_read_u32(dev, "ti,pendown-gpio-debounce",
1164a608026eSDaniel Mack 			     &pdata->gpio_pendown_debounce);
1165a608026eSDaniel Mack 
1166767d8336SLinus Walleij 	pdata->wakeup = device_property_read_bool(dev, "wakeup-source") ||
1167767d8336SLinus Walleij 			device_property_read_bool(dev, "linux,wakeup");
1168a608026eSDaniel Mack 
1169a608026eSDaniel Mack 	return pdata;
1170a608026eSDaniel Mack }
1171a608026eSDaniel Mack 
ads7846_regulator_disable(void * regulator)1172845ef3a7SDaniel Mack static void ads7846_regulator_disable(void *regulator)
1173845ef3a7SDaniel Mack {
1174845ef3a7SDaniel Mack 	regulator_disable(regulator);
1175845ef3a7SDaniel Mack }
1176845ef3a7SDaniel Mack 
ads7846_probe(struct spi_device * spi)11775298cc4cSBill Pemberton static int ads7846_probe(struct spi_device *spi)
1178ffa458c1SDavid Brownell {
1179a608026eSDaniel Mack 	const struct ads7846_platform_data *pdata;
1180ffa458c1SDavid Brownell 	struct ads7846 *ts;
1181de609b56SDaniel Mack 	struct device *dev = &spi->dev;
1182e8f462d2SDmitry Torokhov 	struct ads7846_packet *packet;
1183a90f7e98SDmitry Torokhov 	struct input_dev *input_dev;
11840f622bf4SDmitry Torokhov 	unsigned long irq_flags;
1185a90f7e98SDmitry Torokhov 	int err;
1186ffa458c1SDavid Brownell 
1187ffa458c1SDavid Brownell 	if (!spi->irq) {
1188de609b56SDaniel Mack 		dev_dbg(dev, "no IRQ?\n");
1189a608026eSDaniel Mack 		return -EINVAL;
1190ffa458c1SDavid Brownell 	}
1191ffa458c1SDavid Brownell 
1192ffa458c1SDavid Brownell 	/* don't exceed max specified sample rate */
1193d93f70b2SDavid Brownell 	if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
1194de609b56SDaniel Mack 		dev_err(dev, "f(sample) %d KHz?\n",
1195d93f70b2SDavid Brownell 			(spi->max_speed_hz/SAMPLE_BITS)/1000);
1196ffa458c1SDavid Brownell 		return -EINVAL;
1197ffa458c1SDavid Brownell 	}
1198ffa458c1SDavid Brownell 
1199a608026eSDaniel Mack 	/*
1200a608026eSDaniel Mack 	 * We'd set TX word size 8 bits and RX word size to 13 bits ... except
12019084533eSDavid Brownell 	 * that even if the hardware can do that, the SPI controller driver
12029084533eSDavid Brownell 	 * may not.  So we stick to very-portable 8 bit words, both RX and TX.
1203ffa458c1SDavid Brownell 	 */
12049084533eSDavid Brownell 	spi->bits_per_word = 8;
1205376ccca8SOleksij Rempel 	spi->mode &= ~SPI_MODE_X_MASK;
1206376ccca8SOleksij Rempel 	spi->mode |= SPI_MODE_0;
12077937e86aSImre Deak 	err = spi_setup(spi);
12087937e86aSImre Deak 	if (err < 0)
12097937e86aSImre Deak 		return err;
1210ffa458c1SDavid Brownell 
1211845ef3a7SDaniel Mack 	ts = devm_kzalloc(dev, sizeof(struct ads7846), GFP_KERNEL);
1212845ef3a7SDaniel Mack 	if (!ts)
1213845ef3a7SDaniel Mack 		return -ENOMEM;
1214845ef3a7SDaniel Mack 
1215845ef3a7SDaniel Mack 	packet = devm_kzalloc(dev, sizeof(struct ads7846_packet), GFP_KERNEL);
1216845ef3a7SDaniel Mack 	if (!packet)
1217845ef3a7SDaniel Mack 		return -ENOMEM;
1218845ef3a7SDaniel Mack 
1219845ef3a7SDaniel Mack 	input_dev = devm_input_allocate_device(dev);
1220845ef3a7SDaniel Mack 	if (!input_dev)
1221845ef3a7SDaniel Mack 		return -ENOMEM;
1222ffa458c1SDavid Brownell 
1223c12454faSJingoo Han 	spi_set_drvdata(spi, ts);
1224ffa458c1SDavid Brownell 
1225e8f462d2SDmitry Torokhov 	ts->packet = packet;
1226ffa458c1SDavid Brownell 	ts->spi = spi;
1227a90f7e98SDmitry Torokhov 	ts->input = input_dev;
1228ffa458c1SDavid Brownell 
12292991a1caSJason Wang 	mutex_init(&ts->lock);
12302991a1caSJason Wang 	init_waitqueue_head(&ts->wait);
12317de90a8cSImre Deak 
1232de609b56SDaniel Mack 	pdata = dev_get_platdata(dev);
1233a608026eSDaniel Mack 	if (!pdata) {
1234767d8336SLinus Walleij 		pdata = ads7846_get_props(dev);
1235845ef3a7SDaniel Mack 		if (IS_ERR(pdata))
1236845ef3a7SDaniel Mack 			return PTR_ERR(pdata);
1237a608026eSDaniel Mack 	}
1238a608026eSDaniel Mack 
1239ffa458c1SDavid Brownell 	ts->model = pdata->model ? : 7846;
1240ffa458c1SDavid Brownell 	ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
1241ffa458c1SDavid Brownell 	ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
1242a608026eSDaniel Mack 	ts->vref_mv = pdata->vref_mv;
1243a608026eSDaniel Mack 
1244937f5d5eSDaniel Mack 	if (pdata->debounce_max) {
1245d5b415c9SImre Deak 		ts->debounce_max = pdata->debounce_max;
1246da970e69SImre Deak 		if (ts->debounce_max < 2)
1247da970e69SImre Deak 			ts->debounce_max = 2;
1248d5b415c9SImre Deak 		ts->debounce_tol = pdata->debounce_tol;
1249d5b415c9SImre Deak 		ts->debounce_rep = pdata->debounce_rep;
12502991a1caSJason Wang 		ts->filter = ads7846_debounce_filter;
1251da970e69SImre Deak 		ts->filter_data = ts;
12522991a1caSJason Wang 	} else {
1253da970e69SImre Deak 		ts->filter = ads7846_no_filter;
12542991a1caSJason Wang 	}
12554d5975e5SEric Miao 
125657691a1eSDmitry Torokhov 	err = ads7846_setup_pendown(spi, ts, pdata);
12574d5975e5SEric Miao 	if (err)
1258845ef3a7SDaniel Mack 		return err;
1259ffa458c1SDavid Brownell 
12601d25891fSSemih Hazar 	if (pdata->penirq_recheck_delay_usecs)
12611d25891fSSemih Hazar 		ts->penirq_recheck_delay_usecs =
12621d25891fSSemih Hazar 				pdata->penirq_recheck_delay_usecs;
12631d25891fSSemih Hazar 
1264fd746d54SEric Miao 	ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
1265fd746d54SEric Miao 
1266de609b56SDaniel Mack 	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
1267b58895f8SMichael Roth 	snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model);
1268ffa458c1SDavid Brownell 
1269b58895f8SMichael Roth 	input_dev->name = ts->name;
1270a90f7e98SDmitry Torokhov 	input_dev->phys = ts->phys;
1271ffa458c1SDavid Brownell 
12729271cda2SDmitry Torokhov 	input_dev->id.bustype = BUS_SPI;
12739271cda2SDmitry Torokhov 	input_dev->id.product = pdata->model;
12749271cda2SDmitry Torokhov 
1275ccd66139SDmitry Torokhov 	input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
1276a90f7e98SDmitry Torokhov 	input_set_abs_params(input_dev, ABS_X,
1277ffa458c1SDavid Brownell 			pdata->x_min ? : 0,
1278ffa458c1SDavid Brownell 			pdata->x_max ? : MAX_12BIT,
1279ffa458c1SDavid Brownell 			0, 0);
1280a90f7e98SDmitry Torokhov 	input_set_abs_params(input_dev, ABS_Y,
1281ffa458c1SDavid Brownell 			pdata->y_min ? : 0,
1282ffa458c1SDavid Brownell 			pdata->y_max ? : MAX_12BIT,
1283ffa458c1SDavid Brownell 			0, 0);
1284d50584d7SLuca Ellero 	if (ts->model != 7845)
1285a90f7e98SDmitry Torokhov 		input_set_abs_params(input_dev, ABS_PRESSURE,
1286ffa458c1SDavid Brownell 				pdata->pressure_min, pdata->pressure_max, 0, 0);
1287ffa458c1SDavid Brownell 
1288a2f99330SMarco Felsch 	/*
1289a2f99330SMarco Felsch 	 * Parse common framework properties. Must be done here to ensure the
1290a2f99330SMarco Felsch 	 * correct behaviour in case of using the legacy vendor bindings. The
1291a2f99330SMarco Felsch 	 * general binding value overrides the vendor specific one.
1292a2f99330SMarco Felsch 	 */
1293a2f99330SMarco Felsch 	touchscreen_parse_properties(ts->input, false, &ts->core_prop);
1294a2f99330SMarco Felsch 	ts->pressure_max = input_abs_get_max(input_dev, ABS_PRESSURE) ? : ~0;
1295a2f99330SMarco Felsch 
1296a2f99330SMarco Felsch 	/*
1297a2f99330SMarco Felsch 	 * Check if legacy ti,swap-xy binding is used instead of
1298a2f99330SMarco Felsch 	 * touchscreen-swapped-x-y
1299a2f99330SMarco Felsch 	 */
1300a2f99330SMarco Felsch 	if (!ts->core_prop.swap_x_y && pdata->swap_xy) {
1301a2f99330SMarco Felsch 		swap(input_dev->absinfo[ABS_X], input_dev->absinfo[ABS_Y]);
1302a2f99330SMarco Felsch 		ts->core_prop.swap_x_y = true;
1303a2f99330SMarco Felsch 	}
1304a2f99330SMarco Felsch 
13052991a1caSJason Wang 	ads7846_setup_spi_msg(ts, pdata);
1306d5b415c9SImre Deak 
1307845ef3a7SDaniel Mack 	ts->reg = devm_regulator_get(dev, "vcc");
130891143379SGrazvydas Ignotas 	if (IS_ERR(ts->reg)) {
1309067fb2f6SKevin Hilman 		err = PTR_ERR(ts->reg);
1310de609b56SDaniel Mack 		dev_err(dev, "unable to get regulator: %d\n", err);
1311845ef3a7SDaniel Mack 		return err;
131291143379SGrazvydas Ignotas 	}
131391143379SGrazvydas Ignotas 
131491143379SGrazvydas Ignotas 	err = regulator_enable(ts->reg);
131591143379SGrazvydas Ignotas 	if (err) {
1316de609b56SDaniel Mack 		dev_err(dev, "unable to enable regulator: %d\n", err);
1317845ef3a7SDaniel Mack 		return err;
131891143379SGrazvydas Ignotas 	}
131991143379SGrazvydas Ignotas 
1320845ef3a7SDaniel Mack 	err = devm_add_action_or_reset(dev, ads7846_regulator_disable, ts->reg);
1321845ef3a7SDaniel Mack 	if (err)
1322845ef3a7SDaniel Mack 		return err;
1323845ef3a7SDaniel Mack 
13240f622bf4SDmitry Torokhov 	irq_flags = pdata->irq_flags ? : IRQF_TRIGGER_FALLING;
13252991a1caSJason Wang 	irq_flags |= IRQF_ONESHOT;
13267804302bSAnatolij Gustschin 
1327845ef3a7SDaniel Mack 	err = devm_request_threaded_irq(dev, spi->irq,
1328845ef3a7SDaniel Mack 					ads7846_hard_irq, ads7846_irq,
1329de609b56SDaniel Mack 					irq_flags, dev->driver->name, ts);
133036fc5437SDmitry Torokhov 	if (err && err != -EPROBE_DEFER && !pdata->irq_flags) {
1331de609b56SDaniel Mack 		dev_info(dev,
1332c57c0a2aSMichael Roth 			"trying pin change workaround on irq %d\n", spi->irq);
13332991a1caSJason Wang 		irq_flags |= IRQF_TRIGGER_RISING;
1334845ef3a7SDaniel Mack 		err = devm_request_threaded_irq(dev, spi->irq,
13352991a1caSJason Wang 						ads7846_hard_irq, ads7846_irq,
1336845ef3a7SDaniel Mack 						irq_flags, dev->driver->name,
1337845ef3a7SDaniel Mack 						ts);
13380f622bf4SDmitry Torokhov 	}
13390f622bf4SDmitry Torokhov 
1340c57c0a2aSMichael Roth 	if (err) {
1341de609b56SDaniel Mack 		dev_dbg(dev, "irq %d busy?\n", spi->irq);
1342845ef3a7SDaniel Mack 		return err;
1343ffa458c1SDavid Brownell 	}
1344ffa458c1SDavid Brownell 
13452c8dc071SDavid Brownell 	err = ads784x_hwmon_register(spi, ts);
13462c8dc071SDavid Brownell 	if (err)
1347845ef3a7SDaniel Mack 		return err;
13482c8dc071SDavid Brownell 
1349de609b56SDaniel Mack 	dev_info(dev, "touchscreen, irq %d\n", spi->irq);
1350ffa458c1SDavid Brownell 
13512991a1caSJason Wang 	/*
13522991a1caSJason Wang 	 * Take a first sample, leaving nPENIRQ active and vREF off; avoid
1353ffa458c1SDavid Brownell 	 * the touchscreen, in case it's not connected.
1354ffa458c1SDavid Brownell 	 */
13553eac5c7eSAnatolij Gustschin 	if (ts->model == 7845)
1356de609b56SDaniel Mack 		ads7845_read12_ser(dev, PWRDOWN);
13573eac5c7eSAnatolij Gustschin 	else
1358de609b56SDaniel Mack 		(void) ads7846_read12_ser(dev, READ_12BIT_SER(vaux));
1359ffa458c1SDavid Brownell 
1360845ef3a7SDaniel Mack 	err = devm_device_add_group(dev, &ads784x_attr_group);
13618dd51650SDmitry Torokhov 	if (err)
1362845ef3a7SDaniel Mack 		return err;
13637de90a8cSImre Deak 
1364a90f7e98SDmitry Torokhov 	err = input_register_device(input_dev);
1365a90f7e98SDmitry Torokhov 	if (err)
1366845ef3a7SDaniel Mack 		return err;
1367a90f7e98SDmitry Torokhov 
1368de609b56SDaniel Mack 	device_init_wakeup(dev, pdata->wakeup);
1369fdba2bb1SRanjith Lohithakshan 
1370a608026eSDaniel Mack 	/*
1371a608026eSDaniel Mack 	 * If device does not carry platform data we must have allocated it
1372a608026eSDaniel Mack 	 * when parsing DT data.
1373a608026eSDaniel Mack 	 */
1374de609b56SDaniel Mack 	if (!dev_get_platdata(dev))
1375de609b56SDaniel Mack 		devm_kfree(dev, (void *)pdata);
1376a608026eSDaniel Mack 
1377ffa458c1SDavid Brownell 	return 0;
1378ffa458c1SDavid Brownell }
1379ffa458c1SDavid Brownell 
ads7846_remove(struct spi_device * spi)1380a0386bbaSUwe Kleine-König static void ads7846_remove(struct spi_device *spi)
1381ffa458c1SDavid Brownell {
1382c12454faSJingoo Han 	struct ads7846 *ts = spi_get_drvdata(spi);
1383ffa458c1SDavid Brownell 
1384845ef3a7SDaniel Mack 	ads7846_stop(ts);
1385ffa458c1SDavid Brownell }
1386ffa458c1SDavid Brownell 
13872e5a7bd9SDavid Brownell static struct spi_driver ads7846_driver = {
13882e5a7bd9SDavid Brownell 	.driver = {
1389ffa458c1SDavid Brownell 		.name	= "ads7846",
1390f8909d9aSJonathan Cameron 		.pm	= pm_sleep_ptr(&ads7846_pm),
1391767d8336SLinus Walleij 		.of_match_table = ads7846_dt_ids,
13922e5a7bd9SDavid Brownell 	},
1393ffa458c1SDavid Brownell 	.probe		= ads7846_probe,
13941cb0aa88SBill Pemberton 	.remove		= ads7846_remove,
1395ffa458c1SDavid Brownell };
1396ffa458c1SDavid Brownell 
1397ca83922eSAxel Lin module_spi_driver(ads7846_driver);
1398ffa458c1SDavid Brownell 
1399ffa458c1SDavid Brownell MODULE_DESCRIPTION("ADS7846 TouchScreen Driver");
1400ffa458c1SDavid Brownell MODULE_LICENSE("GPL");
1401e0626e38SAnton Vorontsov MODULE_ALIAS("spi:ads7846");
1402