1 // SPDX-License-Identifier: GPL-2.0-only
4 * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver.
5 * For use with Cypress Txx3xx parts.
6 * Supported parts include:
10 * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
11 * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
12 * Copyright (C) 2013 Cypress Semiconductor
14 * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
17 #include "cyttsp_core.h"
19 #include <linux/delay.h>
20 #include <linux/input.h>
21 #include <linux/spi/spi.h>
23 #define CY_SPI_NAME "cyttsp-spi"
25 #define CY_SPI_WR_OP 0x00 /* r/~w */
26 #define CY_SPI_RD_OP 0x01
27 #define CY_SPI_CMD_BYTES 4
28 #define CY_SPI_SYNC_BYTE 2
29 #define CY_SPI_SYNC_ACK1 0x62 /* from protocol v.2 */
30 #define CY_SPI_SYNC_ACK2 0x9D /* from protocol v.2 */
31 #define CY_SPI_DATA_SIZE 128
32 #define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
33 #define CY_SPI_BITS_PER_WORD 8
35 static int cyttsp_spi_xfer(struct device
*dev
, u8
*xfer_buf
,
36 u8 op
, u16 reg
, u8
*buf
, int length
)
38 struct spi_device
*spi
= to_spi_device(dev
);
39 struct spi_message msg
;
40 struct spi_transfer xfer
[2];
41 u8
*wr_buf
= &xfer_buf
[0];
42 u8
*rd_buf
= &xfer_buf
[CY_SPI_DATA_BUF_SIZE
];
46 if (length
> CY_SPI_DATA_SIZE
) {
47 dev_err(dev
, "%s: length %d is too big.\n",
52 memset(wr_buf
, 0, CY_SPI_DATA_BUF_SIZE
);
53 memset(rd_buf
, 0, CY_SPI_DATA_BUF_SIZE
);
55 wr_buf
[0] = 0x00; /* header byte 0 */
56 wr_buf
[1] = 0xFF; /* header byte 1 */
57 wr_buf
[2] = reg
; /* reg index */
58 wr_buf
[3] = op
; /* r/~w */
59 if (op
== CY_SPI_WR_OP
)
60 memcpy(wr_buf
+ CY_SPI_CMD_BYTES
, buf
, length
);
62 memset(xfer
, 0, sizeof(xfer
));
63 spi_message_init(&msg
);
66 We set both TX and RX buffers because Cypress TTSP
67 requires full duplex operation.
69 xfer
[0].tx_buf
= wr_buf
;
70 xfer
[0].rx_buf
= rd_buf
;
73 xfer
[0].len
= length
+ CY_SPI_CMD_BYTES
;
74 spi_message_add_tail(&xfer
[0], &msg
);
78 xfer
[0].len
= CY_SPI_CMD_BYTES
;
79 spi_message_add_tail(&xfer
[0], &msg
);
83 spi_message_add_tail(&xfer
[1], &msg
);
87 dev_err(dev
, "%s: bad operation code=%d\n", __func__
, op
);
91 retval
= spi_sync(spi
, &msg
);
93 dev_dbg(dev
, "%s: spi_sync() error %d, len=%d, op=%d\n",
94 __func__
, retval
, xfer
[1].len
, op
);
97 * do not return here since was a bad ACK sequence
98 * let the following ACK check handle any errors and
99 * allow silent retries
103 if (rd_buf
[CY_SPI_SYNC_BYTE
] != CY_SPI_SYNC_ACK1
||
104 rd_buf
[CY_SPI_SYNC_BYTE
+ 1] != CY_SPI_SYNC_ACK2
) {
105 dev_dbg(dev
, "%s: operation %d failed\n", __func__
, op
);
107 for (i
= 0; i
< CY_SPI_CMD_BYTES
; i
++)
108 dev_dbg(dev
, "%s: test rd_buf[%d]:0x%02x\n",
109 __func__
, i
, rd_buf
[i
]);
110 for (i
= 0; i
< length
; i
++)
111 dev_dbg(dev
, "%s: test buf[%d]:0x%02x\n",
112 __func__
, i
, buf
[i
]);
120 static int cyttsp_spi_read_block_data(struct device
*dev
, u8
*xfer_buf
,
121 u16 addr
, u8 length
, void *data
)
123 return cyttsp_spi_xfer(dev
, xfer_buf
, CY_SPI_RD_OP
, addr
, data
,
127 static int cyttsp_spi_write_block_data(struct device
*dev
, u8
*xfer_buf
,
128 u16 addr
, u8 length
, const void *data
)
130 return cyttsp_spi_xfer(dev
, xfer_buf
, CY_SPI_WR_OP
, addr
, (void *)data
,
134 static const struct cyttsp_bus_ops cyttsp_spi_bus_ops
= {
136 .write
= cyttsp_spi_write_block_data
,
137 .read
= cyttsp_spi_read_block_data
,
140 static int cyttsp_spi_probe(struct spi_device
*spi
)
146 spi
->bits_per_word
= CY_SPI_BITS_PER_WORD
;
147 spi
->mode
= SPI_MODE_0
;
148 error
= spi_setup(spi
);
150 dev_err(&spi
->dev
, "%s: SPI setup error %d\n",
155 ts
= cyttsp_probe(&cyttsp_spi_bus_ops
, &spi
->dev
, spi
->irq
,
156 CY_SPI_DATA_BUF_SIZE
* 2);
160 spi_set_drvdata(spi
, ts
);
165 static const struct of_device_id cyttsp_of_spi_match
[] = {
166 { .compatible
= "cypress,cy8ctma340", },
167 { .compatible
= "cypress,cy8ctst341", },
170 MODULE_DEVICE_TABLE(of
, cyttsp_of_spi_match
);
172 static struct spi_driver cyttsp_spi_driver
= {
175 .pm
= pm_sleep_ptr(&cyttsp_pm_ops
),
176 .of_match_table
= cyttsp_of_spi_match
,
178 .probe
= cyttsp_spi_probe
,
181 module_spi_driver(cyttsp_spi_driver
);
183 MODULE_LICENSE("GPL");
184 MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver");
185 MODULE_AUTHOR("Cypress");
186 MODULE_ALIAS("spi:cyttsp");