tps65090-charger.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Battery charger driver for TI's tps65090
  4. *
  5. * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
  6. */
  7. #include <linux/delay.h>
  8. #include <linux/err.h>
  9. #include <linux/freezer.h>
  10. #include <linux/init.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/kernel.h>
  13. #include <linux/kthread.h>
  14. #include <linux/module.h>
  15. #include <linux/of_device.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/power_supply.h>
  18. #include <linux/slab.h>
  19. #include <linux/mfd/tps65090.h>
  20. #define TPS65090_CHARGER_ENABLE BIT(0)
  21. #define TPS65090_VACG BIT(1)
  22. #define TPS65090_NOITERM BIT(5)
  23. #define POLL_INTERVAL (HZ * 2) /* Used when no irq */
  24. struct tps65090_charger {
  25. struct device *dev;
  26. int ac_online;
  27. int prev_ac_online;
  28. int irq;
  29. struct task_struct *poll_task;
  30. bool passive_mode;
  31. struct power_supply *ac;
  32. struct tps65090_platform_data *pdata;
  33. };
  34. static enum power_supply_property tps65090_ac_props[] = {
  35. POWER_SUPPLY_PROP_ONLINE,
  36. };
  37. static int tps65090_low_chrg_current(struct tps65090_charger *charger)
  38. {
  39. int ret;
  40. if (charger->passive_mode)
  41. return 0;
  42. ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL5,
  43. TPS65090_NOITERM);
  44. if (ret < 0) {
  45. dev_err(charger->dev, "%s(): error reading in register 0x%x\n",
  46. __func__, TPS65090_REG_CG_CTRL5);
  47. return ret;
  48. }
  49. return 0;
  50. }
  51. static int tps65090_enable_charging(struct tps65090_charger *charger)
  52. {
  53. int ret;
  54. uint8_t ctrl0 = 0;
  55. if (charger->passive_mode)
  56. return 0;
  57. ret = tps65090_read(charger->dev->parent, TPS65090_REG_CG_CTRL0,
  58. &ctrl0);
  59. if (ret < 0) {
  60. dev_err(charger->dev, "%s(): error reading in register 0x%x\n",
  61. __func__, TPS65090_REG_CG_CTRL0);
  62. return ret;
  63. }
  64. ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL0,
  65. (ctrl0 | TPS65090_CHARGER_ENABLE));
  66. if (ret < 0) {
  67. dev_err(charger->dev, "%s(): error writing in register 0x%x\n",
  68. __func__, TPS65090_REG_CG_CTRL0);
  69. return ret;
  70. }
  71. return 0;
  72. }
  73. static int tps65090_config_charger(struct tps65090_charger *charger)
  74. {
  75. uint8_t intrmask = 0;
  76. int ret;
  77. if (charger->passive_mode)
  78. return 0;
  79. if (charger->pdata->enable_low_current_chrg) {
  80. ret = tps65090_low_chrg_current(charger);
  81. if (ret < 0) {
  82. dev_err(charger->dev,
  83. "error configuring low charge current\n");
  84. return ret;
  85. }
  86. }
  87. /* Enable the VACG interrupt for AC power detect */
  88. ret = tps65090_read(charger->dev->parent, TPS65090_REG_INTR_MASK,
  89. &intrmask);
  90. if (ret < 0) {
  91. dev_err(charger->dev, "%s(): error reading in register 0x%x\n",
  92. __func__, TPS65090_REG_INTR_MASK);
  93. return ret;
  94. }
  95. ret = tps65090_write(charger->dev->parent, TPS65090_REG_INTR_MASK,
  96. (intrmask | TPS65090_VACG));
  97. if (ret < 0) {
  98. dev_err(charger->dev, "%s(): error writing in register 0x%x\n",
  99. __func__, TPS65090_REG_CG_CTRL0);
  100. return ret;
  101. }
  102. return 0;
  103. }
  104. static int tps65090_ac_get_property(struct power_supply *psy,
  105. enum power_supply_property psp,
  106. union power_supply_propval *val)
  107. {
  108. struct tps65090_charger *charger = power_supply_get_drvdata(psy);
  109. if (psp == POWER_SUPPLY_PROP_ONLINE) {
  110. val->intval = charger->ac_online;
  111. charger->prev_ac_online = charger->ac_online;
  112. return 0;
  113. }
  114. return -EINVAL;
  115. }
  116. static irqreturn_t tps65090_charger_isr(int irq, void *dev_id)
  117. {
  118. struct tps65090_charger *charger = dev_id;
  119. int ret;
  120. uint8_t status1 = 0;
  121. uint8_t intrsts = 0;
  122. ret = tps65090_read(charger->dev->parent, TPS65090_REG_CG_STATUS1,
  123. &status1);
  124. if (ret < 0) {
  125. dev_err(charger->dev, "%s(): Error in reading reg 0x%x\n",
  126. __func__, TPS65090_REG_CG_STATUS1);
  127. return IRQ_HANDLED;
  128. }
  129. msleep(75);
  130. ret = tps65090_read(charger->dev->parent, TPS65090_REG_INTR_STS,
  131. &intrsts);
  132. if (ret < 0) {
  133. dev_err(charger->dev, "%s(): Error in reading reg 0x%x\n",
  134. __func__, TPS65090_REG_INTR_STS);
  135. return IRQ_HANDLED;
  136. }
  137. if (intrsts & TPS65090_VACG) {
  138. ret = tps65090_enable_charging(charger);
  139. if (ret < 0)
  140. return IRQ_HANDLED;
  141. charger->ac_online = 1;
  142. } else {
  143. charger->ac_online = 0;
  144. }
  145. /* Clear interrupts. */
  146. if (!charger->passive_mode) {
  147. ret = tps65090_write(charger->dev->parent,
  148. TPS65090_REG_INTR_STS, 0x00);
  149. if (ret < 0) {
  150. dev_err(charger->dev,
  151. "%s(): Error in writing reg 0x%x\n",
  152. __func__, TPS65090_REG_INTR_STS);
  153. }
  154. }
  155. if (charger->prev_ac_online != charger->ac_online)
  156. power_supply_changed(charger->ac);
  157. return IRQ_HANDLED;
  158. }
  159. static struct tps65090_platform_data *
  160. tps65090_parse_dt_charger_data(struct platform_device *pdev)
  161. {
  162. struct tps65090_platform_data *pdata;
  163. struct device_node *np = pdev->dev.of_node;
  164. unsigned int prop;
  165. pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
  166. if (!pdata) {
  167. dev_err(&pdev->dev, "Memory alloc for tps65090_pdata failed\n");
  168. return NULL;
  169. }
  170. prop = of_property_read_bool(np, "ti,enable-low-current-chrg");
  171. pdata->enable_low_current_chrg = prop;
  172. pdata->irq_base = -1;
  173. return pdata;
  174. }
  175. static int tps65090_charger_poll_task(void *data)
  176. {
  177. set_freezable();
  178. while (!kthread_should_stop()) {
  179. schedule_timeout_interruptible(POLL_INTERVAL);
  180. try_to_freeze();
  181. tps65090_charger_isr(-1, data);
  182. }
  183. return 0;
  184. }
  185. static const struct power_supply_desc tps65090_charger_desc = {
  186. .name = "tps65090-ac",
  187. .type = POWER_SUPPLY_TYPE_MAINS,
  188. .get_property = tps65090_ac_get_property,
  189. .properties = tps65090_ac_props,
  190. .num_properties = ARRAY_SIZE(tps65090_ac_props),
  191. };
  192. static int tps65090_charger_probe(struct platform_device *pdev)
  193. {
  194. struct tps65090_charger *cdata;
  195. struct tps65090_platform_data *pdata;
  196. struct power_supply_config psy_cfg = {};
  197. uint8_t status1 = 0;
  198. int ret;
  199. int irq;
  200. pdata = dev_get_platdata(pdev->dev.parent);
  201. if (IS_ENABLED(CONFIG_OF) && !pdata && pdev->dev.of_node)
  202. pdata = tps65090_parse_dt_charger_data(pdev);
  203. if (!pdata) {
  204. dev_err(&pdev->dev, "%s():no platform data available\n",
  205. __func__);
  206. return -ENODEV;
  207. }
  208. cdata = devm_kzalloc(&pdev->dev, sizeof(*cdata), GFP_KERNEL);
  209. if (!cdata) {
  210. dev_err(&pdev->dev, "failed to allocate memory status\n");
  211. return -ENOMEM;
  212. }
  213. platform_set_drvdata(pdev, cdata);
  214. cdata->dev = &pdev->dev;
  215. cdata->pdata = pdata;
  216. psy_cfg.supplied_to = pdata->supplied_to;
  217. psy_cfg.num_supplicants = pdata->num_supplicants;
  218. psy_cfg.of_node = pdev->dev.of_node;
  219. psy_cfg.drv_data = cdata;
  220. cdata->ac = power_supply_register(&pdev->dev, &tps65090_charger_desc,
  221. &psy_cfg);
  222. if (IS_ERR(cdata->ac)) {
  223. dev_err(&pdev->dev, "failed: power supply register\n");
  224. return PTR_ERR(cdata->ac);
  225. }
  226. irq = platform_get_irq(pdev, 0);
  227. if (irq < 0)
  228. irq = -ENXIO;
  229. cdata->irq = irq;
  230. ret = tps65090_config_charger(cdata);
  231. if (ret < 0) {
  232. dev_err(&pdev->dev, "charger config failed, err %d\n", ret);
  233. goto fail_unregister_supply;
  234. }
  235. /* Check for charger presence */
  236. ret = tps65090_read(cdata->dev->parent, TPS65090_REG_CG_STATUS1,
  237. &status1);
  238. if (ret < 0) {
  239. dev_err(cdata->dev, "%s(): Error in reading reg 0x%x", __func__,
  240. TPS65090_REG_CG_STATUS1);
  241. goto fail_unregister_supply;
  242. }
  243. if (status1 != 0) {
  244. ret = tps65090_enable_charging(cdata);
  245. if (ret < 0) {
  246. dev_err(cdata->dev, "error enabling charger\n");
  247. goto fail_unregister_supply;
  248. }
  249. cdata->ac_online = 1;
  250. power_supply_changed(cdata->ac);
  251. }
  252. if (irq != -ENXIO) {
  253. ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
  254. tps65090_charger_isr, IRQF_ONESHOT, "tps65090-charger", cdata);
  255. if (ret) {
  256. dev_err(cdata->dev,
  257. "Unable to register irq %d err %d\n", irq,
  258. ret);
  259. goto fail_unregister_supply;
  260. }
  261. } else {
  262. cdata->poll_task = kthread_run(tps65090_charger_poll_task,
  263. cdata, "ktps65090charger");
  264. cdata->passive_mode = true;
  265. if (IS_ERR(cdata->poll_task)) {
  266. ret = PTR_ERR(cdata->poll_task);
  267. dev_err(cdata->dev,
  268. "Unable to run kthread err %d\n", ret);
  269. goto fail_unregister_supply;
  270. }
  271. }
  272. return 0;
  273. fail_unregister_supply:
  274. power_supply_unregister(cdata->ac);
  275. return ret;
  276. }
  277. static int tps65090_charger_remove(struct platform_device *pdev)
  278. {
  279. struct tps65090_charger *cdata = platform_get_drvdata(pdev);
  280. if (cdata->irq == -ENXIO)
  281. kthread_stop(cdata->poll_task);
  282. power_supply_unregister(cdata->ac);
  283. return 0;
  284. }
  285. static const struct of_device_id of_tps65090_charger_match[] = {
  286. { .compatible = "ti,tps65090-charger", },
  287. { /* end */ }
  288. };
  289. MODULE_DEVICE_TABLE(of, of_tps65090_charger_match);
  290. static struct platform_driver tps65090_charger_driver = {
  291. .driver = {
  292. .name = "tps65090-charger",
  293. .of_match_table = of_tps65090_charger_match,
  294. },
  295. .probe = tps65090_charger_probe,
  296. .remove = tps65090_charger_remove,
  297. };
  298. module_platform_driver(tps65090_charger_driver);
  299. MODULE_LICENSE("GPL v2");
  300. MODULE_AUTHOR("Syed Rafiuddin <srafiuddin@nvidia.com>");
  301. MODULE_DESCRIPTION("tps65090 battery charger driver");