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