tps65217_charger.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Battery charger driver for TI's tps65217
  3. //
  4. // Copyright (C) 2015 Collabora Ltd.
  5. // Author: Enric Balletbo i Serra <enric.balletbo@collabora.com>
  6. /*
  7. * Battery charger driver for TI's tps65217
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/kthread.h>
  11. #include <linux/device.h>
  12. #include <linux/module.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/init.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/slab.h>
  17. #include <linux/err.h>
  18. #include <linux/of.h>
  19. #include <linux/of_device.h>
  20. #include <linux/power_supply.h>
  21. #include <linux/mfd/core.h>
  22. #include <linux/mfd/tps65217.h>
  23. #define CHARGER_STATUS_PRESENT (TPS65217_STATUS_ACPWR | TPS65217_STATUS_USBPWR)
  24. #define NUM_CHARGER_IRQS 2
  25. #define POLL_INTERVAL (HZ * 2)
  26. struct tps65217_charger {
  27. struct tps65217 *tps;
  28. struct device *dev;
  29. struct power_supply *psy;
  30. int online;
  31. int prev_online;
  32. struct task_struct *poll_task;
  33. };
  34. static enum power_supply_property tps65217_charger_props[] = {
  35. POWER_SUPPLY_PROP_ONLINE,
  36. };
  37. static int tps65217_config_charger(struct tps65217_charger *charger)
  38. {
  39. int ret;
  40. /*
  41. * tps65217 rev. G, p. 31 (see p. 32 for NTC schematic)
  42. *
  43. * The device can be configured to support a 100k NTC (B = 3960) by
  44. * setting the the NTC_TYPE bit in register CHGCONFIG1 to 1. However it
  45. * is not recommended to do so. In sleep mode, the charger continues
  46. * charging the battery, but all register values are reset to default
  47. * values. Therefore, the charger would get the wrong temperature
  48. * information. If 100k NTC setting is required, please contact the
  49. * factory.
  50. *
  51. * ATTENTION, conflicting information, from p. 46
  52. *
  53. * NTC TYPE (for battery temperature measurement)
  54. * 0 – 100k (curve 1, B = 3960)
  55. * 1 – 10k (curve 2, B = 3480) (default on reset)
  56. *
  57. */
  58. ret = tps65217_clear_bits(charger->tps, TPS65217_REG_CHGCONFIG1,
  59. TPS65217_CHGCONFIG1_NTC_TYPE,
  60. TPS65217_PROTECT_NONE);
  61. if (ret) {
  62. dev_err(charger->dev,
  63. "failed to set 100k NTC setting: %d\n", ret);
  64. return ret;
  65. }
  66. return 0;
  67. }
  68. static int tps65217_enable_charging(struct tps65217_charger *charger)
  69. {
  70. int ret;
  71. /* charger already enabled */
  72. if (charger->online)
  73. return 0;
  74. dev_dbg(charger->dev, "%s: enable charging\n", __func__);
  75. ret = tps65217_set_bits(charger->tps, TPS65217_REG_CHGCONFIG1,
  76. TPS65217_CHGCONFIG1_CHG_EN,
  77. TPS65217_CHGCONFIG1_CHG_EN,
  78. TPS65217_PROTECT_NONE);
  79. if (ret) {
  80. dev_err(charger->dev,
  81. "%s: Error in writing CHG_EN in reg 0x%x: %d\n",
  82. __func__, TPS65217_REG_CHGCONFIG1, ret);
  83. return ret;
  84. }
  85. charger->online = 1;
  86. return 0;
  87. }
  88. static int tps65217_charger_get_property(struct power_supply *psy,
  89. enum power_supply_property psp,
  90. union power_supply_propval *val)
  91. {
  92. struct tps65217_charger *charger = power_supply_get_drvdata(psy);
  93. if (psp == POWER_SUPPLY_PROP_ONLINE) {
  94. val->intval = charger->online;
  95. return 0;
  96. }
  97. return -EINVAL;
  98. }
  99. static irqreturn_t tps65217_charger_irq(int irq, void *dev)
  100. {
  101. int ret, val;
  102. struct tps65217_charger *charger = dev;
  103. charger->prev_online = charger->online;
  104. ret = tps65217_reg_read(charger->tps, TPS65217_REG_STATUS, &val);
  105. if (ret < 0) {
  106. dev_err(charger->dev, "%s: Error in reading reg 0x%x\n",
  107. __func__, TPS65217_REG_STATUS);
  108. return IRQ_HANDLED;
  109. }
  110. dev_dbg(charger->dev, "%s: 0x%x\n", __func__, val);
  111. /* check for charger status bit */
  112. if (val & CHARGER_STATUS_PRESENT) {
  113. ret = tps65217_enable_charging(charger);
  114. if (ret) {
  115. dev_err(charger->dev,
  116. "failed to enable charger: %d\n", ret);
  117. return IRQ_HANDLED;
  118. }
  119. } else {
  120. charger->online = 0;
  121. }
  122. if (charger->prev_online != charger->online)
  123. power_supply_changed(charger->psy);
  124. ret = tps65217_reg_read(charger->tps, TPS65217_REG_CHGCONFIG0, &val);
  125. if (ret < 0) {
  126. dev_err(charger->dev, "%s: Error in reading reg 0x%x\n",
  127. __func__, TPS65217_REG_CHGCONFIG0);
  128. return IRQ_HANDLED;
  129. }
  130. if (val & TPS65217_CHGCONFIG0_ACTIVE)
  131. dev_dbg(charger->dev, "%s: charger is charging\n", __func__);
  132. else
  133. dev_dbg(charger->dev,
  134. "%s: charger is NOT charging\n", __func__);
  135. return IRQ_HANDLED;
  136. }
  137. static int tps65217_charger_poll_task(void *data)
  138. {
  139. set_freezable();
  140. while (!kthread_should_stop()) {
  141. schedule_timeout_interruptible(POLL_INTERVAL);
  142. try_to_freeze();
  143. tps65217_charger_irq(-1, data);
  144. }
  145. return 0;
  146. }
  147. static const struct power_supply_desc tps65217_charger_desc = {
  148. .name = "tps65217-charger",
  149. .type = POWER_SUPPLY_TYPE_MAINS,
  150. .get_property = tps65217_charger_get_property,
  151. .properties = tps65217_charger_props,
  152. .num_properties = ARRAY_SIZE(tps65217_charger_props),
  153. };
  154. static int tps65217_charger_probe(struct platform_device *pdev)
  155. {
  156. struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
  157. struct tps65217_charger *charger;
  158. struct power_supply_config cfg = {};
  159. struct task_struct *poll_task;
  160. int irq[NUM_CHARGER_IRQS];
  161. int ret;
  162. int i;
  163. charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
  164. if (!charger)
  165. return -ENOMEM;
  166. platform_set_drvdata(pdev, charger);
  167. charger->tps = tps;
  168. charger->dev = &pdev->dev;
  169. cfg.of_node = pdev->dev.of_node;
  170. cfg.drv_data = charger;
  171. charger->psy = devm_power_supply_register(&pdev->dev,
  172. &tps65217_charger_desc,
  173. &cfg);
  174. if (IS_ERR(charger->psy)) {
  175. dev_err(&pdev->dev, "failed: power supply register\n");
  176. return PTR_ERR(charger->psy);
  177. }
  178. irq[0] = platform_get_irq_byname(pdev, "USB");
  179. irq[1] = platform_get_irq_byname(pdev, "AC");
  180. ret = tps65217_config_charger(charger);
  181. if (ret < 0) {
  182. dev_err(charger->dev, "charger config failed, err %d\n", ret);
  183. return ret;
  184. }
  185. /* Create a polling thread if an interrupt is invalid */
  186. if (irq[0] < 0 || irq[1] < 0) {
  187. poll_task = kthread_run(tps65217_charger_poll_task,
  188. charger, "ktps65217charger");
  189. if (IS_ERR(poll_task)) {
  190. ret = PTR_ERR(poll_task);
  191. dev_err(charger->dev,
  192. "Unable to run kthread err %d\n", ret);
  193. return ret;
  194. }
  195. charger->poll_task = poll_task;
  196. return 0;
  197. }
  198. /* Create IRQ threads for charger interrupts */
  199. for (i = 0; i < NUM_CHARGER_IRQS; i++) {
  200. ret = devm_request_threaded_irq(&pdev->dev, irq[i], NULL,
  201. tps65217_charger_irq,
  202. IRQF_ONESHOT, "tps65217-charger",
  203. charger);
  204. if (ret) {
  205. dev_err(charger->dev,
  206. "Unable to register irq %d err %d\n", irq[i],
  207. ret);
  208. return ret;
  209. }
  210. /* Check current state */
  211. tps65217_charger_irq(-1, charger);
  212. }
  213. return 0;
  214. }
  215. static int tps65217_charger_remove(struct platform_device *pdev)
  216. {
  217. struct tps65217_charger *charger = platform_get_drvdata(pdev);
  218. if (charger->poll_task)
  219. kthread_stop(charger->poll_task);
  220. return 0;
  221. }
  222. static const struct of_device_id tps65217_charger_match_table[] = {
  223. { .compatible = "ti,tps65217-charger", },
  224. { /* sentinel */ }
  225. };
  226. MODULE_DEVICE_TABLE(of, tps65217_charger_match_table);
  227. static struct platform_driver tps65217_charger_driver = {
  228. .probe = tps65217_charger_probe,
  229. .remove = tps65217_charger_remove,
  230. .driver = {
  231. .name = "tps65217-charger",
  232. .of_match_table = of_match_ptr(tps65217_charger_match_table),
  233. },
  234. };
  235. module_platform_driver(tps65217_charger_driver);
  236. MODULE_LICENSE("GPL v2");
  237. MODULE_AUTHOR("Enric Balletbo Serra <enric.balletbo@collabora.com>");
  238. MODULE_DESCRIPTION("TPS65217 battery charger driver");