aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/cyttsp4_spi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-04 18:35:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-04 18:35:08 -0400
commitf5b63ac0f77ecab46796ba5d368ea5dd51834e6e (patch)
tree66788b3327afa62aa7f8fe05951945a2ee1e9e4e /drivers/input/touchscreen/cyttsp4_spi.c
parent98f486f18d16e2214728d101ed8b6a12dce75539 (diff)
parent57961e3ba72f4a8a1aa52e978020ecc2ca03a79f (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: "First round of updates for the input subsystem. You will get a new touchsreen driver for Cypress 4th generation devices, a driver for a special controller implementing PS/2 protocol in OLPC devices, and a driver for power key for SiRFprimaII PWRC. HID and bcm5497 now support for the 2013 MacBook Air. EVIOCGKEY and the rest of evdev ioctls now flush events of matching type from the client's event queue so that clients can be sure any events received after issuing EVIOCG* ioctl are new events. And a host of cleanups and improvements in other drivers" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (87 commits) Input: cyttsp4 - kfree xfer_buf on error path in probe() Input: tps6507x-ts - select INPUT_POLLDEV Input: bcm5974 - add support for the 2013 MacBook Air HID: apple: Add support for the 2013 Macbook Air Input: cyttsp4 - leak on error path in probe() Input: cyttsp4 - silence NULL dereference warning Input: cyttsp4 - silence shift wrap warning Input: tps6507x-ts - convert to polled input device infrastructure ARM: davinci: da850-evm: remove vref from touchscreen platform data Input: cyttsp4 - SPI driver for Cypress TMA4XX touchscreen devices Input: cyttsp4 - I2C driver for Cypress TMA4XX touchscreen devices Input: cyttsp4 - add core driver for Cypress TMA4XX touchscreen devices Input: cyttsp - I2C driver split into two modules Input: add OLPC AP-SP driver Input: nspire-keypad - remove redundant dev_err call in nspire_keypad_probe() Input: tps6507x-ts - remove vref from platform data Input: tps6507x-ts - use bool for booleans Input: tps6507x-ts - remove bogus unreachable code Input: samsung-keypad - let device core setup the default pin configuration Input: wacom_i2c - implement hovering capability ...
Diffstat (limited to 'drivers/input/touchscreen/cyttsp4_spi.c')
-rw-r--r--drivers/input/touchscreen/cyttsp4_spi.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c
new file mode 100644
index 000000000000..f8f891bead34
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp4_spi.c
@@ -0,0 +1,205 @@
1/*
2 * Source for:
3 * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver.
4 * For use with Cypress Txx4xx parts.
5 * Supported parts include:
6 * TMA4XX
7 * TMA1036
8 *
9 * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
10 * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
11 * Copyright (C) 2013 Cypress Semiconductor
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * version 2, and only version 2, as published by the
16 * Free Software Foundation.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
24 *
25 */
26
27#include "cyttsp4_core.h"
28
29#include <linux/delay.h>
30#include <linux/input.h>
31#include <linux/spi/spi.h>
32
33#define CY_SPI_WR_OP 0x00 /* r/~w */
34#define CY_SPI_RD_OP 0x01
35#define CY_SPI_BITS_PER_WORD 8
36#define CY_SPI_A8_BIT 0x02
37#define CY_SPI_WR_HEADER_BYTES 2
38#define CY_SPI_RD_HEADER_BYTES 1
39#define CY_SPI_CMD_BYTES 2
40#define CY_SPI_SYNC_BYTE 0
41#define CY_SPI_SYNC_ACK 0x62 /* from TRM *A protocol */
42#define CY_SPI_DATA_SIZE (2 * 256)
43
44#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
45
46static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
47 u8 op, u8 reg, u8 *buf, int length)
48{
49 struct spi_device *spi = to_spi_device(dev);
50 struct spi_message msg;
51 struct spi_transfer xfer[2];
52 u8 *wr_buf = &xfer_buf[0];
53 u8 rd_buf[CY_SPI_CMD_BYTES];
54 int retval;
55 int i;
56
57 if (length > CY_SPI_DATA_SIZE) {
58 dev_err(dev, "%s: length %d is too big.\n",
59 __func__, length);
60 return -EINVAL;
61 }
62
63 memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE);
64 memset(rd_buf, 0, CY_SPI_CMD_BYTES);
65
66 if (reg > 255)
67 wr_buf[0] = op + CY_SPI_A8_BIT;
68 else
69 wr_buf[0] = op;
70 if (op == CY_SPI_WR_OP)
71 wr_buf[1] = reg % 256;
72 if (op == CY_SPI_WR_OP && length > 0)
73 memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length);
74
75 memset(xfer, 0, sizeof(xfer));
76 spi_message_init(&msg);
77
78 /*
79 We set both TX and RX buffers because Cypress TTSP
80 requires full duplex operation.
81 */
82 xfer[0].tx_buf = wr_buf;
83 xfer[0].rx_buf = rd_buf;
84 switch (op) {
85 case CY_SPI_WR_OP:
86 xfer[0].len = length + CY_SPI_CMD_BYTES;
87 spi_message_add_tail(&xfer[0], &msg);
88 break;
89
90 case CY_SPI_RD_OP:
91 xfer[0].len = CY_SPI_RD_HEADER_BYTES;
92 spi_message_add_tail(&xfer[0], &msg);
93
94 xfer[1].rx_buf = buf;
95 xfer[1].len = length;
96 spi_message_add_tail(&xfer[1], &msg);
97 break;
98
99 default:
100 dev_err(dev, "%s: bad operation code=%d\n", __func__, op);
101 return -EINVAL;
102 }
103
104 retval = spi_sync(spi, &msg);
105 if (retval < 0) {
106 dev_dbg(dev, "%s: spi_sync() error %d, len=%d, op=%d\n",
107 __func__, retval, xfer[1].len, op);
108
109 /*
110 * do not return here since was a bad ACK sequence
111 * let the following ACK check handle any errors and
112 * allow silent retries
113 */
114 }
115
116 if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK) {
117 dev_dbg(dev, "%s: operation %d failed\n", __func__, op);
118
119 for (i = 0; i < CY_SPI_CMD_BYTES; i++)
120 dev_dbg(dev, "%s: test rd_buf[%d]:0x%02x\n",
121 __func__, i, rd_buf[i]);
122 for (i = 0; i < length; i++)
123 dev_dbg(dev, "%s: test buf[%d]:0x%02x\n",
124 __func__, i, buf[i]);
125
126 return -EIO;
127 }
128
129 return 0;
130}
131
132static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
133 u8 addr, u8 length, void *data)
134{
135 int rc;
136
137 rc = cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, NULL, 0);
138 if (rc)
139 return rc;
140 else
141 return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data,
142 length);
143}
144
145static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf,
146 u8 addr, u8 length, const void *data)
147{
148 return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data,
149 length);
150}
151
152static const struct cyttsp4_bus_ops cyttsp_spi_bus_ops = {
153 .bustype = BUS_SPI,
154 .write = cyttsp_spi_write_block_data,
155 .read = cyttsp_spi_read_block_data,
156};
157
158static int cyttsp4_spi_probe(struct spi_device *spi)
159{
160 struct cyttsp4 *ts;
161 int error;
162
163 /* Set up SPI*/
164 spi->bits_per_word = CY_SPI_BITS_PER_WORD;
165 spi->mode = SPI_MODE_0;
166 error = spi_setup(spi);
167 if (error < 0) {
168 dev_err(&spi->dev, "%s: SPI setup error %d\n",
169 __func__, error);
170 return error;
171 }
172
173 ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq,
174 CY_SPI_DATA_BUF_SIZE);
175
176 if (IS_ERR(ts))
177 return PTR_ERR(ts);
178
179 return 0;
180}
181
182static int cyttsp4_spi_remove(struct spi_device *spi)
183{
184 struct cyttsp4 *ts = spi_get_drvdata(spi);
185 cyttsp4_remove(ts);
186
187 return 0;
188}
189
190static struct spi_driver cyttsp4_spi_driver = {
191 .driver = {
192 .name = CYTTSP4_SPI_NAME,
193 .owner = THIS_MODULE,
194 .pm = &cyttsp4_pm_ops,
195 },
196 .probe = cyttsp4_spi_probe,
197 .remove = cyttsp4_spi_remove,
198};
199
200module_spi_driver(cyttsp4_spi_driver);
201
202MODULE_LICENSE("GPL");
203MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver");
204MODULE_AUTHOR("Cypress");
205MODULE_ALIAS("spi:cyttsp4");