axp288_charger.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * axp288_charger.c - X-power AXP288 PMIC Charger driver
  4. *
  5. * Copyright (C) 2016-2017 Hans de Goede <hdegoede@redhat.com>
  6. * Copyright (C) 2014 Intel Corporation
  7. * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
  8. */
  9. #include <linux/acpi.h>
  10. #include <linux/bitops.h>
  11. #include <linux/module.h>
  12. #include <linux/device.h>
  13. #include <linux/regmap.h>
  14. #include <linux/workqueue.h>
  15. #include <linux/delay.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/usb/otg.h>
  18. #include <linux/notifier.h>
  19. #include <linux/power_supply.h>
  20. #include <linux/property.h>
  21. #include <linux/mfd/axp20x.h>
  22. #include <linux/extcon.h>
  23. #include <linux/dmi.h>
  24. #define PS_STAT_VBUS_TRIGGER BIT(0)
  25. #define PS_STAT_BAT_CHRG_DIR BIT(2)
  26. #define PS_STAT_VBAT_ABOVE_VHOLD BIT(3)
  27. #define PS_STAT_VBUS_VALID BIT(4)
  28. #define PS_STAT_VBUS_PRESENT BIT(5)
  29. #define CHRG_STAT_BAT_SAFE_MODE BIT(3)
  30. #define CHRG_STAT_BAT_VALID BIT(4)
  31. #define CHRG_STAT_BAT_PRESENT BIT(5)
  32. #define CHRG_STAT_CHARGING BIT(6)
  33. #define CHRG_STAT_PMIC_OTP BIT(7)
  34. #define VBUS_ISPOUT_CUR_LIM_MASK 0x03
  35. #define VBUS_ISPOUT_CUR_LIM_BIT_POS 0
  36. #define VBUS_ISPOUT_CUR_LIM_900MA 0x0 /* 900mA */
  37. #define VBUS_ISPOUT_CUR_LIM_1500MA 0x1 /* 1500mA */
  38. #define VBUS_ISPOUT_CUR_LIM_2000MA 0x2 /* 2000mA */
  39. #define VBUS_ISPOUT_CUR_NO_LIM 0x3 /* 2500mA */
  40. #define VBUS_ISPOUT_VHOLD_SET_MASK 0x38
  41. #define VBUS_ISPOUT_VHOLD_SET_BIT_POS 0x3
  42. #define VBUS_ISPOUT_VHOLD_SET_OFFSET 4000 /* 4000mV */
  43. #define VBUS_ISPOUT_VHOLD_SET_LSB_RES 100 /* 100mV */
  44. #define VBUS_ISPOUT_VHOLD_SET_4400MV 0x4 /* 4400mV */
  45. #define VBUS_ISPOUT_VBUS_PATH_DIS BIT(7)
  46. #define CHRG_CCCV_CC_MASK 0xf /* 4 bits */
  47. #define CHRG_CCCV_CC_BIT_POS 0
  48. #define CHRG_CCCV_CC_OFFSET 200 /* 200mA */
  49. #define CHRG_CCCV_CC_LSB_RES 200 /* 200mA */
  50. #define CHRG_CCCV_ITERM_20P BIT(4) /* 20% of CC */
  51. #define CHRG_CCCV_CV_MASK 0x60 /* 2 bits */
  52. #define CHRG_CCCV_CV_BIT_POS 5
  53. #define CHRG_CCCV_CV_4100MV 0x0 /* 4.10V */
  54. #define CHRG_CCCV_CV_4150MV 0x1 /* 4.15V */
  55. #define CHRG_CCCV_CV_4200MV 0x2 /* 4.20V */
  56. #define CHRG_CCCV_CV_4350MV 0x3 /* 4.35V */
  57. #define CHRG_CCCV_CHG_EN BIT(7)
  58. #define CNTL2_CC_TIMEOUT_MASK 0x3 /* 2 bits */
  59. #define CNTL2_CC_TIMEOUT_OFFSET 6 /* 6 Hrs */
  60. #define CNTL2_CC_TIMEOUT_LSB_RES 2 /* 2 Hrs */
  61. #define CNTL2_CC_TIMEOUT_12HRS 0x3 /* 12 Hrs */
  62. #define CNTL2_CHGLED_TYPEB BIT(4)
  63. #define CNTL2_CHG_OUT_TURNON BIT(5)
  64. #define CNTL2_PC_TIMEOUT_MASK 0xC0
  65. #define CNTL2_PC_TIMEOUT_OFFSET 40 /* 40 mins */
  66. #define CNTL2_PC_TIMEOUT_LSB_RES 10 /* 10 mins */
  67. #define CNTL2_PC_TIMEOUT_70MINS 0x3
  68. #define CHRG_ILIM_TEMP_LOOP_EN BIT(3)
  69. #define CHRG_VBUS_ILIM_MASK 0xf0
  70. #define CHRG_VBUS_ILIM_BIT_POS 4
  71. #define CHRG_VBUS_ILIM_100MA 0x0 /* 100mA */
  72. #define CHRG_VBUS_ILIM_500MA 0x1 /* 500mA */
  73. #define CHRG_VBUS_ILIM_900MA 0x2 /* 900mA */
  74. #define CHRG_VBUS_ILIM_1500MA 0x3 /* 1500mA */
  75. #define CHRG_VBUS_ILIM_2000MA 0x4 /* 2000mA */
  76. #define CHRG_VBUS_ILIM_2500MA 0x5 /* 2500mA */
  77. #define CHRG_VBUS_ILIM_3000MA 0x6 /* 3000mA */
  78. #define CHRG_VBUS_ILIM_3500MA 0x7 /* 3500mA */
  79. #define CHRG_VBUS_ILIM_4000MA 0x8 /* 4000mA */
  80. #define CHRG_VLTFC_0C 0xA5 /* 0 DegC */
  81. #define CHRG_VHTFC_45C 0x1F /* 45 DegC */
  82. #define FG_CNTL_OCV_ADJ_EN BIT(3)
  83. #define CV_4100MV 4100 /* 4100mV */
  84. #define CV_4150MV 4150 /* 4150mV */
  85. #define CV_4200MV 4200 /* 4200mV */
  86. #define CV_4350MV 4350 /* 4350mV */
  87. #define AXP288_EXTCON_DEV_NAME "axp288_extcon"
  88. #define USB_HOST_EXTCON_HID "INT3496"
  89. #define USB_HOST_EXTCON_NAME "INT3496:00"
  90. enum {
  91. VBUS_OV_IRQ = 0,
  92. CHARGE_DONE_IRQ,
  93. CHARGE_CHARGING_IRQ,
  94. BAT_SAFE_QUIT_IRQ,
  95. BAT_SAFE_ENTER_IRQ,
  96. QCBTU_IRQ,
  97. CBTU_IRQ,
  98. QCBTO_IRQ,
  99. CBTO_IRQ,
  100. CHRG_INTR_END,
  101. };
  102. struct axp288_chrg_info {
  103. struct platform_device *pdev;
  104. struct regmap *regmap;
  105. struct regmap_irq_chip_data *regmap_irqc;
  106. int irq[CHRG_INTR_END];
  107. struct power_supply *psy_usb;
  108. /* OTG/Host mode */
  109. struct {
  110. struct work_struct work;
  111. struct extcon_dev *cable;
  112. struct notifier_block id_nb;
  113. bool id_short;
  114. } otg;
  115. /* SDP/CDP/DCP USB charging cable notifications */
  116. struct {
  117. struct extcon_dev *edev;
  118. struct notifier_block nb;
  119. struct work_struct work;
  120. } cable;
  121. int cc;
  122. int cv;
  123. int max_cc;
  124. int max_cv;
  125. };
  126. static inline int axp288_charger_set_cc(struct axp288_chrg_info *info, int cc)
  127. {
  128. u8 reg_val;
  129. int ret;
  130. if (cc < CHRG_CCCV_CC_OFFSET)
  131. cc = CHRG_CCCV_CC_OFFSET;
  132. else if (cc > info->max_cc)
  133. cc = info->max_cc;
  134. reg_val = (cc - CHRG_CCCV_CC_OFFSET) / CHRG_CCCV_CC_LSB_RES;
  135. cc = (reg_val * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
  136. reg_val = reg_val << CHRG_CCCV_CC_BIT_POS;
  137. ret = regmap_update_bits(info->regmap,
  138. AXP20X_CHRG_CTRL1,
  139. CHRG_CCCV_CC_MASK, reg_val);
  140. if (ret >= 0)
  141. info->cc = cc;
  142. return ret;
  143. }
  144. static inline int axp288_charger_set_cv(struct axp288_chrg_info *info, int cv)
  145. {
  146. u8 reg_val;
  147. int ret;
  148. if (cv <= CV_4100MV) {
  149. reg_val = CHRG_CCCV_CV_4100MV;
  150. cv = CV_4100MV;
  151. } else if (cv <= CV_4150MV) {
  152. reg_val = CHRG_CCCV_CV_4150MV;
  153. cv = CV_4150MV;
  154. } else if (cv <= CV_4200MV) {
  155. reg_val = CHRG_CCCV_CV_4200MV;
  156. cv = CV_4200MV;
  157. } else {
  158. reg_val = CHRG_CCCV_CV_4350MV;
  159. cv = CV_4350MV;
  160. }
  161. reg_val = reg_val << CHRG_CCCV_CV_BIT_POS;
  162. ret = regmap_update_bits(info->regmap,
  163. AXP20X_CHRG_CTRL1,
  164. CHRG_CCCV_CV_MASK, reg_val);
  165. if (ret >= 0)
  166. info->cv = cv;
  167. return ret;
  168. }
  169. static int axp288_charger_get_vbus_inlmt(struct axp288_chrg_info *info)
  170. {
  171. unsigned int val;
  172. int ret;
  173. ret = regmap_read(info->regmap, AXP20X_CHRG_BAK_CTRL, &val);
  174. if (ret < 0)
  175. return ret;
  176. val >>= CHRG_VBUS_ILIM_BIT_POS;
  177. switch (val) {
  178. case CHRG_VBUS_ILIM_100MA:
  179. return 100000;
  180. case CHRG_VBUS_ILIM_500MA:
  181. return 500000;
  182. case CHRG_VBUS_ILIM_900MA:
  183. return 900000;
  184. case CHRG_VBUS_ILIM_1500MA:
  185. return 1500000;
  186. case CHRG_VBUS_ILIM_2000MA:
  187. return 2000000;
  188. case CHRG_VBUS_ILIM_2500MA:
  189. return 2500000;
  190. case CHRG_VBUS_ILIM_3000MA:
  191. return 3000000;
  192. case CHRG_VBUS_ILIM_3500MA:
  193. return 3500000;
  194. default:
  195. /* All b1xxx values map to 4000 mA */
  196. return 4000000;
  197. }
  198. }
  199. static inline int axp288_charger_set_vbus_inlmt(struct axp288_chrg_info *info,
  200. int inlmt)
  201. {
  202. int ret;
  203. u8 reg_val;
  204. if (inlmt >= 4000000)
  205. reg_val = CHRG_VBUS_ILIM_4000MA << CHRG_VBUS_ILIM_BIT_POS;
  206. else if (inlmt >= 3500000)
  207. reg_val = CHRG_VBUS_ILIM_3500MA << CHRG_VBUS_ILIM_BIT_POS;
  208. else if (inlmt >= 3000000)
  209. reg_val = CHRG_VBUS_ILIM_3000MA << CHRG_VBUS_ILIM_BIT_POS;
  210. else if (inlmt >= 2500000)
  211. reg_val = CHRG_VBUS_ILIM_2500MA << CHRG_VBUS_ILIM_BIT_POS;
  212. else if (inlmt >= 2000000)
  213. reg_val = CHRG_VBUS_ILIM_2000MA << CHRG_VBUS_ILIM_BIT_POS;
  214. else if (inlmt >= 1500000)
  215. reg_val = CHRG_VBUS_ILIM_1500MA << CHRG_VBUS_ILIM_BIT_POS;
  216. else if (inlmt >= 900000)
  217. reg_val = CHRG_VBUS_ILIM_900MA << CHRG_VBUS_ILIM_BIT_POS;
  218. else if (inlmt >= 500000)
  219. reg_val = CHRG_VBUS_ILIM_500MA << CHRG_VBUS_ILIM_BIT_POS;
  220. else
  221. reg_val = CHRG_VBUS_ILIM_100MA << CHRG_VBUS_ILIM_BIT_POS;
  222. ret = regmap_update_bits(info->regmap, AXP20X_CHRG_BAK_CTRL,
  223. CHRG_VBUS_ILIM_MASK, reg_val);
  224. if (ret < 0)
  225. dev_err(&info->pdev->dev, "charger BAK control %d\n", ret);
  226. return ret;
  227. }
  228. static int axp288_charger_vbus_path_select(struct axp288_chrg_info *info,
  229. bool enable)
  230. {
  231. int ret;
  232. if (enable)
  233. ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
  234. VBUS_ISPOUT_VBUS_PATH_DIS, 0);
  235. else
  236. ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
  237. VBUS_ISPOUT_VBUS_PATH_DIS, VBUS_ISPOUT_VBUS_PATH_DIS);
  238. if (ret < 0)
  239. dev_err(&info->pdev->dev, "axp288 vbus path select %d\n", ret);
  240. return ret;
  241. }
  242. static int axp288_charger_enable_charger(struct axp288_chrg_info *info,
  243. bool enable)
  244. {
  245. int ret;
  246. if (enable)
  247. ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
  248. CHRG_CCCV_CHG_EN, CHRG_CCCV_CHG_EN);
  249. else
  250. ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
  251. CHRG_CCCV_CHG_EN, 0);
  252. if (ret < 0)
  253. dev_err(&info->pdev->dev, "axp288 enable charger %d\n", ret);
  254. return ret;
  255. }
  256. static int axp288_charger_is_present(struct axp288_chrg_info *info)
  257. {
  258. int ret, present = 0;
  259. unsigned int val;
  260. ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
  261. if (ret < 0)
  262. return ret;
  263. if (val & PS_STAT_VBUS_PRESENT)
  264. present = 1;
  265. return present;
  266. }
  267. static int axp288_charger_is_online(struct axp288_chrg_info *info)
  268. {
  269. int ret, online = 0;
  270. unsigned int val;
  271. ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
  272. if (ret < 0)
  273. return ret;
  274. if (val & PS_STAT_VBUS_VALID)
  275. online = 1;
  276. return online;
  277. }
  278. static int axp288_get_charger_health(struct axp288_chrg_info *info)
  279. {
  280. int ret, pwr_stat, chrg_stat;
  281. int health = POWER_SUPPLY_HEALTH_UNKNOWN;
  282. unsigned int val;
  283. ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
  284. if ((ret < 0) || !(val & PS_STAT_VBUS_PRESENT))
  285. goto health_read_fail;
  286. else
  287. pwr_stat = val;
  288. ret = regmap_read(info->regmap, AXP20X_PWR_OP_MODE, &val);
  289. if (ret < 0)
  290. goto health_read_fail;
  291. else
  292. chrg_stat = val;
  293. if (!(pwr_stat & PS_STAT_VBUS_VALID))
  294. health = POWER_SUPPLY_HEALTH_DEAD;
  295. else if (chrg_stat & CHRG_STAT_PMIC_OTP)
  296. health = POWER_SUPPLY_HEALTH_OVERHEAT;
  297. else if (chrg_stat & CHRG_STAT_BAT_SAFE_MODE)
  298. health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
  299. else
  300. health = POWER_SUPPLY_HEALTH_GOOD;
  301. health_read_fail:
  302. return health;
  303. }
  304. static int axp288_charger_usb_set_property(struct power_supply *psy,
  305. enum power_supply_property psp,
  306. const union power_supply_propval *val)
  307. {
  308. struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
  309. int ret = 0;
  310. int scaled_val;
  311. switch (psp) {
  312. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
  313. scaled_val = min(val->intval, info->max_cc);
  314. scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
  315. ret = axp288_charger_set_cc(info, scaled_val);
  316. if (ret < 0)
  317. dev_warn(&info->pdev->dev, "set charge current failed\n");
  318. break;
  319. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
  320. scaled_val = min(val->intval, info->max_cv);
  321. scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
  322. ret = axp288_charger_set_cv(info, scaled_val);
  323. if (ret < 0)
  324. dev_warn(&info->pdev->dev, "set charge voltage failed\n");
  325. break;
  326. case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
  327. ret = axp288_charger_set_vbus_inlmt(info, val->intval);
  328. if (ret < 0)
  329. dev_warn(&info->pdev->dev, "set input current limit failed\n");
  330. break;
  331. default:
  332. ret = -EINVAL;
  333. }
  334. return ret;
  335. }
  336. static int axp288_charger_usb_get_property(struct power_supply *psy,
  337. enum power_supply_property psp,
  338. union power_supply_propval *val)
  339. {
  340. struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
  341. int ret;
  342. switch (psp) {
  343. case POWER_SUPPLY_PROP_PRESENT:
  344. /* Check for OTG case first */
  345. if (info->otg.id_short) {
  346. val->intval = 0;
  347. break;
  348. }
  349. ret = axp288_charger_is_present(info);
  350. if (ret < 0)
  351. return ret;
  352. val->intval = ret;
  353. break;
  354. case POWER_SUPPLY_PROP_ONLINE:
  355. /* Check for OTG case first */
  356. if (info->otg.id_short) {
  357. val->intval = 0;
  358. break;
  359. }
  360. ret = axp288_charger_is_online(info);
  361. if (ret < 0)
  362. return ret;
  363. val->intval = ret;
  364. break;
  365. case POWER_SUPPLY_PROP_HEALTH:
  366. val->intval = axp288_get_charger_health(info);
  367. break;
  368. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
  369. val->intval = info->cc * 1000;
  370. break;
  371. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
  372. val->intval = info->max_cc * 1000;
  373. break;
  374. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
  375. val->intval = info->cv * 1000;
  376. break;
  377. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
  378. val->intval = info->max_cv * 1000;
  379. break;
  380. case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
  381. ret = axp288_charger_get_vbus_inlmt(info);
  382. if (ret < 0)
  383. return ret;
  384. val->intval = ret;
  385. break;
  386. default:
  387. return -EINVAL;
  388. }
  389. return 0;
  390. }
  391. static int axp288_charger_property_is_writeable(struct power_supply *psy,
  392. enum power_supply_property psp)
  393. {
  394. int ret;
  395. switch (psp) {
  396. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
  397. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
  398. case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
  399. ret = 1;
  400. break;
  401. default:
  402. ret = 0;
  403. }
  404. return ret;
  405. }
  406. static enum power_supply_property axp288_usb_props[] = {
  407. POWER_SUPPLY_PROP_PRESENT,
  408. POWER_SUPPLY_PROP_ONLINE,
  409. POWER_SUPPLY_PROP_TYPE,
  410. POWER_SUPPLY_PROP_HEALTH,
  411. POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
  412. POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
  413. POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
  414. POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
  415. POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
  416. };
  417. static const struct power_supply_desc axp288_charger_desc = {
  418. .name = "axp288_charger",
  419. .type = POWER_SUPPLY_TYPE_USB,
  420. .properties = axp288_usb_props,
  421. .num_properties = ARRAY_SIZE(axp288_usb_props),
  422. .get_property = axp288_charger_usb_get_property,
  423. .set_property = axp288_charger_usb_set_property,
  424. .property_is_writeable = axp288_charger_property_is_writeable,
  425. };
  426. static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev)
  427. {
  428. struct axp288_chrg_info *info = dev;
  429. int i;
  430. for (i = 0; i < CHRG_INTR_END; i++) {
  431. if (info->irq[i] == irq)
  432. break;
  433. }
  434. if (i >= CHRG_INTR_END) {
  435. dev_warn(&info->pdev->dev, "spurious interrupt!!\n");
  436. return IRQ_NONE;
  437. }
  438. switch (i) {
  439. case VBUS_OV_IRQ:
  440. dev_dbg(&info->pdev->dev, "VBUS Over Voltage INTR\n");
  441. break;
  442. case CHARGE_DONE_IRQ:
  443. dev_dbg(&info->pdev->dev, "Charging Done INTR\n");
  444. break;
  445. case CHARGE_CHARGING_IRQ:
  446. dev_dbg(&info->pdev->dev, "Start Charging IRQ\n");
  447. break;
  448. case BAT_SAFE_QUIT_IRQ:
  449. dev_dbg(&info->pdev->dev,
  450. "Quit Safe Mode(restart timer) Charging IRQ\n");
  451. break;
  452. case BAT_SAFE_ENTER_IRQ:
  453. dev_dbg(&info->pdev->dev,
  454. "Enter Safe Mode(timer expire) Charging IRQ\n");
  455. break;
  456. case QCBTU_IRQ:
  457. dev_dbg(&info->pdev->dev,
  458. "Quit Battery Under Temperature(CHRG) INTR\n");
  459. break;
  460. case CBTU_IRQ:
  461. dev_dbg(&info->pdev->dev,
  462. "Hit Battery Under Temperature(CHRG) INTR\n");
  463. break;
  464. case QCBTO_IRQ:
  465. dev_dbg(&info->pdev->dev,
  466. "Quit Battery Over Temperature(CHRG) INTR\n");
  467. break;
  468. case CBTO_IRQ:
  469. dev_dbg(&info->pdev->dev,
  470. "Hit Battery Over Temperature(CHRG) INTR\n");
  471. break;
  472. default:
  473. dev_warn(&info->pdev->dev, "Spurious Interrupt!!!\n");
  474. goto out;
  475. }
  476. power_supply_changed(info->psy_usb);
  477. out:
  478. return IRQ_HANDLED;
  479. }
  480. /*
  481. * The HP Pavilion x2 10 series comes in a number of variants:
  482. * Bay Trail SoC + AXP288 PMIC, Micro-USB, DMI_BOARD_NAME: "8021"
  483. * Bay Trail SoC + AXP288 PMIC, Type-C, DMI_BOARD_NAME: "815D"
  484. * Cherry Trail SoC + AXP288 PMIC, Type-C, DMI_BOARD_NAME: "813E"
  485. * Cherry Trail SoC + TI PMIC, Type-C, DMI_BOARD_NAME: "827C" or "82F4"
  486. *
  487. * The variants with the AXP288 + Type-C connector are all kinds of special:
  488. *
  489. * 1. They use a Type-C connector which the AXP288 does not support, so when
  490. * using a Type-C charger it is not recognized. Unlike most AXP288 devices,
  491. * this model actually has mostly working ACPI AC / Battery code, the ACPI code
  492. * "solves" this by simply setting the input_current_limit to 3A.
  493. * There are still some issues with the ACPI code, so we use this native driver,
  494. * and to solve the charging not working (500mA is not enough) issue we hardcode
  495. * the 3A input_current_limit like the ACPI code does.
  496. *
  497. * 2. If no charger is connected the machine boots with the vbus-path disabled.
  498. * Normally this is done when a 5V boost converter is active to avoid the PMIC
  499. * trying to charge from the 5V boost converter's output. This is done when
  500. * an OTG host cable is inserted and the ID pin on the micro-B receptacle is
  501. * pulled low and the ID pin has an ACPI event handler associated with it
  502. * which re-enables the vbus-path when the ID pin is pulled high when the
  503. * OTG host cable is removed. The Type-C connector has no ID pin, there is
  504. * no ID pin handler and there appears to be no 5V boost converter, so we
  505. * end up not charging because the vbus-path is disabled, until we unplug
  506. * the charger which automatically clears the vbus-path disable bit and then
  507. * on the second plug-in of the adapter we start charging. To solve the not
  508. * charging on first charger plugin we unconditionally enable the vbus-path at
  509. * probe on this model, which is safe since there is no 5V boost converter.
  510. */
  511. static const struct dmi_system_id axp288_hp_x2_dmi_ids[] = {
  512. {
  513. .matches = {
  514. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
  515. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
  516. DMI_EXACT_MATCH(DMI_BOARD_NAME, "815D"),
  517. },
  518. },
  519. {
  520. .matches = {
  521. DMI_EXACT_MATCH(DMI_SYS_VENDOR, "HP"),
  522. DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
  523. DMI_EXACT_MATCH(DMI_BOARD_NAME, "813E"),
  524. },
  525. },
  526. {} /* Terminating entry */
  527. };
  528. static void axp288_charger_extcon_evt_worker(struct work_struct *work)
  529. {
  530. struct axp288_chrg_info *info =
  531. container_of(work, struct axp288_chrg_info, cable.work);
  532. int ret, current_limit;
  533. struct extcon_dev *edev = info->cable.edev;
  534. unsigned int val;
  535. ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
  536. if (ret < 0) {
  537. dev_err(&info->pdev->dev, "Error reading status (%d)\n", ret);
  538. return;
  539. }
  540. /* Offline? Disable charging and bail */
  541. if (!(val & PS_STAT_VBUS_VALID)) {
  542. dev_dbg(&info->pdev->dev, "USB charger disconnected\n");
  543. axp288_charger_enable_charger(info, false);
  544. power_supply_changed(info->psy_usb);
  545. return;
  546. }
  547. /* Determine cable/charger type */
  548. if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
  549. /* See comment above axp288_hp_x2_dmi_ids declaration */
  550. dev_dbg(&info->pdev->dev, "HP X2 with Type-C, setting inlmt to 3A\n");
  551. current_limit = 3000000;
  552. } else if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
  553. dev_dbg(&info->pdev->dev, "USB SDP charger is connected\n");
  554. current_limit = 500000;
  555. } else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
  556. dev_dbg(&info->pdev->dev, "USB CDP charger is connected\n");
  557. current_limit = 1500000;
  558. } else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {
  559. dev_dbg(&info->pdev->dev, "USB DCP charger is connected\n");
  560. current_limit = 2000000;
  561. } else {
  562. /* Charger type detection still in progress, bail. */
  563. return;
  564. }
  565. /* Set vbus current limit first, then enable charger */
  566. ret = axp288_charger_set_vbus_inlmt(info, current_limit);
  567. if (ret == 0)
  568. axp288_charger_enable_charger(info, true);
  569. else
  570. dev_err(&info->pdev->dev,
  571. "error setting current limit (%d)\n", ret);
  572. power_supply_changed(info->psy_usb);
  573. }
  574. static int axp288_charger_handle_cable_evt(struct notifier_block *nb,
  575. unsigned long event, void *param)
  576. {
  577. struct axp288_chrg_info *info =
  578. container_of(nb, struct axp288_chrg_info, cable.nb);
  579. schedule_work(&info->cable.work);
  580. return NOTIFY_OK;
  581. }
  582. static void axp288_charger_otg_evt_worker(struct work_struct *work)
  583. {
  584. struct axp288_chrg_info *info =
  585. container_of(work, struct axp288_chrg_info, otg.work);
  586. struct extcon_dev *edev = info->otg.cable;
  587. int ret, usb_host = extcon_get_state(edev, EXTCON_USB_HOST);
  588. dev_dbg(&info->pdev->dev, "external connector USB-Host is %s\n",
  589. usb_host ? "attached" : "detached");
  590. /*
  591. * Set usb_id_short flag to avoid running charger detection logic
  592. * in case usb host.
  593. */
  594. info->otg.id_short = usb_host;
  595. /* Disable VBUS path before enabling the 5V boost */
  596. ret = axp288_charger_vbus_path_select(info, !info->otg.id_short);
  597. if (ret < 0)
  598. dev_warn(&info->pdev->dev, "vbus path disable failed\n");
  599. }
  600. static int axp288_charger_handle_otg_evt(struct notifier_block *nb,
  601. unsigned long event, void *param)
  602. {
  603. struct axp288_chrg_info *info =
  604. container_of(nb, struct axp288_chrg_info, otg.id_nb);
  605. schedule_work(&info->otg.work);
  606. return NOTIFY_OK;
  607. }
  608. static int charger_init_hw_regs(struct axp288_chrg_info *info)
  609. {
  610. int ret, cc, cv;
  611. unsigned int val;
  612. /* Program temperature thresholds */
  613. ret = regmap_write(info->regmap, AXP20X_V_LTF_CHRG, CHRG_VLTFC_0C);
  614. if (ret < 0) {
  615. dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
  616. AXP20X_V_LTF_CHRG, ret);
  617. return ret;
  618. }
  619. ret = regmap_write(info->regmap, AXP20X_V_HTF_CHRG, CHRG_VHTFC_45C);
  620. if (ret < 0) {
  621. dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
  622. AXP20X_V_HTF_CHRG, ret);
  623. return ret;
  624. }
  625. /* Do not turn-off charger o/p after charge cycle ends */
  626. ret = regmap_update_bits(info->regmap,
  627. AXP20X_CHRG_CTRL2,
  628. CNTL2_CHG_OUT_TURNON, CNTL2_CHG_OUT_TURNON);
  629. if (ret < 0) {
  630. dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
  631. AXP20X_CHRG_CTRL2, ret);
  632. return ret;
  633. }
  634. /* Setup ending condition for charging to be 10% of I(chrg) */
  635. ret = regmap_update_bits(info->regmap,
  636. AXP20X_CHRG_CTRL1,
  637. CHRG_CCCV_ITERM_20P, 0);
  638. if (ret < 0) {
  639. dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
  640. AXP20X_CHRG_CTRL1, ret);
  641. return ret;
  642. }
  643. /* Disable OCV-SOC curve calibration */
  644. ret = regmap_update_bits(info->regmap,
  645. AXP20X_CC_CTRL,
  646. FG_CNTL_OCV_ADJ_EN, 0);
  647. if (ret < 0) {
  648. dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
  649. AXP20X_CC_CTRL, ret);
  650. return ret;
  651. }
  652. if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
  653. /* See comment above axp288_hp_x2_dmi_ids declaration */
  654. ret = axp288_charger_vbus_path_select(info, true);
  655. if (ret < 0)
  656. return ret;
  657. } else {
  658. /* Set Vhold to the factory default / recommended 4.4V */
  659. val = VBUS_ISPOUT_VHOLD_SET_4400MV << VBUS_ISPOUT_VHOLD_SET_BIT_POS;
  660. ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
  661. VBUS_ISPOUT_VHOLD_SET_MASK, val);
  662. if (ret < 0) {
  663. dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
  664. AXP20X_VBUS_IPSOUT_MGMT, ret);
  665. return ret;
  666. }
  667. }
  668. /* Read current charge voltage and current limit */
  669. ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val);
  670. if (ret < 0) {
  671. dev_err(&info->pdev->dev, "register(%x) read error(%d)\n",
  672. AXP20X_CHRG_CTRL1, ret);
  673. return ret;
  674. }
  675. /* Determine charge voltage */
  676. cv = (val & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS;
  677. switch (cv) {
  678. case CHRG_CCCV_CV_4100MV:
  679. info->cv = CV_4100MV;
  680. break;
  681. case CHRG_CCCV_CV_4150MV:
  682. info->cv = CV_4150MV;
  683. break;
  684. case CHRG_CCCV_CV_4200MV:
  685. info->cv = CV_4200MV;
  686. break;
  687. case CHRG_CCCV_CV_4350MV:
  688. info->cv = CV_4350MV;
  689. break;
  690. }
  691. /* Determine charge current limit */
  692. cc = (val & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS;
  693. cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
  694. info->cc = cc;
  695. /*
  696. * Do not allow the user to configure higher settings then those
  697. * set by the firmware
  698. */
  699. info->max_cv = info->cv;
  700. info->max_cc = info->cc;
  701. return 0;
  702. }
  703. static void axp288_charger_cancel_work(void *data)
  704. {
  705. struct axp288_chrg_info *info = data;
  706. cancel_work_sync(&info->otg.work);
  707. cancel_work_sync(&info->cable.work);
  708. }
  709. static int axp288_charger_probe(struct platform_device *pdev)
  710. {
  711. int ret, i, pirq;
  712. struct axp288_chrg_info *info;
  713. struct device *dev = &pdev->dev;
  714. struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
  715. struct power_supply_config charger_cfg = {};
  716. unsigned int val;
  717. /*
  718. * On some devices the fuelgauge and charger parts of the axp288 are
  719. * not used, check that the fuelgauge is enabled (CC_CTRL != 0).
  720. */
  721. ret = regmap_read(axp20x->regmap, AXP20X_CC_CTRL, &val);
  722. if (ret < 0)
  723. return ret;
  724. if (val == 0)
  725. return -ENODEV;
  726. info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
  727. if (!info)
  728. return -ENOMEM;
  729. info->pdev = pdev;
  730. info->regmap = axp20x->regmap;
  731. info->regmap_irqc = axp20x->regmap_irqc;
  732. info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME);
  733. if (info->cable.edev == NULL) {
  734. dev_dbg(&pdev->dev, "%s is not ready, probe deferred\n",
  735. AXP288_EXTCON_DEV_NAME);
  736. return -EPROBE_DEFER;
  737. }
  738. if (acpi_dev_present(USB_HOST_EXTCON_HID, NULL, -1)) {
  739. info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_NAME);
  740. if (info->otg.cable == NULL) {
  741. dev_dbg(dev, "EXTCON_USB_HOST is not ready, probe deferred\n");
  742. return -EPROBE_DEFER;
  743. }
  744. dev_info(&pdev->dev,
  745. "Using " USB_HOST_EXTCON_HID " extcon for usb-id\n");
  746. }
  747. platform_set_drvdata(pdev, info);
  748. ret = charger_init_hw_regs(info);
  749. if (ret)
  750. return ret;
  751. /* Register with power supply class */
  752. charger_cfg.drv_data = info;
  753. info->psy_usb = devm_power_supply_register(dev, &axp288_charger_desc,
  754. &charger_cfg);
  755. if (IS_ERR(info->psy_usb)) {
  756. ret = PTR_ERR(info->psy_usb);
  757. dev_err(dev, "failed to register power supply: %d\n", ret);
  758. return ret;
  759. }
  760. /* Cancel our work on cleanup, register this before the notifiers */
  761. ret = devm_add_action(dev, axp288_charger_cancel_work, info);
  762. if (ret)
  763. return ret;
  764. /* Register for extcon notification */
  765. INIT_WORK(&info->cable.work, axp288_charger_extcon_evt_worker);
  766. info->cable.nb.notifier_call = axp288_charger_handle_cable_evt;
  767. ret = devm_extcon_register_notifier_all(dev, info->cable.edev,
  768. &info->cable.nb);
  769. if (ret) {
  770. dev_err(dev, "failed to register cable extcon notifier\n");
  771. return ret;
  772. }
  773. schedule_work(&info->cable.work);
  774. /* Register for OTG notification */
  775. INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker);
  776. info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt;
  777. if (info->otg.cable) {
  778. ret = devm_extcon_register_notifier(&pdev->dev, info->otg.cable,
  779. EXTCON_USB_HOST, &info->otg.id_nb);
  780. if (ret) {
  781. dev_err(dev, "failed to register EXTCON_USB_HOST notifier\n");
  782. return ret;
  783. }
  784. schedule_work(&info->otg.work);
  785. }
  786. /* Register charger interrupts */
  787. for (i = 0; i < CHRG_INTR_END; i++) {
  788. pirq = platform_get_irq(info->pdev, i);
  789. if (pirq < 0)
  790. return pirq;
  791. info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
  792. if (info->irq[i] < 0) {
  793. dev_warn(&info->pdev->dev,
  794. "failed to get virtual interrupt=%d\n", pirq);
  795. return info->irq[i];
  796. }
  797. ret = devm_request_threaded_irq(&info->pdev->dev, info->irq[i],
  798. NULL, axp288_charger_irq_thread_handler,
  799. IRQF_ONESHOT, info->pdev->name, info);
  800. if (ret) {
  801. dev_err(&pdev->dev, "failed to request interrupt=%d\n",
  802. info->irq[i]);
  803. return ret;
  804. }
  805. }
  806. return 0;
  807. }
  808. static const struct platform_device_id axp288_charger_id_table[] = {
  809. { .name = "axp288_charger" },
  810. {},
  811. };
  812. MODULE_DEVICE_TABLE(platform, axp288_charger_id_table);
  813. static struct platform_driver axp288_charger_driver = {
  814. .probe = axp288_charger_probe,
  815. .id_table = axp288_charger_id_table,
  816. .driver = {
  817. .name = "axp288_charger",
  818. },
  819. };
  820. module_platform_driver(axp288_charger_driver);
  821. MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
  822. MODULE_DESCRIPTION("X-power AXP288 Charger Driver");
  823. MODULE_LICENSE("GPL v2");