tc3589x-keypad.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. /*
  2. * Copyright (C) ST-Ericsson SA 2010
  3. *
  4. * Author: Jayeeta Banerjee <jayeeta.banerjee@stericsson.com>
  5. * Author: Sundar Iyer <sundar.iyer@stericsson.com>
  6. *
  7. * License Terms: GNU General Public License, version 2
  8. *
  9. * TC35893 MFD Keypad Controller driver
  10. */
  11. #include <linux/module.h>
  12. #include <linux/init.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/input.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/input/matrix_keypad.h>
  17. #include <linux/i2c.h>
  18. #include <linux/slab.h>
  19. #include <linux/mfd/tc3589x.h>
  20. /* Maximum supported keypad matrix row/columns size */
  21. #define TC3589x_MAX_KPROW 8
  22. #define TC3589x_MAX_KPCOL 12
  23. /* keypad related Constants */
  24. #define TC3589x_MAX_DEBOUNCE_SETTLE 0xFF
  25. #define DEDICATED_KEY_VAL 0xFF
  26. /* Pull up/down masks */
  27. #define TC3589x_NO_PULL_MASK 0x0
  28. #define TC3589x_PULL_DOWN_MASK 0x1
  29. #define TC3589x_PULL_UP_MASK 0x2
  30. #define TC3589x_PULLUP_ALL_MASK 0xAA
  31. #define TC3589x_IO_PULL_VAL(index, mask) ((mask)<<((index)%4)*2))
  32. /* Bit masks for IOCFG register */
  33. #define IOCFG_BALLCFG 0x01
  34. #define IOCFG_IG 0x08
  35. #define KP_EVCODE_COL_MASK 0x0F
  36. #define KP_EVCODE_ROW_MASK 0x70
  37. #define KP_RELEASE_EVT_MASK 0x80
  38. #define KP_ROW_SHIFT 4
  39. #define KP_NO_VALID_KEY_MASK 0x7F
  40. /* bit masks for RESTCTRL register */
  41. #define TC3589x_KBDRST 0x2
  42. #define TC3589x_IRQRST 0x10
  43. #define TC3589x_RESET_ALL 0x1B
  44. /* KBDMFS register bit mask */
  45. #define TC3589x_KBDMFS_EN 0x1
  46. /* CLKEN register bitmask */
  47. #define KPD_CLK_EN 0x1
  48. /* RSTINTCLR register bit mask */
  49. #define IRQ_CLEAR 0x1
  50. /* bit masks for keyboard interrupts*/
  51. #define TC3589x_EVT_LOSS_INT 0x8
  52. #define TC3589x_EVT_INT 0x4
  53. #define TC3589x_KBD_LOSS_INT 0x2
  54. #define TC3589x_KBD_INT 0x1
  55. /* bit masks for keyboard interrupt clear*/
  56. #define TC3589x_EVT_INT_CLR 0x2
  57. #define TC3589x_KBD_INT_CLR 0x1
  58. #define TC3589x_KBD_KEYMAP_SIZE 64
  59. /**
  60. * struct tc_keypad - data structure used by keypad driver
  61. * @input: pointer to input device object
  62. * @board: keypad platform device
  63. * @krow: number of rows
  64. * @kcol: number of coloumns
  65. * @keymap: matrix scan code table for keycodes
  66. */
  67. struct tc_keypad {
  68. struct tc3589x *tc3589x;
  69. struct input_dev *input;
  70. const struct tc3589x_keypad_platform_data *board;
  71. unsigned int krow;
  72. unsigned int kcol;
  73. unsigned short keymap[TC3589x_KBD_KEYMAP_SIZE];
  74. bool keypad_stopped;
  75. };
  76. static int __devinit tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad)
  77. {
  78. int ret;
  79. struct tc3589x *tc3589x = keypad->tc3589x;
  80. u8 settle_time = keypad->board->settle_time;
  81. u8 dbounce_period = keypad->board->debounce_period;
  82. u8 rows = keypad->board->krow & 0xf; /* mask out the nibble */
  83. u8 column = keypad->board->kcol & 0xf; /* mask out the nibble */
  84. /* validate platform configurations */
  85. if (keypad->board->kcol > TC3589x_MAX_KPCOL ||
  86. keypad->board->krow > TC3589x_MAX_KPROW ||
  87. keypad->board->debounce_period > TC3589x_MAX_DEBOUNCE_SETTLE ||
  88. keypad->board->settle_time > TC3589x_MAX_DEBOUNCE_SETTLE)
  89. return -EINVAL;
  90. /* configure KBDSIZE 4 LSbits for cols and 4 MSbits for rows */
  91. ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSIZE,
  92. (rows << KP_ROW_SHIFT) | column);
  93. if (ret < 0)
  94. return ret;
  95. /* configure dedicated key config, no dedicated key selected */
  96. ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_LSB, DEDICATED_KEY_VAL);
  97. if (ret < 0)
  98. return ret;
  99. ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_MSB, DEDICATED_KEY_VAL);
  100. if (ret < 0)
  101. return ret;
  102. /* Configure settle time */
  103. ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG, settle_time);
  104. if (ret < 0)
  105. return ret;
  106. /* Configure debounce time */
  107. ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE, dbounce_period);
  108. if (ret < 0)
  109. return ret;
  110. /* Start of initialise keypad GPIOs */
  111. ret = tc3589x_set_bits(tc3589x, TC3589x_IOCFG, 0x0, IOCFG_IG);
  112. if (ret < 0)
  113. return ret;
  114. /* Configure pull-up resistors for all row GPIOs */
  115. ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_LSB,
  116. TC3589x_PULLUP_ALL_MASK);
  117. if (ret < 0)
  118. return ret;
  119. ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_MSB,
  120. TC3589x_PULLUP_ALL_MASK);
  121. if (ret < 0)
  122. return ret;
  123. /* Configure pull-up resistors for all column GPIOs */
  124. ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_LSB,
  125. TC3589x_PULLUP_ALL_MASK);
  126. if (ret < 0)
  127. return ret;
  128. ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_MSB,
  129. TC3589x_PULLUP_ALL_MASK);
  130. if (ret < 0)
  131. return ret;
  132. ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG2_LSB,
  133. TC3589x_PULLUP_ALL_MASK);
  134. return ret;
  135. }
  136. #define TC35893_DATA_REGS 4
  137. #define TC35893_KEYCODE_FIFO_EMPTY 0x7f
  138. #define TC35893_KEYCODE_FIFO_CLEAR 0xff
  139. #define TC35893_KEYPAD_ROW_SHIFT 0x3
  140. static irqreturn_t tc3589x_keypad_irq(int irq, void *dev)
  141. {
  142. struct tc_keypad *keypad = dev;
  143. struct tc3589x *tc3589x = keypad->tc3589x;
  144. u8 i, row_index, col_index, kbd_code, up;
  145. u8 code;
  146. for (i = 0; i < TC35893_DATA_REGS * 2; i++) {
  147. kbd_code = tc3589x_reg_read(tc3589x, TC3589x_EVTCODE_FIFO);
  148. /* loop till fifo is empty and no more keys are pressed */
  149. if (kbd_code == TC35893_KEYCODE_FIFO_EMPTY ||
  150. kbd_code == TC35893_KEYCODE_FIFO_CLEAR)
  151. continue;
  152. /* valid key is found */
  153. col_index = kbd_code & KP_EVCODE_COL_MASK;
  154. row_index = (kbd_code & KP_EVCODE_ROW_MASK) >> KP_ROW_SHIFT;
  155. code = MATRIX_SCAN_CODE(row_index, col_index,
  156. TC35893_KEYPAD_ROW_SHIFT);
  157. up = kbd_code & KP_RELEASE_EVT_MASK;
  158. input_event(keypad->input, EV_MSC, MSC_SCAN, code);
  159. input_report_key(keypad->input, keypad->keymap[code], !up);
  160. input_sync(keypad->input);
  161. }
  162. /* clear IRQ */
  163. tc3589x_set_bits(tc3589x, TC3589x_KBDIC,
  164. 0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR);
  165. /* enable IRQ */
  166. tc3589x_set_bits(tc3589x, TC3589x_KBDMSK,
  167. 0x0, TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT);
  168. return IRQ_HANDLED;
  169. }
  170. static int tc3589x_keypad_enable(struct tc_keypad *keypad)
  171. {
  172. struct tc3589x *tc3589x = keypad->tc3589x;
  173. int ret;
  174. /* pull the keypad module out of reset */
  175. ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x0);
  176. if (ret < 0)
  177. return ret;
  178. /* configure KBDMFS */
  179. ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMFS, 0x0, TC3589x_KBDMFS_EN);
  180. if (ret < 0)
  181. return ret;
  182. /* enable the keypad clock */
  183. ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x0, KPD_CLK_EN);
  184. if (ret < 0)
  185. return ret;
  186. /* clear pending IRQs */
  187. ret = tc3589x_set_bits(tc3589x, TC3589x_RSTINTCLR, 0x0, 0x1);
  188. if (ret < 0)
  189. return ret;
  190. /* enable the IRQs */
  191. ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, 0x0,
  192. TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT);
  193. if (ret < 0)
  194. return ret;
  195. keypad->keypad_stopped = false;
  196. return ret;
  197. }
  198. static int tc3589x_keypad_disable(struct tc_keypad *keypad)
  199. {
  200. struct tc3589x *tc3589x = keypad->tc3589x;
  201. int ret;
  202. /* clear IRQ */
  203. ret = tc3589x_set_bits(tc3589x, TC3589x_KBDIC,
  204. 0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR);
  205. if (ret < 0)
  206. return ret;
  207. /* disable all interrupts */
  208. ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK,
  209. ~(TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT), 0x0);
  210. if (ret < 0)
  211. return ret;
  212. /* disable the keypad module */
  213. ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x1, 0x0);
  214. if (ret < 0)
  215. return ret;
  216. /* put the keypad module into reset */
  217. ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x1);
  218. keypad->keypad_stopped = true;
  219. return ret;
  220. }
  221. static int tc3589x_keypad_open(struct input_dev *input)
  222. {
  223. int error;
  224. struct tc_keypad *keypad = input_get_drvdata(input);
  225. /* enable the keypad module */
  226. error = tc3589x_keypad_enable(keypad);
  227. if (error < 0) {
  228. dev_err(&input->dev, "failed to enable keypad module\n");
  229. return error;
  230. }
  231. error = tc3589x_keypad_init_key_hardware(keypad);
  232. if (error < 0) {
  233. dev_err(&input->dev, "failed to configure keypad module\n");
  234. return error;
  235. }
  236. return 0;
  237. }
  238. static void tc3589x_keypad_close(struct input_dev *input)
  239. {
  240. struct tc_keypad *keypad = input_get_drvdata(input);
  241. /* disable the keypad module */
  242. tc3589x_keypad_disable(keypad);
  243. }
  244. static int __devinit tc3589x_keypad_probe(struct platform_device *pdev)
  245. {
  246. struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
  247. struct tc_keypad *keypad;
  248. struct input_dev *input;
  249. const struct tc3589x_keypad_platform_data *plat;
  250. int error, irq;
  251. plat = tc3589x->pdata->keypad;
  252. if (!plat) {
  253. dev_err(&pdev->dev, "invalid keypad platform data\n");
  254. return -EINVAL;
  255. }
  256. irq = platform_get_irq(pdev, 0);
  257. if (irq < 0)
  258. return irq;
  259. keypad = kzalloc(sizeof(struct tc_keypad), GFP_KERNEL);
  260. input = input_allocate_device();
  261. if (!keypad || !input) {
  262. dev_err(&pdev->dev, "failed to allocate keypad memory\n");
  263. error = -ENOMEM;
  264. goto err_free_mem;
  265. }
  266. keypad->board = plat;
  267. keypad->input = input;
  268. keypad->tc3589x = tc3589x;
  269. input->id.bustype = BUS_I2C;
  270. input->name = pdev->name;
  271. input->dev.parent = &pdev->dev;
  272. input->keycode = keypad->keymap;
  273. input->keycodesize = sizeof(keypad->keymap[0]);
  274. input->keycodemax = ARRAY_SIZE(keypad->keymap);
  275. input->open = tc3589x_keypad_open;
  276. input->close = tc3589x_keypad_close;
  277. input_set_drvdata(input, keypad);
  278. input_set_capability(input, EV_MSC, MSC_SCAN);
  279. __set_bit(EV_KEY, input->evbit);
  280. if (!plat->no_autorepeat)
  281. __set_bit(EV_REP, input->evbit);
  282. matrix_keypad_build_keymap(plat->keymap_data, 0x3,
  283. input->keycode, input->keybit);
  284. error = request_threaded_irq(irq, NULL,
  285. tc3589x_keypad_irq, plat->irqtype,
  286. "tc3589x-keypad", keypad);
  287. if (error < 0) {
  288. dev_err(&pdev->dev,
  289. "Could not allocate irq %d,error %d\n",
  290. irq, error);
  291. goto err_free_mem;
  292. }
  293. error = input_register_device(input);
  294. if (error) {
  295. dev_err(&pdev->dev, "Could not register input device\n");
  296. goto err_free_irq;
  297. }
  298. /* let platform decide if keypad is a wakeup source or not */
  299. device_init_wakeup(&pdev->dev, plat->enable_wakeup);
  300. device_set_wakeup_capable(&pdev->dev, plat->enable_wakeup);
  301. platform_set_drvdata(pdev, keypad);
  302. return 0;
  303. err_free_irq:
  304. free_irq(irq, keypad);
  305. err_free_mem:
  306. input_free_device(input);
  307. kfree(keypad);
  308. return error;
  309. }
  310. static int __devexit tc3589x_keypad_remove(struct platform_device *pdev)
  311. {
  312. struct tc_keypad *keypad = platform_get_drvdata(pdev);
  313. int irq = platform_get_irq(pdev, 0);
  314. if (!keypad->keypad_stopped)
  315. tc3589x_keypad_disable(keypad);
  316. free_irq(irq, keypad);
  317. input_unregister_device(keypad->input);
  318. kfree(keypad);
  319. return 0;
  320. }
  321. #ifdef CONFIG_PM
  322. static int tc3589x_keypad_suspend(struct device *dev)
  323. {
  324. struct platform_device *pdev = to_platform_device(dev);
  325. struct tc_keypad *keypad = platform_get_drvdata(pdev);
  326. int irq = platform_get_irq(pdev, 0);
  327. /* keypad is already off; we do nothing */
  328. if (keypad->keypad_stopped)
  329. return 0;
  330. /* if device is not a wakeup source, disable it for powersave */
  331. if (!device_may_wakeup(&pdev->dev))
  332. tc3589x_keypad_disable(keypad);
  333. else
  334. enable_irq_wake(irq);
  335. return 0;
  336. }
  337. static int tc3589x_keypad_resume(struct device *dev)
  338. {
  339. struct platform_device *pdev = to_platform_device(dev);
  340. struct tc_keypad *keypad = platform_get_drvdata(pdev);
  341. int irq = platform_get_irq(pdev, 0);
  342. if (!keypad->keypad_stopped)
  343. return 0;
  344. /* enable the device to resume normal operations */
  345. if (!device_may_wakeup(&pdev->dev))
  346. tc3589x_keypad_enable(keypad);
  347. else
  348. disable_irq_wake(irq);
  349. return 0;
  350. }
  351. static const SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops,
  352. tc3589x_keypad_suspend, tc3589x_keypad_resume);
  353. #endif
  354. static struct platform_driver tc3589x_keypad_driver = {
  355. .driver.name = "tc3589x-keypad",
  356. .driver.owner = THIS_MODULE,
  357. #ifdef CONFIG_PM
  358. .driver.pm = &tc3589x_keypad_dev_pm_ops,
  359. #endif
  360. .probe = tc3589x_keypad_probe,
  361. .remove = __devexit_p(tc3589x_keypad_remove),
  362. };
  363. static int __init tc3589x_keypad_init(void)
  364. {
  365. return platform_driver_register(&tc3589x_keypad_driver);
  366. }
  367. module_init(tc3589x_keypad_init);
  368. static void __exit tc3589x_keypad_exit(void)
  369. {
  370. return platform_driver_unregister(&tc3589x_keypad_driver);
  371. }
  372. module_exit(tc3589x_keypad_exit);
  373. MODULE_LICENSE("GPL v2");
  374. MODULE_AUTHOR("Jayeeta Banerjee/Sundar Iyer");
  375. MODULE_DESCRIPTION("TC35893 Keypad Driver");
  376. MODULE_ALIAS("platform:tc3589x-keypad");