1/* 2 * AD714X CapTouch Programmable Controller driver (SPI bus) 3 * 4 * Copyright 2009-2011 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later. 7 */ 8 9#include <linux/input.h> /* BUS_SPI */ 10#include <linux/module.h> 11#include <linux/spi/spi.h> 12#include <linux/pm.h> 13#include <linux/types.h> 14#include "ad714x.h" 15 16#define AD714x_SPI_CMD_PREFIX 0xE000 /* bits 15:11 */ 17#define AD714x_SPI_READ BIT(10) 18 19static int __maybe_unused ad714x_spi_suspend(struct device *dev) 20{ 21 return ad714x_disable(spi_get_drvdata(to_spi_device(dev))); 22} 23 24static int __maybe_unused ad714x_spi_resume(struct device *dev) 25{ 26 return ad714x_enable(spi_get_drvdata(to_spi_device(dev))); 27} 28 29static SIMPLE_DEV_PM_OPS(ad714x_spi_pm, ad714x_spi_suspend, ad714x_spi_resume); 30 31static int ad714x_spi_read(struct ad714x_chip *chip, 32 unsigned short reg, unsigned short *data, size_t len) 33{ 34 struct spi_device *spi = to_spi_device(chip->dev); 35 struct spi_message message; 36 struct spi_transfer xfer[2]; 37 int i; 38 int error; 39 40 spi_message_init(&message); 41 memset(xfer, 0, sizeof(xfer)); 42 43 chip->xfer_buf[0] = cpu_to_be16(AD714x_SPI_CMD_PREFIX | 44 AD714x_SPI_READ | reg); 45 xfer[0].tx_buf = &chip->xfer_buf[0]; 46 xfer[0].len = sizeof(chip->xfer_buf[0]); 47 spi_message_add_tail(&xfer[0], &message); 48 49 xfer[1].rx_buf = &chip->xfer_buf[1]; 50 xfer[1].len = sizeof(chip->xfer_buf[1]) * len; 51 spi_message_add_tail(&xfer[1], &message); 52 53 error = spi_sync(spi, &message); 54 if (unlikely(error)) { 55 dev_err(chip->dev, "SPI read error: %d\n", error); 56 return error; 57 } 58 59 for (i = 0; i < len; i++) 60 data[i] = be16_to_cpu(chip->xfer_buf[i + 1]); 61 62 return 0; 63} 64 65static int ad714x_spi_write(struct ad714x_chip *chip, 66 unsigned short reg, unsigned short data) 67{ 68 struct spi_device *spi = to_spi_device(chip->dev); 69 int error; 70 71 chip->xfer_buf[0] = cpu_to_be16(AD714x_SPI_CMD_PREFIX | reg); 72 chip->xfer_buf[1] = cpu_to_be16(data); 73 74 error = spi_write(spi, (u8 *)chip->xfer_buf, 75 2 * sizeof(*chip->xfer_buf)); 76 if (unlikely(error)) { 77 dev_err(chip->dev, "SPI write error: %d\n", error); 78 return error; 79 } 80 81 return 0; 82} 83 84static int ad714x_spi_probe(struct spi_device *spi) 85{ 86 struct ad714x_chip *chip; 87 int err; 88 89 spi->bits_per_word = 8; 90 err = spi_setup(spi); 91 if (err < 0) 92 return err; 93 94 chip = ad714x_probe(&spi->dev, BUS_SPI, spi->irq, 95 ad714x_spi_read, ad714x_spi_write); 96 if (IS_ERR(chip)) 97 return PTR_ERR(chip); 98 99 spi_set_drvdata(spi, chip); 100 101 return 0; 102} 103 104static int ad714x_spi_remove(struct spi_device *spi) 105{ 106 struct ad714x_chip *chip = spi_get_drvdata(spi); 107 108 ad714x_remove(chip); 109 110 return 0; 111} 112 113static struct spi_driver ad714x_spi_driver = { 114 .driver = { 115 .name = "ad714x_captouch", 116 .owner = THIS_MODULE, 117 .pm = &ad714x_spi_pm, 118 }, 119 .probe = ad714x_spi_probe, 120 .remove = ad714x_spi_remove, 121}; 122 123module_spi_driver(ad714x_spi_driver); 124 125MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor SPI Bus Driver"); 126MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 127MODULE_LICENSE("GPL"); 128