nxp-bbnsm-pwrkey.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // SPDX-License-Identifier: GPL-2.0+
  2. //
  3. // Copyright 2022 NXP.
  4. #include <linux/device.h>
  5. #include <linux/err.h>
  6. #include <linux/init.h>
  7. #include <linux/input.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/io.h>
  10. #include <linux/jiffies.h>
  11. #include <linux/kernel.h>
  12. #include <linux/mfd/syscon.h>
  13. #include <linux/module.h>
  14. #include <linux/of.h>
  15. #include <linux/of_address.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/pm_wakeirq.h>
  18. #include <linux/regmap.h>
  19. #define BBNSM_CTRL 0x8
  20. #define BBNSM_INT_EN 0x10
  21. #define BBNSM_EVENTS 0x14
  22. #define BBNSM_PAD_CTRL 0x24
  23. #define BBNSM_BTN_PRESSED BIT(7)
  24. #define BBNSM_PWR_ON BIT(6)
  25. #define BBNSM_BTN_OFF BIT(5)
  26. #define BBNSM_EMG_OFF BIT(4)
  27. #define BBNSM_PWRKEY_EVENTS (BBNSM_PWR_ON | BBNSM_BTN_OFF | BBNSM_EMG_OFF)
  28. #define BBNSM_DP_EN BIT(24)
  29. #define DEBOUNCE_TIME 30
  30. #define REPEAT_INTERVAL 60
  31. struct bbnsm_pwrkey {
  32. struct regmap *regmap;
  33. int irq;
  34. int keycode;
  35. int keystate; /* 1:pressed */
  36. bool suspended;
  37. struct timer_list check_timer;
  38. struct input_dev *input;
  39. };
  40. static void bbnsm_pwrkey_check_for_events(struct timer_list *t)
  41. {
  42. struct bbnsm_pwrkey *bbnsm = timer_container_of(bbnsm, t, check_timer);
  43. struct input_dev *input = bbnsm->input;
  44. u32 state;
  45. regmap_read(bbnsm->regmap, BBNSM_EVENTS, &state);
  46. state = state & BBNSM_BTN_PRESSED ? 1 : 0;
  47. /* only report new event if status changed */
  48. if (state ^ bbnsm->keystate) {
  49. bbnsm->keystate = state;
  50. input_event(input, EV_KEY, bbnsm->keycode, state);
  51. input_sync(input);
  52. pm_relax(bbnsm->input->dev.parent);
  53. }
  54. /* repeat check if pressed long */
  55. if (state)
  56. mod_timer(&bbnsm->check_timer,
  57. jiffies + msecs_to_jiffies(REPEAT_INTERVAL));
  58. }
  59. static irqreturn_t bbnsm_pwrkey_interrupt(int irq, void *dev_id)
  60. {
  61. struct platform_device *pdev = dev_id;
  62. struct bbnsm_pwrkey *bbnsm = platform_get_drvdata(pdev);
  63. struct input_dev *input = bbnsm->input;
  64. u32 event;
  65. regmap_read(bbnsm->regmap, BBNSM_EVENTS, &event);
  66. if (!(event & BBNSM_BTN_OFF))
  67. return IRQ_NONE;
  68. pm_wakeup_event(bbnsm->input->dev.parent, 0);
  69. /*
  70. * Directly report key event after resume to make sure key press
  71. * event is never missed.
  72. */
  73. if (bbnsm->suspended) {
  74. bbnsm->keystate = 1;
  75. input_event(input, EV_KEY, bbnsm->keycode, 1);
  76. input_sync(input);
  77. /* Fire at most once per suspend/resume cycle */
  78. bbnsm->suspended = false;
  79. }
  80. mod_timer(&bbnsm->check_timer,
  81. jiffies + msecs_to_jiffies(DEBOUNCE_TIME));
  82. /* clear PWR OFF */
  83. regmap_write(bbnsm->regmap, BBNSM_EVENTS, BBNSM_BTN_OFF);
  84. return IRQ_HANDLED;
  85. }
  86. static void bbnsm_pwrkey_act(void *pdata)
  87. {
  88. struct bbnsm_pwrkey *bbnsm = pdata;
  89. timer_shutdown_sync(&bbnsm->check_timer);
  90. }
  91. static int bbnsm_pwrkey_probe(struct platform_device *pdev)
  92. {
  93. struct bbnsm_pwrkey *bbnsm;
  94. struct input_dev *input;
  95. struct device_node *np = pdev->dev.of_node;
  96. int error;
  97. bbnsm = devm_kzalloc(&pdev->dev, sizeof(*bbnsm), GFP_KERNEL);
  98. if (!bbnsm)
  99. return -ENOMEM;
  100. bbnsm->regmap = syscon_node_to_regmap(np->parent);
  101. if (IS_ERR(bbnsm->regmap)) {
  102. dev_err(&pdev->dev, "bbnsm pwerkey get regmap failed\n");
  103. return PTR_ERR(bbnsm->regmap);
  104. }
  105. if (device_property_read_u32(&pdev->dev, "linux,code",
  106. &bbnsm->keycode)) {
  107. bbnsm->keycode = KEY_POWER;
  108. dev_warn(&pdev->dev, "key code is not specified, using default KEY_POWER\n");
  109. }
  110. bbnsm->irq = platform_get_irq(pdev, 0);
  111. if (bbnsm->irq < 0)
  112. return -EINVAL;
  113. /* config the BBNSM power related register */
  114. regmap_update_bits(bbnsm->regmap, BBNSM_CTRL, BBNSM_DP_EN, BBNSM_DP_EN);
  115. /* clear the unexpected interrupt before driver ready */
  116. regmap_write_bits(bbnsm->regmap, BBNSM_EVENTS, BBNSM_PWRKEY_EVENTS,
  117. BBNSM_PWRKEY_EVENTS);
  118. timer_setup(&bbnsm->check_timer, bbnsm_pwrkey_check_for_events, 0);
  119. input = devm_input_allocate_device(&pdev->dev);
  120. if (!input) {
  121. dev_err(&pdev->dev, "failed to allocate the input device\n");
  122. return -ENOMEM;
  123. }
  124. input->name = pdev->name;
  125. input->phys = "bbnsm-pwrkey/input0";
  126. input->id.bustype = BUS_HOST;
  127. input_set_capability(input, EV_KEY, bbnsm->keycode);
  128. /* input customer action to cancel release timer */
  129. error = devm_add_action(&pdev->dev, bbnsm_pwrkey_act, bbnsm);
  130. if (error) {
  131. dev_err(&pdev->dev, "failed to register remove action\n");
  132. return error;
  133. }
  134. bbnsm->input = input;
  135. platform_set_drvdata(pdev, bbnsm);
  136. error = devm_request_irq(&pdev->dev, bbnsm->irq, bbnsm_pwrkey_interrupt,
  137. IRQF_SHARED, pdev->name, pdev);
  138. if (error) {
  139. dev_err(&pdev->dev, "interrupt not available.\n");
  140. return error;
  141. }
  142. error = input_register_device(input);
  143. if (error) {
  144. dev_err(&pdev->dev, "failed to register input device\n");
  145. return error;
  146. }
  147. device_init_wakeup(&pdev->dev, true);
  148. error = dev_pm_set_wake_irq(&pdev->dev, bbnsm->irq);
  149. if (error)
  150. dev_warn(&pdev->dev, "irq wake enable failed.\n");
  151. return 0;
  152. }
  153. static void bbnsm_pwrkey_remove(struct platform_device *pdev)
  154. {
  155. dev_pm_clear_wake_irq(&pdev->dev);
  156. device_init_wakeup(&pdev->dev, false);
  157. }
  158. static int __maybe_unused bbnsm_pwrkey_suspend(struct device *dev)
  159. {
  160. struct platform_device *pdev = to_platform_device(dev);
  161. struct bbnsm_pwrkey *bbnsm = platform_get_drvdata(pdev);
  162. bbnsm->suspended = true;
  163. return 0;
  164. }
  165. static int __maybe_unused bbnsm_pwrkey_resume(struct device *dev)
  166. {
  167. struct platform_device *pdev = to_platform_device(dev);
  168. struct bbnsm_pwrkey *bbnsm = platform_get_drvdata(pdev);
  169. bbnsm->suspended = false;
  170. return 0;
  171. }
  172. static SIMPLE_DEV_PM_OPS(bbnsm_pwrkey_pm_ops, bbnsm_pwrkey_suspend,
  173. bbnsm_pwrkey_resume);
  174. static const struct of_device_id bbnsm_pwrkey_ids[] = {
  175. { .compatible = "nxp,imx93-bbnsm-pwrkey" },
  176. { /* sentinel */ }
  177. };
  178. MODULE_DEVICE_TABLE(of, bbnsm_pwrkey_ids);
  179. static struct platform_driver bbnsm_pwrkey_driver = {
  180. .driver = {
  181. .name = "bbnsm_pwrkey",
  182. .pm = &bbnsm_pwrkey_pm_ops,
  183. .of_match_table = bbnsm_pwrkey_ids,
  184. },
  185. .probe = bbnsm_pwrkey_probe,
  186. .remove = bbnsm_pwrkey_remove,
  187. };
  188. module_platform_driver(bbnsm_pwrkey_driver);
  189. MODULE_AUTHOR("Jacky Bai <ping.bai@nxp.com>");
  190. MODULE_DESCRIPTION("NXP bbnsm power key Driver");
  191. MODULE_LICENSE("GPL");