max8903_charger.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /*
  2. * max8903_charger.c - Maxim 8903 USB/Adapter Charger Driver
  3. *
  4. * Copyright (C) 2011 Samsung Electronics
  5. * MyungJoo Ham <myungjoo.ham@samsung.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. */
  22. #include <linux/gpio.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/module.h>
  25. #include <linux/of.h>
  26. #include <linux/of_device.h>
  27. #include <linux/of_gpio.h>
  28. #include <linux/slab.h>
  29. #include <linux/power_supply.h>
  30. #include <linux/platform_device.h>
  31. #include <linux/power/max8903_charger.h>
  32. struct max8903_data {
  33. struct max8903_pdata *pdata;
  34. struct device *dev;
  35. struct power_supply *psy;
  36. struct power_supply_desc psy_desc;
  37. bool fault;
  38. bool usb_in;
  39. bool ta_in;
  40. };
  41. static enum power_supply_property max8903_charger_props[] = {
  42. POWER_SUPPLY_PROP_STATUS, /* Charger status output */
  43. POWER_SUPPLY_PROP_ONLINE, /* External power source */
  44. POWER_SUPPLY_PROP_HEALTH, /* Fault or OK */
  45. };
  46. static int max8903_get_property(struct power_supply *psy,
  47. enum power_supply_property psp,
  48. union power_supply_propval *val)
  49. {
  50. struct max8903_data *data = power_supply_get_drvdata(psy);
  51. switch (psp) {
  52. case POWER_SUPPLY_PROP_STATUS:
  53. val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
  54. if (gpio_is_valid(data->pdata->chg)) {
  55. if (gpio_get_value(data->pdata->chg) == 0)
  56. val->intval = POWER_SUPPLY_STATUS_CHARGING;
  57. else if (data->usb_in || data->ta_in)
  58. val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
  59. else
  60. val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
  61. }
  62. break;
  63. case POWER_SUPPLY_PROP_ONLINE:
  64. val->intval = 0;
  65. if (data->usb_in || data->ta_in)
  66. val->intval = 1;
  67. break;
  68. case POWER_SUPPLY_PROP_HEALTH:
  69. val->intval = POWER_SUPPLY_HEALTH_GOOD;
  70. if (data->fault)
  71. val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
  72. break;
  73. default:
  74. return -EINVAL;
  75. }
  76. return 0;
  77. }
  78. static irqreturn_t max8903_dcin(int irq, void *_data)
  79. {
  80. struct max8903_data *data = _data;
  81. struct max8903_pdata *pdata = data->pdata;
  82. bool ta_in;
  83. enum power_supply_type old_type;
  84. ta_in = gpio_get_value(pdata->dok) ? false : true;
  85. if (ta_in == data->ta_in)
  86. return IRQ_HANDLED;
  87. data->ta_in = ta_in;
  88. /* Set Current-Limit-Mode 1:DC 0:USB */
  89. if (gpio_is_valid(pdata->dcm))
  90. gpio_set_value(pdata->dcm, ta_in ? 1 : 0);
  91. /* Charger Enable / Disable (cen is negated) */
  92. if (gpio_is_valid(pdata->cen))
  93. gpio_set_value(pdata->cen, ta_in ? 0 :
  94. (data->usb_in ? 0 : 1));
  95. dev_dbg(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ?
  96. "Connected" : "Disconnected");
  97. old_type = data->psy_desc.type;
  98. if (data->ta_in)
  99. data->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
  100. else if (data->usb_in)
  101. data->psy_desc.type = POWER_SUPPLY_TYPE_USB;
  102. else
  103. data->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
  104. if (old_type != data->psy_desc.type)
  105. power_supply_changed(data->psy);
  106. return IRQ_HANDLED;
  107. }
  108. static irqreturn_t max8903_usbin(int irq, void *_data)
  109. {
  110. struct max8903_data *data = _data;
  111. struct max8903_pdata *pdata = data->pdata;
  112. bool usb_in;
  113. enum power_supply_type old_type;
  114. usb_in = gpio_get_value(pdata->uok) ? false : true;
  115. if (usb_in == data->usb_in)
  116. return IRQ_HANDLED;
  117. data->usb_in = usb_in;
  118. /* Do not touch Current-Limit-Mode */
  119. /* Charger Enable / Disable (cen is negated) */
  120. if (gpio_is_valid(pdata->cen))
  121. gpio_set_value(pdata->cen, usb_in ? 0 :
  122. (data->ta_in ? 0 : 1));
  123. dev_dbg(data->dev, "USB Charger %s.\n", usb_in ?
  124. "Connected" : "Disconnected");
  125. old_type = data->psy_desc.type;
  126. if (data->ta_in)
  127. data->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
  128. else if (data->usb_in)
  129. data->psy_desc.type = POWER_SUPPLY_TYPE_USB;
  130. else
  131. data->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
  132. if (old_type != data->psy_desc.type)
  133. power_supply_changed(data->psy);
  134. return IRQ_HANDLED;
  135. }
  136. static irqreturn_t max8903_fault(int irq, void *_data)
  137. {
  138. struct max8903_data *data = _data;
  139. struct max8903_pdata *pdata = data->pdata;
  140. bool fault;
  141. fault = gpio_get_value(pdata->flt) ? false : true;
  142. if (fault == data->fault)
  143. return IRQ_HANDLED;
  144. data->fault = fault;
  145. if (fault)
  146. dev_err(data->dev, "Charger suffers a fault and stops.\n");
  147. else
  148. dev_err(data->dev, "Charger recovered from a fault.\n");
  149. return IRQ_HANDLED;
  150. }
  151. static struct max8903_pdata *max8903_parse_dt_data(struct device *dev)
  152. {
  153. struct device_node *np = dev->of_node;
  154. struct max8903_pdata *pdata = NULL;
  155. if (!np)
  156. return NULL;
  157. pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
  158. if (!pdata)
  159. return NULL;
  160. pdata->dc_valid = false;
  161. pdata->usb_valid = false;
  162. pdata->cen = of_get_named_gpio(np, "cen-gpios", 0);
  163. if (!gpio_is_valid(pdata->cen))
  164. pdata->cen = -EINVAL;
  165. pdata->chg = of_get_named_gpio(np, "chg-gpios", 0);
  166. if (!gpio_is_valid(pdata->chg))
  167. pdata->chg = -EINVAL;
  168. pdata->flt = of_get_named_gpio(np, "flt-gpios", 0);
  169. if (!gpio_is_valid(pdata->flt))
  170. pdata->flt = -EINVAL;
  171. pdata->usus = of_get_named_gpio(np, "usus-gpios", 0);
  172. if (!gpio_is_valid(pdata->usus))
  173. pdata->usus = -EINVAL;
  174. pdata->dcm = of_get_named_gpio(np, "dcm-gpios", 0);
  175. if (!gpio_is_valid(pdata->dcm))
  176. pdata->dcm = -EINVAL;
  177. pdata->dok = of_get_named_gpio(np, "dok-gpios", 0);
  178. if (!gpio_is_valid(pdata->dok))
  179. pdata->dok = -EINVAL;
  180. else
  181. pdata->dc_valid = true;
  182. pdata->uok = of_get_named_gpio(np, "uok-gpios", 0);
  183. if (!gpio_is_valid(pdata->uok))
  184. pdata->uok = -EINVAL;
  185. else
  186. pdata->usb_valid = true;
  187. return pdata;
  188. }
  189. static int max8903_setup_gpios(struct platform_device *pdev)
  190. {
  191. struct max8903_data *data = platform_get_drvdata(pdev);
  192. struct device *dev = &pdev->dev;
  193. struct max8903_pdata *pdata = pdev->dev.platform_data;
  194. int ret = 0;
  195. int gpio;
  196. int ta_in = 0;
  197. int usb_in = 0;
  198. if (pdata->dc_valid) {
  199. if (gpio_is_valid(pdata->dok)) {
  200. ret = devm_gpio_request(dev, pdata->dok,
  201. data->psy_desc.name);
  202. if (ret) {
  203. dev_err(dev,
  204. "Failed GPIO request for dok: %d err %d\n",
  205. pdata->dok, ret);
  206. return ret;
  207. }
  208. gpio = pdata->dok; /* PULL_UPed Interrupt */
  209. ta_in = gpio_get_value(gpio) ? 0 : 1;
  210. } else {
  211. dev_err(dev, "When DC is wired, DOK should be wired as well.\n");
  212. return -EINVAL;
  213. }
  214. }
  215. if (gpio_is_valid(pdata->dcm)) {
  216. ret = devm_gpio_request(dev, pdata->dcm, data->psy_desc.name);
  217. if (ret) {
  218. dev_err(dev,
  219. "Failed GPIO request for dcm: %d err %d\n",
  220. pdata->dcm, ret);
  221. return ret;
  222. }
  223. gpio = pdata->dcm; /* Output */
  224. gpio_set_value(gpio, ta_in);
  225. }
  226. if (pdata->usb_valid) {
  227. if (gpio_is_valid(pdata->uok)) {
  228. ret = devm_gpio_request(dev, pdata->uok,
  229. data->psy_desc.name);
  230. if (ret) {
  231. dev_err(dev,
  232. "Failed GPIO request for uok: %d err %d\n",
  233. pdata->uok, ret);
  234. return ret;
  235. }
  236. gpio = pdata->uok;
  237. usb_in = gpio_get_value(gpio) ? 0 : 1;
  238. } else {
  239. dev_err(dev, "When USB is wired, UOK should be wired."
  240. "as well.\n");
  241. return -EINVAL;
  242. }
  243. }
  244. if (gpio_is_valid(pdata->cen)) {
  245. ret = devm_gpio_request(dev, pdata->cen, data->psy_desc.name);
  246. if (ret) {
  247. dev_err(dev,
  248. "Failed GPIO request for cen: %d err %d\n",
  249. pdata->cen, ret);
  250. return ret;
  251. }
  252. gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1);
  253. }
  254. if (gpio_is_valid(pdata->chg)) {
  255. ret = devm_gpio_request(dev, pdata->chg, data->psy_desc.name);
  256. if (ret) {
  257. dev_err(dev,
  258. "Failed GPIO request for chg: %d err %d\n",
  259. pdata->chg, ret);
  260. return ret;
  261. }
  262. }
  263. if (gpio_is_valid(pdata->flt)) {
  264. ret = devm_gpio_request(dev, pdata->flt, data->psy_desc.name);
  265. if (ret) {
  266. dev_err(dev,
  267. "Failed GPIO request for flt: %d err %d\n",
  268. pdata->flt, ret);
  269. return ret;
  270. }
  271. }
  272. if (gpio_is_valid(pdata->usus)) {
  273. ret = devm_gpio_request(dev, pdata->usus, data->psy_desc.name);
  274. if (ret) {
  275. dev_err(dev,
  276. "Failed GPIO request for usus: %d err %d\n",
  277. pdata->usus, ret);
  278. return ret;
  279. }
  280. }
  281. data->fault = false;
  282. data->ta_in = ta_in;
  283. data->usb_in = usb_in;
  284. return 0;
  285. }
  286. static int max8903_probe(struct platform_device *pdev)
  287. {
  288. struct max8903_data *data;
  289. struct device *dev = &pdev->dev;
  290. struct max8903_pdata *pdata = pdev->dev.platform_data;
  291. struct power_supply_config psy_cfg = {};
  292. int ret = 0;
  293. data = devm_kzalloc(dev, sizeof(struct max8903_data), GFP_KERNEL);
  294. if (!data)
  295. return -ENOMEM;
  296. if (IS_ENABLED(CONFIG_OF) && !pdata && dev->of_node)
  297. pdata = max8903_parse_dt_data(dev);
  298. if (!pdata) {
  299. dev_err(dev, "No platform data.\n");
  300. return -EINVAL;
  301. }
  302. pdev->dev.platform_data = pdata;
  303. data->pdata = pdata;
  304. data->dev = dev;
  305. platform_set_drvdata(pdev, data);
  306. if (pdata->dc_valid == false && pdata->usb_valid == false) {
  307. dev_err(dev, "No valid power sources.\n");
  308. return -EINVAL;
  309. }
  310. ret = max8903_setup_gpios(pdev);
  311. if (ret)
  312. return ret;
  313. data->psy_desc.name = "max8903_charger";
  314. data->psy_desc.type = (data->ta_in) ? POWER_SUPPLY_TYPE_MAINS :
  315. ((data->usb_in) ? POWER_SUPPLY_TYPE_USB :
  316. POWER_SUPPLY_TYPE_BATTERY);
  317. data->psy_desc.get_property = max8903_get_property;
  318. data->psy_desc.properties = max8903_charger_props;
  319. data->psy_desc.num_properties = ARRAY_SIZE(max8903_charger_props);
  320. psy_cfg.of_node = dev->of_node;
  321. psy_cfg.drv_data = data;
  322. data->psy = devm_power_supply_register(dev, &data->psy_desc, &psy_cfg);
  323. if (IS_ERR(data->psy)) {
  324. dev_err(dev, "failed: power supply register.\n");
  325. return PTR_ERR(data->psy);
  326. }
  327. if (pdata->dc_valid) {
  328. ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->dok),
  329. NULL, max8903_dcin,
  330. IRQF_TRIGGER_FALLING |
  331. IRQF_TRIGGER_RISING | IRQF_ONESHOT,
  332. "MAX8903 DC IN", data);
  333. if (ret) {
  334. dev_err(dev, "Cannot request irq %d for DC (%d)\n",
  335. gpio_to_irq(pdata->dok), ret);
  336. return ret;
  337. }
  338. }
  339. if (pdata->usb_valid) {
  340. ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->uok),
  341. NULL, max8903_usbin,
  342. IRQF_TRIGGER_FALLING |
  343. IRQF_TRIGGER_RISING | IRQF_ONESHOT,
  344. "MAX8903 USB IN", data);
  345. if (ret) {
  346. dev_err(dev, "Cannot request irq %d for USB (%d)\n",
  347. gpio_to_irq(pdata->uok), ret);
  348. return ret;
  349. }
  350. }
  351. if (gpio_is_valid(pdata->flt)) {
  352. ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->flt),
  353. NULL, max8903_fault,
  354. IRQF_TRIGGER_FALLING |
  355. IRQF_TRIGGER_RISING | IRQF_ONESHOT,
  356. "MAX8903 Fault", data);
  357. if (ret) {
  358. dev_err(dev, "Cannot request irq %d for Fault (%d)\n",
  359. gpio_to_irq(pdata->flt), ret);
  360. return ret;
  361. }
  362. }
  363. return 0;
  364. }
  365. static const struct of_device_id max8903_match_ids[] = {
  366. { .compatible = "maxim,max8903", },
  367. { /* sentinel */ }
  368. };
  369. MODULE_DEVICE_TABLE(of, max8903_match_ids);
  370. static struct platform_driver max8903_driver = {
  371. .probe = max8903_probe,
  372. .driver = {
  373. .name = "max8903-charger",
  374. .of_match_table = max8903_match_ids
  375. },
  376. };
  377. module_platform_driver(max8903_driver);
  378. MODULE_LICENSE("GPL");
  379. MODULE_DESCRIPTION("MAX8903 Charger Driver");
  380. MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
  381. MODULE_ALIAS("platform:max8903-charger");