root/drivers/power/supply/sc27xx_fuel_gauge.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sc27xx_fgu_adc_to_current
  2. sc27xx_fgu_adc_to_voltage
  3. sc27xx_fgu_voltage_to_adc
  4. sc27xx_fgu_is_first_poweron
  5. sc27xx_fgu_save_boot_mode
  6. sc27xx_fgu_save_last_cap
  7. sc27xx_fgu_read_last_cap
  8. sc27xx_fgu_get_boot_capacity
  9. sc27xx_fgu_set_clbcnt
  10. sc27xx_fgu_get_clbcnt
  11. sc27xx_fgu_get_capacity
  12. sc27xx_fgu_get_vbat_vol
  13. sc27xx_fgu_get_current
  14. sc27xx_fgu_get_vbat_ocv
  15. sc27xx_fgu_get_charge_vol
  16. sc27xx_fgu_get_temp
  17. sc27xx_fgu_get_health
  18. sc27xx_fgu_get_status
  19. sc27xx_fgu_get_property
  20. sc27xx_fgu_set_property
  21. sc27xx_fgu_external_power_changed
  22. sc27xx_fgu_property_is_writeable
  23. sc27xx_fgu_adjust_cap
  24. sc27xx_fgu_capacity_calibration
  25. sc27xx_fgu_interrupt
  26. sc27xx_fgu_bat_detection
  27. sc27xx_fgu_disable
  28. sc27xx_fgu_cap_to_clbcnt
  29. sc27xx_fgu_calibration
  30. sc27xx_fgu_hw_init
  31. sc27xx_fgu_probe
  32. sc27xx_fgu_resume
  33. sc27xx_fgu_suspend

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

/* [<][>][^][v][top][bottom][index][help] */