root/drivers/input/keyboard/lm8333.c

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

DEFINITIONS

This source file includes following definitions.
  1. lm8333_read8
  2. lm8333_write8
  3. lm8333_read_block
  4. lm8333_key_handler
  5. lm8333_irq_thread
  6. lm8333_probe
  7. lm8333_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * LM8333 keypad driver
   4  * Copyright (C) 2012 Wolfram Sang, Pengutronix <kernel@pengutronix.de>
   5  */
   6 
   7 #include <linux/module.h>
   8 #include <linux/slab.h>
   9 #include <linux/irq.h>
  10 #include <linux/i2c.h>
  11 #include <linux/interrupt.h>
  12 #include <linux/input/matrix_keypad.h>
  13 #include <linux/input/lm8333.h>
  14 
  15 #define LM8333_FIFO_READ                0x20
  16 #define LM8333_DEBOUNCE                 0x22
  17 #define LM8333_READ_INT                 0xD0
  18 #define LM8333_ACTIVE                   0xE4
  19 #define LM8333_READ_ERROR               0xF0
  20 
  21 #define LM8333_KEYPAD_IRQ               (1 << 0)
  22 #define LM8333_ERROR_IRQ                (1 << 3)
  23 
  24 #define LM8333_ERROR_KEYOVR             0x04
  25 #define LM8333_ERROR_FIFOOVR            0x40
  26 
  27 #define LM8333_FIFO_TRANSFER_SIZE       16
  28 
  29 #define LM8333_NUM_ROWS         8
  30 #define LM8333_NUM_COLS         16
  31 #define LM8333_ROW_SHIFT        4
  32 
  33 struct lm8333 {
  34         struct i2c_client *client;
  35         struct input_dev *input;
  36         unsigned short keycodes[LM8333_NUM_ROWS << LM8333_ROW_SHIFT];
  37 };
  38 
  39 /* The accessors try twice because the first access may be needed for wakeup */
  40 #define LM8333_READ_RETRIES 2
  41 
  42 int lm8333_read8(struct lm8333 *lm8333, u8 cmd)
  43 {
  44         int retries = 0, ret;
  45 
  46         do {
  47                 ret = i2c_smbus_read_byte_data(lm8333->client, cmd);
  48         } while (ret < 0 && retries++ < LM8333_READ_RETRIES);
  49 
  50         return ret;
  51 }
  52 
  53 int lm8333_write8(struct lm8333 *lm8333, u8 cmd, u8 val)
  54 {
  55         int retries = 0, ret;
  56 
  57         do {
  58                 ret = i2c_smbus_write_byte_data(lm8333->client, cmd, val);
  59         } while (ret < 0 && retries++ < LM8333_READ_RETRIES);
  60 
  61         return ret;
  62 }
  63 
  64 int lm8333_read_block(struct lm8333 *lm8333, u8 cmd, u8 len, u8 *buf)
  65 {
  66         int retries = 0, ret;
  67 
  68         do {
  69                 ret = i2c_smbus_read_i2c_block_data(lm8333->client,
  70                                                     cmd, len, buf);
  71         } while (ret < 0 && retries++ < LM8333_READ_RETRIES);
  72 
  73         return ret;
  74 }
  75 
  76 static void lm8333_key_handler(struct lm8333 *lm8333)
  77 {
  78         struct input_dev *input = lm8333->input;
  79         u8 keys[LM8333_FIFO_TRANSFER_SIZE];
  80         u8 code, pressed;
  81         int i, ret;
  82 
  83         ret = lm8333_read_block(lm8333, LM8333_FIFO_READ,
  84                                 LM8333_FIFO_TRANSFER_SIZE, keys);
  85         if (ret != LM8333_FIFO_TRANSFER_SIZE) {
  86                 dev_err(&lm8333->client->dev,
  87                         "Error %d while reading FIFO\n", ret);
  88                 return;
  89         }
  90 
  91         for (i = 0; i < LM8333_FIFO_TRANSFER_SIZE && keys[i]; i++) {
  92                 pressed = keys[i] & 0x80;
  93                 code = keys[i] & 0x7f;
  94 
  95                 input_event(input, EV_MSC, MSC_SCAN, code);
  96                 input_report_key(input, lm8333->keycodes[code], pressed);
  97         }
  98 
  99         input_sync(input);
 100 }
 101 
 102 static irqreturn_t lm8333_irq_thread(int irq, void *data)
 103 {
 104         struct lm8333 *lm8333 = data;
 105         u8 status = lm8333_read8(lm8333, LM8333_READ_INT);
 106 
 107         if (!status)
 108                 return IRQ_NONE;
 109 
 110         if (status & LM8333_ERROR_IRQ) {
 111                 u8 err = lm8333_read8(lm8333, LM8333_READ_ERROR);
 112 
 113                 if (err & (LM8333_ERROR_KEYOVR | LM8333_ERROR_FIFOOVR)) {
 114                         u8 dummy[LM8333_FIFO_TRANSFER_SIZE];
 115 
 116                         lm8333_read_block(lm8333, LM8333_FIFO_READ,
 117                                         LM8333_FIFO_TRANSFER_SIZE, dummy);
 118                 }
 119                 dev_err(&lm8333->client->dev, "Got error %02x\n", err);
 120         }
 121 
 122         if (status & LM8333_KEYPAD_IRQ)
 123                 lm8333_key_handler(lm8333);
 124 
 125         return IRQ_HANDLED;
 126 }
 127 
 128 static int lm8333_probe(struct i2c_client *client,
 129                                   const struct i2c_device_id *id)
 130 {
 131         const struct lm8333_platform_data *pdata =
 132                         dev_get_platdata(&client->dev);
 133         struct lm8333 *lm8333;
 134         struct input_dev *input;
 135         int err, active_time;
 136 
 137         if (!pdata)
 138                 return -EINVAL;
 139 
 140         active_time = pdata->active_time ?: 500;
 141         if (active_time / 3 <= pdata->debounce_time / 3) {
 142                 dev_err(&client->dev, "Active time not big enough!\n");
 143                 return -EINVAL;
 144         }
 145 
 146         lm8333 = kzalloc(sizeof(*lm8333), GFP_KERNEL);
 147         input = input_allocate_device();
 148         if (!lm8333 || !input) {
 149                 err = -ENOMEM;
 150                 goto free_mem;
 151         }
 152 
 153         lm8333->client = client;
 154         lm8333->input = input;
 155 
 156         input->name = client->name;
 157         input->dev.parent = &client->dev;
 158         input->id.bustype = BUS_I2C;
 159 
 160         input_set_capability(input, EV_MSC, MSC_SCAN);
 161 
 162         err = matrix_keypad_build_keymap(pdata->matrix_data, NULL,
 163                                          LM8333_NUM_ROWS, LM8333_NUM_COLS,
 164                                          lm8333->keycodes, input);
 165         if (err)
 166                 goto free_mem;
 167 
 168         if (pdata->debounce_time) {
 169                 err = lm8333_write8(lm8333, LM8333_DEBOUNCE,
 170                                     pdata->debounce_time / 3);
 171                 if (err)
 172                         dev_warn(&client->dev, "Unable to set debounce time\n");
 173         }
 174 
 175         if (pdata->active_time) {
 176                 err = lm8333_write8(lm8333, LM8333_ACTIVE,
 177                                     pdata->active_time / 3);
 178                 if (err)
 179                         dev_warn(&client->dev, "Unable to set active time\n");
 180         }
 181 
 182         err = request_threaded_irq(client->irq, NULL, lm8333_irq_thread,
 183                                    IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 184                                    "lm8333", lm8333);
 185         if (err)
 186                 goto free_mem;
 187 
 188         err = input_register_device(input);
 189         if (err)
 190                 goto free_irq;
 191 
 192         i2c_set_clientdata(client, lm8333);
 193         return 0;
 194 
 195  free_irq:
 196         free_irq(client->irq, lm8333);
 197  free_mem:
 198         input_free_device(input);
 199         kfree(lm8333);
 200         return err;
 201 }
 202 
 203 static int lm8333_remove(struct i2c_client *client)
 204 {
 205         struct lm8333 *lm8333 = i2c_get_clientdata(client);
 206 
 207         free_irq(client->irq, lm8333);
 208         input_unregister_device(lm8333->input);
 209         kfree(lm8333);
 210 
 211         return 0;
 212 }
 213 
 214 static const struct i2c_device_id lm8333_id[] = {
 215         { "lm8333", 0 },
 216         { }
 217 };
 218 MODULE_DEVICE_TABLE(i2c, lm8333_id);
 219 
 220 static struct i2c_driver lm8333_driver = {
 221         .driver = {
 222                 .name           = "lm8333",
 223         },
 224         .probe          = lm8333_probe,
 225         .remove         = lm8333_remove,
 226         .id_table       = lm8333_id,
 227 };
 228 module_i2c_driver(lm8333_driver);
 229 
 230 MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
 231 MODULE_DESCRIPTION("LM8333 keyboard driver");
 232 MODULE_LICENSE("GPL v2");

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