lm8333.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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. #include <linux/i2c.h>
  7. #include <linux/input.h>
  8. #include <linux/input/matrix_keypad.h>
  9. #include <linux/input/lm8333.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/module.h>
  12. #include <linux/slab.h>
  13. #define LM8333_FIFO_READ 0x20
  14. #define LM8333_DEBOUNCE 0x22
  15. #define LM8333_READ_INT 0xD0
  16. #define LM8333_ACTIVE 0xE4
  17. #define LM8333_READ_ERROR 0xF0
  18. #define LM8333_KEYPAD_IRQ (1 << 0)
  19. #define LM8333_ERROR_IRQ (1 << 3)
  20. #define LM8333_ERROR_KEYOVR 0x04
  21. #define LM8333_ERROR_FIFOOVR 0x40
  22. #define LM8333_FIFO_TRANSFER_SIZE 16
  23. #define LM8333_NUM_ROWS 8
  24. #define LM8333_NUM_COLS 16
  25. #define LM8333_ROW_SHIFT 4
  26. struct lm8333 {
  27. struct i2c_client *client;
  28. struct input_dev *input;
  29. unsigned short keycodes[LM8333_NUM_ROWS << LM8333_ROW_SHIFT];
  30. };
  31. /* The accessors try twice because the first access may be needed for wakeup */
  32. #define LM8333_READ_RETRIES 2
  33. int lm8333_read8(struct lm8333 *lm8333, u8 cmd)
  34. {
  35. int retries = 0, ret;
  36. do {
  37. ret = i2c_smbus_read_byte_data(lm8333->client, cmd);
  38. } while (ret < 0 && retries++ < LM8333_READ_RETRIES);
  39. return ret;
  40. }
  41. int lm8333_write8(struct lm8333 *lm8333, u8 cmd, u8 val)
  42. {
  43. int retries = 0, ret;
  44. do {
  45. ret = i2c_smbus_write_byte_data(lm8333->client, cmd, val);
  46. } while (ret < 0 && retries++ < LM8333_READ_RETRIES);
  47. return ret;
  48. }
  49. int lm8333_read_block(struct lm8333 *lm8333, u8 cmd, u8 len, u8 *buf)
  50. {
  51. int retries = 0, ret;
  52. do {
  53. ret = i2c_smbus_read_i2c_block_data(lm8333->client,
  54. cmd, len, buf);
  55. } while (ret < 0 && retries++ < LM8333_READ_RETRIES);
  56. return ret;
  57. }
  58. static void lm8333_key_handler(struct lm8333 *lm8333)
  59. {
  60. struct input_dev *input = lm8333->input;
  61. u8 keys[LM8333_FIFO_TRANSFER_SIZE];
  62. u8 code, pressed;
  63. int i, ret;
  64. ret = lm8333_read_block(lm8333, LM8333_FIFO_READ,
  65. LM8333_FIFO_TRANSFER_SIZE, keys);
  66. if (ret != LM8333_FIFO_TRANSFER_SIZE) {
  67. dev_err(&lm8333->client->dev,
  68. "Error %d while reading FIFO\n", ret);
  69. return;
  70. }
  71. for (i = 0; i < LM8333_FIFO_TRANSFER_SIZE && keys[i]; i++) {
  72. pressed = keys[i] & 0x80;
  73. code = keys[i] & 0x7f;
  74. input_event(input, EV_MSC, MSC_SCAN, code);
  75. input_report_key(input, lm8333->keycodes[code], pressed);
  76. }
  77. input_sync(input);
  78. }
  79. static irqreturn_t lm8333_irq_thread(int irq, void *data)
  80. {
  81. struct lm8333 *lm8333 = data;
  82. u8 status = lm8333_read8(lm8333, LM8333_READ_INT);
  83. if (!status)
  84. return IRQ_NONE;
  85. if (status & LM8333_ERROR_IRQ) {
  86. u8 err = lm8333_read8(lm8333, LM8333_READ_ERROR);
  87. if (err & (LM8333_ERROR_KEYOVR | LM8333_ERROR_FIFOOVR)) {
  88. u8 dummy[LM8333_FIFO_TRANSFER_SIZE];
  89. lm8333_read_block(lm8333, LM8333_FIFO_READ,
  90. LM8333_FIFO_TRANSFER_SIZE, dummy);
  91. }
  92. dev_err(&lm8333->client->dev, "Got error %02x\n", err);
  93. }
  94. if (status & LM8333_KEYPAD_IRQ)
  95. lm8333_key_handler(lm8333);
  96. return IRQ_HANDLED;
  97. }
  98. static int lm8333_probe(struct i2c_client *client)
  99. {
  100. const struct lm8333_platform_data *pdata =
  101. dev_get_platdata(&client->dev);
  102. struct lm8333 *lm8333;
  103. struct input_dev *input;
  104. int err, active_time;
  105. if (!pdata)
  106. return -EINVAL;
  107. active_time = pdata->active_time ?: 500;
  108. if (active_time / 3 <= pdata->debounce_time / 3) {
  109. dev_err(&client->dev, "Active time not big enough!\n");
  110. return -EINVAL;
  111. }
  112. lm8333 = devm_kzalloc(&client->dev, sizeof(*lm8333), GFP_KERNEL);
  113. if (!lm8333)
  114. return -ENOMEM;
  115. input = devm_input_allocate_device(&client->dev);
  116. if (!input)
  117. return -ENOMEM;
  118. lm8333->client = client;
  119. lm8333->input = input;
  120. input->name = client->name;
  121. input->id.bustype = BUS_I2C;
  122. input_set_capability(input, EV_MSC, MSC_SCAN);
  123. err = matrix_keypad_build_keymap(pdata->matrix_data, NULL,
  124. LM8333_NUM_ROWS, LM8333_NUM_COLS,
  125. lm8333->keycodes, input);
  126. if (err)
  127. return err;
  128. if (pdata->debounce_time) {
  129. err = lm8333_write8(lm8333, LM8333_DEBOUNCE,
  130. pdata->debounce_time / 3);
  131. if (err)
  132. dev_warn(&client->dev, "Unable to set debounce time\n");
  133. }
  134. if (pdata->active_time) {
  135. err = lm8333_write8(lm8333, LM8333_ACTIVE,
  136. pdata->active_time / 3);
  137. if (err)
  138. dev_warn(&client->dev, "Unable to set active time\n");
  139. }
  140. err = devm_request_threaded_irq(&client->dev, client->irq,
  141. NULL, lm8333_irq_thread,
  142. IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
  143. "lm8333", lm8333);
  144. if (err)
  145. return err;
  146. err = input_register_device(input);
  147. if (err)
  148. return err;
  149. i2c_set_clientdata(client, lm8333);
  150. return 0;
  151. }
  152. static const struct i2c_device_id lm8333_id[] = {
  153. { "lm8333" },
  154. { }
  155. };
  156. MODULE_DEVICE_TABLE(i2c, lm8333_id);
  157. static struct i2c_driver lm8333_driver = {
  158. .driver = {
  159. .name = "lm8333",
  160. },
  161. .probe = lm8333_probe,
  162. .id_table = lm8333_id,
  163. };
  164. module_i2c_driver(lm8333_driver);
  165. MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
  166. MODULE_DESCRIPTION("LM8333 keyboard driver");
  167. MODULE_LICENSE("GPL v2");