#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/nvmem-consumer.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
 #include <linux/regmap.h>
+#include <linux/slab.h>
 
 /* PMIC global control registers definition */
 #define SC27XX_MODULE_EN0              0xc08
 #define SC27XX_FGU_CLBCNT_MASK         GENMASK(15, 0)
 #define SC27XX_FGU_CLBCNT_SHIFT                16
 
-#define SC27XX_FGU_1000MV_ADC          686
-#define SC27XX_FGU_1000MA_ADC          1372
 #define SC27XX_FGU_CUR_BASIC_ADC       8192
 #define SC27XX_FGU_SAMPLE_HZ           2
 
  * @init_clbcnt: the initial coulomb counter
  * @max_volt: the maximum constant input voltage in millivolt
  * @table_len: the capacity table length
+ * @cur_1000ma_adc: ADC value corresponding to 1000 mA
+ * @vol_1000mv_adc: ADC value corresponding to 1000 mV
  * @cap_table: capacity table with corresponding ocv
  */
 struct sc27xx_fgu_data {
        int init_clbcnt;
        int max_volt;
        int table_len;
+       int cur_1000ma_adc;
+       int vol_1000mv_adc;
        struct power_supply_battery_ocv_table *cap_table;
 };
 
        "sc2723_charger",
 };
 
-static int sc27xx_fgu_adc_to_current(int adc)
+static int sc27xx_fgu_adc_to_current(struct sc27xx_fgu_data *data, int adc)
 {
-       return DIV_ROUND_CLOSEST(adc * 1000, SC27XX_FGU_1000MA_ADC);
+       return DIV_ROUND_CLOSEST(adc * 1000, data->cur_1000ma_adc);
 }
 
-static int sc27xx_fgu_adc_to_voltage(int adc)
+static int sc27xx_fgu_adc_to_voltage(struct sc27xx_fgu_data *data, int adc)
 {
-       return DIV_ROUND_CLOSEST(adc * 1000, SC27XX_FGU_1000MV_ADC);
+       return DIV_ROUND_CLOSEST(adc * 1000, data->vol_1000mv_adc);
 }
 
 /*
                return ret;
 
        cur <<= 1;
-       oci = sc27xx_fgu_adc_to_current(cur - SC27XX_FGU_CUR_BASIC_ADC);
+       oci = sc27xx_fgu_adc_to_current(data, cur - SC27XX_FGU_CUR_BASIC_ADC);
 
        /*
         * Should get the OCV from SC27XX_FGU_POCV register at the system
        if (ret)
                return ret;
 
-       volt = sc27xx_fgu_adc_to_voltage(volt);
+       volt = sc27xx_fgu_adc_to_voltage(data, volt);
        ocv = volt * 1000 - oci * data->internal_resist;
 
        /*
         * as 100 to improve the precision.
         */
        temp = DIV_ROUND_CLOSEST(delta_clbcnt, 360);
-       temp = sc27xx_fgu_adc_to_current(temp);
+       temp = sc27xx_fgu_adc_to_current(data, temp);
 
        /*
         * Convert to capacity percent of the battery total capacity,
         * It is ADC values reading from registers which need to convert to
         * corresponding voltage values.
         */
-       *val = sc27xx_fgu_adc_to_voltage(vol);
+       *val = sc27xx_fgu_adc_to_voltage(data, vol);
 
        return 0;
 }
         * It is ADC values reading from registers which need to convert to
         * corresponding current values.
         */
-       *val = sc27xx_fgu_adc_to_current(cur - SC27XX_FGU_CUR_BASIC_ADC);
+       *val = sc27xx_fgu_adc_to_current(data, cur - SC27XX_FGU_CUR_BASIC_ADC);
 
        return 0;
 }
        return DIV_ROUND_CLOSEST(cur_cap * 36, 10);
 }
 
+static int sc27xx_fgu_calibration(struct sc27xx_fgu_data *data)
+{
+       struct nvmem_cell *cell;
+       int calib_data, cal_4200mv;
+       void *buf;
+       size_t len;
+
+       cell = nvmem_cell_get(data->dev, "fgu_calib");
+       if (IS_ERR(cell))
+               return PTR_ERR(cell);
+
+       buf = nvmem_cell_read(cell, &len);
+       nvmem_cell_put(cell);
+
+       if (IS_ERR(buf))
+               return PTR_ERR(buf);
+
+       memcpy(&calib_data, buf, min(len, sizeof(u32)));
+
+       /*
+        * Get the ADC value corresponding to 4200 mV from eFuse controller
+        * according to below formula. Then convert to ADC values corresponding
+        * to 1000 mV and 1000 mA.
+        */
+       cal_4200mv = (calib_data & 0x1ff) + 6963 - 4096 - 256;
+       data->vol_1000mv_adc = DIV_ROUND_CLOSEST(cal_4200mv * 10, 42);
+       data->cur_1000ma_adc = data->vol_1000mv_adc * 4;
+
+       kfree(buf);
+       return 0;
+}
+
 static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
 {
        struct power_supply_battery_info info = { };
 
        power_supply_put_battery_info(data->battery, &info);
 
+       ret = sc27xx_fgu_calibration(data);
+       if (ret)
+               return ret;
+
        /* Enable the FGU module */
        ret = regmap_update_bits(data->regmap, SC27XX_MODULE_EN0,
                                 SC27XX_FGU_EN, SC27XX_FGU_EN);