imx_sc_key.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2019 NXP.
  4. */
  5. #include <linux/err.h>
  6. #include <linux/device.h>
  7. #include <linux/firmware/imx/sci.h>
  8. #include <linux/init.h>
  9. #include <linux/input.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/jiffies.h>
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/of.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/property.h>
  17. #define DEBOUNCE_TIME 30
  18. #define REPEAT_INTERVAL 60
  19. #define SC_IRQ_BUTTON 1
  20. #define SC_IRQ_GROUP_WAKE 3
  21. #define IMX_SC_MISC_FUNC_GET_BUTTON_STATUS 18
  22. struct imx_key_drv_data {
  23. u32 keycode;
  24. bool keystate; /* true: pressed, false: released */
  25. struct delayed_work check_work;
  26. struct input_dev *input;
  27. struct imx_sc_ipc *key_ipc_handle;
  28. struct notifier_block key_notifier;
  29. };
  30. struct imx_sc_msg_key {
  31. struct imx_sc_rpc_msg hdr;
  32. u32 state;
  33. };
  34. static int imx_sc_key_notify(struct notifier_block *nb,
  35. unsigned long event, void *group)
  36. {
  37. struct imx_key_drv_data *priv =
  38. container_of(nb,
  39. struct imx_key_drv_data,
  40. key_notifier);
  41. if ((event & SC_IRQ_BUTTON) && (*(u8 *)group == SC_IRQ_GROUP_WAKE)) {
  42. schedule_delayed_work(&priv->check_work,
  43. msecs_to_jiffies(DEBOUNCE_TIME));
  44. pm_wakeup_event(priv->input->dev.parent, 0);
  45. }
  46. return 0;
  47. }
  48. static void imx_sc_check_for_events(struct work_struct *work)
  49. {
  50. struct imx_key_drv_data *priv =
  51. container_of(work,
  52. struct imx_key_drv_data,
  53. check_work.work);
  54. struct input_dev *input = priv->input;
  55. struct imx_sc_msg_key msg;
  56. struct imx_sc_rpc_msg *hdr = &msg.hdr;
  57. bool state;
  58. int error;
  59. hdr->ver = IMX_SC_RPC_VERSION;
  60. hdr->svc = IMX_SC_RPC_SVC_MISC;
  61. hdr->func = IMX_SC_MISC_FUNC_GET_BUTTON_STATUS;
  62. hdr->size = 1;
  63. error = imx_scu_call_rpc(priv->key_ipc_handle, &msg, true);
  64. if (error) {
  65. dev_err(&input->dev, "read imx sc key failed, error %d\n", error);
  66. return;
  67. }
  68. /*
  69. * The response data from SCU firmware is 4 bytes,
  70. * but ONLY the first byte is the key state, other
  71. * 3 bytes could be some dirty data, so we should
  72. * ONLY take the first byte as key state.
  73. */
  74. state = (bool)(msg.state & 0xff);
  75. if (state ^ priv->keystate) {
  76. priv->keystate = state;
  77. input_event(input, EV_KEY, priv->keycode, state);
  78. input_sync(input);
  79. if (!priv->keystate)
  80. pm_relax(priv->input->dev.parent);
  81. }
  82. if (state)
  83. schedule_delayed_work(&priv->check_work,
  84. msecs_to_jiffies(REPEAT_INTERVAL));
  85. }
  86. static void imx_sc_key_action(void *data)
  87. {
  88. struct imx_key_drv_data *priv = data;
  89. imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, false);
  90. imx_scu_irq_unregister_notifier(&priv->key_notifier);
  91. cancel_delayed_work_sync(&priv->check_work);
  92. }
  93. static int imx_sc_key_probe(struct platform_device *pdev)
  94. {
  95. struct imx_key_drv_data *priv;
  96. struct input_dev *input;
  97. int error;
  98. priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  99. if (!priv)
  100. return -ENOMEM;
  101. error = imx_scu_get_handle(&priv->key_ipc_handle);
  102. if (error)
  103. return error;
  104. if (device_property_read_u32(&pdev->dev, "linux,keycodes",
  105. &priv->keycode)) {
  106. dev_err(&pdev->dev, "missing linux,keycodes property\n");
  107. return -EINVAL;
  108. }
  109. INIT_DELAYED_WORK(&priv->check_work, imx_sc_check_for_events);
  110. input = devm_input_allocate_device(&pdev->dev);
  111. if (!input) {
  112. dev_err(&pdev->dev, "failed to allocate the input device\n");
  113. return -ENOMEM;
  114. }
  115. input->name = pdev->name;
  116. input->phys = "imx-sc-key/input0";
  117. input->id.bustype = BUS_HOST;
  118. input_set_capability(input, EV_KEY, priv->keycode);
  119. error = input_register_device(input);
  120. if (error) {
  121. dev_err(&pdev->dev, "failed to register input device\n");
  122. return error;
  123. }
  124. priv->input = input;
  125. platform_set_drvdata(pdev, priv);
  126. error = imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON,
  127. true);
  128. if (error) {
  129. dev_err(&pdev->dev, "failed to enable scu group irq\n");
  130. return error;
  131. }
  132. error = devm_add_action_or_reset(&pdev->dev, imx_sc_key_action, &priv);
  133. if (error)
  134. return error;
  135. priv->key_notifier.notifier_call = imx_sc_key_notify;
  136. error = imx_scu_irq_register_notifier(&priv->key_notifier);
  137. if (error)
  138. dev_err(&pdev->dev, "failed to register scu notifier\n");
  139. return error;
  140. }
  141. static const struct of_device_id imx_sc_key_ids[] = {
  142. { .compatible = "fsl,imx-sc-key" },
  143. { /* sentinel */ }
  144. };
  145. MODULE_DEVICE_TABLE(of, imx_sc_key_ids);
  146. static struct platform_driver imx_sc_key_driver = {
  147. .driver = {
  148. .name = "imx-sc-key",
  149. .of_match_table = imx_sc_key_ids,
  150. },
  151. .probe = imx_sc_key_probe,
  152. };
  153. module_platform_driver(imx_sc_key_driver);
  154. MODULE_AUTHOR("Anson Huang <[email protected]>");
  155. MODULE_DESCRIPTION("i.MX System Controller Key Driver");
  156. MODULE_LICENSE("GPL v2");