snvs_pwrkey.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * Driver for the IMX SNVS ON/OFF Power Key
  3. * Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
  4. *
  5. * The code contained herein is licensed under the GNU General Public
  6. * License. You may obtain a copy of the GNU General Public License
  7. * Version 2 or later at the following locations:
  8. *
  9. * http://www.opensource.org/licenses/gpl-license.html
  10. * http://www.gnu.org/copyleft/gpl.html
  11. */
  12. #include <linux/device.h>
  13. #include <linux/err.h>
  14. #include <linux/init.h>
  15. #include <linux/input.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/io.h>
  18. #include <linux/jiffies.h>
  19. #include <linux/kernel.h>
  20. #include <linux/module.h>
  21. #include <linux/of.h>
  22. #include <linux/of_address.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/mfd/syscon.h>
  25. #include <linux/regmap.h>
  26. #define SNVS_LPSR_REG 0x4C /* LP Status Register */
  27. #define SNVS_LPCR_REG 0x38 /* LP Control Register */
  28. #define SNVS_HPSR_REG 0x14
  29. #define SNVS_HPSR_BTN BIT(6)
  30. #define SNVS_LPSR_SPO BIT(18)
  31. #define SNVS_LPCR_DEP_EN BIT(5)
  32. #define DEBOUNCE_TIME 30
  33. #define REPEAT_INTERVAL 60
  34. struct pwrkey_drv_data {
  35. struct regmap *snvs;
  36. int irq;
  37. int keycode;
  38. int keystate; /* 1:pressed */
  39. int wakeup;
  40. struct timer_list check_timer;
  41. struct input_dev *input;
  42. };
  43. static void imx_imx_snvs_check_for_events(unsigned long data)
  44. {
  45. struct pwrkey_drv_data *pdata = (struct pwrkey_drv_data *) data;
  46. struct input_dev *input = pdata->input;
  47. u32 state;
  48. regmap_read(pdata->snvs, SNVS_HPSR_REG, &state);
  49. state = state & SNVS_HPSR_BTN ? 1 : 0;
  50. /* only report new event if status changed */
  51. if (state ^ pdata->keystate) {
  52. pdata->keystate = state;
  53. input_event(input, EV_KEY, pdata->keycode, state);
  54. input_sync(input);
  55. pm_relax(pdata->input->dev.parent);
  56. }
  57. /* repeat check if pressed long */
  58. if (state) {
  59. mod_timer(&pdata->check_timer,
  60. jiffies + msecs_to_jiffies(REPEAT_INTERVAL));
  61. }
  62. }
  63. static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id)
  64. {
  65. struct platform_device *pdev = dev_id;
  66. struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
  67. u32 lp_status;
  68. pm_wakeup_event(pdata->input->dev.parent, 0);
  69. regmap_read(pdata->snvs, SNVS_LPSR_REG, &lp_status);
  70. if (lp_status & SNVS_LPSR_SPO)
  71. mod_timer(&pdata->check_timer, jiffies + msecs_to_jiffies(DEBOUNCE_TIME));
  72. /* clear SPO status */
  73. regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO);
  74. return IRQ_HANDLED;
  75. }
  76. static void imx_snvs_pwrkey_act(void *pdata)
  77. {
  78. struct pwrkey_drv_data *pd = pdata;
  79. del_timer_sync(&pd->check_timer);
  80. }
  81. static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
  82. {
  83. struct pwrkey_drv_data *pdata = NULL;
  84. struct input_dev *input = NULL;
  85. struct device_node *np;
  86. int error;
  87. /* Get SNVS register Page */
  88. np = pdev->dev.of_node;
  89. if (!np)
  90. return -ENODEV;
  91. pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
  92. if (!pdata)
  93. return -ENOMEM;
  94. pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap");
  95. if (!pdata->snvs) {
  96. dev_err(&pdev->dev, "Can't get snvs syscon\n");
  97. return -ENODEV;
  98. }
  99. if (of_property_read_u32(np, "linux,keycode", &pdata->keycode)) {
  100. pdata->keycode = KEY_POWER;
  101. dev_warn(&pdev->dev, "KEY_POWER without setting in dts\n");
  102. }
  103. pdata->wakeup = of_property_read_bool(np, "wakeup-source");
  104. pdata->irq = platform_get_irq(pdev, 0);
  105. if (pdata->irq < 0) {
  106. dev_err(&pdev->dev, "no irq defined in platform data\n");
  107. return -EINVAL;
  108. }
  109. regmap_update_bits(pdata->snvs, SNVS_LPCR_REG, SNVS_LPCR_DEP_EN, SNVS_LPCR_DEP_EN);
  110. /* clear the unexpected interrupt before driver ready */
  111. regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO);
  112. setup_timer(&pdata->check_timer,
  113. imx_imx_snvs_check_for_events, (unsigned long) pdata);
  114. input = devm_input_allocate_device(&pdev->dev);
  115. if (!input) {
  116. dev_err(&pdev->dev, "failed to allocate the input device\n");
  117. return -ENOMEM;
  118. }
  119. input->name = pdev->name;
  120. input->phys = "snvs-pwrkey/input0";
  121. input->id.bustype = BUS_HOST;
  122. input_set_capability(input, EV_KEY, pdata->keycode);
  123. /* input customer action to cancel release timer */
  124. error = devm_add_action(&pdev->dev, imx_snvs_pwrkey_act, pdata);
  125. if (error) {
  126. dev_err(&pdev->dev, "failed to register remove action\n");
  127. return error;
  128. }
  129. error = devm_request_irq(&pdev->dev, pdata->irq,
  130. imx_snvs_pwrkey_interrupt,
  131. 0, pdev->name, pdev);
  132. if (error) {
  133. dev_err(&pdev->dev, "interrupt not available.\n");
  134. return error;
  135. }
  136. error = input_register_device(input);
  137. if (error < 0) {
  138. dev_err(&pdev->dev, "failed to register input device\n");
  139. input_free_device(input);
  140. return error;
  141. }
  142. pdata->input = input;
  143. platform_set_drvdata(pdev, pdata);
  144. device_init_wakeup(&pdev->dev, pdata->wakeup);
  145. return 0;
  146. }
  147. static int imx_snvs_pwrkey_suspend(struct device *dev)
  148. {
  149. struct platform_device *pdev = to_platform_device(dev);
  150. struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
  151. if (device_may_wakeup(&pdev->dev))
  152. enable_irq_wake(pdata->irq);
  153. return 0;
  154. }
  155. static int imx_snvs_pwrkey_resume(struct device *dev)
  156. {
  157. struct platform_device *pdev = to_platform_device(dev);
  158. struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
  159. if (device_may_wakeup(&pdev->dev))
  160. disable_irq_wake(pdata->irq);
  161. return 0;
  162. }
  163. static const struct of_device_id imx_snvs_pwrkey_ids[] = {
  164. { .compatible = "fsl,sec-v4.0-pwrkey" },
  165. { /* sentinel */ }
  166. };
  167. MODULE_DEVICE_TABLE(of, imx_snvs_pwrkey_ids);
  168. static SIMPLE_DEV_PM_OPS(imx_snvs_pwrkey_pm_ops, imx_snvs_pwrkey_suspend,
  169. imx_snvs_pwrkey_resume);
  170. static struct platform_driver imx_snvs_pwrkey_driver = {
  171. .driver = {
  172. .name = "snvs_pwrkey",
  173. .pm = &imx_snvs_pwrkey_pm_ops,
  174. .of_match_table = imx_snvs_pwrkey_ids,
  175. },
  176. .probe = imx_snvs_pwrkey_probe,
  177. };
  178. module_platform_driver(imx_snvs_pwrkey_driver);
  179. MODULE_AUTHOR("Freescale Semiconductor");
  180. MODULE_DESCRIPTION("i.MX snvs power key Driver");
  181. MODULE_LICENSE("GPL");