root/drivers/input/touchscreen/cyttsp4_spi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cyttsp_spi_xfer
  2. cyttsp_spi_read_block_data
  3. cyttsp_spi_write_block_data
  4. cyttsp4_spi_probe
  5. cyttsp4_spi_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Source for:
   4  * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver.
   5  * For use with Cypress Txx4xx parts.
   6  * Supported parts include:
   7  * TMA4XX
   8  * TMA1036
   9  *
  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
  13  *
  14  * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
  15  */
  16 
  17 #include "cyttsp4_core.h"
  18 
  19 #include <linux/delay.h>
  20 #include <linux/input.h>
  21 #include <linux/spi/spi.h>
  22 
  23 #define CY_SPI_WR_OP            0x00 /* r/~w */
  24 #define CY_SPI_RD_OP            0x01
  25 #define CY_SPI_BITS_PER_WORD    8
  26 #define CY_SPI_A8_BIT           0x02
  27 #define CY_SPI_WR_HEADER_BYTES  2
  28 #define CY_SPI_RD_HEADER_BYTES  1
  29 #define CY_SPI_CMD_BYTES        2
  30 #define CY_SPI_SYNC_BYTE        0
  31 #define CY_SPI_SYNC_ACK         0x62 /* from TRM *A protocol */
  32 #define CY_SPI_DATA_SIZE        (2 * 256)
  33 
  34 #define CY_SPI_DATA_BUF_SIZE    (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
  35 
  36 static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
  37                            u8 op, u16 reg, u8 *buf, int length)
  38 {
  39         struct spi_device *spi = to_spi_device(dev);
  40         struct spi_message msg;
  41         struct spi_transfer xfer[2];
  42         u8 *wr_buf = &xfer_buf[0];
  43         u8 rd_buf[CY_SPI_CMD_BYTES];
  44         int retval;
  45         int i;
  46 
  47         if (length > CY_SPI_DATA_SIZE) {
  48                 dev_err(dev, "%s: length %d is too big.\n",
  49                         __func__, length);
  50                 return -EINVAL;
  51         }
  52 
  53         memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE);
  54         memset(rd_buf, 0, CY_SPI_CMD_BYTES);
  55 
  56         wr_buf[0] = op + (((reg >> 8) & 0x1) ? CY_SPI_A8_BIT : 0);
  57         if (op == CY_SPI_WR_OP) {
  58                 wr_buf[1] = reg & 0xFF;
  59                 if (length > 0)
  60                         memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length);
  61         }
  62 
  63         memset(xfer, 0, sizeof(xfer));
  64         spi_message_init(&msg);
  65 
  66         /*
  67           We set both TX and RX buffers because Cypress TTSP
  68           requires full duplex operation.
  69         */
  70         xfer[0].tx_buf = wr_buf;
  71         xfer[0].rx_buf = rd_buf;
  72         switch (op) {
  73         case CY_SPI_WR_OP:
  74                 xfer[0].len = length + CY_SPI_CMD_BYTES;
  75                 spi_message_add_tail(&xfer[0], &msg);
  76                 break;
  77 
  78         case CY_SPI_RD_OP:
  79                 xfer[0].len = CY_SPI_RD_HEADER_BYTES;
  80                 spi_message_add_tail(&xfer[0], &msg);
  81 
  82                 xfer[1].rx_buf = buf;
  83                 xfer[1].len = length;
  84                 spi_message_add_tail(&xfer[1], &msg);
  85                 break;
  86 
  87         default:
  88                 dev_err(dev, "%s: bad operation code=%d\n", __func__, op);
  89                 return -EINVAL;
  90         }
  91 
  92         retval = spi_sync(spi, &msg);
  93         if (retval < 0) {
  94                 dev_dbg(dev, "%s: spi_sync() error %d, len=%d, op=%d\n",
  95                         __func__, retval, xfer[1].len, op);
  96 
  97                 /*
  98                  * do not return here since was a bad ACK sequence
  99                  * let the following ACK check handle any errors and
 100                  * allow silent retries
 101                  */
 102         }
 103 
 104         if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK) {
 105                 dev_dbg(dev, "%s: operation %d failed\n", __func__, op);
 106 
 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]);
 113 
 114                 return -EIO;
 115         }
 116 
 117         return 0;
 118 }
 119 
 120 static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
 121                                       u16 addr, u8 length, void *data)
 122 {
 123         int rc;
 124 
 125         rc = cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, NULL, 0);
 126         if (rc)
 127                 return rc;
 128         else
 129                 return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data,
 130                                 length);
 131 }
 132 
 133 static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf,
 134                                        u16 addr, u8 length, const void *data)
 135 {
 136         return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data,
 137                         length);
 138 }
 139 
 140 static const struct cyttsp4_bus_ops cyttsp_spi_bus_ops = {
 141         .bustype        = BUS_SPI,
 142         .write          = cyttsp_spi_write_block_data,
 143         .read           = cyttsp_spi_read_block_data,
 144 };
 145 
 146 static int cyttsp4_spi_probe(struct spi_device *spi)
 147 {
 148         struct cyttsp4 *ts;
 149         int error;
 150 
 151         /* Set up SPI*/
 152         spi->bits_per_word = CY_SPI_BITS_PER_WORD;
 153         spi->mode = SPI_MODE_0;
 154         error = spi_setup(spi);
 155         if (error < 0) {
 156                 dev_err(&spi->dev, "%s: SPI setup error %d\n",
 157                         __func__, error);
 158                 return error;
 159         }
 160 
 161         ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq,
 162                           CY_SPI_DATA_BUF_SIZE);
 163 
 164         return PTR_ERR_OR_ZERO(ts);
 165 }
 166 
 167 static int cyttsp4_spi_remove(struct spi_device *spi)
 168 {
 169         struct cyttsp4 *ts = spi_get_drvdata(spi);
 170         cyttsp4_remove(ts);
 171 
 172         return 0;
 173 }
 174 
 175 static struct spi_driver cyttsp4_spi_driver = {
 176         .driver = {
 177                 .name   = CYTTSP4_SPI_NAME,
 178                 .pm     = &cyttsp4_pm_ops,
 179         },
 180         .probe  = cyttsp4_spi_probe,
 181         .remove = cyttsp4_spi_remove,
 182 };
 183 
 184 module_spi_driver(cyttsp4_spi_driver);
 185 
 186 MODULE_LICENSE("GPL");
 187 MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver");
 188 MODULE_AUTHOR("Cypress");
 189 MODULE_ALIAS("spi:cyttsp4");

/* [<][>][^][v][top][bottom][index][help] */