samsung-keypad.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /*
  2. * Samsung keypad driver
  3. *
  4. * Copyright (C) 2010 Samsung Electronics Co.Ltd
  5. * Author: Joonyoung Shim <jy0922.shim@samsung.com>
  6. * Author: Donghwa Lee <dh09.lee@samsung.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2 of the License, or (at your
  11. * option) any later version.
  12. */
  13. #include <linux/clk.h>
  14. #include <linux/delay.h>
  15. #include <linux/err.h>
  16. #include <linux/init.h>
  17. #include <linux/input.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/io.h>
  20. #include <linux/module.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/pm.h>
  23. #include <linux/pm_runtime.h>
  24. #include <linux/slab.h>
  25. #include <linux/sched.h>
  26. #include <linux/input/samsung-keypad.h>
  27. #define SAMSUNG_KEYIFCON 0x00
  28. #define SAMSUNG_KEYIFSTSCLR 0x04
  29. #define SAMSUNG_KEYIFCOL 0x08
  30. #define SAMSUNG_KEYIFROW 0x0c
  31. #define SAMSUNG_KEYIFFC 0x10
  32. /* SAMSUNG_KEYIFCON */
  33. #define SAMSUNG_KEYIFCON_INT_F_EN (1 << 0)
  34. #define SAMSUNG_KEYIFCON_INT_R_EN (1 << 1)
  35. #define SAMSUNG_KEYIFCON_DF_EN (1 << 2)
  36. #define SAMSUNG_KEYIFCON_FC_EN (1 << 3)
  37. #define SAMSUNG_KEYIFCON_WAKEUPEN (1 << 4)
  38. /* SAMSUNG_KEYIFSTSCLR */
  39. #define SAMSUNG_KEYIFSTSCLR_P_INT_MASK (0xff << 0)
  40. #define SAMSUNG_KEYIFSTSCLR_R_INT_MASK (0xff << 8)
  41. #define SAMSUNG_KEYIFSTSCLR_R_INT_OFFSET 8
  42. #define S5PV210_KEYIFSTSCLR_P_INT_MASK (0x3fff << 0)
  43. #define S5PV210_KEYIFSTSCLR_R_INT_MASK (0x3fff << 16)
  44. #define S5PV210_KEYIFSTSCLR_R_INT_OFFSET 16
  45. /* SAMSUNG_KEYIFCOL */
  46. #define SAMSUNG_KEYIFCOL_MASK (0xff << 0)
  47. #define S5PV210_KEYIFCOLEN_MASK (0xff << 8)
  48. /* SAMSUNG_KEYIFROW */
  49. #define SAMSUNG_KEYIFROW_MASK (0xff << 0)
  50. #define S5PV210_KEYIFROW_MASK (0x3fff << 0)
  51. /* SAMSUNG_KEYIFFC */
  52. #define SAMSUNG_KEYIFFC_MASK (0x3ff << 0)
  53. enum samsung_keypad_type {
  54. KEYPAD_TYPE_SAMSUNG,
  55. KEYPAD_TYPE_S5PV210,
  56. };
  57. struct samsung_keypad {
  58. struct input_dev *input_dev;
  59. struct platform_device *pdev;
  60. struct clk *clk;
  61. void __iomem *base;
  62. wait_queue_head_t wait;
  63. bool stopped;
  64. bool wake_enabled;
  65. int irq;
  66. unsigned int row_shift;
  67. unsigned int rows;
  68. unsigned int cols;
  69. unsigned int row_state[SAMSUNG_MAX_COLS];
  70. unsigned short keycodes[];
  71. };
  72. static int samsung_keypad_is_s5pv210(struct device *dev)
  73. {
  74. struct platform_device *pdev = to_platform_device(dev);
  75. enum samsung_keypad_type type =
  76. platform_get_device_id(pdev)->driver_data;
  77. return type == KEYPAD_TYPE_S5PV210;
  78. }
  79. static void samsung_keypad_scan(struct samsung_keypad *keypad,
  80. unsigned int *row_state)
  81. {
  82. struct device *dev = keypad->input_dev->dev.parent;
  83. unsigned int col;
  84. unsigned int val;
  85. for (col = 0; col < keypad->cols; col++) {
  86. if (samsung_keypad_is_s5pv210(dev)) {
  87. val = S5PV210_KEYIFCOLEN_MASK;
  88. val &= ~(1 << col) << 8;
  89. } else {
  90. val = SAMSUNG_KEYIFCOL_MASK;
  91. val &= ~(1 << col);
  92. }
  93. writel(val, keypad->base + SAMSUNG_KEYIFCOL);
  94. mdelay(1);
  95. val = readl(keypad->base + SAMSUNG_KEYIFROW);
  96. row_state[col] = ~val & ((1 << keypad->rows) - 1);
  97. }
  98. /* KEYIFCOL reg clear */
  99. writel(0, keypad->base + SAMSUNG_KEYIFCOL);
  100. }
  101. static bool samsung_keypad_report(struct samsung_keypad *keypad,
  102. unsigned int *row_state)
  103. {
  104. struct input_dev *input_dev = keypad->input_dev;
  105. unsigned int changed;
  106. unsigned int pressed;
  107. unsigned int key_down = 0;
  108. unsigned int val;
  109. unsigned int col, row;
  110. for (col = 0; col < keypad->cols; col++) {
  111. changed = row_state[col] ^ keypad->row_state[col];
  112. key_down |= row_state[col];
  113. if (!changed)
  114. continue;
  115. for (row = 0; row < keypad->rows; row++) {
  116. if (!(changed & (1 << row)))
  117. continue;
  118. pressed = row_state[col] & (1 << row);
  119. dev_dbg(&keypad->input_dev->dev,
  120. "key %s, row: %d, col: %d\n",
  121. pressed ? "pressed" : "released", row, col);
  122. val = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
  123. input_event(input_dev, EV_MSC, MSC_SCAN, val);
  124. input_report_key(input_dev,
  125. keypad->keycodes[val], pressed);
  126. }
  127. input_sync(keypad->input_dev);
  128. }
  129. memcpy(keypad->row_state, row_state, sizeof(keypad->row_state));
  130. return key_down;
  131. }
  132. static irqreturn_t samsung_keypad_irq(int irq, void *dev_id)
  133. {
  134. struct samsung_keypad *keypad = dev_id;
  135. unsigned int row_state[SAMSUNG_MAX_COLS];
  136. unsigned int val;
  137. bool key_down;
  138. pm_runtime_get_sync(&keypad->pdev->dev);
  139. do {
  140. val = readl(keypad->base + SAMSUNG_KEYIFSTSCLR);
  141. /* Clear interrupt. */
  142. writel(~0x0, keypad->base + SAMSUNG_KEYIFSTSCLR);
  143. samsung_keypad_scan(keypad, row_state);
  144. key_down = samsung_keypad_report(keypad, row_state);
  145. if (key_down)
  146. wait_event_timeout(keypad->wait, keypad->stopped,
  147. msecs_to_jiffies(50));
  148. } while (key_down && !keypad->stopped);
  149. pm_runtime_put_sync(&keypad->pdev->dev);
  150. return IRQ_HANDLED;
  151. }
  152. static void samsung_keypad_start(struct samsung_keypad *keypad)
  153. {
  154. unsigned int val;
  155. pm_runtime_get_sync(&keypad->pdev->dev);
  156. /* Tell IRQ thread that it may poll the device. */
  157. keypad->stopped = false;
  158. clk_enable(keypad->clk);
  159. /* Enable interrupt bits. */
  160. val = readl(keypad->base + SAMSUNG_KEYIFCON);
  161. val |= SAMSUNG_KEYIFCON_INT_F_EN | SAMSUNG_KEYIFCON_INT_R_EN;
  162. writel(val, keypad->base + SAMSUNG_KEYIFCON);
  163. /* KEYIFCOL reg clear. */
  164. writel(0, keypad->base + SAMSUNG_KEYIFCOL);
  165. pm_runtime_put_sync(&keypad->pdev->dev);
  166. }
  167. static void samsung_keypad_stop(struct samsung_keypad *keypad)
  168. {
  169. unsigned int val;
  170. pm_runtime_get_sync(&keypad->pdev->dev);
  171. /* Signal IRQ thread to stop polling and disable the handler. */
  172. keypad->stopped = true;
  173. wake_up(&keypad->wait);
  174. disable_irq(keypad->irq);
  175. /* Clear interrupt. */
  176. writel(~0x0, keypad->base + SAMSUNG_KEYIFSTSCLR);
  177. /* Disable interrupt bits. */
  178. val = readl(keypad->base + SAMSUNG_KEYIFCON);
  179. val &= ~(SAMSUNG_KEYIFCON_INT_F_EN | SAMSUNG_KEYIFCON_INT_R_EN);
  180. writel(val, keypad->base + SAMSUNG_KEYIFCON);
  181. clk_disable(keypad->clk);
  182. /*
  183. * Now that chip should not generate interrupts we can safely
  184. * re-enable the handler.
  185. */
  186. enable_irq(keypad->irq);
  187. pm_runtime_put_sync(&keypad->pdev->dev);
  188. }
  189. static int samsung_keypad_open(struct input_dev *input_dev)
  190. {
  191. struct samsung_keypad *keypad = input_get_drvdata(input_dev);
  192. samsung_keypad_start(keypad);
  193. return 0;
  194. }
  195. static void samsung_keypad_close(struct input_dev *input_dev)
  196. {
  197. struct samsung_keypad *keypad = input_get_drvdata(input_dev);
  198. samsung_keypad_stop(keypad);
  199. }
  200. static int __devinit samsung_keypad_probe(struct platform_device *pdev)
  201. {
  202. const struct samsung_keypad_platdata *pdata;
  203. const struct matrix_keymap_data *keymap_data;
  204. struct samsung_keypad *keypad;
  205. struct resource *res;
  206. struct input_dev *input_dev;
  207. unsigned int row_shift;
  208. unsigned int keymap_size;
  209. int error;
  210. pdata = pdev->dev.platform_data;
  211. if (!pdata) {
  212. dev_err(&pdev->dev, "no platform data defined\n");
  213. return -EINVAL;
  214. }
  215. keymap_data = pdata->keymap_data;
  216. if (!keymap_data) {
  217. dev_err(&pdev->dev, "no keymap data defined\n");
  218. return -EINVAL;
  219. }
  220. if (!pdata->rows || pdata->rows > SAMSUNG_MAX_ROWS)
  221. return -EINVAL;
  222. if (!pdata->cols || pdata->cols > SAMSUNG_MAX_COLS)
  223. return -EINVAL;
  224. /* initialize the gpio */
  225. if (pdata->cfg_gpio)
  226. pdata->cfg_gpio(pdata->rows, pdata->cols);
  227. row_shift = get_count_order(pdata->cols);
  228. keymap_size = (pdata->rows << row_shift) * sizeof(keypad->keycodes[0]);
  229. keypad = kzalloc(sizeof(*keypad) + keymap_size, GFP_KERNEL);
  230. input_dev = input_allocate_device();
  231. if (!keypad || !input_dev) {
  232. error = -ENOMEM;
  233. goto err_free_mem;
  234. }
  235. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  236. if (!res) {
  237. error = -ENODEV;
  238. goto err_free_mem;
  239. }
  240. keypad->base = ioremap(res->start, resource_size(res));
  241. if (!keypad->base) {
  242. error = -EBUSY;
  243. goto err_free_mem;
  244. }
  245. keypad->clk = clk_get(&pdev->dev, "keypad");
  246. if (IS_ERR(keypad->clk)) {
  247. dev_err(&pdev->dev, "failed to get keypad clk\n");
  248. error = PTR_ERR(keypad->clk);
  249. goto err_unmap_base;
  250. }
  251. keypad->input_dev = input_dev;
  252. keypad->pdev = pdev;
  253. keypad->row_shift = row_shift;
  254. keypad->rows = pdata->rows;
  255. keypad->cols = pdata->cols;
  256. keypad->stopped = true;
  257. init_waitqueue_head(&keypad->wait);
  258. input_dev->name = pdev->name;
  259. input_dev->id.bustype = BUS_HOST;
  260. input_dev->dev.parent = &pdev->dev;
  261. input_set_drvdata(input_dev, keypad);
  262. input_dev->open = samsung_keypad_open;
  263. input_dev->close = samsung_keypad_close;
  264. input_dev->evbit[0] = BIT_MASK(EV_KEY);
  265. if (!pdata->no_autorepeat)
  266. input_dev->evbit[0] |= BIT_MASK(EV_REP);
  267. input_set_capability(input_dev, EV_MSC, MSC_SCAN);
  268. input_dev->keycode = keypad->keycodes;
  269. input_dev->keycodesize = sizeof(keypad->keycodes[0]);
  270. input_dev->keycodemax = pdata->rows << row_shift;
  271. matrix_keypad_build_keymap(keymap_data, row_shift,
  272. input_dev->keycode, input_dev->keybit);
  273. keypad->irq = platform_get_irq(pdev, 0);
  274. if (keypad->irq < 0) {
  275. error = keypad->irq;
  276. goto err_put_clk;
  277. }
  278. error = request_threaded_irq(keypad->irq, NULL, samsung_keypad_irq,
  279. IRQF_ONESHOT, dev_name(&pdev->dev), keypad);
  280. if (error) {
  281. dev_err(&pdev->dev, "failed to register keypad interrupt\n");
  282. goto err_put_clk;
  283. }
  284. device_init_wakeup(&pdev->dev, pdata->wakeup);
  285. platform_set_drvdata(pdev, keypad);
  286. pm_runtime_enable(&pdev->dev);
  287. error = input_register_device(keypad->input_dev);
  288. if (error)
  289. goto err_free_irq;
  290. return 0;
  291. err_free_irq:
  292. free_irq(keypad->irq, keypad);
  293. pm_runtime_disable(&pdev->dev);
  294. device_init_wakeup(&pdev->dev, 0);
  295. platform_set_drvdata(pdev, NULL);
  296. err_put_clk:
  297. clk_put(keypad->clk);
  298. err_unmap_base:
  299. iounmap(keypad->base);
  300. err_free_mem:
  301. input_free_device(input_dev);
  302. kfree(keypad);
  303. return error;
  304. }
  305. static int __devexit samsung_keypad_remove(struct platform_device *pdev)
  306. {
  307. struct samsung_keypad *keypad = platform_get_drvdata(pdev);
  308. pm_runtime_disable(&pdev->dev);
  309. device_init_wakeup(&pdev->dev, 0);
  310. platform_set_drvdata(pdev, NULL);
  311. input_unregister_device(keypad->input_dev);
  312. /*
  313. * It is safe to free IRQ after unregistering device because
  314. * samsung_keypad_close will shut off interrupts.
  315. */
  316. free_irq(keypad->irq, keypad);
  317. clk_put(keypad->clk);
  318. iounmap(keypad->base);
  319. kfree(keypad);
  320. return 0;
  321. }
  322. #ifdef CONFIG_PM_RUNTIME
  323. static int samsung_keypad_runtime_suspend(struct device *dev)
  324. {
  325. struct platform_device *pdev = to_platform_device(dev);
  326. struct samsung_keypad *keypad = platform_get_drvdata(pdev);
  327. unsigned int val;
  328. int error;
  329. if (keypad->stopped)
  330. return 0;
  331. /* This may fail on some SoCs due to lack of controller support */
  332. error = enable_irq_wake(keypad->irq);
  333. if (!error)
  334. keypad->wake_enabled = true;
  335. val = readl(keypad->base + SAMSUNG_KEYIFCON);
  336. val |= SAMSUNG_KEYIFCON_WAKEUPEN;
  337. writel(val, keypad->base + SAMSUNG_KEYIFCON);
  338. clk_disable(keypad->clk);
  339. return 0;
  340. }
  341. static int samsung_keypad_runtime_resume(struct device *dev)
  342. {
  343. struct platform_device *pdev = to_platform_device(dev);
  344. struct samsung_keypad *keypad = platform_get_drvdata(pdev);
  345. unsigned int val;
  346. if (keypad->stopped)
  347. return 0;
  348. clk_enable(keypad->clk);
  349. val = readl(keypad->base + SAMSUNG_KEYIFCON);
  350. val &= ~SAMSUNG_KEYIFCON_WAKEUPEN;
  351. writel(val, keypad->base + SAMSUNG_KEYIFCON);
  352. if (keypad->wake_enabled)
  353. disable_irq_wake(keypad->irq);
  354. return 0;
  355. }
  356. #endif
  357. #ifdef CONFIG_PM_SLEEP
  358. static void samsung_keypad_toggle_wakeup(struct samsung_keypad *keypad,
  359. bool enable)
  360. {
  361. unsigned int val;
  362. clk_enable(keypad->clk);
  363. val = readl(keypad->base + SAMSUNG_KEYIFCON);
  364. if (enable) {
  365. val |= SAMSUNG_KEYIFCON_WAKEUPEN;
  366. if (device_may_wakeup(&keypad->pdev->dev))
  367. enable_irq_wake(keypad->irq);
  368. } else {
  369. val &= ~SAMSUNG_KEYIFCON_WAKEUPEN;
  370. if (device_may_wakeup(&keypad->pdev->dev))
  371. disable_irq_wake(keypad->irq);
  372. }
  373. writel(val, keypad->base + SAMSUNG_KEYIFCON);
  374. clk_disable(keypad->clk);
  375. }
  376. static int samsung_keypad_suspend(struct device *dev)
  377. {
  378. struct platform_device *pdev = to_platform_device(dev);
  379. struct samsung_keypad *keypad = platform_get_drvdata(pdev);
  380. struct input_dev *input_dev = keypad->input_dev;
  381. mutex_lock(&input_dev->mutex);
  382. if (input_dev->users)
  383. samsung_keypad_stop(keypad);
  384. samsung_keypad_toggle_wakeup(keypad, true);
  385. mutex_unlock(&input_dev->mutex);
  386. return 0;
  387. }
  388. static int samsung_keypad_resume(struct device *dev)
  389. {
  390. struct platform_device *pdev = to_platform_device(dev);
  391. struct samsung_keypad *keypad = platform_get_drvdata(pdev);
  392. struct input_dev *input_dev = keypad->input_dev;
  393. mutex_lock(&input_dev->mutex);
  394. samsung_keypad_toggle_wakeup(keypad, false);
  395. if (input_dev->users)
  396. samsung_keypad_start(keypad);
  397. mutex_unlock(&input_dev->mutex);
  398. return 0;
  399. }
  400. #endif
  401. static const struct dev_pm_ops samsung_keypad_pm_ops = {
  402. SET_SYSTEM_SLEEP_PM_OPS(samsung_keypad_suspend, samsung_keypad_resume)
  403. SET_RUNTIME_PM_OPS(samsung_keypad_runtime_suspend,
  404. samsung_keypad_runtime_resume, NULL)
  405. };
  406. static struct platform_device_id samsung_keypad_driver_ids[] = {
  407. {
  408. .name = "samsung-keypad",
  409. .driver_data = KEYPAD_TYPE_SAMSUNG,
  410. }, {
  411. .name = "s5pv210-keypad",
  412. .driver_data = KEYPAD_TYPE_S5PV210,
  413. },
  414. { },
  415. };
  416. MODULE_DEVICE_TABLE(platform, samsung_keypad_driver_ids);
  417. static struct platform_driver samsung_keypad_driver = {
  418. .probe = samsung_keypad_probe,
  419. .remove = __devexit_p(samsung_keypad_remove),
  420. .driver = {
  421. .name = "samsung-keypad",
  422. .owner = THIS_MODULE,
  423. .pm = &samsung_keypad_pm_ops,
  424. },
  425. .id_table = samsung_keypad_driver_ids,
  426. };
  427. module_platform_driver(samsung_keypad_driver);
  428. MODULE_DESCRIPTION("Samsung keypad driver");
  429. MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
  430. MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
  431. MODULE_LICENSE("GPL");