adp5061.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * ADP5061 I2C Programmable Linear Battery Charger
  4. *
  5. * Copyright 2018 Analog Devices Inc.
  6. */
  7. #include <linux/init.h>
  8. #include <linux/module.h>
  9. #include <linux/slab.h>
  10. #include <linux/i2c.h>
  11. #include <linux/delay.h>
  12. #include <linux/pm.h>
  13. #include <linux/mod_devicetable.h>
  14. #include <linux/power_supply.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/of.h>
  17. #include <linux/regmap.h>
  18. /* ADP5061 registers definition */
  19. #define ADP5061_ID 0x00
  20. #define ADP5061_REV 0x01
  21. #define ADP5061_VINX_SET 0x02
  22. #define ADP5061_TERM_SET 0x03
  23. #define ADP5061_CHG_CURR 0x04
  24. #define ADP5061_VOLTAGE_TH 0x05
  25. #define ADP5061_TIMER_SET 0x06
  26. #define ADP5061_FUNC_SET_1 0x07
  27. #define ADP5061_FUNC_SET_2 0x08
  28. #define ADP5061_INT_EN 0x09
  29. #define ADP5061_INT_ACT 0x0A
  30. #define ADP5061_CHG_STATUS_1 0x0B
  31. #define ADP5061_CHG_STATUS_2 0x0C
  32. #define ADP5061_FAULT 0x0D
  33. #define ADP5061_BATTERY_SHORT 0x10
  34. #define ADP5061_IEND 0x11
  35. /* ADP5061_VINX_SET */
  36. #define ADP5061_VINX_SET_ILIM_MSK GENMASK(3, 0)
  37. #define ADP5061_VINX_SET_ILIM_MODE(x) (((x) & 0x0F) << 0)
  38. /* ADP5061_TERM_SET */
  39. #define ADP5061_TERM_SET_VTRM_MSK GENMASK(7, 2)
  40. #define ADP5061_TERM_SET_VTRM_MODE(x) (((x) & 0x3F) << 2)
  41. #define ADP5061_TERM_SET_CHG_VLIM_MSK GENMASK(1, 0)
  42. #define ADP5061_TERM_SET_CHG_VLIM_MODE(x) (((x) & 0x03) << 0)
  43. /* ADP5061_CHG_CURR */
  44. #define ADP5061_CHG_CURR_ICHG_MSK GENMASK(6, 2)
  45. #define ADP5061_CHG_CURR_ICHG_MODE(x) (((x) & 0x1F) << 2)
  46. #define ADP5061_CHG_CURR_ITRK_DEAD_MSK GENMASK(1, 0)
  47. #define ADP5061_CHG_CURR_ITRK_DEAD_MODE(x) (((x) & 0x03) << 0)
  48. /* ADP5061_VOLTAGE_TH */
  49. #define ADP5061_VOLTAGE_TH_DIS_RCH_MSK BIT(7)
  50. #define ADP5061_VOLTAGE_TH_DIS_RCH_MODE(x) (((x) & 0x01) << 7)
  51. #define ADP5061_VOLTAGE_TH_VRCH_MSK GENMASK(6, 5)
  52. #define ADP5061_VOLTAGE_TH_VRCH_MODE(x) (((x) & 0x03) << 5)
  53. #define ADP5061_VOLTAGE_TH_VTRK_DEAD_MSK GENMASK(4, 3)
  54. #define ADP5061_VOLTAGE_TH_VTRK_DEAD_MODE(x) (((x) & 0x03) << 3)
  55. #define ADP5061_VOLTAGE_TH_VWEAK_MSK GENMASK(2, 0)
  56. #define ADP5061_VOLTAGE_TH_VWEAK_MODE(x) (((x) & 0x07) << 0)
  57. /* ADP5061_CHG_STATUS_1 */
  58. #define ADP5061_CHG_STATUS_1_VIN_OV(x) (((x) >> 7) & 0x1)
  59. #define ADP5061_CHG_STATUS_1_VIN_OK(x) (((x) >> 6) & 0x1)
  60. #define ADP5061_CHG_STATUS_1_VIN_ILIM(x) (((x) >> 5) & 0x1)
  61. #define ADP5061_CHG_STATUS_1_THERM_LIM(x) (((x) >> 4) & 0x1)
  62. #define ADP5061_CHG_STATUS_1_CHDONE(x) (((x) >> 3) & 0x1)
  63. #define ADP5061_CHG_STATUS_1_CHG_STATUS(x) (((x) >> 0) & 0x7)
  64. /* ADP5061_CHG_STATUS_2 */
  65. #define ADP5061_CHG_STATUS_2_THR_STATUS(x) (((x) >> 5) & 0x7)
  66. #define ADP5061_CHG_STATUS_2_RCH_LIM_INFO(x) (((x) >> 3) & 0x1)
  67. #define ADP5061_CHG_STATUS_2_BAT_STATUS(x) (((x) >> 0) & 0x7)
  68. /* ADP5061_IEND */
  69. #define ADP5061_IEND_IEND_MSK GENMASK(7, 5)
  70. #define ADP5061_IEND_IEND_MODE(x) (((x) & 0x07) << 5)
  71. #define ADP5061_NO_BATTERY 0x01
  72. #define ADP5061_ICHG_MAX 1300 // mA
  73. enum adp5061_chg_status {
  74. ADP5061_CHG_OFF,
  75. ADP5061_CHG_TRICKLE,
  76. ADP5061_CHG_FAST_CC,
  77. ADP5061_CHG_FAST_CV,
  78. ADP5061_CHG_COMPLETE,
  79. ADP5061_CHG_LDO_MODE,
  80. ADP5061_CHG_TIMER_EXP,
  81. ADP5061_CHG_BAT_DET,
  82. };
  83. static const int adp5061_chg_type[4] = {
  84. [ADP5061_CHG_OFF] = POWER_SUPPLY_CHARGE_TYPE_NONE,
  85. [ADP5061_CHG_TRICKLE] = POWER_SUPPLY_CHARGE_TYPE_TRICKLE,
  86. [ADP5061_CHG_FAST_CC] = POWER_SUPPLY_CHARGE_TYPE_FAST,
  87. [ADP5061_CHG_FAST_CV] = POWER_SUPPLY_CHARGE_TYPE_FAST,
  88. };
  89. static const int adp5061_vweak_th[8] = {
  90. 2700, 2800, 2900, 3000, 3100, 3200, 3300, 3400,
  91. };
  92. static const int adp5061_prechg_current[4] = {
  93. 5, 10, 20, 80,
  94. };
  95. static const int adp5061_vmin[4] = {
  96. 2000, 2500, 2600, 2900,
  97. };
  98. static const int adp5061_const_chg_vmax[4] = {
  99. 3200, 3400, 3700, 3800,
  100. };
  101. static const int adp5061_const_ichg[24] = {
  102. 50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650,
  103. 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1200, 1300,
  104. };
  105. static const int adp5061_vmax[36] = {
  106. 3800, 3820, 3840, 3860, 3880, 3900, 3920, 3940, 3960, 3980,
  107. 4000, 4020, 4040, 4060, 4080, 4100, 4120, 4140, 4160, 4180,
  108. 4200, 4220, 4240, 4260, 4280, 4300, 4320, 4340, 4360, 4380,
  109. 4400, 4420, 4440, 4460, 4480, 4500,
  110. };
  111. static const int adp5061_in_current_lim[16] = {
  112. 100, 150, 200, 250, 300, 400, 500, 600, 700,
  113. 800, 900, 1000, 1200, 1500, 1800, 2100,
  114. };
  115. static const int adp5061_iend[8] = {
  116. 12500, 32500, 52500, 72500, 92500, 117500, 142500, 170000,
  117. };
  118. struct adp5061_state {
  119. struct i2c_client *client;
  120. struct regmap *regmap;
  121. struct power_supply *psy;
  122. };
  123. static int adp5061_get_array_index(const int *array, u8 size, int val)
  124. {
  125. int i;
  126. for (i = 1; i < size; i++) {
  127. if (val < array[i])
  128. break;
  129. }
  130. return i-1;
  131. }
  132. static int adp5061_get_status(struct adp5061_state *st,
  133. u8 *status1, u8 *status2)
  134. {
  135. u8 buf[2];
  136. int ret;
  137. /* CHG_STATUS1 and CHG_STATUS2 are adjacent regs */
  138. ret = regmap_bulk_read(st->regmap, ADP5061_CHG_STATUS_1,
  139. &buf[0], 2);
  140. if (ret < 0)
  141. return ret;
  142. *status1 = buf[0];
  143. *status2 = buf[1];
  144. return ret;
  145. }
  146. static int adp5061_get_input_current_limit(struct adp5061_state *st,
  147. union power_supply_propval *val)
  148. {
  149. unsigned int regval;
  150. int mode, ret;
  151. ret = regmap_read(st->regmap, ADP5061_VINX_SET, &regval);
  152. if (ret < 0)
  153. return ret;
  154. mode = ADP5061_VINX_SET_ILIM_MODE(regval);
  155. val->intval = adp5061_in_current_lim[mode] * 1000;
  156. return ret;
  157. }
  158. static int adp5061_set_input_current_limit(struct adp5061_state *st, int val)
  159. {
  160. int index;
  161. /* Convert from uA to mA */
  162. val /= 1000;
  163. index = adp5061_get_array_index(adp5061_in_current_lim,
  164. ARRAY_SIZE(adp5061_in_current_lim),
  165. val);
  166. if (index < 0)
  167. return index;
  168. return regmap_update_bits(st->regmap, ADP5061_VINX_SET,
  169. ADP5061_VINX_SET_ILIM_MSK,
  170. ADP5061_VINX_SET_ILIM_MODE(index));
  171. }
  172. static int adp5061_set_min_voltage(struct adp5061_state *st, int val)
  173. {
  174. int index;
  175. /* Convert from uV to mV */
  176. val /= 1000;
  177. index = adp5061_get_array_index(adp5061_vmin,
  178. ARRAY_SIZE(adp5061_vmin),
  179. val);
  180. if (index < 0)
  181. return index;
  182. return regmap_update_bits(st->regmap, ADP5061_VOLTAGE_TH,
  183. ADP5061_VOLTAGE_TH_VTRK_DEAD_MSK,
  184. ADP5061_VOLTAGE_TH_VTRK_DEAD_MODE(index));
  185. }
  186. static int adp5061_get_min_voltage(struct adp5061_state *st,
  187. union power_supply_propval *val)
  188. {
  189. unsigned int regval;
  190. int ret;
  191. ret = regmap_read(st->regmap, ADP5061_VOLTAGE_TH, &regval);
  192. if (ret < 0)
  193. return ret;
  194. regval = ((regval & ADP5061_VOLTAGE_TH_VTRK_DEAD_MSK) >> 3);
  195. val->intval = adp5061_vmin[regval] * 1000;
  196. return ret;
  197. }
  198. static int adp5061_get_chg_volt_lim(struct adp5061_state *st,
  199. union power_supply_propval *val)
  200. {
  201. unsigned int regval;
  202. int mode, ret;
  203. ret = regmap_read(st->regmap, ADP5061_TERM_SET, &regval);
  204. if (ret < 0)
  205. return ret;
  206. mode = ADP5061_TERM_SET_CHG_VLIM_MODE(regval);
  207. val->intval = adp5061_const_chg_vmax[mode] * 1000;
  208. return ret;
  209. }
  210. static int adp5061_get_max_voltage(struct adp5061_state *st,
  211. union power_supply_propval *val)
  212. {
  213. unsigned int regval;
  214. int ret;
  215. ret = regmap_read(st->regmap, ADP5061_TERM_SET, &regval);
  216. if (ret < 0)
  217. return ret;
  218. regval = ((regval & ADP5061_TERM_SET_VTRM_MSK) >> 2) - 0x0F;
  219. if (regval >= ARRAY_SIZE(adp5061_vmax))
  220. regval = ARRAY_SIZE(adp5061_vmax) - 1;
  221. val->intval = adp5061_vmax[regval] * 1000;
  222. return ret;
  223. }
  224. static int adp5061_set_max_voltage(struct adp5061_state *st, int val)
  225. {
  226. int vmax_index;
  227. /* Convert from uV to mV */
  228. val /= 1000;
  229. if (val > 4500)
  230. val = 4500;
  231. vmax_index = adp5061_get_array_index(adp5061_vmax,
  232. ARRAY_SIZE(adp5061_vmax), val);
  233. if (vmax_index < 0)
  234. return vmax_index;
  235. vmax_index += 0x0F;
  236. return regmap_update_bits(st->regmap, ADP5061_TERM_SET,
  237. ADP5061_TERM_SET_VTRM_MSK,
  238. ADP5061_TERM_SET_VTRM_MODE(vmax_index));
  239. }
  240. static int adp5061_set_const_chg_vmax(struct adp5061_state *st, int val)
  241. {
  242. int index;
  243. /* Convert from uV to mV */
  244. val /= 1000;
  245. index = adp5061_get_array_index(adp5061_const_chg_vmax,
  246. ARRAY_SIZE(adp5061_const_chg_vmax),
  247. val);
  248. if (index < 0)
  249. return index;
  250. return regmap_update_bits(st->regmap, ADP5061_TERM_SET,
  251. ADP5061_TERM_SET_CHG_VLIM_MSK,
  252. ADP5061_TERM_SET_CHG_VLIM_MODE(index));
  253. }
  254. static int adp5061_set_const_chg_current(struct adp5061_state *st, int val)
  255. {
  256. int index;
  257. /* Convert from uA to mA */
  258. val /= 1000;
  259. if (val > ADP5061_ICHG_MAX)
  260. val = ADP5061_ICHG_MAX;
  261. index = adp5061_get_array_index(adp5061_const_ichg,
  262. ARRAY_SIZE(adp5061_const_ichg),
  263. val);
  264. if (index < 0)
  265. return index;
  266. return regmap_update_bits(st->regmap, ADP5061_CHG_CURR,
  267. ADP5061_CHG_CURR_ICHG_MSK,
  268. ADP5061_CHG_CURR_ICHG_MODE(index));
  269. }
  270. static int adp5061_get_const_chg_current(struct adp5061_state *st,
  271. union power_supply_propval *val)
  272. {
  273. unsigned int regval;
  274. int ret;
  275. ret = regmap_read(st->regmap, ADP5061_CHG_CURR, &regval);
  276. if (ret < 0)
  277. return ret;
  278. regval = ((regval & ADP5061_CHG_CURR_ICHG_MSK) >> 2);
  279. if (regval >= ARRAY_SIZE(adp5061_const_ichg))
  280. regval = ARRAY_SIZE(adp5061_const_ichg) - 1;
  281. val->intval = adp5061_const_ichg[regval] * 1000;
  282. return ret;
  283. }
  284. static int adp5061_get_prechg_current(struct adp5061_state *st,
  285. union power_supply_propval *val)
  286. {
  287. unsigned int regval;
  288. int ret;
  289. ret = regmap_read(st->regmap, ADP5061_CHG_CURR, &regval);
  290. if (ret < 0)
  291. return ret;
  292. regval &= ADP5061_CHG_CURR_ITRK_DEAD_MSK;
  293. val->intval = adp5061_prechg_current[regval] * 1000;
  294. return ret;
  295. }
  296. static int adp5061_set_prechg_current(struct adp5061_state *st, int val)
  297. {
  298. int index;
  299. /* Convert from uA to mA */
  300. val /= 1000;
  301. index = adp5061_get_array_index(adp5061_prechg_current,
  302. ARRAY_SIZE(adp5061_prechg_current),
  303. val);
  304. if (index < 0)
  305. return index;
  306. return regmap_update_bits(st->regmap, ADP5061_CHG_CURR,
  307. ADP5061_CHG_CURR_ITRK_DEAD_MSK,
  308. ADP5061_CHG_CURR_ITRK_DEAD_MODE(index));
  309. }
  310. static int adp5061_get_vweak_th(struct adp5061_state *st,
  311. union power_supply_propval *val)
  312. {
  313. unsigned int regval;
  314. int ret;
  315. ret = regmap_read(st->regmap, ADP5061_VOLTAGE_TH, &regval);
  316. if (ret < 0)
  317. return ret;
  318. regval &= ADP5061_VOLTAGE_TH_VWEAK_MSK;
  319. val->intval = adp5061_vweak_th[regval] * 1000;
  320. return ret;
  321. }
  322. static int adp5061_set_vweak_th(struct adp5061_state *st, int val)
  323. {
  324. int index;
  325. /* Convert from uV to mV */
  326. val /= 1000;
  327. index = adp5061_get_array_index(adp5061_vweak_th,
  328. ARRAY_SIZE(adp5061_vweak_th),
  329. val);
  330. if (index < 0)
  331. return index;
  332. return regmap_update_bits(st->regmap, ADP5061_VOLTAGE_TH,
  333. ADP5061_VOLTAGE_TH_VWEAK_MSK,
  334. ADP5061_VOLTAGE_TH_VWEAK_MODE(index));
  335. }
  336. static int adp5061_get_chg_type(struct adp5061_state *st,
  337. union power_supply_propval *val)
  338. {
  339. u8 status1, status2;
  340. int chg_type, ret;
  341. ret = adp5061_get_status(st, &status1, &status2);
  342. if (ret < 0)
  343. return ret;
  344. chg_type = adp5061_chg_type[ADP5061_CHG_STATUS_1_CHG_STATUS(status1)];
  345. if (chg_type > ADP5061_CHG_FAST_CV)
  346. val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
  347. else
  348. val->intval = chg_type;
  349. return ret;
  350. }
  351. static int adp5061_get_charger_status(struct adp5061_state *st,
  352. union power_supply_propval *val)
  353. {
  354. u8 status1, status2;
  355. int ret;
  356. ret = adp5061_get_status(st, &status1, &status2);
  357. if (ret < 0)
  358. return ret;
  359. switch (ADP5061_CHG_STATUS_1_CHG_STATUS(status1)) {
  360. case ADP5061_CHG_OFF:
  361. val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
  362. break;
  363. case ADP5061_CHG_TRICKLE:
  364. case ADP5061_CHG_FAST_CC:
  365. case ADP5061_CHG_FAST_CV:
  366. val->intval = POWER_SUPPLY_STATUS_CHARGING;
  367. break;
  368. case ADP5061_CHG_COMPLETE:
  369. val->intval = POWER_SUPPLY_STATUS_FULL;
  370. break;
  371. case ADP5061_CHG_TIMER_EXP:
  372. /* The battery must be discharging if there is a charge fault */
  373. val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
  374. break;
  375. default:
  376. val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
  377. }
  378. return ret;
  379. }
  380. static int adp5061_get_battery_status(struct adp5061_state *st,
  381. union power_supply_propval *val)
  382. {
  383. u8 status1, status2;
  384. int ret;
  385. ret = adp5061_get_status(st, &status1, &status2);
  386. if (ret < 0)
  387. return ret;
  388. switch (ADP5061_CHG_STATUS_2_BAT_STATUS(status2)) {
  389. case 0x0: /* Battery monitor off */
  390. case 0x1: /* No battery */
  391. val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
  392. break;
  393. case 0x2: /* VBAT < VTRK */
  394. val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
  395. break;
  396. case 0x3: /* VTRK < VBAT_SNS < VWEAK */
  397. val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
  398. break;
  399. case 0x4: /* VBAT_SNS > VWEAK */
  400. val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
  401. break;
  402. }
  403. return ret;
  404. }
  405. static int adp5061_get_termination_current(struct adp5061_state *st,
  406. union power_supply_propval *val)
  407. {
  408. unsigned int regval;
  409. int ret;
  410. ret = regmap_read(st->regmap, ADP5061_IEND, &regval);
  411. if (ret < 0)
  412. return ret;
  413. regval = (regval & ADP5061_IEND_IEND_MSK) >> 5;
  414. val->intval = adp5061_iend[regval];
  415. return ret;
  416. }
  417. static int adp5061_set_termination_current(struct adp5061_state *st, int val)
  418. {
  419. int index;
  420. index = adp5061_get_array_index(adp5061_iend,
  421. ARRAY_SIZE(adp5061_iend),
  422. val);
  423. if (index < 0)
  424. return index;
  425. return regmap_update_bits(st->regmap, ADP5061_IEND,
  426. ADP5061_IEND_IEND_MSK,
  427. ADP5061_IEND_IEND_MODE(index));
  428. }
  429. static int adp5061_get_property(struct power_supply *psy,
  430. enum power_supply_property psp,
  431. union power_supply_propval *val)
  432. {
  433. struct adp5061_state *st = power_supply_get_drvdata(psy);
  434. u8 status1, status2;
  435. int mode, ret;
  436. switch (psp) {
  437. case POWER_SUPPLY_PROP_PRESENT:
  438. ret = adp5061_get_status(st, &status1, &status2);
  439. if (ret < 0)
  440. return ret;
  441. mode = ADP5061_CHG_STATUS_2_BAT_STATUS(status2);
  442. if (mode == ADP5061_NO_BATTERY)
  443. val->intval = 0;
  444. else
  445. val->intval = 1;
  446. break;
  447. case POWER_SUPPLY_PROP_CHARGE_TYPE:
  448. return adp5061_get_chg_type(st, val);
  449. case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
  450. /* This property is used to indicate the input current
  451. * limit into VINx (ILIM)
  452. */
  453. return adp5061_get_input_current_limit(st, val);
  454. case POWER_SUPPLY_PROP_VOLTAGE_MAX:
  455. /* This property is used to indicate the termination
  456. * voltage (VTRM)
  457. */
  458. return adp5061_get_max_voltage(st, val);
  459. case POWER_SUPPLY_PROP_VOLTAGE_MIN:
  460. /*
  461. * This property is used to indicate the trickle to fast
  462. * charge threshold (VTRK_DEAD)
  463. */
  464. return adp5061_get_min_voltage(st, val);
  465. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
  466. /* This property is used to indicate the charging
  467. * voltage limit (CHG_VLIM)
  468. */
  469. return adp5061_get_chg_volt_lim(st, val);
  470. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
  471. /*
  472. * This property is used to indicate the value of the constant
  473. * current charge (ICHG)
  474. */
  475. return adp5061_get_const_chg_current(st, val);
  476. case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
  477. /*
  478. * This property is used to indicate the value of the trickle
  479. * and weak charge currents (ITRK_DEAD)
  480. */
  481. return adp5061_get_prechg_current(st, val);
  482. case POWER_SUPPLY_PROP_VOLTAGE_AVG:
  483. /*
  484. * This property is used to set the VWEAK threshold
  485. * bellow this value, weak charge mode is entered
  486. * above this value, fast chargerge mode is entered
  487. */
  488. return adp5061_get_vweak_th(st, val);
  489. case POWER_SUPPLY_PROP_STATUS:
  490. /*
  491. * Indicate the charger status in relation to power
  492. * supply status property
  493. */
  494. return adp5061_get_charger_status(st, val);
  495. case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
  496. /*
  497. * Indicate the battery status in relation to power
  498. * supply capacity level property
  499. */
  500. return adp5061_get_battery_status(st, val);
  501. case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
  502. /* Indicate the values of the termination current */
  503. return adp5061_get_termination_current(st, val);
  504. default:
  505. return -EINVAL;
  506. }
  507. return 0;
  508. }
  509. static int adp5061_set_property(struct power_supply *psy,
  510. enum power_supply_property psp,
  511. const union power_supply_propval *val)
  512. {
  513. struct adp5061_state *st = power_supply_get_drvdata(psy);
  514. switch (psp) {
  515. case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
  516. return adp5061_set_input_current_limit(st, val->intval);
  517. case POWER_SUPPLY_PROP_VOLTAGE_MAX:
  518. return adp5061_set_max_voltage(st, val->intval);
  519. case POWER_SUPPLY_PROP_VOLTAGE_MIN:
  520. return adp5061_set_min_voltage(st, val->intval);
  521. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
  522. return adp5061_set_const_chg_vmax(st, val->intval);
  523. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
  524. return adp5061_set_const_chg_current(st, val->intval);
  525. case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
  526. return adp5061_set_prechg_current(st, val->intval);
  527. case POWER_SUPPLY_PROP_VOLTAGE_AVG:
  528. return adp5061_set_vweak_th(st, val->intval);
  529. case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
  530. return adp5061_set_termination_current(st, val->intval);
  531. default:
  532. return -EINVAL;
  533. }
  534. return 0;
  535. }
  536. static int adp5061_prop_writeable(struct power_supply *psy,
  537. enum power_supply_property psp)
  538. {
  539. switch (psp) {
  540. case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
  541. case POWER_SUPPLY_PROP_VOLTAGE_MAX:
  542. case POWER_SUPPLY_PROP_VOLTAGE_MIN:
  543. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
  544. case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
  545. case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
  546. case POWER_SUPPLY_PROP_VOLTAGE_AVG:
  547. case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
  548. return 1;
  549. default:
  550. return 0;
  551. }
  552. }
  553. static enum power_supply_property adp5061_props[] = {
  554. POWER_SUPPLY_PROP_PRESENT,
  555. POWER_SUPPLY_PROP_CHARGE_TYPE,
  556. POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
  557. POWER_SUPPLY_PROP_VOLTAGE_MAX,
  558. POWER_SUPPLY_PROP_VOLTAGE_MIN,
  559. POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
  560. POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
  561. POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
  562. POWER_SUPPLY_PROP_VOLTAGE_AVG,
  563. POWER_SUPPLY_PROP_STATUS,
  564. POWER_SUPPLY_PROP_CAPACITY_LEVEL,
  565. POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
  566. };
  567. static const struct regmap_config adp5061_regmap_config = {
  568. .reg_bits = 8,
  569. .val_bits = 8,
  570. };
  571. static const struct power_supply_desc adp5061_desc = {
  572. .name = "adp5061",
  573. .type = POWER_SUPPLY_TYPE_USB,
  574. .get_property = adp5061_get_property,
  575. .set_property = adp5061_set_property,
  576. .property_is_writeable = adp5061_prop_writeable,
  577. .properties = adp5061_props,
  578. .num_properties = ARRAY_SIZE(adp5061_props),
  579. };
  580. static int adp5061_probe(struct i2c_client *client,
  581. const struct i2c_device_id *id)
  582. {
  583. struct power_supply_config psy_cfg = {};
  584. struct adp5061_state *st;
  585. st = devm_kzalloc(&client->dev, sizeof(*st), GFP_KERNEL);
  586. if (!st)
  587. return -ENOMEM;
  588. st->client = client;
  589. st->regmap = devm_regmap_init_i2c(client,
  590. &adp5061_regmap_config);
  591. if (IS_ERR(st->regmap)) {
  592. dev_err(&client->dev, "Failed to initialize register map\n");
  593. return -EINVAL;
  594. }
  595. i2c_set_clientdata(client, st);
  596. psy_cfg.drv_data = st;
  597. st->psy = devm_power_supply_register(&client->dev,
  598. &adp5061_desc,
  599. &psy_cfg);
  600. if (IS_ERR(st->psy)) {
  601. dev_err(&client->dev, "Failed to register power supply\n");
  602. return PTR_ERR(st->psy);
  603. }
  604. return 0;
  605. }
  606. static const struct i2c_device_id adp5061_id[] = {
  607. { "adp5061", 0},
  608. { }
  609. };
  610. MODULE_DEVICE_TABLE(i2c, adp5061_id);
  611. static struct i2c_driver adp5061_driver = {
  612. .driver = {
  613. .name = KBUILD_MODNAME,
  614. },
  615. .probe = adp5061_probe,
  616. .id_table = adp5061_id,
  617. };
  618. module_i2c_driver(adp5061_driver);
  619. MODULE_DESCRIPTION("Analog Devices adp5061 battery charger driver");
  620. MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
  621. MODULE_LICENSE("GPL v2");