pm8941-pwrkey.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
  3. * Copyright (c) 2014, Sony Mobile Communications Inc.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 and
  7. * only version 2 as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <linux/delay.h>
  15. #include <linux/errno.h>
  16. #include <linux/input.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/kernel.h>
  19. #include <linux/log2.h>
  20. #include <linux/module.h>
  21. #include <linux/of.h>
  22. #include <linux/of_device.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/reboot.h>
  25. #include <linux/regmap.h>
  26. #define PON_REV2 0x01
  27. #define PON_RT_STS 0x10
  28. #define PON_KPDPWR_N_SET BIT(0)
  29. #define PON_RESIN_N_SET BIT(1)
  30. #define PON_PS_HOLD_RST_CTL 0x5a
  31. #define PON_PS_HOLD_RST_CTL2 0x5b
  32. #define PON_PS_HOLD_ENABLE BIT(7)
  33. #define PON_PS_HOLD_TYPE_MASK 0x0f
  34. #define PON_PS_HOLD_TYPE_SHUTDOWN 4
  35. #define PON_PS_HOLD_TYPE_HARD_RESET 7
  36. #define PON_PULL_CTL 0x70
  37. #define PON_KPDPWR_PULL_UP BIT(1)
  38. #define PON_RESIN_PULL_UP BIT(0)
  39. #define PON_DBC_CTL 0x71
  40. #define PON_DBC_DELAY_MASK 0x7
  41. struct pm8941_data {
  42. unsigned int pull_up_bit;
  43. unsigned int status_bit;
  44. };
  45. struct pm8941_pwrkey {
  46. struct device *dev;
  47. int irq;
  48. u32 baseaddr;
  49. struct regmap *regmap;
  50. struct input_dev *input;
  51. unsigned int revision;
  52. struct notifier_block reboot_notifier;
  53. u32 code;
  54. const struct pm8941_data *data;
  55. };
  56. static int pm8941_reboot_notify(struct notifier_block *nb,
  57. unsigned long code, void *unused)
  58. {
  59. struct pm8941_pwrkey *pwrkey = container_of(nb, struct pm8941_pwrkey,
  60. reboot_notifier);
  61. unsigned int enable_reg;
  62. unsigned int reset_type;
  63. int error;
  64. /* PMICs with revision 0 have the enable bit in same register as ctrl */
  65. if (pwrkey->revision == 0)
  66. enable_reg = PON_PS_HOLD_RST_CTL;
  67. else
  68. enable_reg = PON_PS_HOLD_RST_CTL2;
  69. error = regmap_update_bits(pwrkey->regmap,
  70. pwrkey->baseaddr + enable_reg,
  71. PON_PS_HOLD_ENABLE,
  72. 0);
  73. if (error)
  74. dev_err(pwrkey->dev,
  75. "unable to clear ps hold reset enable: %d\n",
  76. error);
  77. /*
  78. * Updates of PON_PS_HOLD_ENABLE requires 3 sleep cycles between
  79. * writes.
  80. */
  81. usleep_range(100, 1000);
  82. switch (code) {
  83. case SYS_HALT:
  84. case SYS_POWER_OFF:
  85. reset_type = PON_PS_HOLD_TYPE_SHUTDOWN;
  86. break;
  87. case SYS_RESTART:
  88. default:
  89. reset_type = PON_PS_HOLD_TYPE_HARD_RESET;
  90. break;
  91. }
  92. error = regmap_update_bits(pwrkey->regmap,
  93. pwrkey->baseaddr + PON_PS_HOLD_RST_CTL,
  94. PON_PS_HOLD_TYPE_MASK,
  95. reset_type);
  96. if (error)
  97. dev_err(pwrkey->dev, "unable to set ps hold reset type: %d\n",
  98. error);
  99. error = regmap_update_bits(pwrkey->regmap,
  100. pwrkey->baseaddr + enable_reg,
  101. PON_PS_HOLD_ENABLE,
  102. PON_PS_HOLD_ENABLE);
  103. if (error)
  104. dev_err(pwrkey->dev, "unable to re-set enable: %d\n", error);
  105. return NOTIFY_DONE;
  106. }
  107. static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data)
  108. {
  109. struct pm8941_pwrkey *pwrkey = _data;
  110. unsigned int sts;
  111. int error;
  112. error = regmap_read(pwrkey->regmap,
  113. pwrkey->baseaddr + PON_RT_STS, &sts);
  114. if (error)
  115. return IRQ_HANDLED;
  116. input_report_key(pwrkey->input, pwrkey->code,
  117. sts & pwrkey->data->status_bit);
  118. input_sync(pwrkey->input);
  119. return IRQ_HANDLED;
  120. }
  121. static int __maybe_unused pm8941_pwrkey_suspend(struct device *dev)
  122. {
  123. struct pm8941_pwrkey *pwrkey = dev_get_drvdata(dev);
  124. if (device_may_wakeup(dev))
  125. enable_irq_wake(pwrkey->irq);
  126. return 0;
  127. }
  128. static int __maybe_unused pm8941_pwrkey_resume(struct device *dev)
  129. {
  130. struct pm8941_pwrkey *pwrkey = dev_get_drvdata(dev);
  131. if (device_may_wakeup(dev))
  132. disable_irq_wake(pwrkey->irq);
  133. return 0;
  134. }
  135. static SIMPLE_DEV_PM_OPS(pm8941_pwr_key_pm_ops,
  136. pm8941_pwrkey_suspend, pm8941_pwrkey_resume);
  137. static int pm8941_pwrkey_probe(struct platform_device *pdev)
  138. {
  139. struct pm8941_pwrkey *pwrkey;
  140. bool pull_up;
  141. struct device *parent;
  142. u32 req_delay;
  143. int error;
  144. if (of_property_read_u32(pdev->dev.of_node, "debounce", &req_delay))
  145. req_delay = 15625;
  146. if (req_delay > 2000000 || req_delay == 0) {
  147. dev_err(&pdev->dev, "invalid debounce time: %u\n", req_delay);
  148. return -EINVAL;
  149. }
  150. pull_up = of_property_read_bool(pdev->dev.of_node, "bias-pull-up");
  151. pwrkey = devm_kzalloc(&pdev->dev, sizeof(*pwrkey), GFP_KERNEL);
  152. if (!pwrkey)
  153. return -ENOMEM;
  154. pwrkey->dev = &pdev->dev;
  155. pwrkey->data = of_device_get_match_data(&pdev->dev);
  156. parent = pdev->dev.parent;
  157. pwrkey->regmap = dev_get_regmap(parent, NULL);
  158. if (!pwrkey->regmap) {
  159. /*
  160. * We failed to get regmap for parent. Let's see if we are
  161. * a child of pon node and read regmap and reg from its
  162. * parent.
  163. */
  164. pwrkey->regmap = dev_get_regmap(parent->parent, NULL);
  165. if (!pwrkey->regmap) {
  166. dev_err(&pdev->dev, "failed to locate regmap\n");
  167. return -ENODEV;
  168. }
  169. error = of_property_read_u32(parent->of_node,
  170. "reg", &pwrkey->baseaddr);
  171. } else {
  172. error = of_property_read_u32(pdev->dev.of_node, "reg",
  173. &pwrkey->baseaddr);
  174. }
  175. if (error)
  176. return error;
  177. pwrkey->irq = platform_get_irq(pdev, 0);
  178. if (pwrkey->irq < 0) {
  179. dev_err(&pdev->dev, "failed to get irq\n");
  180. return pwrkey->irq;
  181. }
  182. error = regmap_read(pwrkey->regmap, pwrkey->baseaddr + PON_REV2,
  183. &pwrkey->revision);
  184. if (error) {
  185. dev_err(&pdev->dev, "failed to set debounce: %d\n", error);
  186. return error;
  187. }
  188. error = of_property_read_u32(pdev->dev.of_node, "linux,code",
  189. &pwrkey->code);
  190. if (error) {
  191. dev_dbg(&pdev->dev,
  192. "no linux,code assuming power (%d)\n", error);
  193. pwrkey->code = KEY_POWER;
  194. }
  195. pwrkey->input = devm_input_allocate_device(&pdev->dev);
  196. if (!pwrkey->input) {
  197. dev_dbg(&pdev->dev, "unable to allocate input device\n");
  198. return -ENOMEM;
  199. }
  200. input_set_capability(pwrkey->input, EV_KEY, pwrkey->code);
  201. pwrkey->input->name = "pm8941_pwrkey";
  202. pwrkey->input->phys = "pm8941_pwrkey/input0";
  203. req_delay = (req_delay << 6) / USEC_PER_SEC;
  204. req_delay = ilog2(req_delay);
  205. error = regmap_update_bits(pwrkey->regmap,
  206. pwrkey->baseaddr + PON_DBC_CTL,
  207. PON_DBC_DELAY_MASK,
  208. req_delay);
  209. if (error) {
  210. dev_err(&pdev->dev, "failed to set debounce: %d\n", error);
  211. return error;
  212. }
  213. error = regmap_update_bits(pwrkey->regmap,
  214. pwrkey->baseaddr + PON_PULL_CTL,
  215. pwrkey->data->pull_up_bit,
  216. pull_up ? pwrkey->data->pull_up_bit : 0);
  217. if (error) {
  218. dev_err(&pdev->dev, "failed to set pull: %d\n", error);
  219. return error;
  220. }
  221. error = devm_request_threaded_irq(&pdev->dev, pwrkey->irq,
  222. NULL, pm8941_pwrkey_irq,
  223. IRQF_ONESHOT,
  224. "pm8941_pwrkey", pwrkey);
  225. if (error) {
  226. dev_err(&pdev->dev, "failed requesting IRQ: %d\n", error);
  227. return error;
  228. }
  229. error = input_register_device(pwrkey->input);
  230. if (error) {
  231. dev_err(&pdev->dev, "failed to register input device: %d\n",
  232. error);
  233. return error;
  234. }
  235. pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify,
  236. error = register_reboot_notifier(&pwrkey->reboot_notifier);
  237. if (error) {
  238. dev_err(&pdev->dev, "failed to register reboot notifier: %d\n",
  239. error);
  240. return error;
  241. }
  242. platform_set_drvdata(pdev, pwrkey);
  243. device_init_wakeup(&pdev->dev, 1);
  244. return 0;
  245. }
  246. static int pm8941_pwrkey_remove(struct platform_device *pdev)
  247. {
  248. struct pm8941_pwrkey *pwrkey = platform_get_drvdata(pdev);
  249. unregister_reboot_notifier(&pwrkey->reboot_notifier);
  250. return 0;
  251. }
  252. static const struct pm8941_data pwrkey_data = {
  253. .pull_up_bit = PON_KPDPWR_PULL_UP,
  254. .status_bit = PON_KPDPWR_N_SET,
  255. };
  256. static const struct pm8941_data resin_data = {
  257. .pull_up_bit = PON_RESIN_PULL_UP,
  258. .status_bit = PON_RESIN_N_SET,
  259. };
  260. static const struct of_device_id pm8941_pwr_key_id_table[] = {
  261. { .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data },
  262. { .compatible = "qcom,pm8941-resin", .data = &resin_data },
  263. { }
  264. };
  265. MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table);
  266. static struct platform_driver pm8941_pwrkey_driver = {
  267. .probe = pm8941_pwrkey_probe,
  268. .remove = pm8941_pwrkey_remove,
  269. .driver = {
  270. .name = "pm8941-pwrkey",
  271. .pm = &pm8941_pwr_key_pm_ops,
  272. .of_match_table = of_match_ptr(pm8941_pwr_key_id_table),
  273. },
  274. };
  275. module_platform_driver(pm8941_pwrkey_driver);
  276. MODULE_DESCRIPTION("PM8941 Power Key driver");
  277. MODULE_LICENSE("GPL v2");