max77650-charger.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Copyright (C) 2018 BayLibre SAS
  4. // Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
  5. //
  6. // Battery charger driver for MAXIM 77650/77651 charger/power-supply.
  7. #include <linux/i2c.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/mfd/max77650.h>
  10. #include <linux/module.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/power_supply.h>
  13. #include <linux/regmap.h>
  14. #define MAX77650_CHARGER_ENABLED BIT(0)
  15. #define MAX77650_CHARGER_DISABLED 0x00
  16. #define MAX77650_CHARGER_CHG_EN_MASK BIT(0)
  17. #define MAX77650_CHG_DETAILS_MASK GENMASK(7, 4)
  18. #define MAX77650_CHG_DETAILS_BITS(_reg) \
  19. (((_reg) & MAX77650_CHG_DETAILS_MASK) >> 4)
  20. /* Charger is OFF. */
  21. #define MAX77650_CHG_OFF 0x00
  22. /* Charger is in prequalification mode. */
  23. #define MAX77650_CHG_PREQ 0x01
  24. /* Charger is in fast-charge constant current mode. */
  25. #define MAX77650_CHG_ON_CURR 0x02
  26. /* Charger is in JEITA modified fast-charge constant-current mode. */
  27. #define MAX77650_CHG_ON_CURR_JEITA 0x03
  28. /* Charger is in fast-charge constant-voltage mode. */
  29. #define MAX77650_CHG_ON_VOLT 0x04
  30. /* Charger is in JEITA modified fast-charge constant-voltage mode. */
  31. #define MAX77650_CHG_ON_VOLT_JEITA 0x05
  32. /* Charger is in top-off mode. */
  33. #define MAX77650_CHG_ON_TOPOFF 0x06
  34. /* Charger is in JEITA modified top-off mode. */
  35. #define MAX77650_CHG_ON_TOPOFF_JEITA 0x07
  36. /* Charger is done. */
  37. #define MAX77650_CHG_DONE 0x08
  38. /* Charger is JEITA modified done. */
  39. #define MAX77650_CHG_DONE_JEITA 0x09
  40. /* Charger is suspended due to a prequalification timer fault. */
  41. #define MAX77650_CHG_SUSP_PREQ_TIM_FAULT 0x0a
  42. /* Charger is suspended due to a fast-charge timer fault. */
  43. #define MAX77650_CHG_SUSP_FAST_CHG_TIM_FAULT 0x0b
  44. /* Charger is suspended due to a battery temperature fault. */
  45. #define MAX77650_CHG_SUSP_BATT_TEMP_FAULT 0x0c
  46. #define MAX77650_CHGIN_DETAILS_MASK GENMASK(3, 2)
  47. #define MAX77650_CHGIN_DETAILS_BITS(_reg) \
  48. (((_reg) & MAX77650_CHGIN_DETAILS_MASK) >> 2)
  49. #define MAX77650_CHGIN_UNDERVOLTAGE_LOCKOUT 0x00
  50. #define MAX77650_CHGIN_OVERVOLTAGE_LOCKOUT 0x01
  51. #define MAX77650_CHGIN_OKAY 0x11
  52. #define MAX77650_CHARGER_CHG_MASK BIT(1)
  53. #define MAX77650_CHARGER_CHG_CHARGING(_reg) \
  54. (((_reg) & MAX77650_CHARGER_CHG_MASK) > 1)
  55. #define MAX77650_CHARGER_VCHGIN_MIN_MASK 0xc0
  56. #define MAX77650_CHARGER_VCHGIN_MIN_SHIFT(_val) ((_val) << 5)
  57. #define MAX77650_CHARGER_ICHGIN_LIM_MASK 0x1c
  58. #define MAX77650_CHARGER_ICHGIN_LIM_SHIFT(_val) ((_val) << 2)
  59. struct max77650_charger_data {
  60. struct regmap *map;
  61. struct device *dev;
  62. };
  63. static enum power_supply_property max77650_charger_properties[] = {
  64. POWER_SUPPLY_PROP_STATUS,
  65. POWER_SUPPLY_PROP_ONLINE,
  66. POWER_SUPPLY_PROP_CHARGE_TYPE
  67. };
  68. static const unsigned int max77650_charger_vchgin_min_table[] = {
  69. 4000000, 4100000, 4200000, 4300000, 4400000, 4500000, 4600000, 4700000
  70. };
  71. static const unsigned int max77650_charger_ichgin_lim_table[] = {
  72. 95000, 190000, 285000, 380000, 475000
  73. };
  74. static int max77650_charger_set_vchgin_min(struct max77650_charger_data *chg,
  75. unsigned int val)
  76. {
  77. int i, rv;
  78. for (i = 0; i < ARRAY_SIZE(max77650_charger_vchgin_min_table); i++) {
  79. if (val == max77650_charger_vchgin_min_table[i]) {
  80. rv = regmap_update_bits(chg->map,
  81. MAX77650_REG_CNFG_CHG_B,
  82. MAX77650_CHARGER_VCHGIN_MIN_MASK,
  83. MAX77650_CHARGER_VCHGIN_MIN_SHIFT(i));
  84. if (rv)
  85. return rv;
  86. return 0;
  87. }
  88. }
  89. return -EINVAL;
  90. }
  91. static int max77650_charger_set_ichgin_lim(struct max77650_charger_data *chg,
  92. unsigned int val)
  93. {
  94. int i, rv;
  95. for (i = 0; i < ARRAY_SIZE(max77650_charger_ichgin_lim_table); i++) {
  96. if (val == max77650_charger_ichgin_lim_table[i]) {
  97. rv = regmap_update_bits(chg->map,
  98. MAX77650_REG_CNFG_CHG_B,
  99. MAX77650_CHARGER_ICHGIN_LIM_MASK,
  100. MAX77650_CHARGER_ICHGIN_LIM_SHIFT(i));
  101. if (rv)
  102. return rv;
  103. return 0;
  104. }
  105. }
  106. return -EINVAL;
  107. }
  108. static int max77650_charger_enable(struct max77650_charger_data *chg)
  109. {
  110. int rv;
  111. rv = regmap_update_bits(chg->map,
  112. MAX77650_REG_CNFG_CHG_B,
  113. MAX77650_CHARGER_CHG_EN_MASK,
  114. MAX77650_CHARGER_ENABLED);
  115. if (rv)
  116. dev_err(chg->dev, "unable to enable the charger: %d\n", rv);
  117. return rv;
  118. }
  119. static void max77650_charger_disable(struct max77650_charger_data *chg)
  120. {
  121. int rv;
  122. rv = regmap_update_bits(chg->map,
  123. MAX77650_REG_CNFG_CHG_B,
  124. MAX77650_CHARGER_CHG_EN_MASK,
  125. MAX77650_CHARGER_DISABLED);
  126. if (rv)
  127. dev_err(chg->dev, "unable to disable the charger: %d\n", rv);
  128. }
  129. static irqreturn_t max77650_charger_check_status(int irq, void *data)
  130. {
  131. struct max77650_charger_data *chg = data;
  132. int rv, reg;
  133. rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, &reg);
  134. if (rv) {
  135. dev_err(chg->dev,
  136. "unable to read the charger status: %d\n", rv);
  137. return IRQ_HANDLED;
  138. }
  139. switch (MAX77650_CHGIN_DETAILS_BITS(reg)) {
  140. case MAX77650_CHGIN_UNDERVOLTAGE_LOCKOUT:
  141. dev_err(chg->dev, "undervoltage lockout detected, disabling charger\n");
  142. max77650_charger_disable(chg);
  143. break;
  144. case MAX77650_CHGIN_OVERVOLTAGE_LOCKOUT:
  145. dev_err(chg->dev, "overvoltage lockout detected, disabling charger\n");
  146. max77650_charger_disable(chg);
  147. break;
  148. case MAX77650_CHGIN_OKAY:
  149. max77650_charger_enable(chg);
  150. break;
  151. default:
  152. /* May be 0x10 - debouncing */
  153. break;
  154. }
  155. return IRQ_HANDLED;
  156. }
  157. static int max77650_charger_get_property(struct power_supply *psy,
  158. enum power_supply_property psp,
  159. union power_supply_propval *val)
  160. {
  161. struct max77650_charger_data *chg = power_supply_get_drvdata(psy);
  162. int rv, reg;
  163. switch (psp) {
  164. case POWER_SUPPLY_PROP_STATUS:
  165. rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, &reg);
  166. if (rv)
  167. return rv;
  168. if (MAX77650_CHARGER_CHG_CHARGING(reg)) {
  169. val->intval = POWER_SUPPLY_STATUS_CHARGING;
  170. break;
  171. }
  172. switch (MAX77650_CHG_DETAILS_BITS(reg)) {
  173. case MAX77650_CHG_OFF:
  174. case MAX77650_CHG_SUSP_PREQ_TIM_FAULT:
  175. case MAX77650_CHG_SUSP_FAST_CHG_TIM_FAULT:
  176. case MAX77650_CHG_SUSP_BATT_TEMP_FAULT:
  177. val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
  178. break;
  179. case MAX77650_CHG_PREQ:
  180. case MAX77650_CHG_ON_CURR:
  181. case MAX77650_CHG_ON_CURR_JEITA:
  182. case MAX77650_CHG_ON_VOLT:
  183. case MAX77650_CHG_ON_VOLT_JEITA:
  184. case MAX77650_CHG_ON_TOPOFF:
  185. case MAX77650_CHG_ON_TOPOFF_JEITA:
  186. val->intval = POWER_SUPPLY_STATUS_CHARGING;
  187. break;
  188. case MAX77650_CHG_DONE:
  189. val->intval = POWER_SUPPLY_STATUS_FULL;
  190. break;
  191. default:
  192. val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
  193. }
  194. break;
  195. case POWER_SUPPLY_PROP_ONLINE:
  196. rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, &reg);
  197. if (rv)
  198. return rv;
  199. val->intval = MAX77650_CHARGER_CHG_CHARGING(reg);
  200. break;
  201. case POWER_SUPPLY_PROP_CHARGE_TYPE:
  202. rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, &reg);
  203. if (rv)
  204. return rv;
  205. if (!MAX77650_CHARGER_CHG_CHARGING(reg)) {
  206. val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
  207. break;
  208. }
  209. switch (MAX77650_CHG_DETAILS_BITS(reg)) {
  210. case MAX77650_CHG_PREQ:
  211. case MAX77650_CHG_ON_CURR:
  212. case MAX77650_CHG_ON_CURR_JEITA:
  213. case MAX77650_CHG_ON_VOLT:
  214. case MAX77650_CHG_ON_VOLT_JEITA:
  215. val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
  216. break;
  217. case MAX77650_CHG_ON_TOPOFF:
  218. case MAX77650_CHG_ON_TOPOFF_JEITA:
  219. val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
  220. break;
  221. default:
  222. val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
  223. }
  224. break;
  225. default:
  226. return -EINVAL;
  227. }
  228. return 0;
  229. }
  230. static const struct power_supply_desc max77650_battery_desc = {
  231. .name = "max77650",
  232. .type = POWER_SUPPLY_TYPE_USB,
  233. .get_property = max77650_charger_get_property,
  234. .properties = max77650_charger_properties,
  235. .num_properties = ARRAY_SIZE(max77650_charger_properties),
  236. };
  237. static int max77650_charger_probe(struct platform_device *pdev)
  238. {
  239. struct power_supply_config pscfg = {};
  240. struct max77650_charger_data *chg;
  241. struct power_supply *battery;
  242. struct device *dev, *parent;
  243. int rv, chg_irq, chgin_irq;
  244. unsigned int prop;
  245. dev = &pdev->dev;
  246. parent = dev->parent;
  247. chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL);
  248. if (!chg)
  249. return -ENOMEM;
  250. platform_set_drvdata(pdev, chg);
  251. chg->map = dev_get_regmap(parent, NULL);
  252. if (!chg->map)
  253. return -ENODEV;
  254. chg->dev = dev;
  255. pscfg.of_node = dev->of_node;
  256. pscfg.drv_data = chg;
  257. chg_irq = platform_get_irq_byname(pdev, "CHG");
  258. if (chg_irq < 0)
  259. return chg_irq;
  260. chgin_irq = platform_get_irq_byname(pdev, "CHGIN");
  261. if (chgin_irq < 0)
  262. return chgin_irq;
  263. rv = devm_request_any_context_irq(dev, chg_irq,
  264. max77650_charger_check_status,
  265. IRQF_ONESHOT, "chg", chg);
  266. if (rv < 0)
  267. return rv;
  268. rv = devm_request_any_context_irq(dev, chgin_irq,
  269. max77650_charger_check_status,
  270. IRQF_ONESHOT, "chgin", chg);
  271. if (rv < 0)
  272. return rv;
  273. battery = devm_power_supply_register(dev,
  274. &max77650_battery_desc, &pscfg);
  275. if (IS_ERR(battery))
  276. return PTR_ERR(battery);
  277. rv = of_property_read_u32(dev->of_node,
  278. "input-voltage-min-microvolt", &prop);
  279. if (rv == 0) {
  280. rv = max77650_charger_set_vchgin_min(chg, prop);
  281. if (rv)
  282. return rv;
  283. }
  284. rv = of_property_read_u32(dev->of_node,
  285. "input-current-limit-microamp", &prop);
  286. if (rv == 0) {
  287. rv = max77650_charger_set_ichgin_lim(chg, prop);
  288. if (rv)
  289. return rv;
  290. }
  291. return max77650_charger_enable(chg);
  292. }
  293. static void max77650_charger_remove(struct platform_device *pdev)
  294. {
  295. struct max77650_charger_data *chg = platform_get_drvdata(pdev);
  296. max77650_charger_disable(chg);
  297. }
  298. static const struct of_device_id max77650_charger_of_match[] = {
  299. { .compatible = "maxim,max77650-charger" },
  300. { }
  301. };
  302. MODULE_DEVICE_TABLE(of, max77650_charger_of_match);
  303. static struct platform_driver max77650_charger_driver = {
  304. .driver = {
  305. .name = "max77650-charger",
  306. .of_match_table = max77650_charger_of_match,
  307. },
  308. .probe = max77650_charger_probe,
  309. .remove_new = max77650_charger_remove,
  310. };
  311. module_platform_driver(max77650_charger_driver);
  312. MODULE_DESCRIPTION("MAXIM 77650/77651 charger driver");
  313. MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
  314. MODULE_LICENSE("GPL v2");
  315. MODULE_ALIAS("platform:max77650-charger");