linux/drivers/input/keyboard/lm8333.c
<<
>>
Prefs
   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
  33struct 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
  42int 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
  53int 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
  64int 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
  76static 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
 102static 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
 128static 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
 203static 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
 214static const struct i2c_device_id lm8333_id[] = {
 215        { "lm8333", 0 },
 216        { }
 217};
 218MODULE_DEVICE_TABLE(i2c, lm8333_id);
 219
 220static 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};
 228module_i2c_driver(lm8333_driver);
 229
 230MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
 231MODULE_DESCRIPTION("LM8333 keyboard driver");
 232MODULE_LICENSE("GPL v2");
 233