1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (C) 2018 Spreadtrum Communications Inc. |
3 | |
4 | #include <linux/gpio/consumer.h> |
5 | #include <linux/iio/consumer.h> |
6 | #include <linux/interrupt.h> |
7 | #include <linux/kernel.h> |
8 | #include <linux/math64.h> |
9 | #include <linux/module.h> |
10 | #include <linux/nvmem-consumer.h> |
11 | #include <linux/of.h> |
12 | #include <linux/platform_device.h> |
13 | #include <linux/power_supply.h> |
14 | #include <linux/regmap.h> |
15 | #include <linux/slab.h> |
16 | |
17 | /* PMIC global control registers definition */ |
18 | #define SC27XX_MODULE_EN0 0xc08 |
19 | #define SC27XX_CLK_EN0 0xc18 |
20 | #define SC27XX_FGU_EN BIT(7) |
21 | #define SC27XX_FGU_RTC_EN BIT(6) |
22 | |
23 | /* FGU registers definition */ |
24 | #define SC27XX_FGU_START 0x0 |
25 | #define SC27XX_FGU_CONFIG 0x4 |
26 | #define SC27XX_FGU_ADC_CONFIG 0x8 |
27 | #define SC27XX_FGU_STATUS 0xc |
28 | #define SC27XX_FGU_INT_EN 0x10 |
29 | #define SC27XX_FGU_INT_CLR 0x14 |
30 | #define SC27XX_FGU_INT_STS 0x1c |
31 | #define SC27XX_FGU_VOLTAGE 0x20 |
32 | #define SC27XX_FGU_OCV 0x24 |
33 | #define SC27XX_FGU_POCV 0x28 |
34 | #define SC27XX_FGU_CURRENT 0x2c |
35 | #define SC27XX_FGU_LOW_OVERLOAD 0x34 |
36 | #define SC27XX_FGU_CLBCNT_SETH 0x50 |
37 | #define SC27XX_FGU_CLBCNT_SETL 0x54 |
38 | #define SC27XX_FGU_CLBCNT_DELTH 0x58 |
39 | #define SC27XX_FGU_CLBCNT_DELTL 0x5c |
40 | #define SC27XX_FGU_CLBCNT_VALH 0x68 |
41 | #define SC27XX_FGU_CLBCNT_VALL 0x6c |
42 | #define SC27XX_FGU_CLBCNT_QMAXL 0x74 |
43 | #define SC27XX_FGU_USER_AREA_SET 0xa0 |
44 | #define SC27XX_FGU_USER_AREA_CLEAR 0xa4 |
45 | #define SC27XX_FGU_USER_AREA_STATUS 0xa8 |
46 | #define SC27XX_FGU_VOLTAGE_BUF 0xd0 |
47 | #define SC27XX_FGU_CURRENT_BUF 0xf0 |
48 | |
49 | #define SC27XX_WRITE_SELCLB_EN BIT(0) |
50 | #define SC27XX_FGU_CLBCNT_MASK GENMASK(15, 0) |
51 | #define SC27XX_FGU_CLBCNT_SHIFT 16 |
52 | #define SC27XX_FGU_LOW_OVERLOAD_MASK GENMASK(12, 0) |
53 | |
54 | #define SC27XX_FGU_INT_MASK GENMASK(9, 0) |
55 | #define SC27XX_FGU_LOW_OVERLOAD_INT BIT(0) |
56 | #define SC27XX_FGU_CLBCNT_DELTA_INT BIT(2) |
57 | |
58 | #define SC27XX_FGU_MODE_AREA_MASK GENMASK(15, 12) |
59 | #define SC27XX_FGU_CAP_AREA_MASK GENMASK(11, 0) |
60 | #define SC27XX_FGU_MODE_AREA_SHIFT 12 |
61 | |
62 | #define SC27XX_FGU_FIRST_POWERTON GENMASK(3, 0) |
63 | #define SC27XX_FGU_DEFAULT_CAP GENMASK(11, 0) |
64 | #define SC27XX_FGU_NORMAIL_POWERTON 0x5 |
65 | |
66 | #define SC27XX_FGU_CUR_BASIC_ADC 8192 |
67 | #define SC27XX_FGU_SAMPLE_HZ 2 |
68 | /* micro Ohms */ |
69 | #define SC27XX_FGU_IDEAL_RESISTANCE 20000 |
70 | |
71 | /* |
72 | * struct sc27xx_fgu_data: describe the FGU device |
73 | * @regmap: regmap for register access |
74 | * @dev: platform device |
75 | * @battery: battery power supply |
76 | * @base: the base offset for the controller |
77 | * @lock: protect the structure |
78 | * @gpiod: GPIO for battery detection |
79 | * @channel: IIO channel to get battery temperature |
80 | * @charge_chan: IIO channel to get charge voltage |
81 | * @internal_resist: the battery internal resistance in mOhm |
82 | * @total_cap: the total capacity of the battery in mAh |
83 | * @init_cap: the initial capacity of the battery in mAh |
84 | * @alarm_cap: the alarm capacity |
85 | * @init_clbcnt: the initial coulomb counter |
86 | * @max_volt: the maximum constant input voltage in millivolt |
87 | * @min_volt: the minimum drained battery voltage in microvolt |
88 | * @boot_volt: the voltage measured during boot in microvolt |
89 | * @table_len: the capacity table length |
90 | * @resist_table_len: the resistance table length |
91 | * @cur_1000ma_adc: ADC value corresponding to 1000 mA |
92 | * @vol_1000mv_adc: ADC value corresponding to 1000 mV |
93 | * @calib_resist: the real resistance of coulomb counter chip in uOhm |
94 | * @cap_table: capacity table with corresponding ocv |
95 | * @resist_table: resistance percent table with corresponding temperature |
96 | */ |
97 | struct sc27xx_fgu_data { |
98 | struct regmap *regmap; |
99 | struct device *dev; |
100 | struct power_supply *battery; |
101 | u32 base; |
102 | struct mutex lock; |
103 | struct gpio_desc *gpiod; |
104 | struct iio_channel *channel; |
105 | struct iio_channel *charge_chan; |
106 | bool bat_present; |
107 | int internal_resist; |
108 | int total_cap; |
109 | int init_cap; |
110 | int alarm_cap; |
111 | int init_clbcnt; |
112 | int max_volt; |
113 | int min_volt; |
114 | int boot_volt; |
115 | int table_len; |
116 | int resist_table_len; |
117 | int cur_1000ma_adc; |
118 | int vol_1000mv_adc; |
119 | int calib_resist; |
120 | struct power_supply_battery_ocv_table *cap_table; |
121 | struct power_supply_resistance_temp_table *resist_table; |
122 | }; |
123 | |
124 | static int sc27xx_fgu_cap_to_clbcnt(struct sc27xx_fgu_data *data, int capacity); |
125 | static void sc27xx_fgu_capacity_calibration(struct sc27xx_fgu_data *data, |
126 | int cap, bool int_mode); |
127 | static void sc27xx_fgu_adjust_cap(struct sc27xx_fgu_data *data, int cap); |
128 | static int sc27xx_fgu_get_temp(struct sc27xx_fgu_data *data, int *temp); |
129 | |
130 | static const char * const sc27xx_charger_supply_name[] = { |
131 | "sc2731_charger" , |
132 | "sc2720_charger" , |
133 | "sc2721_charger" , |
134 | "sc2723_charger" , |
135 | }; |
136 | |
137 | static int sc27xx_fgu_adc_to_current(struct sc27xx_fgu_data *data, s64 adc) |
138 | { |
139 | return DIV_S64_ROUND_CLOSEST(adc * 1000, data->cur_1000ma_adc); |
140 | } |
141 | |
142 | static int sc27xx_fgu_adc_to_voltage(struct sc27xx_fgu_data *data, s64 adc) |
143 | { |
144 | return DIV_S64_ROUND_CLOSEST(adc * 1000, data->vol_1000mv_adc); |
145 | } |
146 | |
147 | static int sc27xx_fgu_voltage_to_adc(struct sc27xx_fgu_data *data, int vol) |
148 | { |
149 | return DIV_ROUND_CLOSEST(vol * data->vol_1000mv_adc, 1000); |
150 | } |
151 | |
152 | static bool sc27xx_fgu_is_first_poweron(struct sc27xx_fgu_data *data) |
153 | { |
154 | int ret, status, cap, mode; |
155 | |
156 | ret = regmap_read(map: data->regmap, |
157 | reg: data->base + SC27XX_FGU_USER_AREA_STATUS, val: &status); |
158 | if (ret) |
159 | return false; |
160 | |
161 | /* |
162 | * We use low 4 bits to save the last battery capacity and high 12 bits |
163 | * to save the system boot mode. |
164 | */ |
165 | mode = (status & SC27XX_FGU_MODE_AREA_MASK) >> SC27XX_FGU_MODE_AREA_SHIFT; |
166 | cap = status & SC27XX_FGU_CAP_AREA_MASK; |
167 | |
168 | /* |
169 | * When FGU has been powered down, the user area registers became |
170 | * default value (0xffff), which can be used to valid if the system is |
171 | * first power on or not. |
172 | */ |
173 | if (mode == SC27XX_FGU_FIRST_POWERTON || cap == SC27XX_FGU_DEFAULT_CAP) |
174 | return true; |
175 | |
176 | return false; |
177 | } |
178 | |
179 | static int sc27xx_fgu_save_boot_mode(struct sc27xx_fgu_data *data, |
180 | int boot_mode) |
181 | { |
182 | int ret; |
183 | |
184 | ret = regmap_update_bits(map: data->regmap, |
185 | reg: data->base + SC27XX_FGU_USER_AREA_CLEAR, |
186 | SC27XX_FGU_MODE_AREA_MASK, |
187 | SC27XX_FGU_MODE_AREA_MASK); |
188 | if (ret) |
189 | return ret; |
190 | |
191 | /* |
192 | * Since the user area registers are put on power always-on region, |
193 | * then these registers changing time will be a little long. Thus |
194 | * here we should delay 200us to wait until values are updated |
195 | * successfully according to the datasheet. |
196 | */ |
197 | udelay(200); |
198 | |
199 | ret = regmap_update_bits(map: data->regmap, |
200 | reg: data->base + SC27XX_FGU_USER_AREA_SET, |
201 | SC27XX_FGU_MODE_AREA_MASK, |
202 | val: boot_mode << SC27XX_FGU_MODE_AREA_SHIFT); |
203 | if (ret) |
204 | return ret; |
205 | |
206 | /* |
207 | * Since the user area registers are put on power always-on region, |
208 | * then these registers changing time will be a little long. Thus |
209 | * here we should delay 200us to wait until values are updated |
210 | * successfully according to the datasheet. |
211 | */ |
212 | udelay(200); |
213 | |
214 | /* |
215 | * According to the datasheet, we should set the USER_AREA_CLEAR to 0 to |
216 | * make the user area data available, otherwise we can not save the user |
217 | * area data. |
218 | */ |
219 | return regmap_update_bits(map: data->regmap, |
220 | reg: data->base + SC27XX_FGU_USER_AREA_CLEAR, |
221 | SC27XX_FGU_MODE_AREA_MASK, val: 0); |
222 | } |
223 | |
224 | static int sc27xx_fgu_save_last_cap(struct sc27xx_fgu_data *data, int cap) |
225 | { |
226 | int ret; |
227 | |
228 | ret = regmap_update_bits(map: data->regmap, |
229 | reg: data->base + SC27XX_FGU_USER_AREA_CLEAR, |
230 | SC27XX_FGU_CAP_AREA_MASK, |
231 | SC27XX_FGU_CAP_AREA_MASK); |
232 | if (ret) |
233 | return ret; |
234 | |
235 | /* |
236 | * Since the user area registers are put on power always-on region, |
237 | * then these registers changing time will be a little long. Thus |
238 | * here we should delay 200us to wait until values are updated |
239 | * successfully according to the datasheet. |
240 | */ |
241 | udelay(200); |
242 | |
243 | ret = regmap_update_bits(map: data->regmap, |
244 | reg: data->base + SC27XX_FGU_USER_AREA_SET, |
245 | SC27XX_FGU_CAP_AREA_MASK, val: cap); |
246 | if (ret) |
247 | return ret; |
248 | |
249 | /* |
250 | * Since the user area registers are put on power always-on region, |
251 | * then these registers changing time will be a little long. Thus |
252 | * here we should delay 200us to wait until values are updated |
253 | * successfully according to the datasheet. |
254 | */ |
255 | udelay(200); |
256 | |
257 | /* |
258 | * According to the datasheet, we should set the USER_AREA_CLEAR to 0 to |
259 | * make the user area data available, otherwise we can not save the user |
260 | * area data. |
261 | */ |
262 | return regmap_update_bits(map: data->regmap, |
263 | reg: data->base + SC27XX_FGU_USER_AREA_CLEAR, |
264 | SC27XX_FGU_CAP_AREA_MASK, val: 0); |
265 | } |
266 | |
267 | static int sc27xx_fgu_read_last_cap(struct sc27xx_fgu_data *data, int *cap) |
268 | { |
269 | int ret, value; |
270 | |
271 | ret = regmap_read(map: data->regmap, |
272 | reg: data->base + SC27XX_FGU_USER_AREA_STATUS, val: &value); |
273 | if (ret) |
274 | return ret; |
275 | |
276 | *cap = value & SC27XX_FGU_CAP_AREA_MASK; |
277 | return 0; |
278 | } |
279 | |
280 | /* |
281 | * When system boots on, we can not read battery capacity from coulomb |
282 | * registers, since now the coulomb registers are invalid. So we should |
283 | * calculate the battery open circuit voltage, and get current battery |
284 | * capacity according to the capacity table. |
285 | */ |
286 | static int sc27xx_fgu_get_boot_capacity(struct sc27xx_fgu_data *data, int *cap) |
287 | { |
288 | int volt, cur, oci, ocv, ret; |
289 | bool is_first_poweron = sc27xx_fgu_is_first_poweron(data); |
290 | |
291 | /* |
292 | * If system is not the first power on, we should use the last saved |
293 | * battery capacity as the initial battery capacity. Otherwise we should |
294 | * re-calculate the initial battery capacity. |
295 | */ |
296 | if (!is_first_poweron) { |
297 | ret = sc27xx_fgu_read_last_cap(data, cap); |
298 | if (ret) |
299 | return ret; |
300 | |
301 | return sc27xx_fgu_save_boot_mode(data, SC27XX_FGU_NORMAIL_POWERTON); |
302 | } |
303 | |
304 | /* |
305 | * After system booting on, the SC27XX_FGU_CLBCNT_QMAXL register saved |
306 | * the first sampled open circuit current. |
307 | */ |
308 | ret = regmap_read(map: data->regmap, reg: data->base + SC27XX_FGU_CLBCNT_QMAXL, |
309 | val: &cur); |
310 | if (ret) |
311 | return ret; |
312 | |
313 | cur <<= 1; |
314 | oci = sc27xx_fgu_adc_to_current(data, adc: cur - SC27XX_FGU_CUR_BASIC_ADC); |
315 | |
316 | /* |
317 | * Should get the OCV from SC27XX_FGU_POCV register at the system |
318 | * beginning. It is ADC values reading from registers which need to |
319 | * convert the corresponding voltage. |
320 | */ |
321 | ret = regmap_read(map: data->regmap, reg: data->base + SC27XX_FGU_POCV, val: &volt); |
322 | if (ret) |
323 | return ret; |
324 | |
325 | volt = sc27xx_fgu_adc_to_voltage(data, adc: volt); |
326 | ocv = volt * 1000 - oci * data->internal_resist; |
327 | data->boot_volt = ocv; |
328 | |
329 | /* |
330 | * Parse the capacity table to look up the correct capacity percent |
331 | * according to current battery's corresponding OCV values. |
332 | */ |
333 | *cap = power_supply_ocv2cap_simple(table: data->cap_table, table_len: data->table_len, |
334 | ocv); |
335 | |
336 | ret = sc27xx_fgu_save_last_cap(data, cap: *cap); |
337 | if (ret) |
338 | return ret; |
339 | |
340 | return sc27xx_fgu_save_boot_mode(data, SC27XX_FGU_NORMAIL_POWERTON); |
341 | } |
342 | |
343 | static int sc27xx_fgu_set_clbcnt(struct sc27xx_fgu_data *data, int clbcnt) |
344 | { |
345 | int ret; |
346 | |
347 | ret = regmap_update_bits(map: data->regmap, |
348 | reg: data->base + SC27XX_FGU_CLBCNT_SETL, |
349 | SC27XX_FGU_CLBCNT_MASK, val: clbcnt); |
350 | if (ret) |
351 | return ret; |
352 | |
353 | ret = regmap_update_bits(map: data->regmap, |
354 | reg: data->base + SC27XX_FGU_CLBCNT_SETH, |
355 | SC27XX_FGU_CLBCNT_MASK, |
356 | val: clbcnt >> SC27XX_FGU_CLBCNT_SHIFT); |
357 | if (ret) |
358 | return ret; |
359 | |
360 | return regmap_update_bits(map: data->regmap, reg: data->base + SC27XX_FGU_START, |
361 | SC27XX_WRITE_SELCLB_EN, |
362 | SC27XX_WRITE_SELCLB_EN); |
363 | } |
364 | |
365 | static int sc27xx_fgu_get_clbcnt(struct sc27xx_fgu_data *data, int *clb_cnt) |
366 | { |
367 | int ccl, cch, ret; |
368 | |
369 | ret = regmap_read(map: data->regmap, reg: data->base + SC27XX_FGU_CLBCNT_VALL, |
370 | val: &ccl); |
371 | if (ret) |
372 | return ret; |
373 | |
374 | ret = regmap_read(map: data->regmap, reg: data->base + SC27XX_FGU_CLBCNT_VALH, |
375 | val: &cch); |
376 | if (ret) |
377 | return ret; |
378 | |
379 | *clb_cnt = ccl & SC27XX_FGU_CLBCNT_MASK; |
380 | *clb_cnt |= (cch & SC27XX_FGU_CLBCNT_MASK) << SC27XX_FGU_CLBCNT_SHIFT; |
381 | |
382 | return 0; |
383 | } |
384 | |
385 | static int sc27xx_fgu_get_vol_now(struct sc27xx_fgu_data *data, int *val) |
386 | { |
387 | int ret; |
388 | u32 vol; |
389 | |
390 | ret = regmap_read(map: data->regmap, reg: data->base + SC27XX_FGU_VOLTAGE_BUF, |
391 | val: &vol); |
392 | if (ret) |
393 | return ret; |
394 | |
395 | /* |
396 | * It is ADC values reading from registers which need to convert to |
397 | * corresponding voltage values. |
398 | */ |
399 | *val = sc27xx_fgu_adc_to_voltage(data, adc: vol); |
400 | |
401 | return 0; |
402 | } |
403 | |
404 | static int sc27xx_fgu_get_cur_now(struct sc27xx_fgu_data *data, int *val) |
405 | { |
406 | int ret; |
407 | u32 cur; |
408 | |
409 | ret = regmap_read(map: data->regmap, reg: data->base + SC27XX_FGU_CURRENT_BUF, |
410 | val: &cur); |
411 | if (ret) |
412 | return ret; |
413 | |
414 | /* |
415 | * It is ADC values reading from registers which need to convert to |
416 | * corresponding current values. |
417 | */ |
418 | *val = sc27xx_fgu_adc_to_current(data, adc: cur - SC27XX_FGU_CUR_BASIC_ADC); |
419 | |
420 | return 0; |
421 | } |
422 | |
423 | static int sc27xx_fgu_get_capacity(struct sc27xx_fgu_data *data, int *cap) |
424 | { |
425 | int ret, cur_clbcnt, delta_clbcnt, delta_cap, temp; |
426 | |
427 | /* Get current coulomb counters firstly */ |
428 | ret = sc27xx_fgu_get_clbcnt(data, clb_cnt: &cur_clbcnt); |
429 | if (ret) |
430 | return ret; |
431 | |
432 | delta_clbcnt = cur_clbcnt - data->init_clbcnt; |
433 | |
434 | /* |
435 | * Convert coulomb counter to delta capacity (mAh), and set multiplier |
436 | * as 10 to improve the precision. |
437 | */ |
438 | temp = DIV_ROUND_CLOSEST(delta_clbcnt * 10, 36 * SC27XX_FGU_SAMPLE_HZ); |
439 | temp = sc27xx_fgu_adc_to_current(data, adc: temp / 1000); |
440 | |
441 | /* |
442 | * Convert to capacity percent of the battery total capacity, |
443 | * and multiplier is 100 too. |
444 | */ |
445 | delta_cap = DIV_ROUND_CLOSEST(temp * 100, data->total_cap); |
446 | *cap = delta_cap + data->init_cap; |
447 | |
448 | /* Calibrate the battery capacity in a normal range. */ |
449 | sc27xx_fgu_capacity_calibration(data, cap: *cap, int_mode: false); |
450 | |
451 | return 0; |
452 | } |
453 | |
454 | static int sc27xx_fgu_get_vbat_vol(struct sc27xx_fgu_data *data, int *val) |
455 | { |
456 | int ret, vol; |
457 | |
458 | ret = regmap_read(map: data->regmap, reg: data->base + SC27XX_FGU_VOLTAGE, val: &vol); |
459 | if (ret) |
460 | return ret; |
461 | |
462 | /* |
463 | * It is ADC values reading from registers which need to convert to |
464 | * corresponding voltage values. |
465 | */ |
466 | *val = sc27xx_fgu_adc_to_voltage(data, adc: vol); |
467 | |
468 | return 0; |
469 | } |
470 | |
471 | static int sc27xx_fgu_get_current(struct sc27xx_fgu_data *data, int *val) |
472 | { |
473 | int ret, cur; |
474 | |
475 | ret = regmap_read(map: data->regmap, reg: data->base + SC27XX_FGU_CURRENT, val: &cur); |
476 | if (ret) |
477 | return ret; |
478 | |
479 | /* |
480 | * It is ADC values reading from registers which need to convert to |
481 | * corresponding current values. |
482 | */ |
483 | *val = sc27xx_fgu_adc_to_current(data, adc: cur - SC27XX_FGU_CUR_BASIC_ADC); |
484 | |
485 | return 0; |
486 | } |
487 | |
488 | static int sc27xx_fgu_get_vbat_ocv(struct sc27xx_fgu_data *data, int *val) |
489 | { |
490 | int vol, cur, ret, temp, resistance; |
491 | |
492 | ret = sc27xx_fgu_get_vbat_vol(data, val: &vol); |
493 | if (ret) |
494 | return ret; |
495 | |
496 | ret = sc27xx_fgu_get_current(data, val: &cur); |
497 | if (ret) |
498 | return ret; |
499 | |
500 | resistance = data->internal_resist; |
501 | if (data->resist_table_len > 0) { |
502 | ret = sc27xx_fgu_get_temp(data, temp: &temp); |
503 | if (ret) |
504 | return ret; |
505 | |
506 | resistance = power_supply_temp2resist_simple(table: data->resist_table, |
507 | table_len: data->resist_table_len, temp); |
508 | resistance = data->internal_resist * resistance / 100; |
509 | } |
510 | |
511 | /* Return the battery OCV in micro volts. */ |
512 | *val = vol * 1000 - cur * resistance; |
513 | |
514 | return 0; |
515 | } |
516 | |
517 | static int sc27xx_fgu_get_charge_vol(struct sc27xx_fgu_data *data, int *val) |
518 | { |
519 | int ret, vol; |
520 | |
521 | ret = iio_read_channel_processed(chan: data->charge_chan, val: &vol); |
522 | if (ret < 0) |
523 | return ret; |
524 | |
525 | *val = vol * 1000; |
526 | return 0; |
527 | } |
528 | |
529 | static int sc27xx_fgu_get_temp(struct sc27xx_fgu_data *data, int *temp) |
530 | { |
531 | return iio_read_channel_processed(chan: data->channel, val: temp); |
532 | } |
533 | |
534 | static int sc27xx_fgu_get_health(struct sc27xx_fgu_data *data, int *health) |
535 | { |
536 | int ret, vol; |
537 | |
538 | ret = sc27xx_fgu_get_vbat_vol(data, val: &vol); |
539 | if (ret) |
540 | return ret; |
541 | |
542 | if (vol > data->max_volt) |
543 | *health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; |
544 | else |
545 | *health = POWER_SUPPLY_HEALTH_GOOD; |
546 | |
547 | return 0; |
548 | } |
549 | |
550 | static int sc27xx_fgu_get_status(struct sc27xx_fgu_data *data, int *status) |
551 | { |
552 | union power_supply_propval val; |
553 | struct power_supply *psy; |
554 | int i, ret = -EINVAL; |
555 | |
556 | for (i = 0; i < ARRAY_SIZE(sc27xx_charger_supply_name); i++) { |
557 | psy = power_supply_get_by_name(name: sc27xx_charger_supply_name[i]); |
558 | if (!psy) |
559 | continue; |
560 | |
561 | ret = power_supply_get_property(psy, psp: POWER_SUPPLY_PROP_STATUS, |
562 | val: &val); |
563 | power_supply_put(psy); |
564 | if (ret) |
565 | return ret; |
566 | |
567 | *status = val.intval; |
568 | } |
569 | |
570 | return ret; |
571 | } |
572 | |
573 | static int sc27xx_fgu_get_property(struct power_supply *psy, |
574 | enum power_supply_property psp, |
575 | union power_supply_propval *val) |
576 | { |
577 | struct sc27xx_fgu_data *data = power_supply_get_drvdata(psy); |
578 | int ret = 0; |
579 | int value; |
580 | |
581 | mutex_lock(&data->lock); |
582 | |
583 | switch (psp) { |
584 | case POWER_SUPPLY_PROP_STATUS: |
585 | ret = sc27xx_fgu_get_status(data, status: &value); |
586 | if (ret) |
587 | goto error; |
588 | |
589 | val->intval = value; |
590 | break; |
591 | |
592 | case POWER_SUPPLY_PROP_HEALTH: |
593 | ret = sc27xx_fgu_get_health(data, health: &value); |
594 | if (ret) |
595 | goto error; |
596 | |
597 | val->intval = value; |
598 | break; |
599 | |
600 | case POWER_SUPPLY_PROP_PRESENT: |
601 | val->intval = data->bat_present; |
602 | break; |
603 | |
604 | case POWER_SUPPLY_PROP_TEMP: |
605 | ret = sc27xx_fgu_get_temp(data, temp: &value); |
606 | if (ret) |
607 | goto error; |
608 | |
609 | val->intval = value; |
610 | break; |
611 | |
612 | case POWER_SUPPLY_PROP_TECHNOLOGY: |
613 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; |
614 | break; |
615 | |
616 | case POWER_SUPPLY_PROP_CAPACITY: |
617 | ret = sc27xx_fgu_get_capacity(data, cap: &value); |
618 | if (ret) |
619 | goto error; |
620 | |
621 | val->intval = value; |
622 | break; |
623 | |
624 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: |
625 | ret = sc27xx_fgu_get_vbat_vol(data, val: &value); |
626 | if (ret) |
627 | goto error; |
628 | |
629 | val->intval = value * 1000; |
630 | break; |
631 | |
632 | case POWER_SUPPLY_PROP_VOLTAGE_OCV: |
633 | ret = sc27xx_fgu_get_vbat_ocv(data, val: &value); |
634 | if (ret) |
635 | goto error; |
636 | |
637 | val->intval = value; |
638 | break; |
639 | |
640 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: |
641 | ret = sc27xx_fgu_get_charge_vol(data, val: &value); |
642 | if (ret) |
643 | goto error; |
644 | |
645 | val->intval = value; |
646 | break; |
647 | |
648 | case POWER_SUPPLY_PROP_CURRENT_AVG: |
649 | ret = sc27xx_fgu_get_current(data, val: &value); |
650 | if (ret) |
651 | goto error; |
652 | |
653 | val->intval = value * 1000; |
654 | break; |
655 | |
656 | case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: |
657 | val->intval = data->total_cap * 1000; |
658 | break; |
659 | |
660 | case POWER_SUPPLY_PROP_CHARGE_NOW: |
661 | ret = sc27xx_fgu_get_clbcnt(data, clb_cnt: &value); |
662 | if (ret) |
663 | goto error; |
664 | |
665 | value = DIV_ROUND_CLOSEST(value * 10, |
666 | 36 * SC27XX_FGU_SAMPLE_HZ); |
667 | val->intval = sc27xx_fgu_adc_to_current(data, adc: value); |
668 | |
669 | break; |
670 | |
671 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
672 | ret = sc27xx_fgu_get_vol_now(data, val: &value); |
673 | if (ret) |
674 | goto error; |
675 | |
676 | val->intval = value * 1000; |
677 | break; |
678 | |
679 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
680 | ret = sc27xx_fgu_get_cur_now(data, val: &value); |
681 | if (ret) |
682 | goto error; |
683 | |
684 | val->intval = value * 1000; |
685 | break; |
686 | |
687 | case POWER_SUPPLY_PROP_VOLTAGE_BOOT: |
688 | val->intval = data->boot_volt; |
689 | break; |
690 | |
691 | default: |
692 | ret = -EINVAL; |
693 | break; |
694 | } |
695 | |
696 | error: |
697 | mutex_unlock(lock: &data->lock); |
698 | return ret; |
699 | } |
700 | |
701 | static int sc27xx_fgu_set_property(struct power_supply *psy, |
702 | enum power_supply_property psp, |
703 | const union power_supply_propval *val) |
704 | { |
705 | struct sc27xx_fgu_data *data = power_supply_get_drvdata(psy); |
706 | int ret; |
707 | |
708 | mutex_lock(&data->lock); |
709 | |
710 | switch (psp) { |
711 | case POWER_SUPPLY_PROP_CAPACITY: |
712 | ret = sc27xx_fgu_save_last_cap(data, cap: val->intval); |
713 | if (ret < 0) |
714 | dev_err(data->dev, "failed to save battery capacity\n" ); |
715 | break; |
716 | |
717 | case POWER_SUPPLY_PROP_CALIBRATE: |
718 | sc27xx_fgu_adjust_cap(data, cap: val->intval); |
719 | ret = 0; |
720 | break; |
721 | |
722 | case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: |
723 | data->total_cap = val->intval / 1000; |
724 | ret = 0; |
725 | break; |
726 | |
727 | default: |
728 | ret = -EINVAL; |
729 | } |
730 | |
731 | mutex_unlock(lock: &data->lock); |
732 | |
733 | return ret; |
734 | } |
735 | |
736 | static int sc27xx_fgu_property_is_writeable(struct power_supply *psy, |
737 | enum power_supply_property psp) |
738 | { |
739 | return psp == POWER_SUPPLY_PROP_CAPACITY || |
740 | psp == POWER_SUPPLY_PROP_CALIBRATE || |
741 | psp == POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; |
742 | } |
743 | |
744 | static enum power_supply_property sc27xx_fgu_props[] = { |
745 | POWER_SUPPLY_PROP_STATUS, |
746 | POWER_SUPPLY_PROP_HEALTH, |
747 | POWER_SUPPLY_PROP_PRESENT, |
748 | POWER_SUPPLY_PROP_TEMP, |
749 | POWER_SUPPLY_PROP_TECHNOLOGY, |
750 | POWER_SUPPLY_PROP_CAPACITY, |
751 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
752 | POWER_SUPPLY_PROP_VOLTAGE_OCV, |
753 | POWER_SUPPLY_PROP_VOLTAGE_AVG, |
754 | POWER_SUPPLY_PROP_VOLTAGE_BOOT, |
755 | POWER_SUPPLY_PROP_CURRENT_NOW, |
756 | POWER_SUPPLY_PROP_CURRENT_AVG, |
757 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, |
758 | POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, |
759 | POWER_SUPPLY_PROP_CALIBRATE, |
760 | POWER_SUPPLY_PROP_CHARGE_NOW |
761 | }; |
762 | |
763 | static const struct power_supply_desc sc27xx_fgu_desc = { |
764 | .name = "sc27xx-fgu" , |
765 | .type = POWER_SUPPLY_TYPE_BATTERY, |
766 | .properties = sc27xx_fgu_props, |
767 | .num_properties = ARRAY_SIZE(sc27xx_fgu_props), |
768 | .get_property = sc27xx_fgu_get_property, |
769 | .set_property = sc27xx_fgu_set_property, |
770 | .external_power_changed = power_supply_changed, |
771 | .property_is_writeable = sc27xx_fgu_property_is_writeable, |
772 | .no_thermal = true, |
773 | }; |
774 | |
775 | static void sc27xx_fgu_adjust_cap(struct sc27xx_fgu_data *data, int cap) |
776 | { |
777 | int ret; |
778 | |
779 | data->init_cap = cap; |
780 | ret = sc27xx_fgu_get_clbcnt(data, clb_cnt: &data->init_clbcnt); |
781 | if (ret) |
782 | dev_err(data->dev, "failed to get init coulomb counter\n" ); |
783 | } |
784 | |
785 | static void sc27xx_fgu_capacity_calibration(struct sc27xx_fgu_data *data, |
786 | int cap, bool int_mode) |
787 | { |
788 | int ret, ocv, chg_sts, adc; |
789 | |
790 | ret = sc27xx_fgu_get_vbat_ocv(data, val: &ocv); |
791 | if (ret) { |
792 | dev_err(data->dev, "get battery ocv error.\n" ); |
793 | return; |
794 | } |
795 | |
796 | ret = sc27xx_fgu_get_status(data, status: &chg_sts); |
797 | if (ret) { |
798 | dev_err(data->dev, "get charger status error.\n" ); |
799 | return; |
800 | } |
801 | |
802 | /* |
803 | * If we are in charging mode, then we do not need to calibrate the |
804 | * lower capacity. |
805 | */ |
806 | if (chg_sts == POWER_SUPPLY_STATUS_CHARGING) |
807 | return; |
808 | |
809 | if ((ocv > data->cap_table[0].ocv && cap < 100) || cap > 100) { |
810 | /* |
811 | * If current OCV value is larger than the max OCV value in |
812 | * OCV table, or the current capacity is larger than 100, |
813 | * we should force the inititial capacity to 100. |
814 | */ |
815 | sc27xx_fgu_adjust_cap(data, cap: 100); |
816 | } else if (ocv <= data->cap_table[data->table_len - 1].ocv) { |
817 | /* |
818 | * If current OCV value is leass than the minimum OCV value in |
819 | * OCV table, we should force the inititial capacity to 0. |
820 | */ |
821 | sc27xx_fgu_adjust_cap(data, cap: 0); |
822 | } else if ((ocv > data->cap_table[data->table_len - 1].ocv && cap <= 0) || |
823 | (ocv > data->min_volt && cap <= data->alarm_cap)) { |
824 | /* |
825 | * If current OCV value is not matchable with current capacity, |
826 | * we should re-calculate current capacity by looking up the |
827 | * OCV table. |
828 | */ |
829 | int cur_cap = power_supply_ocv2cap_simple(table: data->cap_table, |
830 | table_len: data->table_len, ocv); |
831 | |
832 | sc27xx_fgu_adjust_cap(data, cap: cur_cap); |
833 | } else if (ocv <= data->min_volt) { |
834 | /* |
835 | * If current OCV value is less than the low alarm voltage, but |
836 | * current capacity is larger than the alarm capacity, we should |
837 | * adjust the inititial capacity to alarm capacity. |
838 | */ |
839 | if (cap > data->alarm_cap) { |
840 | sc27xx_fgu_adjust_cap(data, cap: data->alarm_cap); |
841 | } else { |
842 | int cur_cap; |
843 | |
844 | /* |
845 | * If current capacity is equal with 0 or less than 0 |
846 | * (some error occurs), we should adjust inititial |
847 | * capacity to the capacity corresponding to current OCV |
848 | * value. |
849 | */ |
850 | cur_cap = power_supply_ocv2cap_simple(table: data->cap_table, |
851 | table_len: data->table_len, |
852 | ocv); |
853 | sc27xx_fgu_adjust_cap(data, cap: cur_cap); |
854 | } |
855 | |
856 | if (!int_mode) |
857 | return; |
858 | |
859 | /* |
860 | * After adjusting the battery capacity, we should set the |
861 | * lowest alarm voltage instead. |
862 | */ |
863 | data->min_volt = data->cap_table[data->table_len - 1].ocv; |
864 | data->alarm_cap = power_supply_ocv2cap_simple(table: data->cap_table, |
865 | table_len: data->table_len, |
866 | ocv: data->min_volt); |
867 | |
868 | adc = sc27xx_fgu_voltage_to_adc(data, vol: data->min_volt / 1000); |
869 | regmap_update_bits(map: data->regmap, |
870 | reg: data->base + SC27XX_FGU_LOW_OVERLOAD, |
871 | SC27XX_FGU_LOW_OVERLOAD_MASK, val: adc); |
872 | } |
873 | } |
874 | |
875 | static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id) |
876 | { |
877 | struct sc27xx_fgu_data *data = dev_id; |
878 | int ret, cap; |
879 | u32 status; |
880 | |
881 | mutex_lock(&data->lock); |
882 | |
883 | ret = regmap_read(map: data->regmap, reg: data->base + SC27XX_FGU_INT_STS, |
884 | val: &status); |
885 | if (ret) |
886 | goto out; |
887 | |
888 | ret = regmap_update_bits(map: data->regmap, reg: data->base + SC27XX_FGU_INT_CLR, |
889 | mask: status, val: status); |
890 | if (ret) |
891 | goto out; |
892 | |
893 | /* |
894 | * When low overload voltage interrupt happens, we should calibrate the |
895 | * battery capacity in lower voltage stage. |
896 | */ |
897 | if (!(status & SC27XX_FGU_LOW_OVERLOAD_INT)) |
898 | goto out; |
899 | |
900 | ret = sc27xx_fgu_get_capacity(data, cap: &cap); |
901 | if (ret) |
902 | goto out; |
903 | |
904 | sc27xx_fgu_capacity_calibration(data, cap, int_mode: true); |
905 | |
906 | out: |
907 | mutex_unlock(lock: &data->lock); |
908 | |
909 | power_supply_changed(psy: data->battery); |
910 | return IRQ_HANDLED; |
911 | } |
912 | |
913 | static irqreturn_t sc27xx_fgu_bat_detection(int irq, void *dev_id) |
914 | { |
915 | struct sc27xx_fgu_data *data = dev_id; |
916 | int state; |
917 | |
918 | mutex_lock(&data->lock); |
919 | |
920 | state = gpiod_get_value_cansleep(desc: data->gpiod); |
921 | if (state < 0) { |
922 | dev_err(data->dev, "failed to get gpio state\n" ); |
923 | mutex_unlock(lock: &data->lock); |
924 | return IRQ_RETVAL(state); |
925 | } |
926 | |
927 | data->bat_present = !!state; |
928 | |
929 | mutex_unlock(lock: &data->lock); |
930 | |
931 | power_supply_changed(psy: data->battery); |
932 | return IRQ_HANDLED; |
933 | } |
934 | |
935 | static void sc27xx_fgu_disable(void *_data) |
936 | { |
937 | struct sc27xx_fgu_data *data = _data; |
938 | |
939 | regmap_update_bits(map: data->regmap, SC27XX_CLK_EN0, SC27XX_FGU_RTC_EN, val: 0); |
940 | regmap_update_bits(map: data->regmap, SC27XX_MODULE_EN0, SC27XX_FGU_EN, val: 0); |
941 | } |
942 | |
943 | static int sc27xx_fgu_cap_to_clbcnt(struct sc27xx_fgu_data *data, int capacity) |
944 | { |
945 | /* |
946 | * Get current capacity (mAh) = battery total capacity (mAh) * |
947 | * current capacity percent (capacity / 100). |
948 | */ |
949 | int cur_cap = DIV_ROUND_CLOSEST(data->total_cap * capacity, 100); |
950 | |
951 | /* |
952 | * Convert current capacity (mAh) to coulomb counter according to the |
953 | * formula: 1 mAh =3.6 coulomb. |
954 | */ |
955 | return DIV_ROUND_CLOSEST(cur_cap * 36 * data->cur_1000ma_adc * SC27XX_FGU_SAMPLE_HZ, 10); |
956 | } |
957 | |
958 | static int sc27xx_fgu_calibration(struct sc27xx_fgu_data *data) |
959 | { |
960 | struct nvmem_cell *cell; |
961 | int calib_data, cal_4200mv; |
962 | void *buf; |
963 | size_t len; |
964 | |
965 | cell = nvmem_cell_get(dev: data->dev, id: "fgu_calib" ); |
966 | if (IS_ERR(ptr: cell)) |
967 | return PTR_ERR(ptr: cell); |
968 | |
969 | buf = nvmem_cell_read(cell, len: &len); |
970 | nvmem_cell_put(cell); |
971 | |
972 | if (IS_ERR(ptr: buf)) |
973 | return PTR_ERR(ptr: buf); |
974 | |
975 | memcpy(&calib_data, buf, min(len, sizeof(u32))); |
976 | |
977 | /* |
978 | * Get the ADC value corresponding to 4200 mV from eFuse controller |
979 | * according to below formula. Then convert to ADC values corresponding |
980 | * to 1000 mV and 1000 mA. |
981 | */ |
982 | cal_4200mv = (calib_data & 0x1ff) + 6963 - 4096 - 256; |
983 | data->vol_1000mv_adc = DIV_ROUND_CLOSEST(cal_4200mv * 10, 42); |
984 | data->cur_1000ma_adc = |
985 | DIV_ROUND_CLOSEST(data->vol_1000mv_adc * 4 * data->calib_resist, |
986 | SC27XX_FGU_IDEAL_RESISTANCE); |
987 | |
988 | kfree(objp: buf); |
989 | return 0; |
990 | } |
991 | |
992 | static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data) |
993 | { |
994 | struct power_supply_battery_info *info; |
995 | struct power_supply_battery_ocv_table *table; |
996 | int ret, delta_clbcnt, alarm_adc; |
997 | |
998 | ret = power_supply_get_battery_info(psy: data->battery, info_out: &info); |
999 | if (ret) { |
1000 | dev_err(data->dev, "failed to get battery information\n" ); |
1001 | return ret; |
1002 | } |
1003 | |
1004 | data->total_cap = info->charge_full_design_uah / 1000; |
1005 | data->max_volt = info->constant_charge_voltage_max_uv / 1000; |
1006 | data->internal_resist = info->factory_internal_resistance_uohm / 1000; |
1007 | data->min_volt = info->voltage_min_design_uv; |
1008 | |
1009 | /* |
1010 | * For SC27XX fuel gauge device, we only use one ocv-capacity |
1011 | * table in normal temperature 20 Celsius. |
1012 | */ |
1013 | table = power_supply_find_ocv2cap_table(info, temp: 20, table_len: &data->table_len); |
1014 | if (!table) |
1015 | return -EINVAL; |
1016 | |
1017 | data->cap_table = devm_kmemdup(dev: data->dev, src: table, |
1018 | len: data->table_len * sizeof(*table), |
1019 | GFP_KERNEL); |
1020 | if (!data->cap_table) { |
1021 | power_supply_put_battery_info(psy: data->battery, info); |
1022 | return -ENOMEM; |
1023 | } |
1024 | |
1025 | data->alarm_cap = power_supply_ocv2cap_simple(table: data->cap_table, |
1026 | table_len: data->table_len, |
1027 | ocv: data->min_volt); |
1028 | if (!data->alarm_cap) |
1029 | data->alarm_cap += 1; |
1030 | |
1031 | data->resist_table_len = info->resist_table_size; |
1032 | if (data->resist_table_len > 0) { |
1033 | data->resist_table = devm_kmemdup(dev: data->dev, src: info->resist_table, |
1034 | len: data->resist_table_len * |
1035 | sizeof(struct power_supply_resistance_temp_table), |
1036 | GFP_KERNEL); |
1037 | if (!data->resist_table) { |
1038 | power_supply_put_battery_info(psy: data->battery, info); |
1039 | return -ENOMEM; |
1040 | } |
1041 | } |
1042 | |
1043 | power_supply_put_battery_info(psy: data->battery, info); |
1044 | |
1045 | ret = sc27xx_fgu_calibration(data); |
1046 | if (ret) |
1047 | return ret; |
1048 | |
1049 | /* Enable the FGU module */ |
1050 | ret = regmap_update_bits(map: data->regmap, SC27XX_MODULE_EN0, |
1051 | SC27XX_FGU_EN, SC27XX_FGU_EN); |
1052 | if (ret) { |
1053 | dev_err(data->dev, "failed to enable fgu\n" ); |
1054 | return ret; |
1055 | } |
1056 | |
1057 | /* Enable the FGU RTC clock to make it work */ |
1058 | ret = regmap_update_bits(map: data->regmap, SC27XX_CLK_EN0, |
1059 | SC27XX_FGU_RTC_EN, SC27XX_FGU_RTC_EN); |
1060 | if (ret) { |
1061 | dev_err(data->dev, "failed to enable fgu RTC clock\n" ); |
1062 | goto disable_fgu; |
1063 | } |
1064 | |
1065 | ret = regmap_update_bits(map: data->regmap, reg: data->base + SC27XX_FGU_INT_CLR, |
1066 | SC27XX_FGU_INT_MASK, SC27XX_FGU_INT_MASK); |
1067 | if (ret) { |
1068 | dev_err(data->dev, "failed to clear interrupt status\n" ); |
1069 | goto disable_clk; |
1070 | } |
1071 | |
1072 | /* |
1073 | * Set the voltage low overload threshold, which means when the battery |
1074 | * voltage is lower than this threshold, the controller will generate |
1075 | * one interrupt to notify. |
1076 | */ |
1077 | alarm_adc = sc27xx_fgu_voltage_to_adc(data, vol: data->min_volt / 1000); |
1078 | ret = regmap_update_bits(map: data->regmap, reg: data->base + SC27XX_FGU_LOW_OVERLOAD, |
1079 | SC27XX_FGU_LOW_OVERLOAD_MASK, val: alarm_adc); |
1080 | if (ret) { |
1081 | dev_err(data->dev, "failed to set fgu low overload\n" ); |
1082 | goto disable_clk; |
1083 | } |
1084 | |
1085 | /* |
1086 | * Set the coulomb counter delta threshold, that means when the coulomb |
1087 | * counter change is multiples of the delta threshold, the controller |
1088 | * will generate one interrupt to notify the users to update the battery |
1089 | * capacity. Now we set the delta threshold as a counter value of 1% |
1090 | * capacity. |
1091 | */ |
1092 | delta_clbcnt = sc27xx_fgu_cap_to_clbcnt(data, capacity: 1); |
1093 | |
1094 | ret = regmap_update_bits(map: data->regmap, reg: data->base + SC27XX_FGU_CLBCNT_DELTL, |
1095 | SC27XX_FGU_CLBCNT_MASK, val: delta_clbcnt); |
1096 | if (ret) { |
1097 | dev_err(data->dev, "failed to set low delta coulomb counter\n" ); |
1098 | goto disable_clk; |
1099 | } |
1100 | |
1101 | ret = regmap_update_bits(map: data->regmap, reg: data->base + SC27XX_FGU_CLBCNT_DELTH, |
1102 | SC27XX_FGU_CLBCNT_MASK, |
1103 | val: delta_clbcnt >> SC27XX_FGU_CLBCNT_SHIFT); |
1104 | if (ret) { |
1105 | dev_err(data->dev, "failed to set high delta coulomb counter\n" ); |
1106 | goto disable_clk; |
1107 | } |
1108 | |
1109 | /* |
1110 | * Get the boot battery capacity when system powers on, which is used to |
1111 | * initialize the coulomb counter. After that, we can read the coulomb |
1112 | * counter to measure the battery capacity. |
1113 | */ |
1114 | ret = sc27xx_fgu_get_boot_capacity(data, cap: &data->init_cap); |
1115 | if (ret) { |
1116 | dev_err(data->dev, "failed to get boot capacity\n" ); |
1117 | goto disable_clk; |
1118 | } |
1119 | |
1120 | /* |
1121 | * Convert battery capacity to the corresponding initial coulomb counter |
1122 | * and set into coulomb counter registers. |
1123 | */ |
1124 | data->init_clbcnt = sc27xx_fgu_cap_to_clbcnt(data, capacity: data->init_cap); |
1125 | ret = sc27xx_fgu_set_clbcnt(data, clbcnt: data->init_clbcnt); |
1126 | if (ret) { |
1127 | dev_err(data->dev, "failed to initialize coulomb counter\n" ); |
1128 | goto disable_clk; |
1129 | } |
1130 | |
1131 | return 0; |
1132 | |
1133 | disable_clk: |
1134 | regmap_update_bits(map: data->regmap, SC27XX_CLK_EN0, SC27XX_FGU_RTC_EN, val: 0); |
1135 | disable_fgu: |
1136 | regmap_update_bits(map: data->regmap, SC27XX_MODULE_EN0, SC27XX_FGU_EN, val: 0); |
1137 | |
1138 | return ret; |
1139 | } |
1140 | |
1141 | static int sc27xx_fgu_probe(struct platform_device *pdev) |
1142 | { |
1143 | struct device *dev = &pdev->dev; |
1144 | struct device_node *np = dev->of_node; |
1145 | struct power_supply_config fgu_cfg = { }; |
1146 | struct sc27xx_fgu_data *data; |
1147 | int ret, irq; |
1148 | |
1149 | data = devm_kzalloc(dev, size: sizeof(*data), GFP_KERNEL); |
1150 | if (!data) |
1151 | return -ENOMEM; |
1152 | |
1153 | data->regmap = dev_get_regmap(dev: dev->parent, NULL); |
1154 | if (!data->regmap) { |
1155 | dev_err(dev, "failed to get regmap\n" ); |
1156 | return -ENODEV; |
1157 | } |
1158 | |
1159 | ret = device_property_read_u32(dev, propname: "reg" , val: &data->base); |
1160 | if (ret) { |
1161 | dev_err(dev, "failed to get fgu address\n" ); |
1162 | return ret; |
1163 | } |
1164 | |
1165 | ret = device_property_read_u32(dev: &pdev->dev, |
1166 | propname: "sprd,calib-resistance-micro-ohms" , |
1167 | val: &data->calib_resist); |
1168 | if (ret) { |
1169 | dev_err(&pdev->dev, |
1170 | "failed to get fgu calibration resistance\n" ); |
1171 | return ret; |
1172 | } |
1173 | |
1174 | data->channel = devm_iio_channel_get(dev, consumer_channel: "bat-temp" ); |
1175 | if (IS_ERR(ptr: data->channel)) { |
1176 | dev_err(dev, "failed to get IIO channel\n" ); |
1177 | return PTR_ERR(ptr: data->channel); |
1178 | } |
1179 | |
1180 | data->charge_chan = devm_iio_channel_get(dev, consumer_channel: "charge-vol" ); |
1181 | if (IS_ERR(ptr: data->charge_chan)) { |
1182 | dev_err(dev, "failed to get charge IIO channel\n" ); |
1183 | return PTR_ERR(ptr: data->charge_chan); |
1184 | } |
1185 | |
1186 | data->gpiod = devm_gpiod_get(dev, con_id: "bat-detect" , flags: GPIOD_IN); |
1187 | if (IS_ERR(ptr: data->gpiod)) { |
1188 | dev_err(dev, "failed to get battery detection GPIO\n" ); |
1189 | return PTR_ERR(ptr: data->gpiod); |
1190 | } |
1191 | |
1192 | ret = gpiod_get_value_cansleep(desc: data->gpiod); |
1193 | if (ret < 0) { |
1194 | dev_err(dev, "failed to get gpio state\n" ); |
1195 | return ret; |
1196 | } |
1197 | |
1198 | data->bat_present = !!ret; |
1199 | mutex_init(&data->lock); |
1200 | data->dev = dev; |
1201 | platform_set_drvdata(pdev, data); |
1202 | |
1203 | fgu_cfg.drv_data = data; |
1204 | fgu_cfg.of_node = np; |
1205 | data->battery = devm_power_supply_register(parent: dev, desc: &sc27xx_fgu_desc, |
1206 | cfg: &fgu_cfg); |
1207 | if (IS_ERR(ptr: data->battery)) { |
1208 | dev_err(dev, "failed to register power supply\n" ); |
1209 | return PTR_ERR(ptr: data->battery); |
1210 | } |
1211 | |
1212 | ret = sc27xx_fgu_hw_init(data); |
1213 | if (ret) { |
1214 | dev_err(dev, "failed to initialize fgu hardware\n" ); |
1215 | return ret; |
1216 | } |
1217 | |
1218 | ret = devm_add_action_or_reset(dev, sc27xx_fgu_disable, data); |
1219 | if (ret) { |
1220 | dev_err(dev, "failed to add fgu disable action\n" ); |
1221 | return ret; |
1222 | } |
1223 | |
1224 | irq = platform_get_irq(pdev, 0); |
1225 | if (irq < 0) |
1226 | return irq; |
1227 | |
1228 | ret = devm_request_threaded_irq(dev: data->dev, irq, NULL, |
1229 | thread_fn: sc27xx_fgu_interrupt, |
1230 | IRQF_NO_SUSPEND | IRQF_ONESHOT, |
1231 | devname: pdev->name, dev_id: data); |
1232 | if (ret) { |
1233 | dev_err(data->dev, "failed to request fgu IRQ\n" ); |
1234 | return ret; |
1235 | } |
1236 | |
1237 | irq = gpiod_to_irq(desc: data->gpiod); |
1238 | if (irq < 0) { |
1239 | dev_err(dev, "failed to translate GPIO to IRQ\n" ); |
1240 | return irq; |
1241 | } |
1242 | |
1243 | ret = devm_request_threaded_irq(dev, irq, NULL, |
1244 | thread_fn: sc27xx_fgu_bat_detection, |
1245 | IRQF_ONESHOT | IRQF_TRIGGER_RISING | |
1246 | IRQF_TRIGGER_FALLING, |
1247 | devname: pdev->name, dev_id: data); |
1248 | if (ret) { |
1249 | dev_err(dev, "failed to request IRQ\n" ); |
1250 | return ret; |
1251 | } |
1252 | |
1253 | return 0; |
1254 | } |
1255 | |
1256 | #ifdef CONFIG_PM_SLEEP |
1257 | static int sc27xx_fgu_resume(struct device *dev) |
1258 | { |
1259 | struct sc27xx_fgu_data *data = dev_get_drvdata(dev); |
1260 | int ret; |
1261 | |
1262 | ret = regmap_update_bits(map: data->regmap, reg: data->base + SC27XX_FGU_INT_EN, |
1263 | SC27XX_FGU_LOW_OVERLOAD_INT | |
1264 | SC27XX_FGU_CLBCNT_DELTA_INT, val: 0); |
1265 | if (ret) { |
1266 | dev_err(data->dev, "failed to disable fgu interrupts\n" ); |
1267 | return ret; |
1268 | } |
1269 | |
1270 | return 0; |
1271 | } |
1272 | |
1273 | static int sc27xx_fgu_suspend(struct device *dev) |
1274 | { |
1275 | struct sc27xx_fgu_data *data = dev_get_drvdata(dev); |
1276 | int ret, status, ocv; |
1277 | |
1278 | ret = sc27xx_fgu_get_status(data, status: &status); |
1279 | if (ret) |
1280 | return ret; |
1281 | |
1282 | /* |
1283 | * If we are charging, then no need to enable the FGU interrupts to |
1284 | * adjust the battery capacity. |
1285 | */ |
1286 | if (status != POWER_SUPPLY_STATUS_NOT_CHARGING && |
1287 | status != POWER_SUPPLY_STATUS_DISCHARGING) |
1288 | return 0; |
1289 | |
1290 | ret = regmap_update_bits(map: data->regmap, reg: data->base + SC27XX_FGU_INT_EN, |
1291 | SC27XX_FGU_LOW_OVERLOAD_INT, |
1292 | SC27XX_FGU_LOW_OVERLOAD_INT); |
1293 | if (ret) { |
1294 | dev_err(data->dev, "failed to enable low voltage interrupt\n" ); |
1295 | return ret; |
1296 | } |
1297 | |
1298 | ret = sc27xx_fgu_get_vbat_ocv(data, val: &ocv); |
1299 | if (ret) |
1300 | goto disable_int; |
1301 | |
1302 | /* |
1303 | * If current OCV is less than the minimum voltage, we should enable the |
1304 | * coulomb counter threshold interrupt to notify events to adjust the |
1305 | * battery capacity. |
1306 | */ |
1307 | if (ocv < data->min_volt) { |
1308 | ret = regmap_update_bits(map: data->regmap, |
1309 | reg: data->base + SC27XX_FGU_INT_EN, |
1310 | SC27XX_FGU_CLBCNT_DELTA_INT, |
1311 | SC27XX_FGU_CLBCNT_DELTA_INT); |
1312 | if (ret) { |
1313 | dev_err(data->dev, |
1314 | "failed to enable coulomb threshold int\n" ); |
1315 | goto disable_int; |
1316 | } |
1317 | } |
1318 | |
1319 | return 0; |
1320 | |
1321 | disable_int: |
1322 | regmap_update_bits(map: data->regmap, reg: data->base + SC27XX_FGU_INT_EN, |
1323 | SC27XX_FGU_LOW_OVERLOAD_INT, val: 0); |
1324 | return ret; |
1325 | } |
1326 | #endif |
1327 | |
1328 | static const struct dev_pm_ops sc27xx_fgu_pm_ops = { |
1329 | SET_SYSTEM_SLEEP_PM_OPS(sc27xx_fgu_suspend, sc27xx_fgu_resume) |
1330 | }; |
1331 | |
1332 | static const struct of_device_id sc27xx_fgu_of_match[] = { |
1333 | { .compatible = "sprd,sc2731-fgu" , }, |
1334 | { } |
1335 | }; |
1336 | MODULE_DEVICE_TABLE(of, sc27xx_fgu_of_match); |
1337 | |
1338 | static struct platform_driver sc27xx_fgu_driver = { |
1339 | .probe = sc27xx_fgu_probe, |
1340 | .driver = { |
1341 | .name = "sc27xx-fgu" , |
1342 | .of_match_table = sc27xx_fgu_of_match, |
1343 | .pm = &sc27xx_fgu_pm_ops, |
1344 | } |
1345 | }; |
1346 | |
1347 | module_platform_driver(sc27xx_fgu_driver); |
1348 | |
1349 | MODULE_DESCRIPTION("Spreadtrum SC27XX PMICs Fual Gauge Unit Driver" ); |
1350 | MODULE_LICENSE("GPL v2" ); |
1351 | |