da9063_onkey.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * OnKey device driver for DA9063, DA9062 and DA9061 PMICs
  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. #include <linux/mfd/da9062/core.h>
  27. #include <linux/mfd/da9062/registers.h>
  28. struct da906x_chip_config {
  29. /* REGS */
  30. int onkey_status;
  31. int onkey_pwr_signalling;
  32. int onkey_fault_log;
  33. int onkey_shutdown;
  34. /* MASKS */
  35. int onkey_nonkey_mask;
  36. int onkey_nonkey_lock_mask;
  37. int onkey_key_reset_mask;
  38. int onkey_shutdown_mask;
  39. /* NAMES */
  40. const char *name;
  41. };
  42. struct da9063_onkey {
  43. struct delayed_work work;
  44. struct input_dev *input;
  45. struct device *dev;
  46. struct regmap *regmap;
  47. const struct da906x_chip_config *config;
  48. char phys[32];
  49. bool key_power;
  50. };
  51. static const struct da906x_chip_config da9063_regs = {
  52. /* REGS */
  53. .onkey_status = DA9063_REG_STATUS_A,
  54. .onkey_pwr_signalling = DA9063_REG_CONTROL_B,
  55. .onkey_fault_log = DA9063_REG_FAULT_LOG,
  56. .onkey_shutdown = DA9063_REG_CONTROL_F,
  57. /* MASKS */
  58. .onkey_nonkey_mask = DA9063_NONKEY,
  59. .onkey_nonkey_lock_mask = DA9063_NONKEY_LOCK,
  60. .onkey_key_reset_mask = DA9063_KEY_RESET,
  61. .onkey_shutdown_mask = DA9063_SHUTDOWN,
  62. /* NAMES */
  63. .name = DA9063_DRVNAME_ONKEY,
  64. };
  65. static const struct da906x_chip_config da9062_regs = {
  66. /* REGS */
  67. .onkey_status = DA9062AA_STATUS_A,
  68. .onkey_pwr_signalling = DA9062AA_CONTROL_B,
  69. .onkey_fault_log = DA9062AA_FAULT_LOG,
  70. .onkey_shutdown = DA9062AA_CONTROL_F,
  71. /* MASKS */
  72. .onkey_nonkey_mask = DA9062AA_NONKEY_MASK,
  73. .onkey_nonkey_lock_mask = DA9062AA_NONKEY_LOCK_MASK,
  74. .onkey_key_reset_mask = DA9062AA_KEY_RESET_MASK,
  75. .onkey_shutdown_mask = DA9062AA_SHUTDOWN_MASK,
  76. /* NAMES */
  77. .name = "da9062-onkey",
  78. };
  79. static const struct of_device_id da9063_compatible_reg_id_table[] = {
  80. { .compatible = "dlg,da9063-onkey", .data = &da9063_regs },
  81. { .compatible = "dlg,da9062-onkey", .data = &da9062_regs },
  82. { },
  83. };
  84. MODULE_DEVICE_TABLE(of, da9063_compatible_reg_id_table);
  85. static void da9063_poll_on(struct work_struct *work)
  86. {
  87. struct da9063_onkey *onkey = container_of(work,
  88. struct da9063_onkey,
  89. work.work);
  90. const struct da906x_chip_config *config = onkey->config;
  91. unsigned int val;
  92. int fault_log = 0;
  93. bool poll = true;
  94. int error;
  95. /* Poll to see when the pin is released */
  96. error = regmap_read(onkey->regmap,
  97. config->onkey_status,
  98. &val);
  99. if (error) {
  100. dev_err(onkey->dev,
  101. "Failed to read ON status: %d\n", error);
  102. goto err_poll;
  103. }
  104. if (!(val & config->onkey_nonkey_mask)) {
  105. error = regmap_update_bits(onkey->regmap,
  106. config->onkey_pwr_signalling,
  107. config->onkey_nonkey_lock_mask,
  108. 0);
  109. if (error) {
  110. dev_err(onkey->dev,
  111. "Failed to reset the Key Delay %d\n", error);
  112. goto err_poll;
  113. }
  114. input_report_key(onkey->input, KEY_POWER, 0);
  115. input_sync(onkey->input);
  116. poll = false;
  117. }
  118. /*
  119. * If the fault log KEY_RESET is detected, then clear it
  120. * and shut down the system.
  121. */
  122. error = regmap_read(onkey->regmap,
  123. config->onkey_fault_log,
  124. &fault_log);
  125. if (error) {
  126. dev_warn(&onkey->input->dev,
  127. "Cannot read FAULT_LOG: %d\n", error);
  128. } else if (fault_log & config->onkey_key_reset_mask) {
  129. error = regmap_write(onkey->regmap,
  130. config->onkey_fault_log,
  131. config->onkey_key_reset_mask);
  132. if (error) {
  133. dev_warn(&onkey->input->dev,
  134. "Cannot reset KEY_RESET fault log: %d\n",
  135. error);
  136. } else {
  137. /* at this point we do any S/W housekeeping
  138. * and then send shutdown command
  139. */
  140. dev_dbg(&onkey->input->dev,
  141. "Sending SHUTDOWN to PMIC ...\n");
  142. error = regmap_write(onkey->regmap,
  143. config->onkey_shutdown,
  144. config->onkey_shutdown_mask);
  145. if (error)
  146. dev_err(&onkey->input->dev,
  147. "Cannot SHUTDOWN PMIC: %d\n",
  148. error);
  149. }
  150. }
  151. err_poll:
  152. if (poll)
  153. schedule_delayed_work(&onkey->work, msecs_to_jiffies(50));
  154. }
  155. static irqreturn_t da9063_onkey_irq_handler(int irq, void *data)
  156. {
  157. struct da9063_onkey *onkey = data;
  158. const struct da906x_chip_config *config = onkey->config;
  159. unsigned int val;
  160. int error;
  161. error = regmap_read(onkey->regmap,
  162. config->onkey_status,
  163. &val);
  164. if (onkey->key_power && !error && (val & config->onkey_nonkey_mask)) {
  165. input_report_key(onkey->input, KEY_POWER, 1);
  166. input_sync(onkey->input);
  167. schedule_delayed_work(&onkey->work, 0);
  168. dev_dbg(onkey->dev, "KEY_POWER long press.\n");
  169. } else {
  170. input_report_key(onkey->input, KEY_POWER, 1);
  171. input_sync(onkey->input);
  172. input_report_key(onkey->input, KEY_POWER, 0);
  173. input_sync(onkey->input);
  174. dev_dbg(onkey->dev, "KEY_POWER short press.\n");
  175. }
  176. return IRQ_HANDLED;
  177. }
  178. static void da9063_cancel_poll(void *data)
  179. {
  180. struct da9063_onkey *onkey = data;
  181. cancel_delayed_work_sync(&onkey->work);
  182. }
  183. static int da9063_onkey_probe(struct platform_device *pdev)
  184. {
  185. struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
  186. struct da9063_pdata *pdata = dev_get_platdata(da9063->dev);
  187. struct da9063_onkey *onkey;
  188. const struct of_device_id *match;
  189. int irq;
  190. int error;
  191. match = of_match_node(da9063_compatible_reg_id_table,
  192. pdev->dev.of_node);
  193. if (!match)
  194. return -ENXIO;
  195. onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey),
  196. GFP_KERNEL);
  197. if (!onkey) {
  198. dev_err(&pdev->dev, "Failed to allocate memory.\n");
  199. return -ENOMEM;
  200. }
  201. onkey->config = match->data;
  202. onkey->dev = &pdev->dev;
  203. onkey->regmap = dev_get_regmap(pdev->dev.parent, NULL);
  204. if (!onkey->regmap) {
  205. dev_err(&pdev->dev, "Parent regmap unavailable.\n");
  206. return -ENXIO;
  207. }
  208. if (pdata)
  209. onkey->key_power = pdata->key_power;
  210. else
  211. onkey->key_power =
  212. !of_property_read_bool(pdev->dev.of_node,
  213. "dlg,disable-key-power");
  214. onkey->input = devm_input_allocate_device(&pdev->dev);
  215. if (!onkey->input) {
  216. dev_err(&pdev->dev, "Failed to allocated input device.\n");
  217. return -ENOMEM;
  218. }
  219. onkey->input->name = onkey->config->name;
  220. snprintf(onkey->phys, sizeof(onkey->phys), "%s/input0",
  221. onkey->config->name);
  222. onkey->input->phys = onkey->phys;
  223. onkey->input->dev.parent = &pdev->dev;
  224. input_set_capability(onkey->input, EV_KEY, KEY_POWER);
  225. INIT_DELAYED_WORK(&onkey->work, da9063_poll_on);
  226. error = devm_add_action(&pdev->dev, da9063_cancel_poll, onkey);
  227. if (error) {
  228. dev_err(&pdev->dev,
  229. "Failed to add cancel poll action: %d\n",
  230. error);
  231. return error;
  232. }
  233. irq = platform_get_irq_byname(pdev, "ONKEY");
  234. if (irq < 0) {
  235. error = irq;
  236. dev_err(&pdev->dev, "Failed to get platform IRQ: %d\n", error);
  237. return error;
  238. }
  239. error = devm_request_threaded_irq(&pdev->dev, irq,
  240. NULL, da9063_onkey_irq_handler,
  241. IRQF_TRIGGER_LOW | IRQF_ONESHOT,
  242. "ONKEY", onkey);
  243. if (error) {
  244. dev_err(&pdev->dev,
  245. "Failed to request IRQ %d: %d\n", irq, error);
  246. return error;
  247. }
  248. error = input_register_device(onkey->input);
  249. if (error) {
  250. dev_err(&pdev->dev,
  251. "Failed to register input device: %d\n", error);
  252. return error;
  253. }
  254. return 0;
  255. }
  256. static struct platform_driver da9063_onkey_driver = {
  257. .probe = da9063_onkey_probe,
  258. .driver = {
  259. .name = DA9063_DRVNAME_ONKEY,
  260. .of_match_table = da9063_compatible_reg_id_table,
  261. },
  262. };
  263. module_platform_driver(da9063_onkey_driver);
  264. MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
  265. MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063, DA9062 and DA9061");
  266. MODULE_LICENSE("GPL");
  267. MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY);