* @fg_params          fuel gauge parameters
  */
 struct ab8500_bm_data {
-       struct power_supply_battery_info bi;
+       struct power_supply_battery_info *bi;
        int temp_now;
        int temp_interval_chg;
        int temp_interval_nochg;
 
 int ab8500_bm_of_probe(struct power_supply *psy,
                       struct ab8500_bm_data *bm)
 {
-       struct power_supply_battery_info *bi = &bm->bi;
+       struct power_supply_battery_info *bi;
        struct device *dev = &psy->dev;
        int ret;
 
-       ret = power_supply_get_battery_info(psy, bi);
+       ret = power_supply_get_battery_info(psy, &bm->bi);
        if (ret) {
                dev_err(dev, "cannot retrieve battery info\n");
                return ret;
        }
+       bi = bm->bi;
 
        /* Fill in defaults for any data missing from the device tree */
        if (bi->charge_full_design_uah < 0)
 void ab8500_bm_of_remove(struct power_supply *psy,
                         struct ab8500_bm_data *bm)
 {
-       power_supply_put_battery_info(psy, &bm->bi);
+       power_supply_put_battery_info(psy, bm->bi);
 }
 
  */
 static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
 {
+       struct power_supply_battery_info *bi = di->bm->bi;
        int temp, ret;
        static int prev;
        int rbat, rntc, vntc;
 
        if ((di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL) &&
-           (di->bm->bi.technology == POWER_SUPPLY_TECHNOLOGY_UNKNOWN)) {
+           (bi && (bi->technology == POWER_SUPPLY_TECHNOLOGY_UNKNOWN))) {
 
                rbat = ab8500_btemp_get_batctrl_res(di);
                if (rbat < 0) {
         * that need it.
         */
        if ((di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL) &&
-           (di->bm->bi.technology == POWER_SUPPLY_TECHNOLOGY_LIPO) &&
+           (di->bm->bi && (di->bm->bi->technology == POWER_SUPPLY_TECHNOLOGY_LIPO)) &&
            (res <= 53407) && (res >= 12500)) {
                dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
                di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA;
                        val->intval = 1;
                break;
        case POWER_SUPPLY_PROP_TECHNOLOGY:
-               val->intval = di->bm->bi.technology;
+               if (di->bm->bi)
+                       val->intval = di->bm->bi->technology;
+               else
+                       val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
                break;
        case POWER_SUPPLY_PROP_TEMP:
                val->intval = ab8500_btemp_get_temp(di);
 
 
 static int ab8500_chargalg_check_charger_enable(struct ab8500_chargalg *di)
 {
-       struct power_supply_battery_info *bi = &di->bm->bi;
+       struct power_supply_battery_info *bi = di->bm->bi;
 
        switch (di->charge_state) {
        case STATE_NORMAL:
  */
 static void ab8500_chargalg_check_temp(struct ab8500_chargalg *di)
 {
-       struct power_supply_battery_info *bi = &di->bm->bi;
+       struct power_supply_battery_info *bi = di->bm->bi;
 
        if (di->batt_data.temp > (bi->temp_alert_min + di->t_hyst_norm) &&
                di->batt_data.temp < (bi->temp_alert_max - di->t_hyst_norm)) {
        if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
                di->charge_state == STATE_NORMAL &&
                !di->maintenance_chg && (di->batt_data.volt_uv >=
-               di->bm->bi.overvoltage_limit_uv ||
+               di->bm->bi->overvoltage_limit_uv ||
                di->events.usb_cv_active || di->events.ac_cv_active) &&
                di->batt_data.avg_curr_ua <
-               di->bm->bi.charge_term_current_ua &&
+               di->bm->bi->charge_term_current_ua &&
                di->batt_data.avg_curr_ua > 0) {
                if (++di->eoc_cnt >= EOC_COND_CNT) {
                        di->eoc_cnt = 0;
 
 static void init_maxim_chg_curr(struct ab8500_chargalg *di)
 {
-       struct power_supply_battery_info *bi = &di->bm->bi;
+       struct power_supply_battery_info *bi = di->bm->bi;
 
        di->ccm.original_iset_ua = bi->constant_charge_current_max_ua;
        di->ccm.current_iset_ua = bi->constant_charge_current_max_ua;
 
 static void handle_maxim_chg_curr(struct ab8500_chargalg *di)
 {
-       struct power_supply_battery_info *bi = &di->bm->bi;
+       struct power_supply_battery_info *bi = di->bm->bi;
        enum maxim_ret ret;
        int result;
 
  */
 static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
 {
-       struct power_supply_battery_info *bi = &di->bm->bi;
+       struct power_supply_battery_info *bi = di->bm->bi;
        int charger_status;
        int ret;
        int curr_step_lvl_ua;
                if (di->events.batt_ovv) {
                        val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
                } else if (di->events.btemp_underover) {
-                       if (di->batt_data.temp <= di->bm->bi.temp_min)
+                       if (di->batt_data.temp <= di->bm->bi->temp_min)
                                val->intval = POWER_SUPPLY_HEALTH_COLD;
                        else
                                val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
 
  */
 static int ab8500_fg_volt_to_capacity(struct ab8500_fg *di, int voltage_uv)
 {
-       struct power_supply_battery_info *bi = &di->bm->bi;
+       struct power_supply_battery_info *bi = di->bm->bi;
 
        /* Multiply by 10 because the capacity is tracked in per mille */
        return power_supply_batinfo_ocv2cap(bi, voltage_uv, di->bat_temp) *  10;
  */
 static int ab8500_fg_battery_resistance(struct ab8500_fg *di)
 {
-       struct power_supply_battery_info *bi = &di->bm->bi;
+       struct power_supply_battery_info *bi = di->bm->bi;
        int resistance_percent = 0;
        int resistance;
 
        struct power_supply *ext = dev_get_drvdata(dev);
        const char **supplicants = (const char **)ext->supplied_to;
        struct ab8500_fg *di;
+       struct power_supply_battery_info *bi;
        union power_supply_propval ret;
        int j;
 
        psy = (struct power_supply *)data;
        di = power_supply_get_drvdata(psy);
+       bi = di->bm->bi;
 
        /*
         * For all psy where the name of your driver
                        switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_BATTERY:
                                if (!di->flags.batt_id_received &&
-                                   (di->bm->bi.technology !=
-                                    POWER_SUPPLY_TECHNOLOGY_UNKNOWN)) {
+                                   (bi && (bi->technology !=
+                                           POWER_SUPPLY_TECHNOLOGY_UNKNOWN))) {
                                        const struct ab8500_battery_type *b;
 
                                        b = di->bm->bat_type;
                                        di->flags.batt_id_received = true;
 
                                        di->bat_cap.max_mah_design =
-                                               di->bm->bi.charge_full_design_uah;
+                                               di->bm->bi->charge_full_design_uah;
 
                                        di->bat_cap.max_mah =
                                                di->bat_cap.max_mah_design;
 
                                        di->vbat_nom_uv =
-                                               di->bm->bi.voltage_max_design_uv;
+                                               di->bm->bi->voltage_max_design_uv;
                                }
 
                                if (ret.intval)
                return -ENOMEM;
        }
 
-       di->bat_cap.max_mah_design = di->bm->bi.charge_full_design_uah;
+       di->bat_cap.max_mah_design = di->bm->bi->charge_full_design_uah;
        di->bat_cap.max_mah = di->bat_cap.max_mah_design;
-       di->vbat_nom_uv = di->bm->bi.voltage_max_design_uv;
+       di->vbat_nom_uv = di->bm->bi->voltage_max_design_uv;
 
        /* Start the coulomb counter */
        ab8500_fg_coulomb_counter(di, true);
 
 {
        struct axp20x_batt_ps *axp20x_batt;
        struct power_supply_config psy_cfg = {};
-       struct power_supply_battery_info info;
+       struct power_supply_battery_info *info;
        struct device *dev = &pdev->dev;
 
        if (!of_device_is_available(pdev->dev.of_node))
        }
 
        if (!power_supply_get_battery_info(axp20x_batt->batt, &info)) {
-               int vmin = info.voltage_min_design_uv;
-               int ccc = info.constant_charge_current_max_ua;
+               int vmin = info->voltage_min_design_uv;
+               int ccc = info->constant_charge_current_max_ua;
 
                if (vmin > 0 && axp20x_set_voltage_min_design(axp20x_batt,
                                                              vmin))
 
 static int bd9995x_fw_probe(struct bd9995x_device *bd)
 {
        int ret;
-       struct power_supply_battery_info info;
+       struct power_supply_battery_info *info;
        u32 property;
        int i;
        int regval;
        struct battery_init battery_inits[] = {
                {
                        .name = "trickle-charging current",
-                       .info_data = &info.tricklecharge_current_ua,
                        .range = &charging_current_ranges[0],
                        .ranges = 2,
                        .data = &init->itrich_set,
                }, {
                        .name = "pre-charging current",
-                       .info_data = &info.precharge_current_ua,
                        .range = &charging_current_ranges[0],
                        .ranges = 2,
                        .data = &init->iprech_set,
                }, {
                        .name = "pre-to-trickle charge voltage threshold",
-                       .info_data = &info.precharge_voltage_max_uv,
                        .range = &trickle_to_pre_threshold_ranges[0],
                        .ranges = 2,
                        .data = &init->vprechg_th_set,
                }, {
                        .name = "charging termination current",
-                       .info_data = &info.charge_term_current_ua,
                        .range = &charging_current_ranges[0],
                        .ranges = 2,
                        .data = &init->iterm_set,
                }, {
                        .name = "charging re-start voltage",
-                       .info_data = &info.charge_restart_voltage_uv,
                        .range = &charge_voltage_regulation_ranges[0],
                        .ranges = 2,
                        .data = &init->vrechg_set,
                }, {
                        .name = "battery overvoltage limit",
-                       .info_data = &info.overvoltage_limit_uv,
                        .range = &charge_voltage_regulation_ranges[0],
                        .ranges = 2,
                        .data = &init->vbatovp_set,
                }, {
                        .name = "fast-charging max current",
-                       .info_data = &info.constant_charge_current_max_ua,
                        .range = &fast_charge_current_ranges[0],
                        .ranges = 1,
                        .data = &init->ichg_set,
                }, {
                        .name = "fast-charging voltage",
-                       .info_data = &info.constant_charge_voltage_max_uv,
                        .range = &charge_voltage_regulation_ranges[0],
                        .ranges = 2,
                        .data = &init->vfastchg_reg_set1,
        if (ret < 0)
                return ret;
 
+       /* Put pointers to the generic battery info */
+       battery_inits[0].info_data = &info->tricklecharge_current_ua;
+       battery_inits[1].info_data = &info->precharge_current_ua;
+       battery_inits[2].info_data = &info->precharge_voltage_max_uv;
+       battery_inits[3].info_data = &info->charge_term_current_ua;
+       battery_inits[4].info_data = &info->charge_restart_voltage_uv;
+       battery_inits[5].info_data = &info->overvoltage_limit_uv;
+       battery_inits[6].info_data = &info->constant_charge_current_max_ua;
+       battery_inits[7].info_data = &info->constant_charge_voltage_max_uv;
+
        for (i = 0; i < ARRAY_SIZE(battery_inits); i++) {
                int val = *battery_inits[i].info_data;
                const struct linear_range *range = battery_inits[i].range;
                        dev_err(bd->dev, "Unsupported value for %s\n",
                                battery_inits[i].name);
 
-                       power_supply_put_battery_info(bd->charger, &info);
+                       power_supply_put_battery_info(bd->charger, info);
                        return -EINVAL;
                }
                if (!found) {
                *(battery_inits[i].data) = regval;
        }
 
-       power_supply_put_battery_info(bd->charger, &info);
+       power_supply_put_battery_info(bd->charger, info);
 
        for (i = 0; i < ARRAY_SIZE(props); i++) {
                ret = device_property_read_u32(bd->dev, props[i].prop,
 
 static int bq24190_get_config(struct bq24190_dev_info *bdi)
 {
        const char * const s = "ti,system-minimum-microvolt";
-       struct power_supply_battery_info info = {};
+       struct power_supply_battery_info *info;
        int v;
 
        if (device_property_read_u32(bdi->dev, s, &v) == 0) {
 
        if (bdi->dev->of_node &&
            !power_supply_get_battery_info(bdi->charger, &info)) {
-               v = info.precharge_current_ua / 1000;
+               v = info->precharge_current_ua / 1000;
                if (v >= BQ24190_REG_PCTCC_IPRECHG_MIN
                 && v <= BQ24190_REG_PCTCC_IPRECHG_MAX)
                        bdi->iprechg = v;
                        dev_warn(bdi->dev, "invalid value for battery:precharge-current-microamp: %d\n",
                                 v);
 
-               v = info.charge_term_current_ua / 1000;
+               v = info->charge_term_current_ua / 1000;
                if (v >= BQ24190_REG_PCTCC_ITERM_MIN
                 && v <= BQ24190_REG_PCTCC_ITERM_MAX)
                        bdi->iterm = v;
 
 static int bq2515x_hw_init(struct bq2515x_device *bq2515x)
 {
        int ret;
-       struct power_supply_battery_info bat_info = { };
+       struct power_supply_battery_info *bat_info;
 
        ret = bq2515x_disable_watchdog_timers(bq2515x);
        if (ret)
 
        } else {
                bq2515x->init_data.ichg =
-                               bat_info.constant_charge_current_max_ua;
+                               bat_info->constant_charge_current_max_ua;
 
                bq2515x->init_data.vbatreg =
-                               bat_info.constant_charge_voltage_max_uv;
+                               bat_info->constant_charge_voltage_max_uv;
 
                bq2515x->init_data.iprechg =
-                               bat_info.precharge_current_ua;
+                               bat_info->precharge_current_ua;
        }
 
        ret = bq2515x_set_const_charge_current(bq2515x,
 
 
 static int bq256xx_hw_init(struct bq256xx_device *bq)
 {
-       struct power_supply_battery_info bat_info = { };
+       struct power_supply_battery_info *bat_info;
        int wd_reg_val = BQ256XX_WATCHDOG_DIS;
        int ret = 0;
        int i;
        if (ret) {
                dev_warn(bq->dev, "battery info missing, default values will be applied\n");
 
-               bat_info.constant_charge_current_max_ua =
+               bat_info->constant_charge_current_max_ua =
                                bq->chip_info->bq256xx_def_ichg;
 
-               bat_info.constant_charge_voltage_max_uv =
+               bat_info->constant_charge_voltage_max_uv =
                                bq->chip_info->bq256xx_def_vbatreg;
 
-               bat_info.precharge_current_ua =
+               bat_info->precharge_current_ua =
                                bq->chip_info->bq256xx_def_iprechg;
 
-               bat_info.charge_term_current_ua =
+               bat_info->charge_term_current_ua =
                                bq->chip_info->bq256xx_def_iterm;
 
                bq->init_data.ichg_max =
                                bq->chip_info->bq256xx_max_vbatreg;
        } else {
                bq->init_data.ichg_max =
-                       bat_info.constant_charge_current_max_ua;
+                       bat_info->constant_charge_current_max_ua;
 
                bq->init_data.vbatreg_max =
-                       bat_info.constant_charge_voltage_max_uv;
+                       bat_info->constant_charge_voltage_max_uv;
        }
 
        ret = bq->chip_info->bq256xx_set_vindpm(bq, bq->init_data.vindpm);
                return ret;
 
        ret = bq->chip_info->bq256xx_set_ichg(bq,
-                               bat_info.constant_charge_current_max_ua);
+                               bat_info->constant_charge_current_max_ua);
        if (ret)
                return ret;
 
        ret = bq->chip_info->bq256xx_set_iprechg(bq,
-                               bat_info.precharge_current_ua);
+                               bat_info->precharge_current_ua);
        if (ret)
                return ret;
 
        ret = bq->chip_info->bq256xx_set_vbatreg(bq,
-                               bat_info.constant_charge_voltage_max_uv);
+                               bat_info->constant_charge_voltage_max_uv);
        if (ret)
                return ret;
 
        ret = bq->chip_info->bq256xx_set_iterm(bq,
-                               bat_info.charge_term_current_ua);
+                               bat_info->charge_term_current_ua);
        if (ret)
                return ret;
 
-       power_supply_put_battery_info(bq->charger, &bat_info);
+       power_supply_put_battery_info(bq->charger, bat_info);
 
        return 0;
 }
 
 
 static int bq25980_hw_init(struct bq25980_device *bq)
 {
-       struct power_supply_battery_info bat_info = { };
+       struct power_supply_battery_info *bat_info;
        int wd_reg_val = BQ25980_WATCHDOG_DIS;
        int wd_max_val = BQ25980_NUM_WD_VAL - 1;
        int ret = 0;
                return -EINVAL;
        }
 
-       bq->init_data.ichg_max = bat_info.constant_charge_current_max_ua;
-       bq->init_data.vreg_max = bat_info.constant_charge_voltage_max_uv;
+       bq->init_data.ichg_max = bat_info->constant_charge_current_max_ua;
+       bq->init_data.vreg_max = bat_info->constant_charge_voltage_max_uv;
 
        if (bq->state.bypass) {
                ret = regmap_update_bits(bq->regmap, BQ25980_CHRGR_CTRL_2,
 
 
 static void bq27xxx_battery_settings(struct bq27xxx_device_info *di)
 {
-       struct power_supply_battery_info info = {};
+       struct power_supply_battery_info *info;
        unsigned int min, max;
 
        if (power_supply_get_battery_info(di->bat, &info) < 0)
                return;
        }
 
-       if (info.energy_full_design_uwh != info.charge_full_design_uah) {
-               if (info.energy_full_design_uwh == -EINVAL)
+       if (info->energy_full_design_uwh != info->charge_full_design_uah) {
+               if (info->energy_full_design_uwh == -EINVAL)
                        dev_warn(di->dev, "missing battery:energy-full-design-microwatt-hours\n");
-               else if (info.charge_full_design_uah == -EINVAL)
+               else if (info->charge_full_design_uah == -EINVAL)
                        dev_warn(di->dev, "missing battery:charge-full-design-microamp-hours\n");
        }
 
        /* assume min == 0 */
        max = di->dm_regs[BQ27XXX_DM_DESIGN_ENERGY].max;
-       if (info.energy_full_design_uwh > max * 1000) {
+       if (info->energy_full_design_uwh > max * 1000) {
                dev_err(di->dev, "invalid battery:energy-full-design-microwatt-hours %d\n",
-                       info.energy_full_design_uwh);
-               info.energy_full_design_uwh = -EINVAL;
+                       info->energy_full_design_uwh);
+               info->energy_full_design_uwh = -EINVAL;
        }
 
        /* assume min == 0 */
        max = di->dm_regs[BQ27XXX_DM_DESIGN_CAPACITY].max;
-       if (info.charge_full_design_uah > max * 1000) {
+       if (info->charge_full_design_uah > max * 1000) {
                dev_err(di->dev, "invalid battery:charge-full-design-microamp-hours %d\n",
-                       info.charge_full_design_uah);
-               info.charge_full_design_uah = -EINVAL;
+                       info->charge_full_design_uah);
+               info->charge_full_design_uah = -EINVAL;
        }
 
        min = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].min;
        max = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].max;
-       if ((info.voltage_min_design_uv < min * 1000 ||
-            info.voltage_min_design_uv > max * 1000) &&
-            info.voltage_min_design_uv != -EINVAL) {
+       if ((info->voltage_min_design_uv < min * 1000 ||
+            info->voltage_min_design_uv > max * 1000) &&
+            info->voltage_min_design_uv != -EINVAL) {
                dev_err(di->dev, "invalid battery:voltage-min-design-microvolt %d\n",
-                       info.voltage_min_design_uv);
-               info.voltage_min_design_uv = -EINVAL;
+                       info->voltage_min_design_uv);
+               info->voltage_min_design_uv = -EINVAL;
        }
 
-       if ((info.energy_full_design_uwh != -EINVAL &&
-            info.charge_full_design_uah != -EINVAL) ||
-            info.voltage_min_design_uv  != -EINVAL)
-               bq27xxx_battery_set_config(di, &info);
+       if ((info->energy_full_design_uwh != -EINVAL &&
+            info->charge_full_design_uah != -EINVAL) ||
+            info->voltage_min_design_uv  != -EINVAL)
+               bq27xxx_battery_set_config(di, info);
 }
 
 /*
 
        struct delayed_work battery_delay_work;
        struct regmap *regmap;
        struct power_supply *rk_bat;
-       struct power_supply_battery_info battery;
+       struct power_supply_battery_info *battery;
        u8 *bat_profile;
 
        bool charger_attached;
 
        case POWER_SUPPLY_PROP_CHARGE_FULL:
        case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
-               if (cw_bat->battery.charge_full_design_uah > 0)
-                       val->intval = cw_bat->battery.charge_full_design_uah;
+               if (cw_bat->battery->charge_full_design_uah > 0)
+                       val->intval = cw_bat->battery->charge_full_design_uah;
                else
                        val->intval = 0;
                break;
 
        case POWER_SUPPLY_PROP_CHARGE_NOW:
-               val->intval = cw_bat->battery.charge_full_design_uah;
+               val->intval = cw_bat->battery->charge_full_design_uah;
                val->intval = val->intval * cw_bat->soc / 100;
                break;
 
        case POWER_SUPPLY_PROP_CURRENT_NOW:
                if (cw_battery_valid_time_to_empty(cw_bat) &&
-                   cw_bat->battery.charge_full_design_uah > 0) {
+                   cw_bat->battery->charge_full_design_uah > 0) {
                        /* calculate remaining capacity */
-                       val->intval = cw_bat->battery.charge_full_design_uah;
+                       val->intval = cw_bat->battery->charge_full_design_uah;
                        val->intval = val->intval * cw_bat->soc / 100;
 
                        /* estimate current based on time to empty */
 
        ret = power_supply_get_battery_info(cw_bat->rk_bat, &cw_bat->battery);
        if (ret) {
+               /* Allocate an empty battery */
+               cw_bat->battery = devm_kzalloc(&client->dev,
+                                              sizeof(cw_bat->battery),
+                                              GFP_KERNEL);
+               if (!cw_bat->battery)
+                       return -ENOMEM;
                dev_warn(cw_bat->dev,
                         "No monitored battery, some properties will be missing\n");
        }
        struct cw_battery *cw_bat = i2c_get_clientdata(client);
 
        cancel_delayed_work_sync(&cw_bat->battery_delay_work);
-       power_supply_put_battery_info(cw_bat->rk_bat, &cw_bat->battery);
+       power_supply_put_battery_info(cw_bat->rk_bat, cw_bat->battery);
        return 0;
 }
 
 
        struct iio_channel *channel;
        struct power_supply_desc desc;
        struct power_supply *battery;
-       struct power_supply_battery_info info;
+       struct power_supply_battery_info *info;
 };
 
 static int ingenic_battery_get_property(struct power_supply *psy,
                                        union power_supply_propval *val)
 {
        struct ingenic_battery *bat = power_supply_get_drvdata(psy);
-       struct power_supply_battery_info *info = &bat->info;
+       struct power_supply_battery_info *info = bat->info;
        int ret;
 
        switch (psp) {
        if (ret != IIO_AVAIL_LIST || scale_type != IIO_VAL_FRACTIONAL_LOG2)
                return -EINVAL;
 
-       max_mV = bat->info.voltage_max_design_uv / 1000;
+       max_mV = bat->info->voltage_max_design_uv / 1000;
 
        for (i = 0; i < scale_len; i += 2) {
                u64 scale_mV = (max_raw * scale_raw[i]) >> scale_raw[i + 1];
                dev_err(dev, "Unable to get battery info: %d\n", ret);
                return ret;
        }
-       if (bat->info.voltage_min_design_uv < 0) {
+       if (bat->info->voltage_min_design_uv < 0) {
                dev_err(dev, "Unable to get voltage min design\n");
-               return bat->info.voltage_min_design_uv;
+               return bat->info->voltage_min_design_uv;
        }
-       if (bat->info.voltage_max_design_uv < 0) {
+       if (bat->info->voltage_max_design_uv < 0) {
                dev_err(dev, "Unable to get voltage max design\n");
-               return bat->info.voltage_max_design_uv;
+               return bat->info->voltage_max_design_uv;
        }
 
        return ingenic_battery_set_scale(bat);
 
 #endif /* CONFIG_OF */
 
 int power_supply_get_battery_info(struct power_supply *psy,
-                                 struct power_supply_battery_info *info)
+                                 struct power_supply_battery_info **info_out)
 {
        struct power_supply_resistance_temp_table *resist_table;
+       struct power_supply_battery_info *info;
        struct device_node *battery_np;
        const char *value;
        int err, len, index;
        const __be32 *list;
 
+       info = devm_kmalloc(&psy->dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
        info->technology                     = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
        info->energy_full_design_uwh         = -EINVAL;
        info->charge_full_design_uah         = -EINVAL;
        info->charge_term_current_ua         = -EINVAL;
        info->constant_charge_current_max_ua = -EINVAL;
        info->constant_charge_voltage_max_uv = -EINVAL;
+       info->tricklecharge_current_ua       = -EINVAL;
+       info->precharge_voltage_max_uv       = -EINVAL;
+       info->charge_restart_voltage_uv      = -EINVAL;
+       info->overvoltage_limit_uv           = -EINVAL;
        info->temp_ambient_alert_min         = INT_MIN;
        info->temp_ambient_alert_max         = INT_MAX;
        info->temp_alert_min                 = INT_MIN;
 
        list = of_get_property(battery_np, "resistance-temp-table", &len);
        if (!list || !len)
-               goto out_put_node;
+               goto out_ret_pointer;
 
        info->resist_table_size = len / (2 * sizeof(__be32));
        resist_table = info->resist_table = devm_kcalloc(&psy->dev,
                resist_table[index].resistance = be32_to_cpu(*list++);
        }
 
+out_ret_pointer:
+       /* Finally return the whole thing */
+       *info_out = info;
+
 out_put_node:
        of_node_put(battery_np);
        return err;
 
        if (info->resist_table)
                devm_kfree(&psy->dev, info->resist_table);
+
+       devm_kfree(&psy->dev, info);
 }
 EXPORT_SYMBOL_GPL(power_supply_put_battery_info);
 
 
 
 static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
 {
-       struct power_supply_battery_info bat_info = { };
+       struct power_supply_battery_info *bat_info;
        u32 term_currrent, term_voltage, cur_val, vol_val;
        int ret;
 
                cur_val = 0x2;
                vol_val = 0x1;
        } else {
-               term_currrent = bat_info.charge_term_current_ua / 1000;
+               term_currrent = bat_info->charge_term_current_ua / 1000;
 
                if (term_currrent <= 90)
                        cur_val = 0;
                else
                        cur_val = ((term_currrent - 90) / 25) + 1;
 
-               term_voltage = bat_info.constant_charge_voltage_max_uv / 1000;
+               term_voltage = bat_info->constant_charge_voltage_max_uv / 1000;
 
                if (term_voltage > 4500)
                        term_voltage = 4500;
                else
                        vol_val = 0;
 
-               power_supply_put_battery_info(info->psy_usb, &bat_info);
+               power_supply_put_battery_info(info->psy_usb, bat_info);
        }
 
        /* Set charge termination current */
 
 
 static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
 {
-       struct power_supply_battery_info info = { };
+       struct power_supply_battery_info *info;
        struct power_supply_battery_ocv_table *table;
        int ret, delta_clbcnt, alarm_adc;
 
                return ret;
        }
 
-       data->total_cap = info.charge_full_design_uah / 1000;
-       data->max_volt = info.constant_charge_voltage_max_uv / 1000;
-       data->internal_resist = info.factory_internal_resistance_uohm / 1000;
-       data->min_volt = info.voltage_min_design_uv;
+       data->total_cap = info->charge_full_design_uah / 1000;
+       data->max_volt = info->constant_charge_voltage_max_uv / 1000;
+       data->internal_resist = info->factory_internal_resistance_uohm / 1000;
+       data->min_volt = info->voltage_min_design_uv;
 
        /*
         * For SC27XX fuel gauge device, we only use one ocv-capacity
         * table in normal temperature 20 Celsius.
         */
-       table = power_supply_find_ocv2cap_table(&info, 20, &data->table_len);
+       table = power_supply_find_ocv2cap_table(info, 20, &data->table_len);
        if (!table)
                return -EINVAL;
 
                                       data->table_len * sizeof(*table),
                                       GFP_KERNEL);
        if (!data->cap_table) {
-               power_supply_put_battery_info(data->battery, &info);
+               power_supply_put_battery_info(data->battery, info);
                return -ENOMEM;
        }
 
        if (!data->alarm_cap)
                data->alarm_cap += 1;
 
-       data->resist_table_len = info.resist_table_size;
+       data->resist_table_len = info->resist_table_size;
        if (data->resist_table_len > 0) {
-               data->resist_table = devm_kmemdup(data->dev, info.resist_table,
+               data->resist_table = devm_kmemdup(data->dev, info->resist_table,
                                                  data->resist_table_len *
                                                  sizeof(struct power_supply_resistance_temp_table),
                                                  GFP_KERNEL);
                if (!data->resist_table) {
-                       power_supply_put_battery_info(data->battery, &info);
+                       power_supply_put_battery_info(data->battery, info);
                        return -ENOMEM;
                }
        }
 
-       power_supply_put_battery_info(data->battery, &info);
+       power_supply_put_battery_info(data->battery, info);
 
        ret = sc27xx_fgu_calibration(data);
        if (ret)
 
 
 static int smb347_get_battery_info(struct smb347_charger *smb)
 {
-       struct power_supply_battery_info info = {};
+       struct power_supply_battery_info *info;
        struct power_supply *supply;
        int err;
 
        if (err)
                return err;
 
-       if (info.constant_charge_current_max_ua != -EINVAL)
-               smb->max_charge_current = info.constant_charge_current_max_ua;
+       if (info->constant_charge_current_max_ua != -EINVAL)
+               smb->max_charge_current = info->constant_charge_current_max_ua;
 
-       if (info.constant_charge_voltage_max_uv != -EINVAL)
-               smb->max_charge_voltage = info.constant_charge_voltage_max_uv;
+       if (info->constant_charge_voltage_max_uv != -EINVAL)
+               smb->max_charge_voltage = info->constant_charge_voltage_max_uv;
 
-       if (info.precharge_current_ua != -EINVAL)
-               smb->pre_charge_current = info.precharge_current_ua;
+       if (info->precharge_current_ua != -EINVAL)
+               smb->pre_charge_current = info->precharge_current_ua;
 
-       if (info.charge_term_current_ua != -EINVAL)
-               smb->termination_current = info.charge_term_current_ua;
+       if (info->charge_term_current_ua != -EINVAL)
+               smb->termination_current = info->charge_term_current_ua;
 
-       if (info.temp_alert_min != INT_MIN)
-               smb->soft_cold_temp_limit = info.temp_alert_min;
+       if (info->temp_alert_min != INT_MIN)
+               smb->soft_cold_temp_limit = info->temp_alert_min;
 
-       if (info.temp_alert_max != INT_MAX)
-               smb->soft_hot_temp_limit = info.temp_alert_max;
+       if (info->temp_alert_max != INT_MAX)
+               smb->soft_hot_temp_limit = info->temp_alert_max;
 
-       if (info.temp_min != INT_MIN)
-               smb->hard_cold_temp_limit = info.temp_min;
+       if (info->temp_min != INT_MIN)
+               smb->hard_cold_temp_limit = info->temp_min;
 
-       if (info.temp_max != INT_MAX)
-               smb->hard_hot_temp_limit = info.temp_max;
+       if (info->temp_max != INT_MAX)
+               smb->hard_hot_temp_limit = info->temp_max;
 
        /* Suspend when battery temperature is outside hard limits */
        if (smb->hard_cold_temp_limit != SMB3XX_TEMP_USE_DEFAULT ||
 
 #endif /* CONFIG_OF */
 
 extern int power_supply_get_battery_info(struct power_supply *psy,
-                                        struct power_supply_battery_info *info);
+                                        struct power_supply_battery_info **info_out);
 extern void power_supply_put_battery_info(struct power_supply *psy,
                                          struct power_supply_battery_info *info);
 extern int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table,