Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Driver for Semtech SX8654 I2C touchscreen controller.
4 *
5 * Copyright (c) 2015 Armadeus Systems
6 * Sébastien Szymanski <sebastien.szymanski@armadeus.com>
7 *
8 * Using code from:
9 * - sx865x.c
10 * Copyright (c) 2013 U-MoBo Srl
11 * Pierluigi Passaro <p.passaro@u-mobo.com>
12 * - sx8650.c
13 * Copyright (c) 2009 Wayne Roberts
14 * - tsc2007.c
15 * Copyright (c) 2008 Kwangwoo Lee
16 * - ads7846.c
17 * Copyright (c) 2005 David Brownell
18 * Copyright (c) 2006 Nokia Corporation
19 * - corgi_ts.c
20 * Copyright (C) 2004-2005 Richard Purdie
21 * - omap_ts.[hc], ads7846.h, ts_osk.c
22 * Copyright (C) 2002 MontaVista Software
23 * Copyright (C) 2004 Texas Instruments
24 * Copyright (C) 2005 Dirk Behme
25 */
26
27#include <linux/bitops.h>
28#include <linux/delay.h>
29#include <linux/gpio/consumer.h>
30#include <linux/i2c.h>
31#include <linux/input.h>
32#include <linux/input/touchscreen.h>
33#include <linux/interrupt.h>
34#include <linux/irq.h>
35#include <linux/module.h>
36#include <linux/of.h>
37
38/* register addresses */
39#define I2C_REG_TOUCH0 0x00
40#define I2C_REG_TOUCH1 0x01
41#define I2C_REG_CHANMASK 0x04
42#define I2C_REG_IRQMASK 0x22
43#define I2C_REG_IRQSRC 0x23
44#define I2C_REG_SOFTRESET 0x3f
45
46#define I2C_REG_SX8650_STAT 0x05
47#define SX8650_STAT_CONVIRQ BIT(7)
48
49/* commands */
50#define CMD_READ_REGISTER 0x40
51#define CMD_PENTRG 0xe0
52
53/* value for I2C_REG_SOFTRESET */
54#define SOFTRESET_VALUE 0xde
55
56/* bits for I2C_REG_IRQSRC */
57#define IRQ_PENTOUCH_TOUCHCONVDONE BIT(3)
58#define IRQ_PENRELEASE BIT(2)
59
60/* bits for RegTouch1 */
61#define CONDIRQ 0x20
62#define RPDNT_100K 0x00
63#define FILT_7SA 0x03
64
65/* bits for I2C_REG_CHANMASK */
66#define CONV_X BIT(7)
67#define CONV_Y BIT(6)
68
69/* coordinates rate: higher nibble of CTRL0 register */
70#define RATE_MANUAL 0x00
71#define RATE_5000CPS 0xf0
72
73/* power delay: lower nibble of CTRL0 register */
74#define POWDLY_1_1MS 0x0b
75
76/* for sx8650, as we have no pen release IRQ there: timeout in ns following the
77 * last PENIRQ after which we assume the pen is lifted.
78 */
79#define SX8650_PENIRQ_TIMEOUT msecs_to_jiffies(10)
80
81#define MAX_12BIT ((1 << 12) - 1)
82#define MAX_I2C_READ_LEN 10 /* see datasheet section 5.1.5 */
83
84/* channel definition */
85#define CH_X 0x00
86#define CH_Y 0x01
87
88struct sx865x_data {
89 u8 cmd_manual;
90 u8 chan_mask;
91 bool has_irq_penrelease;
92 bool has_reg_irqmask;
93 irq_handler_t irqh;
94};
95
96struct sx8654 {
97 struct input_dev *input;
98 struct i2c_client *client;
99 struct gpio_desc *gpio_reset;
100
101 spinlock_t lock; /* for input reporting from irq/timer */
102 struct timer_list timer;
103
104 struct touchscreen_properties props;
105
106 const struct sx865x_data *data;
107};
108
109static inline void sx865x_penrelease(struct sx8654 *ts)
110{
111 struct input_dev *input_dev = ts->input;
112
113 input_report_key(input_dev, BTN_TOUCH, 0);
114 input_sync(input_dev);
115}
116
117static void sx865x_penrelease_timer_handler(struct timer_list *t)
118{
119 struct sx8654 *ts = timer_container_of(ts, t, timer);
120
121 dev_dbg(&ts->client->dev, "penrelease by timer\n");
122
123 guard(spinlock_irqsave)(&ts->lock);
124 sx865x_penrelease(ts);
125}
126
127static irqreturn_t sx8650_irq(int irq, void *handle)
128{
129 struct sx8654 *ts = handle;
130 struct device *dev = &ts->client->dev;
131 int len, i;
132 u8 stat;
133 u16 x, y;
134 u16 ch;
135 u16 chdata;
136 __be16 data[MAX_I2C_READ_LEN / sizeof(__be16)];
137 u8 nchan = hweight32(ts->data->chan_mask);
138 u8 readlen = nchan * sizeof(*data);
139
140 stat = i2c_smbus_read_byte_data(ts->client, CMD_READ_REGISTER
141 | I2C_REG_SX8650_STAT);
142
143 if (!(stat & SX8650_STAT_CONVIRQ)) {
144 dev_dbg(dev, "%s ignore stat [0x%02x]", __func__, stat);
145 return IRQ_HANDLED;
146 }
147
148 len = i2c_master_recv(ts->client, (u8 *)data, readlen);
149 if (len != readlen) {
150 dev_dbg(dev, "ignore short recv (%d)\n", len);
151 return IRQ_HANDLED;
152 }
153
154 guard(spinlock_irqsave)(&ts->lock);
155
156 x = 0;
157 y = 0;
158 for (i = 0; i < nchan; i++) {
159 chdata = be16_to_cpu(data[i]);
160
161 if (unlikely(chdata == 0xFFFF)) {
162 dev_dbg(dev, "invalid qualified data @ %d\n", i);
163 continue;
164 } else if (unlikely(chdata & 0x8000)) {
165 dev_warn(dev, "hibit @ %d [0x%04x]\n", i, chdata);
166 continue;
167 }
168
169 ch = chdata >> 12;
170 if (ch == CH_X)
171 x = chdata & MAX_12BIT;
172 else if (ch == CH_Y)
173 y = chdata & MAX_12BIT;
174 else
175 dev_warn(dev, "unknown channel %d [0x%04x]\n", ch,
176 chdata);
177 }
178
179 touchscreen_report_pos(ts->input, &ts->props, x, y, false);
180 input_report_key(ts->input, BTN_TOUCH, 1);
181 input_sync(ts->input);
182 dev_dbg(dev, "point(%4d,%4d)\n", x, y);
183
184 mod_timer(&ts->timer, jiffies + SX8650_PENIRQ_TIMEOUT);
185
186 return IRQ_HANDLED;
187}
188
189static irqreturn_t sx8654_irq(int irq, void *handle)
190{
191 struct sx8654 *sx8654 = handle;
192 int irqsrc;
193 u8 data[4];
194 unsigned int x, y;
195 int retval;
196
197 irqsrc = i2c_smbus_read_byte_data(sx8654->client,
198 CMD_READ_REGISTER | I2C_REG_IRQSRC);
199 dev_dbg(&sx8654->client->dev, "irqsrc = 0x%x", irqsrc);
200
201 if (irqsrc < 0)
202 goto out;
203
204 if (irqsrc & IRQ_PENRELEASE) {
205 dev_dbg(&sx8654->client->dev, "pen release interrupt");
206
207 input_report_key(sx8654->input, BTN_TOUCH, 0);
208 input_sync(sx8654->input);
209 }
210
211 if (irqsrc & IRQ_PENTOUCH_TOUCHCONVDONE) {
212 dev_dbg(&sx8654->client->dev, "pen touch interrupt");
213
214 retval = i2c_master_recv(sx8654->client, data, sizeof(data));
215 if (retval != sizeof(data))
216 goto out;
217
218 /* invalid data */
219 if (unlikely(data[0] & 0x80 || data[2] & 0x80))
220 goto out;
221
222 x = ((data[0] & 0xf) << 8) | (data[1]);
223 y = ((data[2] & 0xf) << 8) | (data[3]);
224
225 touchscreen_report_pos(sx8654->input, &sx8654->props, x, y,
226 false);
227 input_report_key(sx8654->input, BTN_TOUCH, 1);
228 input_sync(sx8654->input);
229
230 dev_dbg(&sx8654->client->dev, "point(%4d,%4d)\n", x, y);
231 }
232
233out:
234 return IRQ_HANDLED;
235}
236
237static int sx8654_reset(struct sx8654 *ts)
238{
239 int err;
240
241 if (ts->gpio_reset) {
242 gpiod_set_value_cansleep(ts->gpio_reset, 1);
243 udelay(2); /* Tpulse > 1µs */
244 gpiod_set_value_cansleep(ts->gpio_reset, 0);
245 } else {
246 dev_dbg(&ts->client->dev, "NRST unavailable, try softreset\n");
247 err = i2c_smbus_write_byte_data(ts->client, I2C_REG_SOFTRESET,
248 SOFTRESET_VALUE);
249 if (err)
250 return err;
251 }
252
253 return 0;
254}
255
256static int sx8654_open(struct input_dev *dev)
257{
258 struct sx8654 *sx8654 = input_get_drvdata(dev);
259 struct i2c_client *client = sx8654->client;
260 int error;
261
262 /* enable pen trigger mode */
263 error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0,
264 RATE_5000CPS | POWDLY_1_1MS);
265 if (error) {
266 dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed");
267 return error;
268 }
269
270 error = i2c_smbus_write_byte(client, CMD_PENTRG);
271 if (error) {
272 dev_err(&client->dev, "writing command CMD_PENTRG failed");
273 return error;
274 }
275
276 enable_irq(client->irq);
277
278 return 0;
279}
280
281static void sx8654_close(struct input_dev *dev)
282{
283 struct sx8654 *sx8654 = input_get_drvdata(dev);
284 struct i2c_client *client = sx8654->client;
285 int error;
286
287 disable_irq(client->irq);
288
289 if (!sx8654->data->has_irq_penrelease)
290 timer_delete_sync(&sx8654->timer);
291
292 /* enable manual mode mode */
293 error = i2c_smbus_write_byte(client, sx8654->data->cmd_manual);
294 if (error) {
295 dev_err(&client->dev, "writing command CMD_MANUAL failed");
296 return;
297 }
298
299 error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, RATE_MANUAL);
300 if (error) {
301 dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed");
302 return;
303 }
304}
305
306static int sx8654_probe(struct i2c_client *client)
307{
308 const struct i2c_device_id *id = i2c_client_get_device_id(client);
309 struct sx8654 *sx8654;
310 struct input_dev *input;
311 int error;
312
313 if (!i2c_check_functionality(client->adapter,
314 I2C_FUNC_SMBUS_READ_WORD_DATA))
315 return -ENXIO;
316
317 sx8654 = devm_kzalloc(&client->dev, sizeof(*sx8654), GFP_KERNEL);
318 if (!sx8654)
319 return -ENOMEM;
320
321 sx8654->gpio_reset = devm_gpiod_get_optional(&client->dev, "reset",
322 GPIOD_OUT_HIGH);
323 if (IS_ERR(sx8654->gpio_reset))
324 return dev_err_probe(&client->dev, PTR_ERR(sx8654->gpio_reset),
325 "unable to get reset-gpio\n");
326 dev_dbg(&client->dev, "got GPIO reset pin\n");
327
328 sx8654->data = device_get_match_data(&client->dev);
329 if (!sx8654->data)
330 sx8654->data = (const struct sx865x_data *)id->driver_data;
331 if (!sx8654->data) {
332 dev_err(&client->dev, "invalid or missing device data\n");
333 return -EINVAL;
334 }
335
336 if (!sx8654->data->has_irq_penrelease) {
337 dev_dbg(&client->dev, "use timer for penrelease\n");
338 timer_setup(&sx8654->timer, sx865x_penrelease_timer_handler, 0);
339 spin_lock_init(&sx8654->lock);
340 }
341
342 input = devm_input_allocate_device(&client->dev);
343 if (!input)
344 return -ENOMEM;
345
346 input->name = "SX8654 I2C Touchscreen";
347 input->id.bustype = BUS_I2C;
348 input->dev.parent = &client->dev;
349 input->open = sx8654_open;
350 input->close = sx8654_close;
351
352 __set_bit(INPUT_PROP_DIRECT, input->propbit);
353 input_set_capability(input, EV_KEY, BTN_TOUCH);
354 input_set_abs_params(input, ABS_X, 0, MAX_12BIT, 0, 0);
355 input_set_abs_params(input, ABS_Y, 0, MAX_12BIT, 0, 0);
356
357 touchscreen_parse_properties(input, false, &sx8654->props);
358
359 sx8654->client = client;
360 sx8654->input = input;
361
362 input_set_drvdata(sx8654->input, sx8654);
363
364 error = sx8654_reset(sx8654);
365 if (error) {
366 dev_err(&client->dev, "reset failed");
367 return error;
368 }
369
370 error = i2c_smbus_write_byte_data(client, I2C_REG_CHANMASK,
371 sx8654->data->chan_mask);
372 if (error) {
373 dev_err(&client->dev, "writing to I2C_REG_CHANMASK failed");
374 return error;
375 }
376
377 if (sx8654->data->has_reg_irqmask) {
378 error = i2c_smbus_write_byte_data(client, I2C_REG_IRQMASK,
379 IRQ_PENTOUCH_TOUCHCONVDONE |
380 IRQ_PENRELEASE);
381 if (error) {
382 dev_err(&client->dev, "writing I2C_REG_IRQMASK failed");
383 return error;
384 }
385 }
386
387 error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH1,
388 CONDIRQ | RPDNT_100K | FILT_7SA);
389 if (error) {
390 dev_err(&client->dev, "writing to I2C_REG_TOUCH1 failed");
391 return error;
392 }
393
394 /*
395 * Start with the interrupt disabled, it will be enabled in
396 * sx8654_open().
397 */
398 error = devm_request_threaded_irq(&client->dev, client->irq,
399 NULL, sx8654->data->irqh,
400 IRQF_ONESHOT | IRQF_NO_AUTOEN,
401 client->name, sx8654);
402 if (error) {
403 dev_err(&client->dev,
404 "Failed to enable IRQ %d, error: %d\n",
405 client->irq, error);
406 return error;
407 }
408
409 error = input_register_device(sx8654->input);
410 if (error)
411 return error;
412
413 return 0;
414}
415
416static const struct sx865x_data sx8650_data = {
417 .cmd_manual = 0xb0,
418 .has_irq_penrelease = false,
419 .has_reg_irqmask = false,
420 .chan_mask = (CONV_X | CONV_Y),
421 .irqh = sx8650_irq,
422};
423
424static const struct sx865x_data sx8654_data = {
425 .cmd_manual = 0xc0,
426 .has_irq_penrelease = true,
427 .has_reg_irqmask = true,
428 .chan_mask = (CONV_X | CONV_Y),
429 .irqh = sx8654_irq,
430};
431
432#ifdef CONFIG_OF
433static const struct of_device_id sx8654_of_match[] = {
434 {
435 .compatible = "semtech,sx8650",
436 .data = &sx8650_data,
437 }, {
438 .compatible = "semtech,sx8654",
439 .data = &sx8654_data,
440 }, {
441 .compatible = "semtech,sx8655",
442 .data = &sx8654_data,
443 }, {
444 .compatible = "semtech,sx8656",
445 .data = &sx8654_data,
446 },
447 { }
448};
449MODULE_DEVICE_TABLE(of, sx8654_of_match);
450#endif
451
452static const struct i2c_device_id sx8654_id_table[] = {
453 { .name = "semtech_sx8650", .driver_data = (long)&sx8650_data },
454 { .name = "semtech_sx8654", .driver_data = (long)&sx8654_data },
455 { .name = "semtech_sx8655", .driver_data = (long)&sx8654_data },
456 { .name = "semtech_sx8656", .driver_data = (long)&sx8654_data },
457 { }
458};
459MODULE_DEVICE_TABLE(i2c, sx8654_id_table);
460
461static struct i2c_driver sx8654_driver = {
462 .driver = {
463 .name = "sx8654",
464 .of_match_table = of_match_ptr(sx8654_of_match),
465 },
466 .id_table = sx8654_id_table,
467 .probe = sx8654_probe,
468};
469module_i2c_driver(sx8654_driver);
470
471MODULE_AUTHOR("Sébastien Szymanski <sebastien.szymanski@armadeus.com>");
472MODULE_DESCRIPTION("Semtech SX8654 I2C Touchscreen Driver");
473MODULE_LICENSE("GPL");