167bf12caSFerruh Yigit /* 267bf12caSFerruh Yigit * Source for: 367bf12caSFerruh Yigit * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver. 467bf12caSFerruh Yigit * For use with Cypress Txx4xx parts. 567bf12caSFerruh Yigit * Supported parts include: 667bf12caSFerruh Yigit * TMA4XX 767bf12caSFerruh Yigit * TMA1036 867bf12caSFerruh Yigit * 967bf12caSFerruh Yigit * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. 1067bf12caSFerruh Yigit * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> 1167bf12caSFerruh Yigit * Copyright (C) 2013 Cypress Semiconductor 1267bf12caSFerruh Yigit * 1367bf12caSFerruh Yigit * This program is free software; you can redistribute it and/or 1467bf12caSFerruh Yigit * modify it under the terms of the GNU General Public License 1567bf12caSFerruh Yigit * version 2, and only version 2, as published by the 1667bf12caSFerruh Yigit * Free Software Foundation. 1767bf12caSFerruh Yigit * 1867bf12caSFerruh Yigit * This program is distributed in the hope that it will be useful, 1967bf12caSFerruh Yigit * but WITHOUT ANY WARRANTY; without even the implied warranty of 2067bf12caSFerruh Yigit * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2167bf12caSFerruh Yigit * GNU General Public License for more details. 2267bf12caSFerruh Yigit * 2367bf12caSFerruh Yigit * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> 2467bf12caSFerruh Yigit * 2567bf12caSFerruh Yigit */ 2667bf12caSFerruh Yigit 2767bf12caSFerruh Yigit #include "cyttsp4_core.h" 2867bf12caSFerruh Yigit 2967bf12caSFerruh Yigit #include <linux/delay.h> 3067bf12caSFerruh Yigit #include <linux/input.h> 3167bf12caSFerruh Yigit #include <linux/spi/spi.h> 3267bf12caSFerruh Yigit 3367bf12caSFerruh Yigit #define CY_SPI_WR_OP 0x00 /* r/~w */ 3467bf12caSFerruh Yigit #define CY_SPI_RD_OP 0x01 3567bf12caSFerruh Yigit #define CY_SPI_BITS_PER_WORD 8 3667bf12caSFerruh Yigit #define CY_SPI_A8_BIT 0x02 3767bf12caSFerruh Yigit #define CY_SPI_WR_HEADER_BYTES 2 3867bf12caSFerruh Yigit #define CY_SPI_RD_HEADER_BYTES 1 3967bf12caSFerruh Yigit #define CY_SPI_CMD_BYTES 2 4067bf12caSFerruh Yigit #define CY_SPI_SYNC_BYTE 0 4167bf12caSFerruh Yigit #define CY_SPI_SYNC_ACK 0x62 /* from TRM *A protocol */ 4267bf12caSFerruh Yigit #define CY_SPI_DATA_SIZE (2 * 256) 4367bf12caSFerruh Yigit 4467bf12caSFerruh Yigit #define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE) 4567bf12caSFerruh Yigit 4667bf12caSFerruh Yigit static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf, 4762f548d0SFerruh Yigit u8 op, u16 reg, u8 *buf, int length) 4867bf12caSFerruh Yigit { 4967bf12caSFerruh Yigit struct spi_device *spi = to_spi_device(dev); 5067bf12caSFerruh Yigit struct spi_message msg; 5167bf12caSFerruh Yigit struct spi_transfer xfer[2]; 5267bf12caSFerruh Yigit u8 *wr_buf = &xfer_buf[0]; 5367bf12caSFerruh Yigit u8 rd_buf[CY_SPI_CMD_BYTES]; 5467bf12caSFerruh Yigit int retval; 5567bf12caSFerruh Yigit int i; 5667bf12caSFerruh Yigit 5767bf12caSFerruh Yigit if (length > CY_SPI_DATA_SIZE) { 5867bf12caSFerruh Yigit dev_err(dev, "%s: length %d is too big.\n", 5967bf12caSFerruh Yigit __func__, length); 6067bf12caSFerruh Yigit return -EINVAL; 6167bf12caSFerruh Yigit } 6267bf12caSFerruh Yigit 6367bf12caSFerruh Yigit memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE); 6467bf12caSFerruh Yigit memset(rd_buf, 0, CY_SPI_CMD_BYTES); 6567bf12caSFerruh Yigit 6662f548d0SFerruh Yigit wr_buf[0] = op + (((reg >> 8) & 0x1) ? CY_SPI_A8_BIT : 0); 6762f548d0SFerruh Yigit if (op == CY_SPI_WR_OP) { 6862f548d0SFerruh Yigit wr_buf[1] = reg & 0xFF; 6962f548d0SFerruh Yigit if (length > 0) 7067bf12caSFerruh Yigit memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length); 7162f548d0SFerruh Yigit } 7267bf12caSFerruh Yigit 7367bf12caSFerruh Yigit memset(xfer, 0, sizeof(xfer)); 7467bf12caSFerruh Yigit spi_message_init(&msg); 7567bf12caSFerruh Yigit 7667bf12caSFerruh Yigit /* 7767bf12caSFerruh Yigit We set both TX and RX buffers because Cypress TTSP 7867bf12caSFerruh Yigit requires full duplex operation. 7967bf12caSFerruh Yigit */ 8067bf12caSFerruh Yigit xfer[0].tx_buf = wr_buf; 8167bf12caSFerruh Yigit xfer[0].rx_buf = rd_buf; 8267bf12caSFerruh Yigit switch (op) { 8367bf12caSFerruh Yigit case CY_SPI_WR_OP: 8467bf12caSFerruh Yigit xfer[0].len = length + CY_SPI_CMD_BYTES; 8567bf12caSFerruh Yigit spi_message_add_tail(&xfer[0], &msg); 8667bf12caSFerruh Yigit break; 8767bf12caSFerruh Yigit 8867bf12caSFerruh Yigit case CY_SPI_RD_OP: 8967bf12caSFerruh Yigit xfer[0].len = CY_SPI_RD_HEADER_BYTES; 9067bf12caSFerruh Yigit spi_message_add_tail(&xfer[0], &msg); 9167bf12caSFerruh Yigit 9267bf12caSFerruh Yigit xfer[1].rx_buf = buf; 9367bf12caSFerruh Yigit xfer[1].len = length; 9467bf12caSFerruh Yigit spi_message_add_tail(&xfer[1], &msg); 9567bf12caSFerruh Yigit break; 9667bf12caSFerruh Yigit 9767bf12caSFerruh Yigit default: 9867bf12caSFerruh Yigit dev_err(dev, "%s: bad operation code=%d\n", __func__, op); 9967bf12caSFerruh Yigit return -EINVAL; 10067bf12caSFerruh Yigit } 10167bf12caSFerruh Yigit 10267bf12caSFerruh Yigit retval = spi_sync(spi, &msg); 10367bf12caSFerruh Yigit if (retval < 0) { 10467bf12caSFerruh Yigit dev_dbg(dev, "%s: spi_sync() error %d, len=%d, op=%d\n", 10567bf12caSFerruh Yigit __func__, retval, xfer[1].len, op); 10667bf12caSFerruh Yigit 10767bf12caSFerruh Yigit /* 10867bf12caSFerruh Yigit * do not return here since was a bad ACK sequence 10967bf12caSFerruh Yigit * let the following ACK check handle any errors and 11067bf12caSFerruh Yigit * allow silent retries 11167bf12caSFerruh Yigit */ 11267bf12caSFerruh Yigit } 11367bf12caSFerruh Yigit 11467bf12caSFerruh Yigit if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK) { 11567bf12caSFerruh Yigit dev_dbg(dev, "%s: operation %d failed\n", __func__, op); 11667bf12caSFerruh Yigit 11767bf12caSFerruh Yigit for (i = 0; i < CY_SPI_CMD_BYTES; i++) 11867bf12caSFerruh Yigit dev_dbg(dev, "%s: test rd_buf[%d]:0x%02x\n", 11967bf12caSFerruh Yigit __func__, i, rd_buf[i]); 12067bf12caSFerruh Yigit for (i = 0; i < length; i++) 12167bf12caSFerruh Yigit dev_dbg(dev, "%s: test buf[%d]:0x%02x\n", 12267bf12caSFerruh Yigit __func__, i, buf[i]); 12367bf12caSFerruh Yigit 12467bf12caSFerruh Yigit return -EIO; 12567bf12caSFerruh Yigit } 12667bf12caSFerruh Yigit 12767bf12caSFerruh Yigit return 0; 12867bf12caSFerruh Yigit } 12967bf12caSFerruh Yigit 13067bf12caSFerruh Yigit static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf, 13162f548d0SFerruh Yigit u16 addr, u8 length, void *data) 13267bf12caSFerruh Yigit { 13367bf12caSFerruh Yigit int rc; 13467bf12caSFerruh Yigit 13567bf12caSFerruh Yigit rc = cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, NULL, 0); 13667bf12caSFerruh Yigit if (rc) 13767bf12caSFerruh Yigit return rc; 13867bf12caSFerruh Yigit else 13967bf12caSFerruh Yigit return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data, 14067bf12caSFerruh Yigit length); 14167bf12caSFerruh Yigit } 14267bf12caSFerruh Yigit 14367bf12caSFerruh Yigit static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf, 14462f548d0SFerruh Yigit u16 addr, u8 length, const void *data) 14567bf12caSFerruh Yigit { 14667bf12caSFerruh Yigit return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data, 14767bf12caSFerruh Yigit length); 14867bf12caSFerruh Yigit } 14967bf12caSFerruh Yigit 15067bf12caSFerruh Yigit static const struct cyttsp4_bus_ops cyttsp_spi_bus_ops = { 15167bf12caSFerruh Yigit .bustype = BUS_SPI, 15267bf12caSFerruh Yigit .write = cyttsp_spi_write_block_data, 15367bf12caSFerruh Yigit .read = cyttsp_spi_read_block_data, 15467bf12caSFerruh Yigit }; 15567bf12caSFerruh Yigit 15667bf12caSFerruh Yigit static int cyttsp4_spi_probe(struct spi_device *spi) 15767bf12caSFerruh Yigit { 15867bf12caSFerruh Yigit struct cyttsp4 *ts; 15967bf12caSFerruh Yigit int error; 16067bf12caSFerruh Yigit 16167bf12caSFerruh Yigit /* Set up SPI*/ 16267bf12caSFerruh Yigit spi->bits_per_word = CY_SPI_BITS_PER_WORD; 16367bf12caSFerruh Yigit spi->mode = SPI_MODE_0; 16467bf12caSFerruh Yigit error = spi_setup(spi); 16567bf12caSFerruh Yigit if (error < 0) { 16667bf12caSFerruh Yigit dev_err(&spi->dev, "%s: SPI setup error %d\n", 16767bf12caSFerruh Yigit __func__, error); 16867bf12caSFerruh Yigit return error; 16967bf12caSFerruh Yigit } 17067bf12caSFerruh Yigit 17167bf12caSFerruh Yigit ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq, 17267bf12caSFerruh Yigit CY_SPI_DATA_BUF_SIZE); 17367bf12caSFerruh Yigit 17467bf12caSFerruh Yigit if (IS_ERR(ts)) 17567bf12caSFerruh Yigit return PTR_ERR(ts); 17667bf12caSFerruh Yigit 17767bf12caSFerruh Yigit return 0; 17867bf12caSFerruh Yigit } 17967bf12caSFerruh Yigit 18067bf12caSFerruh Yigit static int cyttsp4_spi_remove(struct spi_device *spi) 18167bf12caSFerruh Yigit { 18267bf12caSFerruh Yigit struct cyttsp4 *ts = spi_get_drvdata(spi); 18367bf12caSFerruh Yigit cyttsp4_remove(ts); 18467bf12caSFerruh Yigit 18567bf12caSFerruh Yigit return 0; 18667bf12caSFerruh Yigit } 18767bf12caSFerruh Yigit 18867bf12caSFerruh Yigit static struct spi_driver cyttsp4_spi_driver = { 18967bf12caSFerruh Yigit .driver = { 19067bf12caSFerruh Yigit .name = CYTTSP4_SPI_NAME, 19167bf12caSFerruh Yigit .owner = THIS_MODULE, 19267bf12caSFerruh Yigit .pm = &cyttsp4_pm_ops, 19367bf12caSFerruh Yigit }, 19467bf12caSFerruh Yigit .probe = cyttsp4_spi_probe, 19567bf12caSFerruh Yigit .remove = cyttsp4_spi_remove, 19667bf12caSFerruh Yigit }; 19767bf12caSFerruh Yigit 19867bf12caSFerruh Yigit module_spi_driver(cyttsp4_spi_driver); 19967bf12caSFerruh Yigit 20067bf12caSFerruh Yigit MODULE_LICENSE("GPL"); 20167bf12caSFerruh Yigit MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver"); 20267bf12caSFerruh Yigit MODULE_AUTHOR("Cypress"); 20367bf12caSFerruh Yigit MODULE_ALIAS("spi:cyttsp4"); 204