da9063_onkey.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * OnKey device driver for DA9063
  3. * Copyright (C) 2015 Dialog Semiconductor Ltd.
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; either version 2
  8. * of the License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <linux/module.h>
  16. #include <linux/errno.h>
  17. #include <linux/input.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/workqueue.h>
  21. #include <linux/regmap.h>
  22. #include <linux/of.h>
  23. #include <linux/mfd/da9063/core.h>
  24. #include <linux/mfd/da9063/pdata.h>
  25. #include <linux/mfd/da9063/registers.h>
  26. struct da9063_onkey {
  27. struct da9063 *hw;
  28. struct delayed_work work;
  29. struct input_dev *input;
  30. struct device *dev;
  31. bool key_power;
  32. };
  33. static void da9063_poll_on(struct work_struct *work)
  34. {
  35. struct da9063_onkey *onkey = container_of(work, struct da9063_onkey,
  36. work.work);
  37. unsigned int val;
  38. int fault_log = 0;
  39. bool poll = true;
  40. int error;
  41. /* Poll to see when the pin is released */
  42. error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val);
  43. if (error) {
  44. dev_err(onkey->dev,
  45. "Failed to read ON status: %d\n", error);
  46. goto err_poll;
  47. }
  48. if (!(val & DA9063_NONKEY)) {
  49. error = regmap_update_bits(onkey->hw->regmap,
  50. DA9063_REG_CONTROL_B,
  51. DA9063_NONKEY_LOCK, 0);
  52. if (error) {
  53. dev_err(onkey->dev,
  54. "Failed to reset the Key Delay %d\n", error);
  55. goto err_poll;
  56. }
  57. input_report_key(onkey->input, KEY_POWER, 0);
  58. input_sync(onkey->input);
  59. poll = false;
  60. }
  61. /*
  62. * If the fault log KEY_RESET is detected, then clear it
  63. * and shut down the system.
  64. */
  65. error = regmap_read(onkey->hw->regmap,
  66. DA9063_REG_FAULT_LOG, &fault_log);
  67. if (error) {
  68. dev_warn(&onkey->input->dev,
  69. "Cannot read FAULT_LOG: %d\n", error);
  70. } else if (fault_log & DA9063_KEY_RESET) {
  71. error = regmap_write(onkey->hw->regmap,
  72. DA9063_REG_FAULT_LOG,
  73. DA9063_KEY_RESET);
  74. if (error) {
  75. dev_warn(&onkey->input->dev,
  76. "Cannot reset KEY_RESET fault log: %d\n",
  77. error);
  78. } else {
  79. /* at this point we do any S/W housekeeping
  80. * and then send shutdown command
  81. */
  82. dev_dbg(&onkey->input->dev,
  83. "Sending SHUTDOWN to DA9063 ...\n");
  84. error = regmap_write(onkey->hw->regmap,
  85. DA9063_REG_CONTROL_F,
  86. DA9063_SHUTDOWN);
  87. if (error)
  88. dev_err(&onkey->input->dev,
  89. "Cannot SHUTDOWN DA9063: %d\n",
  90. error);
  91. }
  92. }
  93. err_poll:
  94. if (poll)
  95. schedule_delayed_work(&onkey->work, msecs_to_jiffies(50));
  96. }
  97. static irqreturn_t da9063_onkey_irq_handler(int irq, void *data)
  98. {
  99. struct da9063_onkey *onkey = data;
  100. unsigned int val;
  101. int error;
  102. error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val);
  103. if (onkey->key_power && !error && (val & DA9063_NONKEY)) {
  104. input_report_key(onkey->input, KEY_POWER, 1);
  105. input_sync(onkey->input);
  106. schedule_delayed_work(&onkey->work, 0);
  107. dev_dbg(onkey->dev, "KEY_POWER pressed.\n");
  108. } else {
  109. input_report_key(onkey->input, KEY_SLEEP, 1);
  110. input_sync(onkey->input);
  111. input_report_key(onkey->input, KEY_SLEEP, 0);
  112. input_sync(onkey->input);
  113. dev_dbg(onkey->dev, "KEY_SLEEP pressed.\n");
  114. }
  115. return IRQ_HANDLED;
  116. }
  117. static void da9063_cancel_poll(void *data)
  118. {
  119. struct da9063_onkey *onkey = data;
  120. cancel_delayed_work_sync(&onkey->work);
  121. }
  122. static int da9063_onkey_probe(struct platform_device *pdev)
  123. {
  124. struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
  125. struct da9063_pdata *pdata = dev_get_platdata(da9063->dev);
  126. struct da9063_onkey *onkey;
  127. int irq;
  128. int error;
  129. onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey),
  130. GFP_KERNEL);
  131. if (!onkey) {
  132. dev_err(&pdev->dev, "Failed to allocate memory.\n");
  133. return -ENOMEM;
  134. }
  135. onkey->dev = &pdev->dev;
  136. onkey->hw = da9063;
  137. if (pdata)
  138. onkey->key_power = pdata->key_power;
  139. else
  140. onkey->key_power =
  141. !of_property_read_bool(pdev->dev.of_node,
  142. "dlg,disable-key-power");
  143. onkey->input = devm_input_allocate_device(&pdev->dev);
  144. if (!onkey->input) {
  145. dev_err(&pdev->dev, "Failed to allocated input device.\n");
  146. return -ENOMEM;
  147. }
  148. onkey->input->name = DA9063_DRVNAME_ONKEY;
  149. onkey->input->phys = DA9063_DRVNAME_ONKEY "/input0";
  150. onkey->input->dev.parent = &pdev->dev;
  151. if (onkey->key_power)
  152. input_set_capability(onkey->input, EV_KEY, KEY_POWER);
  153. input_set_capability(onkey->input, EV_KEY, KEY_SLEEP);
  154. INIT_DELAYED_WORK(&onkey->work, da9063_poll_on);
  155. error = devm_add_action(&pdev->dev, da9063_cancel_poll, onkey);
  156. if (error) {
  157. dev_err(&pdev->dev,
  158. "Failed to add cancel poll action: %d\n",
  159. error);
  160. return error;
  161. }
  162. irq = platform_get_irq_byname(pdev, "ONKEY");
  163. if (irq < 0) {
  164. error = irq;
  165. dev_err(&pdev->dev, "Failed to get platform IRQ: %d\n", error);
  166. return error;
  167. }
  168. error = devm_request_threaded_irq(&pdev->dev, irq,
  169. NULL, da9063_onkey_irq_handler,
  170. IRQF_TRIGGER_LOW | IRQF_ONESHOT,
  171. "ONKEY", onkey);
  172. if (error) {
  173. dev_err(&pdev->dev,
  174. "Failed to request IRQ %d: %d\n", irq, error);
  175. return error;
  176. }
  177. error = input_register_device(onkey->input);
  178. if (error) {
  179. dev_err(&pdev->dev,
  180. "Failed to register input device: %d\n", error);
  181. return error;
  182. }
  183. platform_set_drvdata(pdev, onkey);
  184. return 0;
  185. }
  186. static struct platform_driver da9063_onkey_driver = {
  187. .probe = da9063_onkey_probe,
  188. .driver = {
  189. .name = DA9063_DRVNAME_ONKEY,
  190. },
  191. };
  192. module_platform_driver(da9063_onkey_driver);
  193. MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
  194. MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063");
  195. MODULE_LICENSE("GPL");
  196. MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY);