blob: 76da1895b782e6ee1f0ba62becd11619c838d5c9 [file] [log] [blame]
Baolin Wang195ca172018-11-05 15:39:11 +08001// 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/module.h>
Baolin Wang65c9fab2018-11-14 17:07:05 +08009#include <linux/nvmem-consumer.h>
Baolin Wang195ca172018-11-05 15:39:11 +080010#include <linux/of.h>
11#include <linux/platform_device.h>
12#include <linux/power_supply.h>
13#include <linux/regmap.h>
Baolin Wang65c9fab2018-11-14 17:07:05 +080014#include <linux/slab.h>
Baolin Wang195ca172018-11-05 15:39:11 +080015
16/* PMIC global control registers definition */
17#define SC27XX_MODULE_EN0 0xc08
18#define SC27XX_CLK_EN0 0xc18
19#define SC27XX_FGU_EN BIT(7)
20#define SC27XX_FGU_RTC_EN BIT(6)
21
22/* FGU registers definition */
23#define SC27XX_FGU_START 0x0
24#define SC27XX_FGU_CONFIG 0x4
25#define SC27XX_FGU_ADC_CONFIG 0x8
26#define SC27XX_FGU_STATUS 0xc
27#define SC27XX_FGU_INT_EN 0x10
28#define SC27XX_FGU_INT_CLR 0x14
29#define SC27XX_FGU_INT_STS 0x1c
30#define SC27XX_FGU_VOLTAGE 0x20
31#define SC27XX_FGU_OCV 0x24
32#define SC27XX_FGU_POCV 0x28
33#define SC27XX_FGU_CURRENT 0x2c
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +080034#define SC27XX_FGU_LOW_OVERLOAD 0x34
Baolin Wang195ca172018-11-05 15:39:11 +080035#define SC27XX_FGU_CLBCNT_SETH 0x50
36#define SC27XX_FGU_CLBCNT_SETL 0x54
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +080037#define SC27XX_FGU_CLBCNT_DELTH 0x58
38#define SC27XX_FGU_CLBCNT_DELTL 0x5c
Baolin Wang195ca172018-11-05 15:39:11 +080039#define SC27XX_FGU_CLBCNT_VALH 0x68
40#define SC27XX_FGU_CLBCNT_VALL 0x6c
41#define SC27XX_FGU_CLBCNT_QMAXL 0x74
Yuanjiang Yu4a040e72018-12-06 11:20:39 +080042#define SC27XX_FGU_USER_AREA_SET 0xa0
43#define SC27XX_FGU_USER_AREA_CLEAR 0xa4
44#define SC27XX_FGU_USER_AREA_STATUS 0xa8
Baolin Wang195ca172018-11-05 15:39:11 +080045
46#define SC27XX_WRITE_SELCLB_EN BIT(0)
47#define SC27XX_FGU_CLBCNT_MASK GENMASK(15, 0)
48#define SC27XX_FGU_CLBCNT_SHIFT 16
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +080049#define SC27XX_FGU_LOW_OVERLOAD_MASK GENMASK(12, 0)
50
51#define SC27XX_FGU_INT_MASK GENMASK(9, 0)
52#define SC27XX_FGU_LOW_OVERLOAD_INT BIT(0)
53#define SC27XX_FGU_CLBCNT_DELTA_INT BIT(2)
Baolin Wang195ca172018-11-05 15:39:11 +080054
Yuanjiang Yu4a040e72018-12-06 11:20:39 +080055#define SC27XX_FGU_MODE_AREA_MASK GENMASK(15, 12)
56#define SC27XX_FGU_CAP_AREA_MASK GENMASK(11, 0)
57#define SC27XX_FGU_MODE_AREA_SHIFT 12
58
59#define SC27XX_FGU_FIRST_POWERTON GENMASK(3, 0)
60#define SC27XX_FGU_DEFAULT_CAP GENMASK(11, 0)
61#define SC27XX_FGU_NORMAIL_POWERTON 0x5
62
Baolin Wang195ca172018-11-05 15:39:11 +080063#define SC27XX_FGU_CUR_BASIC_ADC 8192
64#define SC27XX_FGU_SAMPLE_HZ 2
65
66/*
67 * struct sc27xx_fgu_data: describe the FGU device
68 * @regmap: regmap for register access
69 * @dev: platform device
70 * @battery: battery power supply
71 * @base: the base offset for the controller
72 * @lock: protect the structure
73 * @gpiod: GPIO for battery detection
74 * @channel: IIO channel to get battery temperature
75 * @internal_resist: the battery internal resistance in mOhm
76 * @total_cap: the total capacity of the battery in mAh
77 * @init_cap: the initial capacity of the battery in mAh
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +080078 * @alarm_cap: the alarm capacity
Baolin Wang195ca172018-11-05 15:39:11 +080079 * @init_clbcnt: the initial coulomb counter
80 * @max_volt: the maximum constant input voltage in millivolt
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +080081 * @min_volt: the minimum drained battery voltage in microvolt
Baolin Wang195ca172018-11-05 15:39:11 +080082 * @table_len: the capacity table length
Baolin Wang65c9fab2018-11-14 17:07:05 +080083 * @cur_1000ma_adc: ADC value corresponding to 1000 mA
84 * @vol_1000mv_adc: ADC value corresponding to 1000 mV
Baolin Wang195ca172018-11-05 15:39:11 +080085 * @cap_table: capacity table with corresponding ocv
86 */
87struct sc27xx_fgu_data {
88 struct regmap *regmap;
89 struct device *dev;
90 struct power_supply *battery;
91 u32 base;
92 struct mutex lock;
93 struct gpio_desc *gpiod;
94 struct iio_channel *channel;
95 bool bat_present;
96 int internal_resist;
97 int total_cap;
98 int init_cap;
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +080099 int alarm_cap;
Baolin Wang195ca172018-11-05 15:39:11 +0800100 int init_clbcnt;
101 int max_volt;
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +0800102 int min_volt;
Baolin Wang195ca172018-11-05 15:39:11 +0800103 int table_len;
Baolin Wang65c9fab2018-11-14 17:07:05 +0800104 int cur_1000ma_adc;
105 int vol_1000mv_adc;
Baolin Wang195ca172018-11-05 15:39:11 +0800106 struct power_supply_battery_ocv_table *cap_table;
107};
108
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +0800109static int sc27xx_fgu_cap_to_clbcnt(struct sc27xx_fgu_data *data, int capacity);
110
Baolin Wang195ca172018-11-05 15:39:11 +0800111static const char * const sc27xx_charger_supply_name[] = {
112 "sc2731_charger",
113 "sc2720_charger",
114 "sc2721_charger",
115 "sc2723_charger",
116};
117
Baolin Wang65c9fab2018-11-14 17:07:05 +0800118static int sc27xx_fgu_adc_to_current(struct sc27xx_fgu_data *data, int adc)
Baolin Wang195ca172018-11-05 15:39:11 +0800119{
Baolin Wang65c9fab2018-11-14 17:07:05 +0800120 return DIV_ROUND_CLOSEST(adc * 1000, data->cur_1000ma_adc);
Baolin Wang195ca172018-11-05 15:39:11 +0800121}
122
Baolin Wang65c9fab2018-11-14 17:07:05 +0800123static int sc27xx_fgu_adc_to_voltage(struct sc27xx_fgu_data *data, int adc)
Baolin Wang195ca172018-11-05 15:39:11 +0800124{
Baolin Wang65c9fab2018-11-14 17:07:05 +0800125 return DIV_ROUND_CLOSEST(adc * 1000, data->vol_1000mv_adc);
Baolin Wang195ca172018-11-05 15:39:11 +0800126}
127
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +0800128static int sc27xx_fgu_voltage_to_adc(struct sc27xx_fgu_data *data, int vol)
129{
130 return DIV_ROUND_CLOSEST(vol * data->vol_1000mv_adc, 1000);
131}
132
Yuanjiang Yu4a040e72018-12-06 11:20:39 +0800133static bool sc27xx_fgu_is_first_poweron(struct sc27xx_fgu_data *data)
134{
135 int ret, status, cap, mode;
136
137 ret = regmap_read(data->regmap,
138 data->base + SC27XX_FGU_USER_AREA_STATUS, &status);
139 if (ret)
140 return false;
141
142 /*
143 * We use low 4 bits to save the last battery capacity and high 12 bits
144 * to save the system boot mode.
145 */
146 mode = (status & SC27XX_FGU_MODE_AREA_MASK) >> SC27XX_FGU_MODE_AREA_SHIFT;
147 cap = status & SC27XX_FGU_CAP_AREA_MASK;
148
149 /*
150 * When FGU has been powered down, the user area registers became
151 * default value (0xffff), which can be used to valid if the system is
152 * first power on or not.
153 */
154 if (mode == SC27XX_FGU_FIRST_POWERTON || cap == SC27XX_FGU_DEFAULT_CAP)
155 return true;
156
157 return false;
158}
159
160static int sc27xx_fgu_save_boot_mode(struct sc27xx_fgu_data *data,
161 int boot_mode)
162{
163 int ret;
164
165 ret = regmap_update_bits(data->regmap,
166 data->base + SC27XX_FGU_USER_AREA_CLEAR,
167 SC27XX_FGU_MODE_AREA_MASK,
168 SC27XX_FGU_MODE_AREA_MASK);
169 if (ret)
170 return ret;
171
172 return regmap_update_bits(data->regmap,
173 data->base + SC27XX_FGU_USER_AREA_SET,
174 SC27XX_FGU_MODE_AREA_MASK,
175 boot_mode << SC27XX_FGU_MODE_AREA_SHIFT);
176}
177
178static int sc27xx_fgu_save_last_cap(struct sc27xx_fgu_data *data, int cap)
179{
180 int ret;
181
182 ret = regmap_update_bits(data->regmap,
183 data->base + SC27XX_FGU_USER_AREA_CLEAR,
184 SC27XX_FGU_CAP_AREA_MASK,
185 SC27XX_FGU_CAP_AREA_MASK);
186 if (ret)
187 return ret;
188
189 return regmap_update_bits(data->regmap,
190 data->base + SC27XX_FGU_USER_AREA_SET,
191 SC27XX_FGU_CAP_AREA_MASK, cap);
192}
193
194static int sc27xx_fgu_read_last_cap(struct sc27xx_fgu_data *data, int *cap)
195{
196 int ret, value;
197
198 ret = regmap_read(data->regmap,
199 data->base + SC27XX_FGU_USER_AREA_STATUS, &value);
200 if (ret)
201 return ret;
202
203 *cap = value & SC27XX_FGU_CAP_AREA_MASK;
204 return 0;
205}
206
Baolin Wang195ca172018-11-05 15:39:11 +0800207/*
208 * When system boots on, we can not read battery capacity from coulomb
209 * registers, since now the coulomb registers are invalid. So we should
210 * calculate the battery open circuit voltage, and get current battery
211 * capacity according to the capacity table.
212 */
213static int sc27xx_fgu_get_boot_capacity(struct sc27xx_fgu_data *data, int *cap)
214{
215 int volt, cur, oci, ocv, ret;
Yuanjiang Yu4a040e72018-12-06 11:20:39 +0800216 bool is_first_poweron = sc27xx_fgu_is_first_poweron(data);
217
218 /*
219 * If system is not the first power on, we should use the last saved
220 * battery capacity as the initial battery capacity. Otherwise we should
221 * re-calculate the initial battery capacity.
222 */
223 if (!is_first_poweron) {
224 ret = sc27xx_fgu_read_last_cap(data, cap);
225 if (ret)
226 return ret;
227
228 return sc27xx_fgu_save_boot_mode(data, SC27XX_FGU_NORMAIL_POWERTON);
229 }
Baolin Wang195ca172018-11-05 15:39:11 +0800230
231 /*
232 * After system booting on, the SC27XX_FGU_CLBCNT_QMAXL register saved
233 * the first sampled open circuit current.
234 */
235 ret = regmap_read(data->regmap, data->base + SC27XX_FGU_CLBCNT_QMAXL,
236 &cur);
237 if (ret)
238 return ret;
239
240 cur <<= 1;
Baolin Wang65c9fab2018-11-14 17:07:05 +0800241 oci = sc27xx_fgu_adc_to_current(data, cur - SC27XX_FGU_CUR_BASIC_ADC);
Baolin Wang195ca172018-11-05 15:39:11 +0800242
243 /*
244 * Should get the OCV from SC27XX_FGU_POCV register at the system
245 * beginning. It is ADC values reading from registers which need to
246 * convert the corresponding voltage.
247 */
248 ret = regmap_read(data->regmap, data->base + SC27XX_FGU_POCV, &volt);
249 if (ret)
250 return ret;
251
Baolin Wang65c9fab2018-11-14 17:07:05 +0800252 volt = sc27xx_fgu_adc_to_voltage(data, volt);
Baolin Wang195ca172018-11-05 15:39:11 +0800253 ocv = volt * 1000 - oci * data->internal_resist;
254
255 /*
256 * Parse the capacity table to look up the correct capacity percent
257 * according to current battery's corresponding OCV values.
258 */
259 *cap = power_supply_ocv2cap_simple(data->cap_table, data->table_len,
260 ocv);
261
Yuanjiang Yu4a040e72018-12-06 11:20:39 +0800262 ret = sc27xx_fgu_save_last_cap(data, *cap);
263 if (ret)
264 return ret;
265
266 return sc27xx_fgu_save_boot_mode(data, SC27XX_FGU_NORMAIL_POWERTON);
Baolin Wang195ca172018-11-05 15:39:11 +0800267}
268
269static int sc27xx_fgu_set_clbcnt(struct sc27xx_fgu_data *data, int clbcnt)
270{
271 int ret;
272
273 clbcnt *= SC27XX_FGU_SAMPLE_HZ;
274
275 ret = regmap_update_bits(data->regmap,
276 data->base + SC27XX_FGU_CLBCNT_SETL,
277 SC27XX_FGU_CLBCNT_MASK, clbcnt);
278 if (ret)
279 return ret;
280
281 ret = regmap_update_bits(data->regmap,
282 data->base + SC27XX_FGU_CLBCNT_SETH,
283 SC27XX_FGU_CLBCNT_MASK,
284 clbcnt >> SC27XX_FGU_CLBCNT_SHIFT);
285 if (ret)
286 return ret;
287
288 return regmap_update_bits(data->regmap, data->base + SC27XX_FGU_START,
289 SC27XX_WRITE_SELCLB_EN,
290 SC27XX_WRITE_SELCLB_EN);
291}
292
293static int sc27xx_fgu_get_clbcnt(struct sc27xx_fgu_data *data, int *clb_cnt)
294{
295 int ccl, cch, ret;
296
297 ret = regmap_read(data->regmap, data->base + SC27XX_FGU_CLBCNT_VALL,
298 &ccl);
299 if (ret)
300 return ret;
301
302 ret = regmap_read(data->regmap, data->base + SC27XX_FGU_CLBCNT_VALH,
303 &cch);
304 if (ret)
305 return ret;
306
307 *clb_cnt = ccl & SC27XX_FGU_CLBCNT_MASK;
308 *clb_cnt |= (cch & SC27XX_FGU_CLBCNT_MASK) << SC27XX_FGU_CLBCNT_SHIFT;
309 *clb_cnt /= SC27XX_FGU_SAMPLE_HZ;
310
311 return 0;
312}
313
314static int sc27xx_fgu_get_capacity(struct sc27xx_fgu_data *data, int *cap)
315{
316 int ret, cur_clbcnt, delta_clbcnt, delta_cap, temp;
317
318 /* Get current coulomb counters firstly */
319 ret = sc27xx_fgu_get_clbcnt(data, &cur_clbcnt);
320 if (ret)
321 return ret;
322
323 delta_clbcnt = cur_clbcnt - data->init_clbcnt;
324
325 /*
326 * Convert coulomb counter to delta capacity (mAh), and set multiplier
327 * as 100 to improve the precision.
328 */
329 temp = DIV_ROUND_CLOSEST(delta_clbcnt, 360);
Baolin Wang65c9fab2018-11-14 17:07:05 +0800330 temp = sc27xx_fgu_adc_to_current(data, temp);
Baolin Wang195ca172018-11-05 15:39:11 +0800331
332 /*
333 * Convert to capacity percent of the battery total capacity,
334 * and multiplier is 100 too.
335 */
336 delta_cap = DIV_ROUND_CLOSEST(temp * 100, data->total_cap);
337 *cap = delta_cap + data->init_cap;
338
339 return 0;
340}
341
342static int sc27xx_fgu_get_vbat_vol(struct sc27xx_fgu_data *data, int *val)
343{
344 int ret, vol;
345
346 ret = regmap_read(data->regmap, data->base + SC27XX_FGU_VOLTAGE, &vol);
347 if (ret)
348 return ret;
349
350 /*
351 * It is ADC values reading from registers which need to convert to
352 * corresponding voltage values.
353 */
Baolin Wang65c9fab2018-11-14 17:07:05 +0800354 *val = sc27xx_fgu_adc_to_voltage(data, vol);
Baolin Wang195ca172018-11-05 15:39:11 +0800355
356 return 0;
357}
358
359static int sc27xx_fgu_get_current(struct sc27xx_fgu_data *data, int *val)
360{
361 int ret, cur;
362
363 ret = regmap_read(data->regmap, data->base + SC27XX_FGU_CURRENT, &cur);
364 if (ret)
365 return ret;
366
367 /*
368 * It is ADC values reading from registers which need to convert to
369 * corresponding current values.
370 */
Baolin Wang65c9fab2018-11-14 17:07:05 +0800371 *val = sc27xx_fgu_adc_to_current(data, cur - SC27XX_FGU_CUR_BASIC_ADC);
Baolin Wang195ca172018-11-05 15:39:11 +0800372
373 return 0;
374}
375
376static int sc27xx_fgu_get_vbat_ocv(struct sc27xx_fgu_data *data, int *val)
377{
378 int vol, cur, ret;
379
380 ret = sc27xx_fgu_get_vbat_vol(data, &vol);
381 if (ret)
382 return ret;
383
384 ret = sc27xx_fgu_get_current(data, &cur);
385 if (ret)
386 return ret;
387
388 /* Return the battery OCV in micro volts. */
389 *val = vol * 1000 - cur * data->internal_resist;
390
391 return 0;
392}
393
394static int sc27xx_fgu_get_temp(struct sc27xx_fgu_data *data, int *temp)
395{
396 return iio_read_channel_processed(data->channel, temp);
397}
398
399static int sc27xx_fgu_get_health(struct sc27xx_fgu_data *data, int *health)
400{
401 int ret, vol;
402
403 ret = sc27xx_fgu_get_vbat_vol(data, &vol);
404 if (ret)
405 return ret;
406
407 if (vol > data->max_volt)
408 *health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
409 else
410 *health = POWER_SUPPLY_HEALTH_GOOD;
411
412 return 0;
413}
414
415static int sc27xx_fgu_get_status(struct sc27xx_fgu_data *data, int *status)
416{
417 union power_supply_propval val;
418 struct power_supply *psy;
419 int i, ret = -EINVAL;
420
421 for (i = 0; i < ARRAY_SIZE(sc27xx_charger_supply_name); i++) {
422 psy = power_supply_get_by_name(sc27xx_charger_supply_name[i]);
423 if (!psy)
424 continue;
425
426 ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS,
427 &val);
428 power_supply_put(psy);
429 if (ret)
430 return ret;
431
432 *status = val.intval;
433 }
434
435 return ret;
436}
437
438static int sc27xx_fgu_get_property(struct power_supply *psy,
439 enum power_supply_property psp,
440 union power_supply_propval *val)
441{
442 struct sc27xx_fgu_data *data = power_supply_get_drvdata(psy);
443 int ret = 0;
444 int value;
445
446 mutex_lock(&data->lock);
447
448 switch (psp) {
449 case POWER_SUPPLY_PROP_STATUS:
450 ret = sc27xx_fgu_get_status(data, &value);
451 if (ret)
452 goto error;
453
454 val->intval = value;
455 break;
456
457 case POWER_SUPPLY_PROP_HEALTH:
458 ret = sc27xx_fgu_get_health(data, &value);
459 if (ret)
460 goto error;
461
462 val->intval = value;
463 break;
464
465 case POWER_SUPPLY_PROP_PRESENT:
466 val->intval = data->bat_present;
467 break;
468
469 case POWER_SUPPLY_PROP_TEMP:
470 ret = sc27xx_fgu_get_temp(data, &value);
471 if (ret)
472 goto error;
473
474 val->intval = value;
475 break;
476
477 case POWER_SUPPLY_PROP_TECHNOLOGY:
478 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
479 break;
480
481 case POWER_SUPPLY_PROP_CAPACITY:
482 ret = sc27xx_fgu_get_capacity(data, &value);
483 if (ret)
484 goto error;
485
486 val->intval = value;
487 break;
488
489 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
490 ret = sc27xx_fgu_get_vbat_vol(data, &value);
491 if (ret)
492 goto error;
493
494 val->intval = value * 1000;
495 break;
496
497 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
498 ret = sc27xx_fgu_get_vbat_ocv(data, &value);
499 if (ret)
500 goto error;
501
502 val->intval = value;
503 break;
504
505 case POWER_SUPPLY_PROP_CURRENT_NOW:
506 case POWER_SUPPLY_PROP_CURRENT_AVG:
507 ret = sc27xx_fgu_get_current(data, &value);
508 if (ret)
509 goto error;
510
511 val->intval = value * 1000;
512 break;
513
514 default:
515 ret = -EINVAL;
516 break;
517 }
518
519error:
520 mutex_unlock(&data->lock);
521 return ret;
522}
523
Yuanjiang Yu4a040e72018-12-06 11:20:39 +0800524static int sc27xx_fgu_set_property(struct power_supply *psy,
525 enum power_supply_property psp,
526 const union power_supply_propval *val)
527{
528 struct sc27xx_fgu_data *data = power_supply_get_drvdata(psy);
529 int ret;
530
531 if (psp != POWER_SUPPLY_PROP_CAPACITY)
532 return -EINVAL;
533
534 mutex_lock(&data->lock);
535
536 ret = sc27xx_fgu_save_last_cap(data, val->intval);
537
538 mutex_unlock(&data->lock);
539
540 if (ret < 0)
541 dev_err(data->dev, "failed to save battery capacity\n");
542
543 return ret;
544}
545
Baolin Wang195ca172018-11-05 15:39:11 +0800546static void sc27xx_fgu_external_power_changed(struct power_supply *psy)
547{
548 struct sc27xx_fgu_data *data = power_supply_get_drvdata(psy);
549
550 power_supply_changed(data->battery);
551}
552
Yuanjiang Yu4a040e72018-12-06 11:20:39 +0800553static int sc27xx_fgu_property_is_writeable(struct power_supply *psy,
554 enum power_supply_property psp)
555{
556 return psp == POWER_SUPPLY_PROP_CAPACITY;
557}
558
Baolin Wang195ca172018-11-05 15:39:11 +0800559static enum power_supply_property sc27xx_fgu_props[] = {
560 POWER_SUPPLY_PROP_STATUS,
561 POWER_SUPPLY_PROP_HEALTH,
562 POWER_SUPPLY_PROP_PRESENT,
563 POWER_SUPPLY_PROP_TEMP,
564 POWER_SUPPLY_PROP_TECHNOLOGY,
565 POWER_SUPPLY_PROP_CAPACITY,
566 POWER_SUPPLY_PROP_VOLTAGE_NOW,
567 POWER_SUPPLY_PROP_VOLTAGE_OCV,
568 POWER_SUPPLY_PROP_CURRENT_NOW,
569 POWER_SUPPLY_PROP_CURRENT_AVG,
570};
571
572static const struct power_supply_desc sc27xx_fgu_desc = {
573 .name = "sc27xx-fgu",
574 .type = POWER_SUPPLY_TYPE_BATTERY,
575 .properties = sc27xx_fgu_props,
576 .num_properties = ARRAY_SIZE(sc27xx_fgu_props),
577 .get_property = sc27xx_fgu_get_property,
Yuanjiang Yu4a040e72018-12-06 11:20:39 +0800578 .set_property = sc27xx_fgu_set_property,
Baolin Wang195ca172018-11-05 15:39:11 +0800579 .external_power_changed = sc27xx_fgu_external_power_changed,
Yuanjiang Yu4a040e72018-12-06 11:20:39 +0800580 .property_is_writeable = sc27xx_fgu_property_is_writeable,
Baolin Wang195ca172018-11-05 15:39:11 +0800581};
582
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +0800583static void sc27xx_fgu_adjust_cap(struct sc27xx_fgu_data *data, int cap)
584{
585 data->init_cap = cap;
586 data->init_clbcnt = sc27xx_fgu_cap_to_clbcnt(data, data->init_cap);
587}
588
589static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id)
590{
591 struct sc27xx_fgu_data *data = dev_id;
592 int ret, cap, ocv, adc;
593 u32 status;
594
595 mutex_lock(&data->lock);
596
597 ret = regmap_read(data->regmap, data->base + SC27XX_FGU_INT_STS,
598 &status);
599 if (ret)
600 goto out;
601
602 ret = regmap_update_bits(data->regmap, data->base + SC27XX_FGU_INT_CLR,
603 status, status);
604 if (ret)
605 goto out;
606
607 /*
608 * When low overload voltage interrupt happens, we should calibrate the
609 * battery capacity in lower voltage stage.
610 */
611 if (!(status & SC27XX_FGU_LOW_OVERLOAD_INT))
612 goto out;
613
614 ret = sc27xx_fgu_get_capacity(data, &cap);
615 if (ret)
616 goto out;
617
618 ret = sc27xx_fgu_get_vbat_ocv(data, &ocv);
619 if (ret)
620 goto out;
621
622 /*
623 * If current OCV value is less than the minimum OCV value in OCV table,
624 * which means now battery capacity is 0%, and we should adjust the
625 * inititial capacity to 0.
626 */
627 if (ocv <= data->cap_table[data->table_len - 1].ocv) {
628 sc27xx_fgu_adjust_cap(data, 0);
629 } else if (ocv <= data->min_volt) {
630 /*
631 * If current OCV value is less than the low alarm voltage, but
632 * current capacity is larger than the alarm capacity, we should
633 * adjust the inititial capacity to alarm capacity.
634 */
635 if (cap > data->alarm_cap) {
636 sc27xx_fgu_adjust_cap(data, data->alarm_cap);
637 } else if (cap <= 0) {
638 int cur_cap;
639
640 /*
641 * If current capacity is equal with 0 or less than 0
642 * (some error occurs), we should adjust inititial
643 * capacity to the capacity corresponding to current OCV
644 * value.
645 */
646 cur_cap = power_supply_ocv2cap_simple(data->cap_table,
647 data->table_len,
648 ocv);
649 sc27xx_fgu_adjust_cap(data, cur_cap);
650 }
651
652 /*
653 * After adjusting the battery capacity, we should set the
654 * lowest alarm voltage instead.
655 */
656 data->min_volt = data->cap_table[data->table_len - 1].ocv;
657 adc = sc27xx_fgu_voltage_to_adc(data, data->min_volt / 1000);
658 regmap_update_bits(data->regmap, data->base + SC27XX_FGU_LOW_OVERLOAD,
659 SC27XX_FGU_LOW_OVERLOAD_MASK, adc);
660 }
661
662out:
663 mutex_unlock(&data->lock);
664
665 power_supply_changed(data->battery);
666 return IRQ_HANDLED;
667}
668
Baolin Wang195ca172018-11-05 15:39:11 +0800669static irqreturn_t sc27xx_fgu_bat_detection(int irq, void *dev_id)
670{
671 struct sc27xx_fgu_data *data = dev_id;
672 int state;
673
674 mutex_lock(&data->lock);
675
676 state = gpiod_get_value_cansleep(data->gpiod);
677 if (state < 0) {
678 dev_err(data->dev, "failed to get gpio state\n");
679 mutex_unlock(&data->lock);
680 return IRQ_RETVAL(state);
681 }
682
683 data->bat_present = !!state;
684
685 mutex_unlock(&data->lock);
686
687 power_supply_changed(data->battery);
688 return IRQ_HANDLED;
689}
690
691static void sc27xx_fgu_disable(void *_data)
692{
693 struct sc27xx_fgu_data *data = _data;
694
695 regmap_update_bits(data->regmap, SC27XX_CLK_EN0, SC27XX_FGU_RTC_EN, 0);
696 regmap_update_bits(data->regmap, SC27XX_MODULE_EN0, SC27XX_FGU_EN, 0);
697}
698
699static int sc27xx_fgu_cap_to_clbcnt(struct sc27xx_fgu_data *data, int capacity)
700{
701 /*
702 * Get current capacity (mAh) = battery total capacity (mAh) *
703 * current capacity percent (capacity / 100).
704 */
705 int cur_cap = DIV_ROUND_CLOSEST(data->total_cap * capacity, 100);
706
707 /*
708 * Convert current capacity (mAh) to coulomb counter according to the
709 * formula: 1 mAh =3.6 coulomb.
710 */
711 return DIV_ROUND_CLOSEST(cur_cap * 36, 10);
712}
713
Baolin Wang65c9fab2018-11-14 17:07:05 +0800714static int sc27xx_fgu_calibration(struct sc27xx_fgu_data *data)
715{
716 struct nvmem_cell *cell;
717 int calib_data, cal_4200mv;
718 void *buf;
719 size_t len;
720
721 cell = nvmem_cell_get(data->dev, "fgu_calib");
722 if (IS_ERR(cell))
723 return PTR_ERR(cell);
724
725 buf = nvmem_cell_read(cell, &len);
726 nvmem_cell_put(cell);
727
728 if (IS_ERR(buf))
729 return PTR_ERR(buf);
730
731 memcpy(&calib_data, buf, min(len, sizeof(u32)));
732
733 /*
734 * Get the ADC value corresponding to 4200 mV from eFuse controller
735 * according to below formula. Then convert to ADC values corresponding
736 * to 1000 mV and 1000 mA.
737 */
738 cal_4200mv = (calib_data & 0x1ff) + 6963 - 4096 - 256;
739 data->vol_1000mv_adc = DIV_ROUND_CLOSEST(cal_4200mv * 10, 42);
740 data->cur_1000ma_adc = data->vol_1000mv_adc * 4;
741
742 kfree(buf);
743 return 0;
744}
745
Baolin Wang195ca172018-11-05 15:39:11 +0800746static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
747{
748 struct power_supply_battery_info info = { };
749 struct power_supply_battery_ocv_table *table;
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +0800750 int ret, delta_clbcnt, alarm_adc;
Baolin Wang195ca172018-11-05 15:39:11 +0800751
752 ret = power_supply_get_battery_info(data->battery, &info);
753 if (ret) {
754 dev_err(data->dev, "failed to get battery information\n");
755 return ret;
756 }
757
758 data->total_cap = info.charge_full_design_uah / 1000;
759 data->max_volt = info.constant_charge_voltage_max_uv / 1000;
760 data->internal_resist = info.factory_internal_resistance_uohm / 1000;
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +0800761 data->min_volt = info.voltage_min_design_uv;
Baolin Wang195ca172018-11-05 15:39:11 +0800762
763 /*
764 * For SC27XX fuel gauge device, we only use one ocv-capacity
765 * table in normal temperature 20 Celsius.
766 */
767 table = power_supply_find_ocv2cap_table(&info, 20, &data->table_len);
768 if (!table)
769 return -EINVAL;
770
771 data->cap_table = devm_kmemdup(data->dev, table,
772 data->table_len * sizeof(*table),
773 GFP_KERNEL);
774 if (!data->cap_table) {
775 power_supply_put_battery_info(data->battery, &info);
776 return -ENOMEM;
777 }
778
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +0800779 data->alarm_cap = power_supply_ocv2cap_simple(data->cap_table,
780 data->table_len,
781 data->min_volt);
782
Baolin Wang195ca172018-11-05 15:39:11 +0800783 power_supply_put_battery_info(data->battery, &info);
784
Baolin Wang65c9fab2018-11-14 17:07:05 +0800785 ret = sc27xx_fgu_calibration(data);
786 if (ret)
787 return ret;
788
Baolin Wang195ca172018-11-05 15:39:11 +0800789 /* Enable the FGU module */
790 ret = regmap_update_bits(data->regmap, SC27XX_MODULE_EN0,
791 SC27XX_FGU_EN, SC27XX_FGU_EN);
792 if (ret) {
793 dev_err(data->dev, "failed to enable fgu\n");
794 return ret;
795 }
796
797 /* Enable the FGU RTC clock to make it work */
798 ret = regmap_update_bits(data->regmap, SC27XX_CLK_EN0,
799 SC27XX_FGU_RTC_EN, SC27XX_FGU_RTC_EN);
800 if (ret) {
801 dev_err(data->dev, "failed to enable fgu RTC clock\n");
802 goto disable_fgu;
803 }
804
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +0800805 ret = regmap_update_bits(data->regmap, data->base + SC27XX_FGU_INT_CLR,
806 SC27XX_FGU_INT_MASK, SC27XX_FGU_INT_MASK);
807 if (ret) {
808 dev_err(data->dev, "failed to clear interrupt status\n");
809 goto disable_clk;
810 }
811
812 /*
813 * Set the voltage low overload threshold, which means when the battery
814 * voltage is lower than this threshold, the controller will generate
815 * one interrupt to notify.
816 */
817 alarm_adc = sc27xx_fgu_voltage_to_adc(data, data->min_volt / 1000);
818 ret = regmap_update_bits(data->regmap, data->base + SC27XX_FGU_LOW_OVERLOAD,
819 SC27XX_FGU_LOW_OVERLOAD_MASK, alarm_adc);
820 if (ret) {
821 dev_err(data->dev, "failed to set fgu low overload\n");
822 goto disable_clk;
823 }
824
825 /*
826 * Set the coulomb counter delta threshold, that means when the coulomb
827 * counter change is multiples of the delta threshold, the controller
828 * will generate one interrupt to notify the users to update the battery
829 * capacity. Now we set the delta threshold as a counter value of 1%
830 * capacity.
831 */
832 delta_clbcnt = sc27xx_fgu_cap_to_clbcnt(data, 1);
833
834 ret = regmap_update_bits(data->regmap, data->base + SC27XX_FGU_CLBCNT_DELTL,
835 SC27XX_FGU_CLBCNT_MASK, delta_clbcnt);
836 if (ret) {
837 dev_err(data->dev, "failed to set low delta coulomb counter\n");
838 goto disable_clk;
839 }
840
841 ret = regmap_update_bits(data->regmap, data->base + SC27XX_FGU_CLBCNT_DELTH,
842 SC27XX_FGU_CLBCNT_MASK,
843 delta_clbcnt >> SC27XX_FGU_CLBCNT_SHIFT);
844 if (ret) {
845 dev_err(data->dev, "failed to set high delta coulomb counter\n");
846 goto disable_clk;
847 }
848
Baolin Wang195ca172018-11-05 15:39:11 +0800849 /*
850 * Get the boot battery capacity when system powers on, which is used to
851 * initialize the coulomb counter. After that, we can read the coulomb
852 * counter to measure the battery capacity.
853 */
854 ret = sc27xx_fgu_get_boot_capacity(data, &data->init_cap);
855 if (ret) {
856 dev_err(data->dev, "failed to get boot capacity\n");
857 goto disable_clk;
858 }
859
860 /*
861 * Convert battery capacity to the corresponding initial coulomb counter
862 * and set into coulomb counter registers.
863 */
864 data->init_clbcnt = sc27xx_fgu_cap_to_clbcnt(data, data->init_cap);
865 ret = sc27xx_fgu_set_clbcnt(data, data->init_clbcnt);
866 if (ret) {
867 dev_err(data->dev, "failed to initialize coulomb counter\n");
868 goto disable_clk;
869 }
870
871 return 0;
872
873disable_clk:
874 regmap_update_bits(data->regmap, SC27XX_CLK_EN0, SC27XX_FGU_RTC_EN, 0);
875disable_fgu:
876 regmap_update_bits(data->regmap, SC27XX_MODULE_EN0, SC27XX_FGU_EN, 0);
877
878 return ret;
879}
880
881static int sc27xx_fgu_probe(struct platform_device *pdev)
882{
883 struct device_node *np = pdev->dev.of_node;
884 struct power_supply_config fgu_cfg = { };
885 struct sc27xx_fgu_data *data;
886 int ret, irq;
887
888 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
889 if (!data)
890 return -ENOMEM;
891
892 data->regmap = dev_get_regmap(pdev->dev.parent, NULL);
893 if (!data->regmap) {
894 dev_err(&pdev->dev, "failed to get regmap\n");
895 return -ENODEV;
896 }
897
898 ret = device_property_read_u32(&pdev->dev, "reg", &data->base);
899 if (ret) {
900 dev_err(&pdev->dev, "failed to get fgu address\n");
901 return ret;
902 }
903
904 data->channel = devm_iio_channel_get(&pdev->dev, "bat-temp");
905 if (IS_ERR(data->channel)) {
906 dev_err(&pdev->dev, "failed to get IIO channel\n");
907 return PTR_ERR(data->channel);
908 }
909
910 data->gpiod = devm_gpiod_get(&pdev->dev, "bat-detect", GPIOD_IN);
911 if (IS_ERR(data->gpiod)) {
912 dev_err(&pdev->dev, "failed to get battery detection GPIO\n");
913 return PTR_ERR(data->gpiod);
914 }
915
916 ret = gpiod_get_value_cansleep(data->gpiod);
917 if (ret < 0) {
918 dev_err(&pdev->dev, "failed to get gpio state\n");
919 return ret;
920 }
921
922 data->bat_present = !!ret;
923 mutex_init(&data->lock);
924 data->dev = &pdev->dev;
Yuanjiang Yue2fb6152018-11-14 17:07:07 +0800925 platform_set_drvdata(pdev, data);
Baolin Wang195ca172018-11-05 15:39:11 +0800926
927 fgu_cfg.drv_data = data;
928 fgu_cfg.of_node = np;
929 data->battery = devm_power_supply_register(&pdev->dev, &sc27xx_fgu_desc,
930 &fgu_cfg);
931 if (IS_ERR(data->battery)) {
932 dev_err(&pdev->dev, "failed to register power supply\n");
933 return PTR_ERR(data->battery);
934 }
935
936 ret = sc27xx_fgu_hw_init(data);
937 if (ret) {
938 dev_err(&pdev->dev, "failed to initialize fgu hardware\n");
939 return ret;
940 }
941
942 ret = devm_add_action(&pdev->dev, sc27xx_fgu_disable, data);
943 if (ret) {
944 sc27xx_fgu_disable(data);
945 dev_err(&pdev->dev, "failed to add fgu disable action\n");
946 return ret;
947 }
948
Yuanjiang Yuedcb1c02018-11-14 17:07:06 +0800949 irq = platform_get_irq(pdev, 0);
950 if (irq < 0) {
951 dev_err(&pdev->dev, "no irq resource specified\n");
952 return irq;
953 }
954
955 ret = devm_request_threaded_irq(data->dev, irq, NULL,
956 sc27xx_fgu_interrupt,
957 IRQF_NO_SUSPEND | IRQF_ONESHOT,
958 pdev->name, data);
959 if (ret) {
960 dev_err(data->dev, "failed to request fgu IRQ\n");
961 return ret;
962 }
963
Baolin Wang195ca172018-11-05 15:39:11 +0800964 irq = gpiod_to_irq(data->gpiod);
965 if (irq < 0) {
966 dev_err(&pdev->dev, "failed to translate GPIO to IRQ\n");
967 return irq;
968 }
969
970 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
971 sc27xx_fgu_bat_detection,
972 IRQF_ONESHOT | IRQF_TRIGGER_RISING |
973 IRQF_TRIGGER_FALLING,
974 pdev->name, data);
975 if (ret) {
976 dev_err(&pdev->dev, "failed to request IRQ\n");
977 return ret;
978 }
979
980 return 0;
981}
982
Yuanjiang Yue2fb6152018-11-14 17:07:07 +0800983#ifdef CONFIG_PM_SLEEP
984static int sc27xx_fgu_resume(struct device *dev)
985{
986 struct sc27xx_fgu_data *data = dev_get_drvdata(dev);
987 int ret;
988
989 ret = regmap_update_bits(data->regmap, data->base + SC27XX_FGU_INT_EN,
990 SC27XX_FGU_LOW_OVERLOAD_INT |
991 SC27XX_FGU_CLBCNT_DELTA_INT, 0);
992 if (ret) {
993 dev_err(data->dev, "failed to disable fgu interrupts\n");
994 return ret;
995 }
996
997 return 0;
998}
999
1000static int sc27xx_fgu_suspend(struct device *dev)
1001{
1002 struct sc27xx_fgu_data *data = dev_get_drvdata(dev);
1003 int ret, status, ocv;
1004
1005 ret = sc27xx_fgu_get_status(data, &status);
1006 if (ret)
1007 return ret;
1008
1009 /*
1010 * If we are charging, then no need to enable the FGU interrupts to
1011 * adjust the battery capacity.
1012 */
1013 if (status != POWER_SUPPLY_STATUS_NOT_CHARGING)
1014 return 0;
1015
1016 ret = regmap_update_bits(data->regmap, data->base + SC27XX_FGU_INT_EN,
1017 SC27XX_FGU_LOW_OVERLOAD_INT,
1018 SC27XX_FGU_LOW_OVERLOAD_INT);
1019 if (ret) {
1020 dev_err(data->dev, "failed to enable low voltage interrupt\n");
1021 return ret;
1022 }
1023
1024 ret = sc27xx_fgu_get_vbat_ocv(data, &ocv);
1025 if (ret)
1026 goto disable_int;
1027
1028 /*
1029 * If current OCV is less than the minimum voltage, we should enable the
1030 * coulomb counter threshold interrupt to notify events to adjust the
1031 * battery capacity.
1032 */
1033 if (ocv < data->min_volt) {
1034 ret = regmap_update_bits(data->regmap,
1035 data->base + SC27XX_FGU_INT_EN,
1036 SC27XX_FGU_CLBCNT_DELTA_INT,
1037 SC27XX_FGU_CLBCNT_DELTA_INT);
1038 if (ret) {
1039 dev_err(data->dev,
1040 "failed to enable coulomb threshold int\n");
1041 goto disable_int;
1042 }
1043 }
1044
1045 return 0;
1046
1047disable_int:
1048 regmap_update_bits(data->regmap, data->base + SC27XX_FGU_INT_EN,
1049 SC27XX_FGU_LOW_OVERLOAD_INT, 0);
1050 return ret;
1051}
1052#endif
1053
1054static const struct dev_pm_ops sc27xx_fgu_pm_ops = {
1055 SET_SYSTEM_SLEEP_PM_OPS(sc27xx_fgu_suspend, sc27xx_fgu_resume)
1056};
1057
Baolin Wang195ca172018-11-05 15:39:11 +08001058static const struct of_device_id sc27xx_fgu_of_match[] = {
1059 { .compatible = "sprd,sc2731-fgu", },
1060 { }
1061};
1062
1063static struct platform_driver sc27xx_fgu_driver = {
1064 .probe = sc27xx_fgu_probe,
1065 .driver = {
1066 .name = "sc27xx-fgu",
1067 .of_match_table = sc27xx_fgu_of_match,
Yuanjiang Yue2fb6152018-11-14 17:07:07 +08001068 .pm = &sc27xx_fgu_pm_ops,
Baolin Wang195ca172018-11-05 15:39:11 +08001069 }
1070};
1071
1072module_platform_driver(sc27xx_fgu_driver);
1073
1074MODULE_DESCRIPTION("Spreadtrum SC27XX PMICs Fual Gauge Unit Driver");
1075MODULE_LICENSE("GPL v2");