root/drivers/input/misc/atmel_captouch.c

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

DEFINITIONS

This source file includes following definitions.
  1. atmel_read
  2. atmel_captouch_isr
  3. atmel_captouch_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Atmel Atmegaxx Capacitive Touch Button Driver
   4  *
   5  * Copyright (C) 2016 Google, inc.
   6  */
   7 
   8 /*
   9  * It's irrelevant that the HW used to develop captouch driver is based
  10  * on Atmega88PA part and uses QtouchADC parts for sensing touch.
  11  * Calling this driver "captouch" is an arbitrary way to distinguish
  12  * the protocol this driver supported by other atmel/qtouch drivers.
  13  *
  14  * Captouch driver supports a newer/different version of the I2C
  15  * registers/commands than the qt1070.c driver.
  16  * Don't let the similarity of the general driver structure fool you.
  17  *
  18  * For raw i2c access from userspace, use i2cset/i2cget
  19  * to poke at /dev/i2c-N devices.
  20  */
  21 
  22 #include <linux/device.h>
  23 #include <linux/kernel.h>
  24 #include <linux/module.h>
  25 #include <linux/init.h>
  26 #include <linux/i2c.h>
  27 #include <linux/input.h>
  28 #include <linux/interrupt.h>
  29 #include <linux/slab.h>
  30 
  31 /* Maximum number of buttons supported */
  32 #define MAX_NUM_OF_BUTTONS              8
  33 
  34 /* Registers */
  35 #define REG_KEY1_THRESHOLD              0x02
  36 #define REG_KEY2_THRESHOLD              0x03
  37 #define REG_KEY3_THRESHOLD              0x04
  38 #define REG_KEY4_THRESHOLD              0x05
  39 
  40 #define REG_KEY1_REF_H                  0x20
  41 #define REG_KEY1_REF_L                  0x21
  42 #define REG_KEY2_REF_H                  0x22
  43 #define REG_KEY2_REF_L                  0x23
  44 #define REG_KEY3_REF_H                  0x24
  45 #define REG_KEY3_REF_L                  0x25
  46 #define REG_KEY4_REF_H                  0x26
  47 #define REG_KEY4_REF_L                  0x27
  48 
  49 #define REG_KEY1_DLT_H                  0x30
  50 #define REG_KEY1_DLT_L                  0x31
  51 #define REG_KEY2_DLT_H                  0x32
  52 #define REG_KEY2_DLT_L                  0x33
  53 #define REG_KEY3_DLT_H                  0x34
  54 #define REG_KEY3_DLT_L                  0x35
  55 #define REG_KEY4_DLT_H                  0x36
  56 #define REG_KEY4_DLT_L                  0x37
  57 
  58 #define REG_KEY_STATE                   0x3C
  59 
  60 /*
  61  * @i2c_client: I2C slave device client pointer
  62  * @input: Input device pointer
  63  * @num_btn: Number of buttons
  64  * @keycodes: map of button# to KeyCode
  65  * @prev_btn: Previous key state to detect button "press" or "release"
  66  * @xfer_buf: I2C transfer buffer
  67  */
  68 struct atmel_captouch_device {
  69         struct i2c_client *client;
  70         struct input_dev *input;
  71         u32 num_btn;
  72         u32 keycodes[MAX_NUM_OF_BUTTONS];
  73         u8 prev_btn;
  74         u8 xfer_buf[8] ____cacheline_aligned;
  75 };
  76 
  77 /*
  78  * Read from I2C slave device
  79  * The protocol is that the client has to provide both the register address
  80  * and the length, and while reading back the device would prepend the data
  81  * with address and length for verification.
  82  */
  83 static int atmel_read(struct atmel_captouch_device *capdev,
  84                          u8 reg, u8 *data, size_t len)
  85 {
  86         struct i2c_client *client = capdev->client;
  87         struct device *dev = &client->dev;
  88         struct i2c_msg msg[2];
  89         int err;
  90 
  91         if (len > sizeof(capdev->xfer_buf) - 2)
  92                 return -EINVAL;
  93 
  94         capdev->xfer_buf[0] = reg;
  95         capdev->xfer_buf[1] = len;
  96 
  97         msg[0].addr = client->addr;
  98         msg[0].flags = 0;
  99         msg[0].buf = capdev->xfer_buf;
 100         msg[0].len = 2;
 101 
 102         msg[1].addr = client->addr;
 103         msg[1].flags = I2C_M_RD;
 104         msg[1].buf = capdev->xfer_buf;
 105         msg[1].len = len + 2;
 106 
 107         err = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
 108         if (err != ARRAY_SIZE(msg))
 109                 return err < 0 ? err : -EIO;
 110 
 111         if (capdev->xfer_buf[0] != reg) {
 112                 dev_err(dev,
 113                         "I2C read error: register address does not match (%#02x vs %02x)\n",
 114                         capdev->xfer_buf[0], reg);
 115                 return -ECOMM;
 116         }
 117 
 118         memcpy(data, &capdev->xfer_buf[2], len);
 119 
 120         return 0;
 121 }
 122 
 123 /*
 124  * Handle interrupt and report the key changes to the input system.
 125  * Multi-touch can be supported; however, it really depends on whether
 126  * the device can multi-touch.
 127  */
 128 static irqreturn_t atmel_captouch_isr(int irq, void *data)
 129 {
 130         struct atmel_captouch_device *capdev = data;
 131         struct device *dev = &capdev->client->dev;
 132         int error;
 133         int i;
 134         u8 new_btn;
 135         u8 changed_btn;
 136 
 137         error = atmel_read(capdev, REG_KEY_STATE, &new_btn, 1);
 138         if (error) {
 139                 dev_err(dev, "failed to read button state: %d\n", error);
 140                 goto out;
 141         }
 142 
 143         dev_dbg(dev, "%s: button state %#02x\n", __func__, new_btn);
 144 
 145         changed_btn = new_btn ^ capdev->prev_btn;
 146         capdev->prev_btn = new_btn;
 147 
 148         for (i = 0; i < capdev->num_btn; i++) {
 149                 if (changed_btn & BIT(i))
 150                         input_report_key(capdev->input,
 151                                          capdev->keycodes[i],
 152                                          new_btn & BIT(i));
 153         }
 154 
 155         input_sync(capdev->input);
 156 
 157 out:
 158         return IRQ_HANDLED;
 159 }
 160 
 161 /*
 162  * Probe function to setup the device, input system and interrupt
 163  */
 164 static int atmel_captouch_probe(struct i2c_client *client,
 165                 const struct i2c_device_id *id)
 166 {
 167         struct atmel_captouch_device *capdev;
 168         struct device *dev = &client->dev;
 169         struct device_node *node;
 170         int i;
 171         int err;
 172 
 173         if (!i2c_check_functionality(client->adapter,
 174                                      I2C_FUNC_SMBUS_BYTE_DATA |
 175                                         I2C_FUNC_SMBUS_WORD_DATA |
 176                                         I2C_FUNC_SMBUS_I2C_BLOCK)) {
 177                 dev_err(dev, "needed i2c functionality is not supported\n");
 178                 return -EINVAL;
 179         }
 180 
 181         capdev = devm_kzalloc(dev, sizeof(*capdev), GFP_KERNEL);
 182         if (!capdev)
 183                 return -ENOMEM;
 184 
 185         capdev->client = client;
 186 
 187         err = atmel_read(capdev, REG_KEY_STATE,
 188                             &capdev->prev_btn, sizeof(capdev->prev_btn));
 189         if (err) {
 190                 dev_err(dev, "failed to read initial button state: %d\n", err);
 191                 return err;
 192         }
 193 
 194         capdev->input = devm_input_allocate_device(dev);
 195         if (!capdev->input) {
 196                 dev_err(dev, "failed to allocate input device\n");
 197                 return -ENOMEM;
 198         }
 199 
 200         capdev->input->id.bustype = BUS_I2C;
 201         capdev->input->id.product = 0x880A;
 202         capdev->input->id.version = 0;
 203         capdev->input->name = "ATMegaXX Capacitive Button Controller";
 204         __set_bit(EV_KEY, capdev->input->evbit);
 205 
 206         node = dev->of_node;
 207         if (!node) {
 208                 dev_err(dev, "failed to find matching node in device tree\n");
 209                 return -EINVAL;
 210         }
 211 
 212         if (of_property_read_bool(node, "autorepeat"))
 213                 __set_bit(EV_REP, capdev->input->evbit);
 214 
 215         capdev->num_btn = of_property_count_u32_elems(node, "linux,keymap");
 216         if (capdev->num_btn > MAX_NUM_OF_BUTTONS)
 217                 capdev->num_btn = MAX_NUM_OF_BUTTONS;
 218 
 219         err = of_property_read_u32_array(node, "linux,keycodes",
 220                                          capdev->keycodes,
 221                                          capdev->num_btn);
 222         if (err) {
 223                 dev_err(dev,
 224                         "failed to read linux,keycode property: %d\n", err);
 225                 return err;
 226         }
 227 
 228         for (i = 0; i < capdev->num_btn; i++)
 229                 __set_bit(capdev->keycodes[i], capdev->input->keybit);
 230 
 231         capdev->input->keycode = capdev->keycodes;
 232         capdev->input->keycodesize = sizeof(capdev->keycodes[0]);
 233         capdev->input->keycodemax = capdev->num_btn;
 234 
 235         err = input_register_device(capdev->input);
 236         if (err)
 237                 return err;
 238 
 239         err = devm_request_threaded_irq(dev, client->irq,
 240                                         NULL, atmel_captouch_isr,
 241                                         IRQF_ONESHOT,
 242                                         "atmel_captouch", capdev);
 243         if (err) {
 244                 dev_err(dev, "failed to request irq %d: %d\n",
 245                         client->irq, err);
 246                 return err;
 247         }
 248 
 249         return 0;
 250 }
 251 
 252 #ifdef CONFIG_OF
 253 static const struct of_device_id atmel_captouch_of_id[] = {
 254         {
 255                 .compatible = "atmel,captouch",
 256         },
 257         { /* sentinel */ }
 258 };
 259 MODULE_DEVICE_TABLE(of, atmel_captouch_of_id);
 260 #endif
 261 
 262 static const struct i2c_device_id atmel_captouch_id[] = {
 263         { "atmel_captouch", 0 },
 264         { }
 265 };
 266 MODULE_DEVICE_TABLE(i2c, atmel_captouch_id);
 267 
 268 static struct i2c_driver atmel_captouch_driver = {
 269         .probe          = atmel_captouch_probe,
 270         .id_table       = atmel_captouch_id,
 271         .driver         = {
 272                 .name   = "atmel_captouch",
 273                 .of_match_table = of_match_ptr(atmel_captouch_of_id),
 274         },
 275 };
 276 module_i2c_driver(atmel_captouch_driver);
 277 
 278 /* Module information */
 279 MODULE_AUTHOR("Hung-yu Wu <hywu@google.com>");
 280 MODULE_DESCRIPTION("Atmel ATmegaXX Capacitance Touch Sensor I2C Driver");
 281 MODULE_LICENSE("GPL v2");

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