adp5061.c 19 KB

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