max8903_charger.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * max8903_charger.c - Maxim 8903 USB/Adapter Charger Driver
  4. *
  5. * Copyright (C) 2011 Samsung Electronics
  6. * MyungJoo Ham <[email protected]>
  7. */
  8. #include <linux/gpio/consumer.h>
  9. #include <linux/interrupt.h>
  10. #include <linux/module.h>
  11. #include <linux/of.h>
  12. #include <linux/of_device.h>
  13. #include <linux/slab.h>
  14. #include <linux/power_supply.h>
  15. #include <linux/platform_device.h>
  16. struct max8903_data {
  17. struct device *dev;
  18. struct power_supply *psy;
  19. struct power_supply_desc psy_desc;
  20. /*
  21. * GPIOs
  22. * chg, flt, dcm and usus are optional.
  23. * dok or uok must be present.
  24. * If dok is present, cen must be present.
  25. */
  26. struct gpio_desc *cen; /* Charger Enable input */
  27. struct gpio_desc *dok; /* DC (Adapter) Power OK output */
  28. struct gpio_desc *uok; /* USB Power OK output */
  29. struct gpio_desc *chg; /* Charger status output */
  30. struct gpio_desc *flt; /* Fault output */
  31. struct gpio_desc *dcm; /* Current-Limit Mode input (1: DC, 2: USB) */
  32. struct gpio_desc *usus; /* USB Suspend Input (1: suspended) */
  33. bool fault;
  34. bool usb_in;
  35. bool ta_in;
  36. };
  37. static enum power_supply_property max8903_charger_props[] = {
  38. POWER_SUPPLY_PROP_STATUS, /* Charger status output */
  39. POWER_SUPPLY_PROP_ONLINE, /* External power source */
  40. POWER_SUPPLY_PROP_HEALTH, /* Fault or OK */
  41. };
  42. static int max8903_get_property(struct power_supply *psy,
  43. enum power_supply_property psp,
  44. union power_supply_propval *val)
  45. {
  46. struct max8903_data *data = power_supply_get_drvdata(psy);
  47. switch (psp) {
  48. case POWER_SUPPLY_PROP_STATUS:
  49. val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
  50. if (data->chg) {
  51. if (gpiod_get_value(data->chg))
  52. /* CHG asserted */
  53. val->intval = POWER_SUPPLY_STATUS_CHARGING;
  54. else if (data->usb_in || data->ta_in)
  55. val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
  56. else
  57. val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
  58. }
  59. break;
  60. case POWER_SUPPLY_PROP_ONLINE:
  61. val->intval = 0;
  62. if (data->usb_in || data->ta_in)
  63. val->intval = 1;
  64. break;
  65. case POWER_SUPPLY_PROP_HEALTH:
  66. val->intval = POWER_SUPPLY_HEALTH_GOOD;
  67. if (data->fault)
  68. val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
  69. break;
  70. default:
  71. return -EINVAL;
  72. }
  73. return 0;
  74. }
  75. static irqreturn_t max8903_dcin(int irq, void *_data)
  76. {
  77. struct max8903_data *data = _data;
  78. bool ta_in;
  79. enum power_supply_type old_type;
  80. /*
  81. * This means the line is asserted.
  82. *
  83. * The signal is active low, but the inversion is handled in the GPIO
  84. * library as the line should be flagged GPIO_ACTIVE_LOW in the device
  85. * tree.
  86. */
  87. ta_in = gpiod_get_value(data->dok);
  88. if (ta_in == data->ta_in)
  89. return IRQ_HANDLED;
  90. data->ta_in = ta_in;
  91. /* Set Current-Limit-Mode 1:DC 0:USB */
  92. if (data->dcm)
  93. gpiod_set_value(data->dcm, ta_in);
  94. /* Charger Enable / Disable */
  95. if (data->cen) {
  96. int val;
  97. if (ta_in)
  98. /* Certainly enable if DOK is asserted */
  99. val = 1;
  100. else if (data->usb_in)
  101. /* Enable if the USB charger is enabled */
  102. val = 1;
  103. else
  104. /* Else default-disable */
  105. val = 0;
  106. gpiod_set_value(data->cen, val);
  107. }
  108. dev_dbg(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ?
  109. "Connected" : "Disconnected");
  110. old_type = data->psy_desc.type;
  111. if (data->ta_in)
  112. data->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
  113. else if (data->usb_in)
  114. data->psy_desc.type = POWER_SUPPLY_TYPE_USB;
  115. else
  116. data->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
  117. if (old_type != data->psy_desc.type)
  118. power_supply_changed(data->psy);
  119. return IRQ_HANDLED;
  120. }
  121. static irqreturn_t max8903_usbin(int irq, void *_data)
  122. {
  123. struct max8903_data *data = _data;
  124. bool usb_in;
  125. enum power_supply_type old_type;
  126. /*
  127. * This means the line is asserted.
  128. *
  129. * The signal is active low, but the inversion is handled in the GPIO
  130. * library as the line should be flagged GPIO_ACTIVE_LOW in the device
  131. * tree.
  132. */
  133. usb_in = gpiod_get_value(data->uok);
  134. if (usb_in == data->usb_in)
  135. return IRQ_HANDLED;
  136. data->usb_in = usb_in;
  137. /* Do not touch Current-Limit-Mode */
  138. /* Charger Enable / Disable */
  139. if (data->cen) {
  140. int val;
  141. if (usb_in)
  142. /* Certainly enable if UOK is asserted */
  143. val = 1;
  144. else if (data->ta_in)
  145. /* Enable if the DC charger is enabled */
  146. val = 1;
  147. else
  148. /* Else default-disable */
  149. val = 0;
  150. gpiod_set_value(data->cen, val);
  151. }
  152. dev_dbg(data->dev, "USB Charger %s.\n", usb_in ?
  153. "Connected" : "Disconnected");
  154. old_type = data->psy_desc.type;
  155. if (data->ta_in)
  156. data->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
  157. else if (data->usb_in)
  158. data->psy_desc.type = POWER_SUPPLY_TYPE_USB;
  159. else
  160. data->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
  161. if (old_type != data->psy_desc.type)
  162. power_supply_changed(data->psy);
  163. return IRQ_HANDLED;
  164. }
  165. static irqreturn_t max8903_fault(int irq, void *_data)
  166. {
  167. struct max8903_data *data = _data;
  168. bool fault;
  169. /*
  170. * This means the line is asserted.
  171. *
  172. * The signal is active low, but the inversion is handled in the GPIO
  173. * library as the line should be flagged GPIO_ACTIVE_LOW in the device
  174. * tree.
  175. */
  176. fault = gpiod_get_value(data->flt);
  177. if (fault == data->fault)
  178. return IRQ_HANDLED;
  179. data->fault = fault;
  180. if (fault)
  181. dev_err(data->dev, "Charger suffers a fault and stops.\n");
  182. else
  183. dev_err(data->dev, "Charger recovered from a fault.\n");
  184. return IRQ_HANDLED;
  185. }
  186. static int max8903_setup_gpios(struct platform_device *pdev)
  187. {
  188. struct max8903_data *data = platform_get_drvdata(pdev);
  189. struct device *dev = &pdev->dev;
  190. bool ta_in = false;
  191. bool usb_in = false;
  192. enum gpiod_flags flags;
  193. data->dok = devm_gpiod_get_optional(dev, "dok", GPIOD_IN);
  194. if (IS_ERR(data->dok))
  195. return dev_err_probe(dev, PTR_ERR(data->dok),
  196. "failed to get DOK GPIO");
  197. if (data->dok) {
  198. gpiod_set_consumer_name(data->dok, data->psy_desc.name);
  199. /*
  200. * The DC OK is pulled up to 1 and goes low when a charger
  201. * is plugged in (active low) but in the device tree the
  202. * line is marked as GPIO_ACTIVE_LOW so we get a 1 (asserted)
  203. * here if the DC charger is plugged in.
  204. */
  205. ta_in = gpiod_get_value(data->dok);
  206. }
  207. data->uok = devm_gpiod_get_optional(dev, "uok", GPIOD_IN);
  208. if (IS_ERR(data->uok))
  209. return dev_err_probe(dev, PTR_ERR(data->uok),
  210. "failed to get UOK GPIO");
  211. if (data->uok) {
  212. gpiod_set_consumer_name(data->uok, data->psy_desc.name);
  213. /*
  214. * The USB OK is pulled up to 1 and goes low when a USB charger
  215. * is plugged in (active low) but in the device tree the
  216. * line is marked as GPIO_ACTIVE_LOW so we get a 1 (asserted)
  217. * here if the USB charger is plugged in.
  218. */
  219. usb_in = gpiod_get_value(data->uok);
  220. }
  221. /* Either DC OK or USB OK must be provided */
  222. if (!data->dok && !data->uok) {
  223. dev_err(dev, "no valid power source\n");
  224. return -EINVAL;
  225. }
  226. /*
  227. * If either charger is already connected at this point,
  228. * assert the CEN line and enable charging from the start.
  229. *
  230. * The line is active low but also marked with GPIO_ACTIVE_LOW
  231. * in the device tree, so when we assert the line with
  232. * GPIOD_OUT_HIGH the line will be driven low.
  233. */
  234. flags = (ta_in || usb_in) ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
  235. /*
  236. * If DC OK is provided, Charger Enable CEN is compulsory
  237. * so this is not optional here.
  238. */
  239. data->cen = devm_gpiod_get(dev, "cen", flags);
  240. if (IS_ERR(data->cen))
  241. return dev_err_probe(dev, PTR_ERR(data->cen),
  242. "failed to get CEN GPIO");
  243. gpiod_set_consumer_name(data->cen, data->psy_desc.name);
  244. /*
  245. * If the DC charger is connected, then select it.
  246. *
  247. * The DCM line should be marked GPIO_ACTIVE_HIGH in the
  248. * device tree. Driving it high will enable the DC charger
  249. * input over the USB charger input.
  250. */
  251. flags = ta_in ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
  252. data->dcm = devm_gpiod_get_optional(dev, "dcm", flags);
  253. if (IS_ERR(data->dcm))
  254. return dev_err_probe(dev, PTR_ERR(data->dcm),
  255. "failed to get DCM GPIO");
  256. gpiod_set_consumer_name(data->dcm, data->psy_desc.name);
  257. data->chg = devm_gpiod_get_optional(dev, "chg", GPIOD_IN);
  258. if (IS_ERR(data->chg))
  259. return dev_err_probe(dev, PTR_ERR(data->chg),
  260. "failed to get CHG GPIO");
  261. gpiod_set_consumer_name(data->chg, data->psy_desc.name);
  262. data->flt = devm_gpiod_get_optional(dev, "flt", GPIOD_IN);
  263. if (IS_ERR(data->flt))
  264. return dev_err_probe(dev, PTR_ERR(data->flt),
  265. "failed to get FLT GPIO");
  266. gpiod_set_consumer_name(data->flt, data->psy_desc.name);
  267. data->usus = devm_gpiod_get_optional(dev, "usus", GPIOD_IN);
  268. if (IS_ERR(data->usus))
  269. return dev_err_probe(dev, PTR_ERR(data->usus),
  270. "failed to get USUS GPIO");
  271. gpiod_set_consumer_name(data->usus, data->psy_desc.name);
  272. data->fault = false;
  273. data->ta_in = ta_in;
  274. data->usb_in = usb_in;
  275. return 0;
  276. }
  277. static int max8903_probe(struct platform_device *pdev)
  278. {
  279. struct max8903_data *data;
  280. struct device *dev = &pdev->dev;
  281. struct power_supply_config psy_cfg = {};
  282. int ret = 0;
  283. data = devm_kzalloc(dev, sizeof(struct max8903_data), GFP_KERNEL);
  284. if (!data)
  285. return -ENOMEM;
  286. data->dev = dev;
  287. platform_set_drvdata(pdev, data);
  288. ret = max8903_setup_gpios(pdev);
  289. if (ret)
  290. return ret;
  291. data->psy_desc.name = "max8903_charger";
  292. data->psy_desc.type = (data->ta_in) ? POWER_SUPPLY_TYPE_MAINS :
  293. ((data->usb_in) ? POWER_SUPPLY_TYPE_USB :
  294. POWER_SUPPLY_TYPE_BATTERY);
  295. data->psy_desc.get_property = max8903_get_property;
  296. data->psy_desc.properties = max8903_charger_props;
  297. data->psy_desc.num_properties = ARRAY_SIZE(max8903_charger_props);
  298. psy_cfg.of_node = dev->of_node;
  299. psy_cfg.drv_data = data;
  300. data->psy = devm_power_supply_register(dev, &data->psy_desc, &psy_cfg);
  301. if (IS_ERR(data->psy)) {
  302. dev_err(dev, "failed: power supply register.\n");
  303. return PTR_ERR(data->psy);
  304. }
  305. if (data->dok) {
  306. ret = devm_request_threaded_irq(dev, gpiod_to_irq(data->dok),
  307. NULL, max8903_dcin,
  308. IRQF_TRIGGER_FALLING |
  309. IRQF_TRIGGER_RISING | IRQF_ONESHOT,
  310. "MAX8903 DC IN", data);
  311. if (ret) {
  312. dev_err(dev, "Cannot request irq %d for DC (%d)\n",
  313. gpiod_to_irq(data->dok), ret);
  314. return ret;
  315. }
  316. }
  317. if (data->uok) {
  318. ret = devm_request_threaded_irq(dev, gpiod_to_irq(data->uok),
  319. NULL, max8903_usbin,
  320. IRQF_TRIGGER_FALLING |
  321. IRQF_TRIGGER_RISING | IRQF_ONESHOT,
  322. "MAX8903 USB IN", data);
  323. if (ret) {
  324. dev_err(dev, "Cannot request irq %d for USB (%d)\n",
  325. gpiod_to_irq(data->uok), ret);
  326. return ret;
  327. }
  328. }
  329. if (data->flt) {
  330. ret = devm_request_threaded_irq(dev, gpiod_to_irq(data->flt),
  331. NULL, max8903_fault,
  332. IRQF_TRIGGER_FALLING |
  333. IRQF_TRIGGER_RISING | IRQF_ONESHOT,
  334. "MAX8903 Fault", data);
  335. if (ret) {
  336. dev_err(dev, "Cannot request irq %d for Fault (%d)\n",
  337. gpiod_to_irq(data->flt), ret);
  338. return ret;
  339. }
  340. }
  341. return 0;
  342. }
  343. static const struct of_device_id max8903_match_ids[] = {
  344. { .compatible = "maxim,max8903", },
  345. { /* sentinel */ }
  346. };
  347. MODULE_DEVICE_TABLE(of, max8903_match_ids);
  348. static struct platform_driver max8903_driver = {
  349. .probe = max8903_probe,
  350. .driver = {
  351. .name = "max8903-charger",
  352. .of_match_table = max8903_match_ids
  353. },
  354. };
  355. module_platform_driver(max8903_driver);
  356. MODULE_LICENSE("GPL");
  357. MODULE_DESCRIPTION("MAX8903 Charger Driver");
  358. MODULE_AUTHOR("MyungJoo Ham <[email protected]>");
  359. MODULE_ALIAS("platform:max8903-charger");