197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 267bf12caSFerruh Yigit /* 367bf12caSFerruh Yigit * Source for: 467bf12caSFerruh Yigit * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver. 567bf12caSFerruh Yigit * For use with Cypress Txx4xx parts. 667bf12caSFerruh Yigit * Supported parts include: 767bf12caSFerruh Yigit * TMA4XX 867bf12caSFerruh Yigit * TMA1036 967bf12caSFerruh Yigit * 1067bf12caSFerruh Yigit * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. 1167bf12caSFerruh Yigit * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> 1267bf12caSFerruh Yigit * Copyright (C) 2013 Cypress Semiconductor 1367bf12caSFerruh Yigit * 1467bf12caSFerruh Yigit * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> 1567bf12caSFerruh Yigit */ 1667bf12caSFerruh Yigit 1767bf12caSFerruh Yigit #include "cyttsp4_core.h" 1867bf12caSFerruh Yigit 1967bf12caSFerruh Yigit #include <linux/delay.h> 2067bf12caSFerruh Yigit #include <linux/input.h> 2167bf12caSFerruh Yigit #include <linux/spi/spi.h> 2267bf12caSFerruh Yigit 2367bf12caSFerruh Yigit #define CY_SPI_WR_OP 0x00 /* r/~w */ 2467bf12caSFerruh Yigit #define CY_SPI_RD_OP 0x01 2567bf12caSFerruh Yigit #define CY_SPI_BITS_PER_WORD 8 2667bf12caSFerruh Yigit #define CY_SPI_A8_BIT 0x02 2767bf12caSFerruh Yigit #define CY_SPI_WR_HEADER_BYTES 2 2867bf12caSFerruh Yigit #define CY_SPI_RD_HEADER_BYTES 1 2967bf12caSFerruh Yigit #define CY_SPI_CMD_BYTES 2 3067bf12caSFerruh Yigit #define CY_SPI_SYNC_BYTE 0 3167bf12caSFerruh Yigit #define CY_SPI_SYNC_ACK 0x62 /* from TRM *A protocol */ 3267bf12caSFerruh Yigit #define CY_SPI_DATA_SIZE (2 * 256) 3367bf12caSFerruh Yigit 3467bf12caSFerruh Yigit #define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE) 3567bf12caSFerruh Yigit 3667bf12caSFerruh Yigit static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf, 3762f548d0SFerruh Yigit u8 op, u16 reg, u8 *buf, int length) 3867bf12caSFerruh Yigit { 3967bf12caSFerruh Yigit struct spi_device *spi = to_spi_device(dev); 4067bf12caSFerruh Yigit struct spi_message msg; 4167bf12caSFerruh Yigit struct spi_transfer xfer[2]; 4267bf12caSFerruh Yigit u8 *wr_buf = &xfer_buf[0]; 4367bf12caSFerruh Yigit u8 rd_buf[CY_SPI_CMD_BYTES]; 4467bf12caSFerruh Yigit int retval; 4567bf12caSFerruh Yigit int i; 4667bf12caSFerruh Yigit 4767bf12caSFerruh Yigit if (length > CY_SPI_DATA_SIZE) { 4867bf12caSFerruh Yigit dev_err(dev, "%s: length %d is too big.\n", 4967bf12caSFerruh Yigit __func__, length); 5067bf12caSFerruh Yigit return -EINVAL; 5167bf12caSFerruh Yigit } 5267bf12caSFerruh Yigit 5367bf12caSFerruh Yigit memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE); 5467bf12caSFerruh Yigit memset(rd_buf, 0, CY_SPI_CMD_BYTES); 5567bf12caSFerruh Yigit 5662f548d0SFerruh Yigit wr_buf[0] = op + (((reg >> 8) & 0x1) ? CY_SPI_A8_BIT : 0); 5762f548d0SFerruh Yigit if (op == CY_SPI_WR_OP) { 5862f548d0SFerruh Yigit wr_buf[1] = reg & 0xFF; 5962f548d0SFerruh Yigit if (length > 0) 6067bf12caSFerruh Yigit memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length); 6162f548d0SFerruh Yigit } 6267bf12caSFerruh Yigit 6367bf12caSFerruh Yigit memset(xfer, 0, sizeof(xfer)); 6467bf12caSFerruh Yigit spi_message_init(&msg); 6567bf12caSFerruh Yigit 6667bf12caSFerruh Yigit /* 6767bf12caSFerruh Yigit We set both TX and RX buffers because Cypress TTSP 6867bf12caSFerruh Yigit requires full duplex operation. 6967bf12caSFerruh Yigit */ 7067bf12caSFerruh Yigit xfer[0].tx_buf = wr_buf; 7167bf12caSFerruh Yigit xfer[0].rx_buf = rd_buf; 7267bf12caSFerruh Yigit switch (op) { 7367bf12caSFerruh Yigit case CY_SPI_WR_OP: 7467bf12caSFerruh Yigit xfer[0].len = length + CY_SPI_CMD_BYTES; 7567bf12caSFerruh Yigit spi_message_add_tail(&xfer[0], &msg); 7667bf12caSFerruh Yigit break; 7767bf12caSFerruh Yigit 7867bf12caSFerruh Yigit case CY_SPI_RD_OP: 7967bf12caSFerruh Yigit xfer[0].len = CY_SPI_RD_HEADER_BYTES; 8067bf12caSFerruh Yigit spi_message_add_tail(&xfer[0], &msg); 8167bf12caSFerruh Yigit 8267bf12caSFerruh Yigit xfer[1].rx_buf = buf; 8367bf12caSFerruh Yigit xfer[1].len = length; 8467bf12caSFerruh Yigit spi_message_add_tail(&xfer[1], &msg); 8567bf12caSFerruh Yigit break; 8667bf12caSFerruh Yigit 8767bf12caSFerruh Yigit default: 8867bf12caSFerruh Yigit dev_err(dev, "%s: bad operation code=%d\n", __func__, op); 8967bf12caSFerruh Yigit return -EINVAL; 9067bf12caSFerruh Yigit } 9167bf12caSFerruh Yigit 9267bf12caSFerruh Yigit retval = spi_sync(spi, &msg); 9367bf12caSFerruh Yigit if (retval < 0) { 9467bf12caSFerruh Yigit dev_dbg(dev, "%s: spi_sync() error %d, len=%d, op=%d\n", 9567bf12caSFerruh Yigit __func__, retval, xfer[1].len, op); 9667bf12caSFerruh Yigit 9767bf12caSFerruh Yigit /* 9867bf12caSFerruh Yigit * do not return here since was a bad ACK sequence 9967bf12caSFerruh Yigit * let the following ACK check handle any errors and 10067bf12caSFerruh Yigit * allow silent retries 10167bf12caSFerruh Yigit */ 10267bf12caSFerruh Yigit } 10367bf12caSFerruh Yigit 10467bf12caSFerruh Yigit if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK) { 10567bf12caSFerruh Yigit dev_dbg(dev, "%s: operation %d failed\n", __func__, op); 10667bf12caSFerruh Yigit 10767bf12caSFerruh Yigit for (i = 0; i < CY_SPI_CMD_BYTES; i++) 10867bf12caSFerruh Yigit dev_dbg(dev, "%s: test rd_buf[%d]:0x%02x\n", 10967bf12caSFerruh Yigit __func__, i, rd_buf[i]); 11067bf12caSFerruh Yigit for (i = 0; i < length; i++) 11167bf12caSFerruh Yigit dev_dbg(dev, "%s: test buf[%d]:0x%02x\n", 11267bf12caSFerruh Yigit __func__, i, buf[i]); 11367bf12caSFerruh Yigit 11467bf12caSFerruh Yigit return -EIO; 11567bf12caSFerruh Yigit } 11667bf12caSFerruh Yigit 11767bf12caSFerruh Yigit return 0; 11867bf12caSFerruh Yigit } 11967bf12caSFerruh Yigit 12067bf12caSFerruh Yigit static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf, 12162f548d0SFerruh Yigit u16 addr, u8 length, void *data) 12267bf12caSFerruh Yigit { 12367bf12caSFerruh Yigit int rc; 12467bf12caSFerruh Yigit 12567bf12caSFerruh Yigit rc = cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, NULL, 0); 12667bf12caSFerruh Yigit if (rc) 12767bf12caSFerruh Yigit return rc; 12867bf12caSFerruh Yigit else 12967bf12caSFerruh Yigit return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data, 13067bf12caSFerruh Yigit length); 13167bf12caSFerruh Yigit } 13267bf12caSFerruh Yigit 13367bf12caSFerruh Yigit static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf, 13462f548d0SFerruh Yigit u16 addr, u8 length, const void *data) 13567bf12caSFerruh Yigit { 13667bf12caSFerruh Yigit return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data, 13767bf12caSFerruh Yigit length); 13867bf12caSFerruh Yigit } 13967bf12caSFerruh Yigit 14067bf12caSFerruh Yigit static const struct cyttsp4_bus_ops cyttsp_spi_bus_ops = { 14167bf12caSFerruh Yigit .bustype = BUS_SPI, 14267bf12caSFerruh Yigit .write = cyttsp_spi_write_block_data, 14367bf12caSFerruh Yigit .read = cyttsp_spi_read_block_data, 14467bf12caSFerruh Yigit }; 14567bf12caSFerruh Yigit 14667bf12caSFerruh Yigit static int cyttsp4_spi_probe(struct spi_device *spi) 14767bf12caSFerruh Yigit { 14867bf12caSFerruh Yigit struct cyttsp4 *ts; 14967bf12caSFerruh Yigit int error; 15067bf12caSFerruh Yigit 15167bf12caSFerruh Yigit /* Set up SPI*/ 15267bf12caSFerruh Yigit spi->bits_per_word = CY_SPI_BITS_PER_WORD; 15367bf12caSFerruh Yigit spi->mode = SPI_MODE_0; 15467bf12caSFerruh Yigit error = spi_setup(spi); 15567bf12caSFerruh Yigit if (error < 0) { 15667bf12caSFerruh Yigit dev_err(&spi->dev, "%s: SPI setup error %d\n", 15767bf12caSFerruh Yigit __func__, error); 15867bf12caSFerruh Yigit return error; 15967bf12caSFerruh Yigit } 16067bf12caSFerruh Yigit 16167bf12caSFerruh Yigit ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq, 16267bf12caSFerruh Yigit CY_SPI_DATA_BUF_SIZE); 16367bf12caSFerruh Yigit 164a0137817SDuan Jiong return PTR_ERR_OR_ZERO(ts); 16567bf12caSFerruh Yigit } 16667bf12caSFerruh Yigit 16767bf12caSFerruh Yigit static int cyttsp4_spi_remove(struct spi_device *spi) 16867bf12caSFerruh Yigit { 16967bf12caSFerruh Yigit struct cyttsp4 *ts = spi_get_drvdata(spi); 17067bf12caSFerruh Yigit cyttsp4_remove(ts); 17167bf12caSFerruh Yigit 17267bf12caSFerruh Yigit return 0; 17367bf12caSFerruh Yigit } 17467bf12caSFerruh Yigit 17567bf12caSFerruh Yigit static struct spi_driver cyttsp4_spi_driver = { 17667bf12caSFerruh Yigit .driver = { 17767bf12caSFerruh Yigit .name = CYTTSP4_SPI_NAME, 17867bf12caSFerruh Yigit .pm = &cyttsp4_pm_ops, 17967bf12caSFerruh Yigit }, 18067bf12caSFerruh Yigit .probe = cyttsp4_spi_probe, 18167bf12caSFerruh Yigit .remove = cyttsp4_spi_remove, 18267bf12caSFerruh Yigit }; 18367bf12caSFerruh Yigit 18467bf12caSFerruh Yigit module_spi_driver(cyttsp4_spi_driver); 18567bf12caSFerruh Yigit 18667bf12caSFerruh Yigit MODULE_LICENSE("GPL"); 18767bf12caSFerruh Yigit MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver"); 18867bf12caSFerruh Yigit MODULE_AUTHOR("Cypress"); 18967bf12caSFerruh Yigit MODULE_ALIAS("spi:cyttsp4"); 190