Merge branch 'for-anton' of git://git.linaro.org/people/ljones/linux-3.0-ux500
authorAnton Vorontsov <anton@enomsg.org>
Sun, 6 Jan 2013 01:14:22 +0000 (17:14 -0800)
committerAnton Vorontsov <anton@enomsg.org>
Sun, 6 Jan 2013 01:14:22 +0000 (17:14 -0800)
1  2 
drivers/mfd/ab8500-core.c
drivers/power/Makefile
drivers/power/ab8500_btemp.c
drivers/power/ab8500_charger.c
drivers/power/ab8500_fg.c
drivers/power/abx500_chargalg.c

index e1650badd106da6e3992b219e77fdc35e20ad1c8,bbd49d7969029741a39523fde2d89df066d2d5aa..30b92652fce929a722dce85eb40a04d1312e8ad2
@@@ -565,10 -565,15 +565,10 @@@ static int ab8500_irq_init(struct ab850
        else
                num_irqs = AB8500_NR_IRQS;
  
 -      if (ab8500->irq_base) {
 -              ab8500->domain = irq_domain_add_legacy(
 -                      NULL, num_irqs, ab8500->irq_base,
 -                      0, &ab8500_irq_ops, ab8500);
 -      }
 -      else {
 -              ab8500->domain = irq_domain_add_linear(
 -                      np, num_irqs, &ab8500_irq_ops, ab8500);
 -      }
 +      /* If ->irq_base is zero this will give a linear mapping */
 +      ab8500->domain = irq_domain_add_simple(NULL,
 +                      num_irqs, ab8500->irq_base,
 +                      &ab8500_irq_ops, ab8500);
  
        if (!ab8500->domain) {
                dev_err(ab8500->dev, "Failed to create irqdomain\n");
@@@ -586,7 -591,39 +586,7 @@@ int ab8500_suspend(struct ab8500 *ab850
                return 0;
  }
  
 -/* AB8500 GPIO Resources */
 -static struct resource __devinitdata ab8500_gpio_resources[] = {
 -      {
 -              .name   = "GPIO_INT6",
 -              .start  = AB8500_INT_GPIO6R,
 -              .end    = AB8500_INT_GPIO41F,
 -              .flags  = IORESOURCE_IRQ,
 -      }
 -};
 -
 -/* AB9540 GPIO Resources */
 -static struct resource __devinitdata ab9540_gpio_resources[] = {
 -      {
 -              .name   = "GPIO_INT6",
 -              .start  = AB8500_INT_GPIO6R,
 -              .end    = AB8500_INT_GPIO41F,
 -              .flags  = IORESOURCE_IRQ,
 -      },
 -      {
 -              .name   = "GPIO_INT14",
 -              .start  = AB9540_INT_GPIO50R,
 -              .end    = AB9540_INT_GPIO54R,
 -              .flags  = IORESOURCE_IRQ,
 -      },
 -      {
 -              .name   = "GPIO_INT15",
 -              .start  = AB9540_INT_GPIO50F,
 -              .end    = AB9540_INT_GPIO54F,
 -              .flags  = IORESOURCE_IRQ,
 -      }
 -};
 -
 -static struct resource __devinitdata ab8500_gpadc_resources[] = {
 +static struct resource ab8500_gpadc_resources[] = {
        {
                .name   = "HW_CONV_END",
                .start  = AB8500_INT_GP_HW_ADC_CONV_END,
        },
  };
  
 -static struct resource __devinitdata ab8500_rtc_resources[] = {
 +static struct resource ab8500_rtc_resources[] = {
        {
                .name   = "60S",
                .start  = AB8500_INT_RTC_60S,
        },
  };
  
 -static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
 +static struct resource ab8500_poweronkey_db_resources[] = {
        {
                .name   = "ONKEY_DBF",
                .start  = AB8500_INT_PON_KEY1DB_F,
        },
  };
  
 -static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
 +static struct resource ab8500_av_acc_detect_resources[] = {
        {
               .name = "ACC_DETECT_1DB_F",
               .start = AB8500_INT_ACC_DETECT_1DB_F,
        },
  };
  
 -static struct resource __devinitdata ab8500_charger_resources[] = {
 +static struct resource ab8500_charger_resources[] = {
        {
                .name = "MAIN_CH_UNPLUG_DET",
                .start = AB8500_INT_MAIN_CH_UNPLUG_DET,
        },
  };
  
 -static struct resource __devinitdata ab8500_btemp_resources[] = {
 +static struct resource ab8500_btemp_resources[] = {
        {
                .name = "BAT_CTRL_INDB",
                .start = AB8500_INT_BAT_CTRL_INDB,
        },
  };
  
 -static struct resource __devinitdata ab8500_fg_resources[] = {
 +static struct resource ab8500_fg_resources[] = {
        {
                .name = "NCONV_ACCU",
                .start = AB8500_INT_CCN_CONV_ACC,
        },
  };
  
 -static struct resource __devinitdata ab8500_chargalg_resources[] = {};
 +static struct resource ab8500_chargalg_resources[] = {};
  
  #ifdef CONFIG_DEBUG_FS
 -static struct resource __devinitdata ab8500_debug_resources[] = {
 +static struct resource ab8500_debug_resources[] = {
        {
                .name   = "IRQ_FIRST",
                .start  = AB8500_INT_MAIN_EXT_CH_NOT_OK,
  };
  #endif
  
 -static struct resource __devinitdata ab8500_usb_resources[] = {
 +static struct resource ab8500_usb_resources[] = {
        {
                .name = "ID_WAKEUP_R",
                .start = AB8500_INT_ID_WAKEUP_R,
        },
  };
  
 -static struct resource __devinitdata ab8505_iddet_resources[] = {
 +static struct resource ab8505_iddet_resources[] = {
        {
                .name  = "KeyDeglitch",
                .start = AB8505_INT_KEYDEGLITCH,
        },
  };
  
 -static struct resource __devinitdata ab8500_temp_resources[] = {
 +static struct resource ab8500_temp_resources[] = {
        {
                .name  = "AB8500_TEMP_WARM",
                .start = AB8500_INT_TEMP_WARM,
        },
  };
  
 -static struct mfd_cell __devinitdata abx500_common_devs[] = {
 +static struct mfd_cell abx500_common_devs[] = {
  #ifdef CONFIG_DEBUG_FS
        {
                .name = "ab8500-debug",
                .name = "ab8500-regulator",
                .of_compatible = "stericsson,ab8500-regulator",
        },
 +      {
 +              .name = "abx500-clk",
 +              .of_compatible = "stericsson,abx500-clk",
 +      },
        {
                .name = "ab8500-gpadc",
                .of_compatible = "stericsson,ab8500-gpadc",
        },
  };
  
 -static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
 +static struct mfd_cell ab8500_bm_devs[] = {
        {
                .name = "ab8500-charger",
                .of_compatible = "stericsson,ab8500-charger",
                .num_resources = ARRAY_SIZE(ab8500_charger_resources),
                .resources = ab8500_charger_resources,
- #ifndef CONFIG_OF
                .platform_data = &ab8500_bm_data,
                .pdata_size = sizeof(ab8500_bm_data),
- #endif
        },
        {
                .name = "ab8500-btemp",
                .of_compatible = "stericsson,ab8500-btemp",
                .num_resources = ARRAY_SIZE(ab8500_btemp_resources),
                .resources = ab8500_btemp_resources,
- #ifndef CONFIG_OF
                .platform_data = &ab8500_bm_data,
                .pdata_size = sizeof(ab8500_bm_data),
- #endif
        },
        {
                .name = "ab8500-fg",
                .of_compatible = "stericsson,ab8500-fg",
                .num_resources = ARRAY_SIZE(ab8500_fg_resources),
                .resources = ab8500_fg_resources,
- #ifndef CONFIG_OF
                .platform_data = &ab8500_bm_data,
                .pdata_size = sizeof(ab8500_bm_data),
- #endif
        },
        {
                .name = "ab8500-chargalg",
                .of_compatible = "stericsson,ab8500-chargalg",
                .num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
                .resources = ab8500_chargalg_resources,
- #ifndef CONFIG_OF
                .platform_data = &ab8500_bm_data,
                .pdata_size = sizeof(ab8500_bm_data),
- #endif
        },
  };
  
 -static struct mfd_cell __devinitdata ab8500_devs[] = {
 +static struct mfd_cell ab8500_devs[] = {
        {
                .name = "ab8500-gpio",
                .of_compatible = "stericsson,ab8500-gpio",
 -              .num_resources = ARRAY_SIZE(ab8500_gpio_resources),
 -              .resources = ab8500_gpio_resources,
        },
        {
                .name = "ab8500-usb",
        },
  };
  
 -static struct mfd_cell __devinitdata ab9540_devs[] = {
 +static struct mfd_cell ab9540_devs[] = {
        {
                .name = "ab8500-gpio",
 -              .num_resources = ARRAY_SIZE(ab9540_gpio_resources),
 -              .resources = ab9540_gpio_resources,
        },
        {
                .name = "ab9540-usb",
  };
  
  /* Device list common to ab9540 and ab8505 */
 -static struct mfd_cell __devinitdata ab9540_ab8505_devs[] = {
 +static struct mfd_cell ab9540_ab8505_devs[] = {
        {
                .name = "ab-iddet",
                .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
@@@ -1231,7 -1260,7 +1223,7 @@@ static struct attribute_group ab9540_at
        .attrs  = ab9540_sysfs_entries,
  };
  
 -static int __devinit ab8500_probe(struct platform_device *pdev)
 +static int ab8500_probe(struct platform_device *pdev)
  {
        static char *switch_off_status[] = {
                "Swoff bit programming",
        int i;
        u8 value;
  
 -      ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
 +      ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
        if (!ab8500)
                return -ENOMEM;
  
        ab8500->dev = &pdev->dev;
  
        resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 -      if (!resource) {
 -              ret = -ENODEV;
 -              goto out_free_ab8500;
 -      }
 +      if (!resource)
 +              return -ENODEV;
  
        ab8500->irq = resource->start;
  
                ret = get_register_interruptible(ab8500, AB8500_MISC,
                        AB8500_IC_NAME_REG, &value);
                if (ret < 0)
 -                      goto out_free_ab8500;
 +                      return ret;
  
                ab8500->version = value;
        }
        ret = get_register_interruptible(ab8500, AB8500_MISC,
                AB8500_REV_REG, &value);
        if (ret < 0)
 -              goto out_free_ab8500;
 +              return ret;
  
        ab8500->chip_id = value;
  
                ab8500->mask_size = AB8500_NUM_IRQ_REGS;
                ab8500->irq_reg_offset = ab8500_irq_regoffset;
        }
 -      ab8500->mask = kzalloc(ab8500->mask_size, GFP_KERNEL);
 +      ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
        if (!ab8500->mask)
                return -ENOMEM;
 -      ab8500->oldmask = kzalloc(ab8500->mask_size, GFP_KERNEL);
 -      if (!ab8500->oldmask) {
 -              ret = -ENOMEM;
 -              goto out_freemask;
 -      }
 +      ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
 +      if (!ab8500->oldmask)
 +              return -ENOMEM;
 +
        /*
         * ab8500 has switched off due to (SWITCH_OFF_STATUS):
         * 0x01 Swoff bit programming
  
        ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
        if (ret)
 -              goto out_freeoldmask;
 +              return ret;
  
        for (i = 0; i < ab8500->mask_size; i++)
                ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
  
        ret = ab8500_irq_init(ab8500, np);
        if (ret)
 -              goto out_freeoldmask;
 +              return ret;
  
        /*  Activate this feature only in ab9540 */
        /*  till tests are done on ab8500 1p2 or later*/
        if (is_ab9540(ab8500)) {
 -              ret = request_threaded_irq(ab8500->irq, NULL,
 -                                      ab8500_hierarchical_irq,
 -                                      IRQF_ONESHOT | IRQF_NO_SUSPEND,
 -                                      "ab8500", ab8500);
 +              ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
 +                                              ab8500_hierarchical_irq,
 +                                              IRQF_ONESHOT | IRQF_NO_SUSPEND,
 +                                              "ab8500", ab8500);
        }
        else {
 -              ret = request_threaded_irq(ab8500->irq, NULL,
 -                                      ab8500_irq,
 -                                      IRQF_ONESHOT | IRQF_NO_SUSPEND,
 -                                      "ab8500", ab8500);
 +              ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
 +                                              ab8500_irq,
 +                                              IRQF_ONESHOT | IRQF_NO_SUSPEND,
 +                                              "ab8500", ab8500);
                if (ret)
 -                      goto out_freeoldmask;
 +                      return ret;
        }
  
        ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
                        ARRAY_SIZE(abx500_common_devs), NULL,
                        ab8500->irq_base, ab8500->domain);
        if (ret)
 -              goto out_freeirq;
 +              return ret;
  
        if (is_ab9540(ab8500))
                ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
                                ARRAY_SIZE(ab8500_devs), NULL,
                                ab8500->irq_base, ab8500->domain);
        if (ret)
 -              goto out_freeirq;
 +              return ret;
  
        if (is_ab9540(ab8500) || is_ab8505(ab8500))
                ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
                                ARRAY_SIZE(ab9540_ab8505_devs), NULL,
                                ab8500->irq_base, ab8500->domain);
        if (ret)
 -              goto out_freeirq;
 +              return ret;
  
        if (!no_bm) {
                /* Add battery management devices */
                dev_err(ab8500->dev, "error creating sysfs entries\n");
  
        return ret;
 -
 -out_freeirq:
 -      free_irq(ab8500->irq, ab8500);
 -out_freeoldmask:
 -      kfree(ab8500->oldmask);
 -out_freemask:
 -      kfree(ab8500->mask);
 -out_free_ab8500:
 -      kfree(ab8500);
 -
 -      return ret;
  }
  
 -static int __devexit ab8500_remove(struct platform_device *pdev)
 +static int ab8500_remove(struct platform_device *pdev)
  {
        struct ab8500 *ab8500 = platform_get_drvdata(pdev);
  
                sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
  
        mfd_remove_devices(ab8500->dev);
 -      free_irq(ab8500->irq, ab8500);
 -
 -      kfree(ab8500->oldmask);
 -      kfree(ab8500->mask);
 -      kfree(ab8500);
  
        return 0;
  }
@@@ -1470,7 -1518,7 +1462,7 @@@ static struct platform_driver ab8500_co
                .owner = THIS_MODULE,
        },
        .probe  = ab8500_probe,
 -      .remove = __devexit_p(ab8500_remove),
 +      .remove = ab8500_remove,
        .id_table = ab8500_id,
  };
  
diff --combined drivers/power/Makefile
index 22c8913382c0839bda10690268fb740e5ea42999,070c73d2ef025a3e6436e2caaf3ab1360e1ef634..b11e0c7ea0f192e0aabbc96c92cfab7657733c00
@@@ -38,7 -38,7 +38,7 @@@ obj-$(CONFIG_CHARGER_PCF50633)        += pcf50
  obj-$(CONFIG_BATTERY_JZ4740)  += jz4740-battery.o
  obj-$(CONFIG_BATTERY_INTEL_MID)       += intel_mid_battery.o
  obj-$(CONFIG_BATTERY_RX51)    += rx51_battery.o
- obj-$(CONFIG_AB8500_BM)               += ab8500_bmdata.o ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o
+ obj-$(CONFIG_AB8500_BM)               += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o
  obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
  obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
  obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
@@@ -51,4 -51,3 +51,4 @@@ obj-$(CONFIG_CHARGER_MAX8998) += max899
  obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o
  obj-$(CONFIG_POWER_AVS)               += avs/
  obj-$(CONFIG_CHARGER_SMB347)  += smb347-charger.o
 +obj-$(CONFIG_POWER_RESET)     += reset/
index 20e2a7d3ef43c0f6877aae8e5b3cb9c08fc6a9ae,158cba5cff53b72a79f0262a853afa6f72faf81a..e1d28039ce7b0fdd4a636dfd0e6b5441bd9f41d4
@@@ -78,12 -78,13 +78,13 @@@ struct ab8500_btemp_ranges 
   * @parent:           Pointer to the struct ab8500
   * @gpadc:            Pointer to the struct gpadc
   * @fg:                       Pointer to the struct fg
-  * @bat:              Pointer to the abx500_bm platform data
+  * @bm:               Platform specific battery management information
   * @btemp_psy:                Structure for BTEMP specific battery properties
   * @events:           Structure for information about events triggered
   * @btemp_ranges:     Battery temperature range structure
   * @btemp_wq:         Work queue for measuring the temperature periodically
   * @btemp_periodic_work:      Work for measuring the temperature periodically
+  * @initialized:      True if battery id read.
   */
  struct ab8500_btemp {
        struct device *dev;
        struct ab8500 *parent;
        struct ab8500_gpadc *gpadc;
        struct ab8500_fg *fg;
-       struct abx500_bm_data *bat;
+       struct abx500_bm_data *bm;
        struct power_supply btemp_psy;
        struct ab8500_btemp_events events;
        struct ab8500_btemp_ranges btemp_ranges;
        struct workqueue_struct *btemp_wq;
        struct delayed_work btemp_periodic_work;
+       bool initialized;
  };
  
  /* BTEMP power supply properties */
@@@ -147,13 -149,13 +149,13 @@@ static int ab8500_btemp_batctrl_volt_to
                return (450000 * (v_batctrl)) / (1800 - v_batctrl);
        }
  
-       if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL) {
+       if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) {
                /*
                 * If the battery has internal NTC, we use the current
                 * source to calculate the resistance, 7uA or 20uA
                 */
                rbs = (v_batctrl * 1000
-                      - di->bat->gnd_lift_resistance * inst_curr)
+                      - di->bm->gnd_lift_resistance * inst_curr)
                      / di->curr_source;
        } else {
                /*
@@@ -209,7 -211,7 +211,7 @@@ static int ab8500_btemp_curr_source_ena
                return 0;
  
        /* Only do this for batteries with internal NTC */
-       if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
+       if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
                if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA)
                        curr = BAT_CTRL_7U_ENA;
                else
                                __func__);
                        goto disable_curr_source;
                }
-       } else if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
+       } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
                dev_dbg(di->dev, "Disable BATCTRL curr source\n");
  
                /* Write 0 to the curr bits */
@@@ -457,9 -459,9 +459,9 @@@ static int ab8500_btemp_measure_temp(st
        int rbat, rntc, vntc;
        u8 id;
  
-       id = di->bat->batt_id;
+       id = di->bm->batt_id;
  
-       if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL &&
+       if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
                        id != BATTERY_UNKNOWN) {
  
                rbat = ab8500_btemp_get_batctrl_res(di);
                }
  
                temp = ab8500_btemp_res_to_temp(di,
-                       di->bat->bat_type[id].r_to_t_tbl,
-                       di->bat->bat_type[id].n_temp_tbl_elements, rbat);
+                       di->bm->bat_type[id].r_to_t_tbl,
+                       di->bm->bat_type[id].n_temp_tbl_elements, rbat);
        } else {
                vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL);
                if (vntc < 0) {
                rntc = 230000 * vntc / (VTVOUT_V - vntc);
  
                temp = ab8500_btemp_res_to_temp(di,
-                       di->bat->bat_type[id].r_to_t_tbl,
-                       di->bat->bat_type[id].n_temp_tbl_elements, rntc);
+                       di->bm->bat_type[id].r_to_t_tbl,
+                       di->bm->bat_type[id].n_temp_tbl_elements, rntc);
                prev = temp;
        }
        dev_dbg(di->dev, "Battery temperature is %d\n", temp);
@@@ -513,7 -515,7 +515,7 @@@ static int ab8500_btemp_id(struct ab850
        u8 i;
  
        di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA;
-       di->bat->batt_id = BATTERY_UNKNOWN;
+       di->bm->batt_id = BATTERY_UNKNOWN;
  
        res =  ab8500_btemp_get_batctrl_res(di);
        if (res < 0) {
        }
  
        /* BATTERY_UNKNOWN is defined on position 0, skip it! */
-       for (i = BATTERY_UNKNOWN + 1; i < di->bat->n_btypes; i++) {
-               if ((res <= di->bat->bat_type[i].resis_high) &&
-                       (res >= di->bat->bat_type[i].resis_low)) {
+       for (i = BATTERY_UNKNOWN + 1; i < di->bm->n_btypes; i++) {
+               if ((res <= di->bm->bat_type[i].resis_high) &&
+                       (res >= di->bm->bat_type[i].resis_low)) {
                        dev_dbg(di->dev, "Battery detected on %s"
                                " low %d < res %d < high: %d"
                                " index: %d\n",
-                               di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL ?
+                               di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL ?
                                "BATCTRL" : "BATTEMP",
-                               di->bat->bat_type[i].resis_low, res,
-                               di->bat->bat_type[i].resis_high, i);
+                               di->bm->bat_type[i].resis_low, res,
+                               di->bm->bat_type[i].resis_high, i);
  
-                       di->bat->batt_id = i;
+                       di->bm->batt_id = i;
                        break;
                }
        }
  
-       if (di->bat->batt_id == BATTERY_UNKNOWN) {
+       if (di->bm->batt_id == BATTERY_UNKNOWN) {
                dev_warn(di->dev, "Battery identified as unknown"
                        ", resistance %d Ohm\n", res);
                return -ENXIO;
         * We only have to change current source if the
         * detected type is Type 1, else we use the 7uA source
         */
-       if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL &&
-                       di->bat->batt_id == 1) {
+       if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
+                       di->bm->batt_id == 1) {
                dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
                di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA;
        }
  
-       return di->bat->batt_id;
+       return di->bm->batt_id;
  }
  
  /**
@@@ -569,6 -571,13 +571,13 @@@ static void ab8500_btemp_periodic_work(
        struct ab8500_btemp *di = container_of(work,
                struct ab8500_btemp, btemp_periodic_work.work);
  
+       if (!di->initialized) {
+               di->initialized = true;
+               /* Identify the battery */
+               if (ab8500_btemp_id(di) < 0)
+                       dev_warn(di->dev, "failed to identify the battery\n");
+       }
        di->bat_temp = ab8500_btemp_measure_temp(di);
  
        if (di->bat_temp != di->prev_bat_temp) {
        }
  
        if (di->events.ac_conn || di->events.usb_conn)
-               interval = di->bat->temp_interval_chg;
+               interval = di->bm->temp_interval_chg;
        else
-               interval = di->bat->temp_interval_nochg;
+               interval = di->bm->temp_interval_nochg;
  
        /* Schedule a new measurement */
        queue_delayed_work(di->btemp_wq,
@@@ -806,7 -815,7 +815,7 @@@ static int ab8500_btemp_get_property(st
                        val->intval = 1;
                break;
        case POWER_SUPPLY_PROP_TECHNOLOGY:
-               val->intval = di->bat->bat_type[di->bat->batt_id].name;
+               val->intval = di->bm->bat_type[di->bm->batt_id].name;
                break;
        case POWER_SUPPLY_PROP_TEMP:
                val->intval = ab8500_btemp_get_temp(di);
@@@ -938,7 -947,7 +947,7 @@@ static int ab8500_btemp_suspend(struct 
  #define ab8500_btemp_resume       NULL
  #endif
  
 -static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
 +static int ab8500_btemp_remove(struct platform_device *pdev)
  {
        struct ab8500_btemp *di = platform_get_drvdata(pdev);
        int i, irq;
@@@ -964,9 -973,10 +973,10 @@@ static char *supply_interface[] = 
        "ab8500_fg",
  };
  
 -static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
 +static int ab8500_btemp_probe(struct platform_device *pdev)
  {
        struct device_node *np = pdev->dev.of_node;
+       struct abx500_bm_data *plat = pdev->dev.platform_data;
        struct ab8500_btemp *di;
        int irq, i, ret = 0;
        u8 val;
                dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__);
                return -ENOMEM;
        }
-       di->bat = pdev->mfd_cell->platform_data;
-       if (!di->bat) {
-               if (np) {
-                       ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
-                       if (ret) {
-                               dev_err(&pdev->dev,
-                                       "failed to get battery information\n");
-                               return ret;
-                       }
-               } else {
-                       dev_err(&pdev->dev, "missing dt node for ab8500_btemp\n");
-                       return -EINVAL;
+       if (!plat) {
+               dev_err(&pdev->dev, "no battery management data supplied\n");
+               return -EINVAL;
+       }
+       di->bm = plat;
+       if (np) {
+               ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to get battery information\n");
+                       return ret;
                }
-       } else {
-               dev_info(&pdev->dev, "falling back to legacy platform data\n");
        }
  
        /* get parent data */
        di->parent = dev_get_drvdata(pdev->dev.parent);
        di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
  
+       di->initialized = false;
        /* BTEMP supply */
        di->btemp_psy.name = "ab8500_btemp";
        di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
        INIT_DEFERRABLE_WORK(&di->btemp_periodic_work,
                ab8500_btemp_periodic_work);
  
-       /* Identify the battery */
-       if (ab8500_btemp_id(di) < 0)
-               dev_warn(di->dev, "failed to identify the battery\n");
        /* Set BTEMP thermal limits. Low and Med are fixed */
        di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT;
        di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT;
@@@ -1103,7 -1109,7 +1109,7 @@@ static const struct of_device_id ab8500
  
  static struct platform_driver ab8500_btemp_driver = {
        .probe = ab8500_btemp_probe,
 -      .remove = __devexit_p(ab8500_btemp_remove),
 +      .remove = ab8500_btemp_remove,
        .suspend = ab8500_btemp_suspend,
        .resume = ab8500_btemp_resume,
        .driver = {
index 3be9c0ee3fc58a2c016cb9509ceb316c54312b5f,2ddface4b2c4af48c3b4095884a20c5d966b6420..e5755f0ba831a998f8d126c5683e5b41756af335
@@@ -79,6 -79,9 +79,9 @@@
  /* Lowest charger voltage is 3.39V -> 0x4E */
  #define LOW_VOLT_REG                  0x4E
  
+ /* Step up/down delay in us */
+ #define STEP_UDELAY                   1000
  /* UsbLineStatus register - usb types */
  enum ab8500_charger_link_status {
        USB_STAT_NOT_CONFIGURED,
@@@ -186,7 -189,7 +189,7 @@@ struct ab8500_charger_usb_state 
   * @autopower_cfg     platform specific power config support for "pwron after pwrloss"
   * @parent:           Pointer to the struct ab8500
   * @gpadc:            Pointer to the struct gpadc
-  * @bat:              Pointer to the abx500_bm platform data
+  * @bm:               Platform specific battery management information
   * @flags:            Structure for information about events triggered
   * @usb_state:                Structure for usb stack information
   * @ac_chg:           AC charger power supply
@@@ -223,7 -226,7 +226,7 @@@ struct ab8500_charger 
        bool autopower_cfg;
        struct ab8500 *parent;
        struct ab8500_gpadc *gpadc;
-       struct abx500_bm_data *bat;
+       struct abx500_bm_data *bm;
        struct ab8500_charger_event_flags flags;
        struct ab8500_charger_usb_state usb_state;
        struct ux500_charger ac_chg;
@@@ -935,6 -938,88 +938,88 @@@ static int ab8500_charger_get_usb_cur(s
        return 0;
  }
  
+ /**
+  * ab8500_charger_set_current() - set charger current
+  * @di:               pointer to the ab8500_charger structure
+  * @ich:      charger current, in mA
+  * @reg:      select what charger register to set
+  *
+  * Set charger current.
+  * There is no state machine in the AB to step up/down the charger
+  * current to avoid dips and spikes on MAIN, VBUS and VBAT when
+  * charging is started. Instead we need to implement
+  * this charger current step-up/down here.
+  * Returns error code in case of failure else 0(on success)
+  */
+ static int ab8500_charger_set_current(struct ab8500_charger *di,
+       int ich, int reg)
+ {
+       int ret, i;
+       int curr_index, prev_curr_index, shift_value;
+       u8 reg_value;
+       switch (reg) {
+       case AB8500_MCH_IPT_CURLVL_REG:
+               shift_value = MAIN_CH_INPUT_CURR_SHIFT;
+               curr_index = ab8500_current_to_regval(ich);
+               break;
+       case AB8500_USBCH_IPT_CRNTLVL_REG:
+               shift_value = VBUS_IN_CURR_LIM_SHIFT;
+               curr_index = ab8500_vbus_in_curr_to_regval(ich);
+               break;
+       case AB8500_CH_OPT_CRNTLVL_REG:
+               shift_value = 0;
+               curr_index = ab8500_current_to_regval(ich);
+               break;
+       default:
+               dev_err(di->dev, "%s current register not valid\n", __func__);
+               return -ENXIO;
+       }
+       if (curr_index < 0) {
+               dev_err(di->dev, "requested current limit out-of-range\n");
+               return -ENXIO;
+       }
+       ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
+               reg, &reg_value);
+       if (ret < 0) {
+               dev_err(di->dev, "%s read failed\n", __func__);
+               return ret;
+       }
+       prev_curr_index = (reg_value >> shift_value);
+       /* only update current if it's been changed */
+       if (prev_curr_index == curr_index)
+               return 0;
+       dev_dbg(di->dev, "%s set charger current: %d mA for reg: 0x%02x\n",
+               __func__, ich, reg);
+       if (prev_curr_index > curr_index) {
+               for (i = prev_curr_index - 1; i >= curr_index; i--) {
+                       ret = abx500_set_register_interruptible(di->dev,
+                               AB8500_CHARGER, reg, (u8) i << shift_value);
+                       if (ret) {
+                               dev_err(di->dev, "%s write failed\n", __func__);
+                               return ret;
+                       }
+                       usleep_range(STEP_UDELAY, STEP_UDELAY * 2);
+               }
+       } else {
+               for (i = prev_curr_index + 1; i <= curr_index; i++) {
+                       ret = abx500_set_register_interruptible(di->dev,
+                               AB8500_CHARGER, reg, (u8) i << shift_value);
+                       if (ret) {
+                               dev_err(di->dev, "%s write failed\n", __func__);
+                               return ret;
+                       }
+                       usleep_range(STEP_UDELAY, STEP_UDELAY * 2);
+               }
+       }
+       return ret;
+ }
  /**
   * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit
   * @di:               pointer to the ab8500_charger structure
  static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di,
                int ich_in)
  {
-       int ret;
-       int input_curr_index;
        int min_value;
  
        /* We should always use to lowest current limit */
-       min_value = min(di->bat->chg_params->usb_curr_max, ich_in);
+       min_value = min(di->bm->chg_params->usb_curr_max, ich_in);
  
        switch (min_value) {
        case 100:
                break;
        }
  
-       input_curr_index = ab8500_vbus_in_curr_to_regval(min_value);
-       if (input_curr_index < 0) {
-               dev_err(di->dev, "VBUS input current limit too high\n");
-               return -ENXIO;
-       }
+       return ab8500_charger_set_current(di, min_value,
+               AB8500_USBCH_IPT_CRNTLVL_REG);
+ }
  
-       ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
-               AB8500_USBCH_IPT_CRNTLVL_REG,
-               input_curr_index << VBUS_IN_CURR_LIM_SHIFT);
-       if (ret)
-               dev_err(di->dev, "%s write failed\n", __func__);
+ /**
+  * ab8500_charger_set_main_in_curr() - set main charger input current
+  * @di:               pointer to the ab8500_charger structure
+  * @ich_in:   input charger current, in mA
+  *
+  * Set main charger input current.
+  * Returns error code in case of failure else 0(on success)
+  */
+ static int ab8500_charger_set_main_in_curr(struct ab8500_charger *di,
+       int ich_in)
+ {
+       return ab8500_charger_set_current(di, ich_in,
+               AB8500_MCH_IPT_CURLVL_REG);
+ }
  
-       return ret;
+ /**
+  * ab8500_charger_set_output_curr() - set charger output current
+  * @di:               pointer to the ab8500_charger structure
+  * @ich_out:  output charger current, in mA
+  *
+  * Set charger output current.
+  * Returns error code in case of failure else 0(on success)
+  */
+ static int ab8500_charger_set_output_curr(struct ab8500_charger *di,
+       int ich_out)
+ {
+       return ab8500_charger_set_current(di, ich_out,
+               AB8500_CH_OPT_CRNTLVL_REG);
  }
  
  /**
@@@ -1074,7 -1176,7 +1176,7 @@@ static int ab8500_charger_ac_en(struct 
                volt_index = ab8500_voltage_to_regval(vset);
                curr_index = ab8500_current_to_regval(iset);
                input_curr_index = ab8500_current_to_regval(
-                       di->bat->chg_params->ac_curr_max);
+                       di->bm->chg_params->ac_curr_max);
                if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) {
                        dev_err(di->dev,
                                "Charger voltage or current too high, "
                        return ret;
                }
                /* MainChInputCurr: current that can be drawn from the charger*/
-               ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
-                       AB8500_MCH_IPT_CURLVL_REG,
-                       input_curr_index << MAIN_CH_INPUT_CURR_SHIFT);
+               ret = ab8500_charger_set_main_in_curr(di,
+                       di->bm->chg_params->ac_curr_max);
                if (ret) {
-                       dev_err(di->dev, "%s write failed\n", __func__);
+                       dev_err(di->dev, "%s Failed to set MainChInputCurr\n",
+                               __func__);
                        return ret;
                }
                /* ChOutputCurentLevel: protected output current */
-               ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
-                       AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index);
+               ret = ab8500_charger_set_output_curr(di, iset);
                if (ret) {
-                       dev_err(di->dev, "%s write failed\n", __func__);
+                       dev_err(di->dev, "%s "
+                               "Failed to set ChOutputCurentLevel\n",
+                               __func__);
                        return ret;
                }
  
                /* Check if VBAT overshoot control should be enabled */
-               if (!di->bat->enable_overshoot)
+               if (!di->bm->enable_overshoot)
                        overshoot = MAIN_CH_NO_OVERSHOOT_ENA_N;
  
                /* Enable Main Charger */
                                return ret;
                        }
  
-                       ret = abx500_set_register_interruptible(di->dev,
-                               AB8500_CHARGER,
-                               AB8500_CH_OPT_CRNTLVL_REG, CH_OP_CUR_LVL_0P1);
+                       ret = ab8500_charger_set_output_curr(di, 0);
                        if (ret) {
-                               dev_err(di->dev,
-                                       "%s write failed\n", __func__);
+                               dev_err(di->dev, "%s "
+                                       "Failed to set ChOutputCurentLevel\n",
+                                       __func__);
                                return ret;
                        }
                } else {
@@@ -1266,14 -1368,15 +1368,15 @@@ static int ab8500_charger_usb_en(struc
                        return ret;
                }
                /* ChOutputCurentLevel: protected output current */
-               ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
-                       AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index);
+               ret = ab8500_charger_set_output_curr(di, ich_out);
                if (ret) {
-                       dev_err(di->dev, "%s write failed\n", __func__);
+                       dev_err(di->dev, "%s "
+                               "Failed to set ChOutputCurentLevel\n",
+                               __func__);
                        return ret;
                }
                /* Check if VBAT overshoot control should be enabled */
-               if (!di->bat->enable_overshoot)
+               if (!di->bm->enable_overshoot)
                        overshoot = USB_CHG_NO_OVERSHOOT_ENA_N;
  
                /* Enable USB Charger */
@@@ -1366,7 -1469,6 +1469,6 @@@ static int ab8500_charger_update_charge
                int ich_out)
  {
        int ret;
-       int curr_index;
        struct ab8500_charger *di;
  
        if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS)
        else
                return -ENXIO;
  
-       curr_index = ab8500_current_to_regval(ich_out);
-       if (curr_index < 0) {
-               dev_err(di->dev,
-                       "Charger current too high, "
-                       "charging not started\n");
-               return -ENXIO;
-       }
-       ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
-               AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index);
+       ret = ab8500_charger_set_output_curr(di, ich_out);
        if (ret) {
-               dev_err(di->dev, "%s write failed\n", __func__);
+               dev_err(di->dev, "%s "
+                       "Failed to set ChOutputCurentLevel\n",
+                       __func__);
                return ret;
        }
  
@@@ -2359,8 -2454,8 +2454,8 @@@ static int ab8500_charger_init_hw_regis
        ret = abx500_set_register_interruptible(di->dev,
                AB8500_RTC,
                AB8500_RTC_BACKUP_CHG_REG,
-               di->bat->bkup_bat_v |
-               di->bat->bkup_bat_i);
+               di->bm->bkup_bat_v |
+               di->bm->bkup_bat_i);
        if (ret) {
                dev_err(di->dev, "failed to setup backup battery charging\n");
                goto out;
@@@ -2492,7 -2587,7 +2587,7 @@@ static int ab8500_charger_suspend(struc
  #define ab8500_charger_resume       NULL
  #endif
  
 -static int __devexit ab8500_charger_remove(struct platform_device *pdev)
 +static int ab8500_charger_remove(struct platform_device *pdev)
  {
        struct ab8500_charger *di = platform_get_drvdata(pdev);
        int i, irq, ret;
@@@ -2538,9 -2633,10 +2633,10 @@@ static char *supply_interface[] = 
        "ab8500_btemp",
  };
  
 -static int __devinit ab8500_charger_probe(struct platform_device *pdev)
 +static int ab8500_charger_probe(struct platform_device *pdev)
  {
        struct device_node *np = pdev->dev.of_node;
+       struct abx500_bm_data *plat = pdev->dev.platform_data;
        struct ab8500_charger *di;
        int irq, i, charger_status, ret = 0;
  
                dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__);
                return -ENOMEM;
        }
-       di->bat = pdev->mfd_cell->platform_data;
-       if (!di->bat) {
-               if (np) {
-                       ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
-                       if (ret) {
-                               dev_err(&pdev->dev,
-                                       "failed to get battery information\n");
-                               return ret;
-                       }
-                       di->autopower_cfg = of_property_read_bool(np, "autopower_cfg");
-               } else {
-                       dev_err(&pdev->dev, "missing dt node for ab8500_charger\n");
-                       return -EINVAL;
+       if (!plat) {
+               dev_err(&pdev->dev, "no battery management data supplied\n");
+               return -EINVAL;
+       }
+       di->bm = plat;
+       if (np) {
+               ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to get battery information\n");
+                       return ret;
                }
-       } else {
-               dev_info(&pdev->dev, "falling back to legacy platform data\n");
+               di->autopower_cfg = of_property_read_bool(np, "autopower_cfg");
+       } else
                di->autopower_cfg = false;
-       }
  
        /* get parent data */
        di->dev = &pdev->dev;
@@@ -2772,7 -2866,7 +2866,7 @@@ static const struct of_device_id ab8500
  
  static struct platform_driver ab8500_charger_driver = {
        .probe = ab8500_charger_probe,
 -      .remove = __devexit_p(ab8500_charger_remove),
 +      .remove = ab8500_charger_remove,
        .suspend = ab8500_charger_suspend,
        .resume = ab8500_charger_resume,
        .driver = {
index b3bf178c346270fdb22800c53ed21b574a25b956,df681a80d8a4adc9438e5dcfa7cd593de342d6e0..3d05c73813c8a594fcbc2ec220c063653c3d953b
@@@ -173,7 -173,7 +173,7 @@@ struct inst_curr_result_list 
   * @avg_cap:          Average capacity filter
   * @parent:           Pointer to the struct ab8500
   * @gpadc:            Pointer to the struct gpadc
-  * @bat:              Pointer to the abx500_bm platform data
+  * @bm:               Platform specific battery management information
   * @fg_psy:           Structure that holds the FG specific battery properties
   * @fg_wq:            Work queue for running the FG algorithm
   * @fg_periodic_work: Work to run the FG algorithm periodically
@@@ -212,7 -212,7 +212,7 @@@ struct ab8500_fg 
        struct ab8500_fg_avg_cap avg_cap;
        struct ab8500 *parent;
        struct ab8500_gpadc *gpadc;
-       struct abx500_bm_data *bat;
+       struct abx500_bm_data *bm;
        struct power_supply fg_psy;
        struct workqueue_struct *fg_wq;
        struct delayed_work fg_periodic_work;
@@@ -355,7 -355,7 +355,7 @@@ static int ab8500_fg_is_low_curr(struc
        /*
         * We want to know if we're in low current mode
         */
-       if (curr > -di->bat->fg_params->high_curr_threshold)
+       if (curr > -di->bm->fg_params->high_curr_threshold)
                return true;
        else
                return false;
@@@ -484,8 -484,9 +484,9 @@@ static int ab8500_fg_coulomb_counter(st
                di->flags.fg_enabled = true;
        } else {
                /* Clear any pending read requests */
-               ret = abx500_set_register_interruptible(di->dev,
-                       AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, 0);
+               ret = abx500_mask_and_set_register_interruptible(di->dev,
+                       AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG,
+                       (RESET_ACCU | READ_REQ), 0);
                if (ret)
                        goto cc_err;
  
@@@ -647,7 -648,7 +648,7 @@@ int ab8500_fg_inst_curr_finalize(struc
         * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm
         */
        val = (val * QLSB_NANO_AMP_HOURS_X10 * 36 * 4) /
-               (1000 * di->bat->fg_res);
+               (1000 * di->bm->fg_res);
  
        if (di->turn_off_fg) {
                dev_dbg(di->dev, "%s Disable FG\n", __func__);
@@@ -750,7 -751,7 +751,7 @@@ static void ab8500_fg_acc_cur_work(stru
         * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm
         */
        di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X10) /
-               (100 * di->bat->fg_res);
+               (100 * di->bm->fg_res);
  
        /*
         * Convert to unit value in mA
         * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm
         */
        di->avg_curr = (val * QLSB_NANO_AMP_HOURS_X10 * 36) /
-               (1000 * di->bat->fg_res * (di->fg_samples / 4));
+               (1000 * di->bm->fg_res * (di->fg_samples / 4));
  
        di->flags.conv_done = true;
  
@@@ -814,8 -815,8 +815,8 @@@ static int ab8500_fg_volt_to_capacity(s
        struct abx500_v_to_cap *tbl;
        int cap = 0;
  
-       tbl = di->bat->bat_type[di->bat->batt_id].v_to_cap_tbl,
-       tbl_size = di->bat->bat_type[di->bat->batt_id].n_v_cap_tbl_elements;
+       tbl = di->bm->bat_type[di->bm->batt_id].v_to_cap_tbl,
+       tbl_size = di->bm->bat_type[di->bm->batt_id].n_v_cap_tbl_elements;
  
        for (i = 0; i < tbl_size; ++i) {
                if (voltage > tbl[i].voltage)
@@@ -866,8 -867,8 +867,8 @@@ static int ab8500_fg_battery_resistance
        struct batres_vs_temp *tbl;
        int resist = 0;
  
-       tbl = di->bat->bat_type[di->bat->batt_id].batres_tbl;
-       tbl_size = di->bat->bat_type[di->bat->batt_id].n_batres_tbl_elements;
+       tbl = di->bm->bat_type[di->bm->batt_id].batres_tbl;
+       tbl_size = di->bm->bat_type[di->bm->batt_id].n_batres_tbl_elements;
  
        for (i = 0; i < tbl_size; ++i) {
                if (di->bat_temp / 10 > tbl[i].temp)
  
        dev_dbg(di->dev, "%s Temp: %d battery internal resistance: %d"
            " fg resistance %d, total: %d (mOhm)\n",
-               __func__, di->bat_temp, resist, di->bat->fg_res / 10,
-               (di->bat->fg_res / 10) + resist);
+               __func__, di->bat_temp, resist, di->bm->fg_res / 10,
+               (di->bm->fg_res / 10) + resist);
  
        /* fg_res variable is in 0.1mOhm */
-       resist += di->bat->fg_res / 10;
+       resist += di->bm->fg_res / 10;
  
        return resist;
  }
@@@ -1110,14 -1111,14 +1111,14 @@@ static int ab8500_fg_capacity_level(str
  
        percent = di->bat_cap.permille / 10;
  
-       if (percent <= di->bat->cap_levels->critical ||
+       if (percent <= di->bm->cap_levels->critical ||
                di->flags.low_bat)
                ret = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
-       else if (percent <= di->bat->cap_levels->low)
+       else if (percent <= di->bm->cap_levels->low)
                ret = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
-       else if (percent <= di->bat->cap_levels->normal)
+       else if (percent <= di->bm->cap_levels->normal)
                ret = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
-       else if (percent <= di->bat->cap_levels->high)
+       else if (percent <= di->bm->cap_levels->high)
                ret = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
        else
                ret = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
@@@ -1182,7 -1183,7 +1183,7 @@@ static void ab8500_fg_check_capacity_li
                        di->bat_cap.prev_percent !=
                        (di->bat_cap.permille) / 10 &&
                        (di->bat_cap.permille / 10) <
-                       di->bat->fg_params->maint_thres) {
+                       di->bm->fg_params->maint_thres) {
                        dev_dbg(di->dev,
                                "battery reported full "
                                "but capacity dropping: %d\n",
@@@ -1284,7 -1285,7 +1285,7 @@@ static void ab8500_fg_algorithm_chargin
        switch (di->charge_state) {
        case AB8500_FG_CHARGE_INIT:
                di->fg_samples = SEC_TO_SAMPLE(
-                       di->bat->fg_params->accu_charging);
+                       di->bm->fg_params->accu_charging);
  
                ab8500_fg_coulomb_counter(di, true);
                ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_READOUT);
@@@ -1346,8 -1347,8 +1347,8 @@@ static bool check_sysfs_capacity(struc
        cap_permille = ab8500_fg_convert_mah_to_permille(di,
                di->bat_cap.user_mah);
  
-       lower = di->bat_cap.permille - di->bat->fg_params->user_cap_limit * 10;
-       upper = di->bat_cap.permille + di->bat->fg_params->user_cap_limit * 10;
+       lower = di->bat_cap.permille - di->bm->fg_params->user_cap_limit * 10;
+       upper = di->bat_cap.permille + di->bm->fg_params->user_cap_limit * 10;
  
        if (lower < 0)
                lower = 0;
@@@ -1387,7 -1388,7 +1388,7 @@@ static void ab8500_fg_algorithm_dischar
        case AB8500_FG_DISCHARGE_INIT:
                /* We use the FG IRQ to work on */
                di->init_cnt = 0;
-               di->fg_samples = SEC_TO_SAMPLE(di->bat->fg_params->init_timer);
+               di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer);
                ab8500_fg_coulomb_counter(di, true);
                ab8500_fg_discharge_state_to(di,
                        AB8500_FG_DISCHARGE_INITMEASURING);
                 * samples to get an initial capacity.
                 * Then go to READOUT
                 */
-               sleep_time = di->bat->fg_params->init_timer;
+               sleep_time = di->bm->fg_params->init_timer;
  
                /* Discard the first [x] seconds */
-               if (di->init_cnt >
-                       di->bat->fg_params->init_discard_time) {
+               if (di->init_cnt > di->bm->fg_params->init_discard_time) {
                        ab8500_fg_calc_cap_discharge_voltage(di, true);
  
                        ab8500_fg_check_capacity_limits(di, true);
                }
  
                di->init_cnt += sleep_time;
-               if (di->init_cnt > di->bat->fg_params->init_total_time)
+               if (di->init_cnt > di->bm->fg_params->init_total_time)
                        ab8500_fg_discharge_state_to(di,
                                AB8500_FG_DISCHARGE_READOUT_INIT);
  
                /* Intentional fallthrough */
  
        case AB8500_FG_DISCHARGE_RECOVERY:
-               sleep_time = di->bat->fg_params->recovery_sleep_timer;
+               sleep_time = di->bm->fg_params->recovery_sleep_timer;
  
                /*
                 * We should check the power consumption
  
                if (ab8500_fg_is_low_curr(di, di->inst_curr)) {
                        if (di->recovery_cnt >
-                               di->bat->fg_params->recovery_total_time) {
+                               di->bm->fg_params->recovery_total_time) {
                                di->fg_samples = SEC_TO_SAMPLE(
-                                       di->bat->fg_params->accu_high_curr);
+                                       di->bm->fg_params->accu_high_curr);
                                ab8500_fg_coulomb_counter(di, true);
                                ab8500_fg_discharge_state_to(di,
                                        AB8500_FG_DISCHARGE_READOUT);
                        di->recovery_cnt += sleep_time;
                } else {
                        di->fg_samples = SEC_TO_SAMPLE(
-                               di->bat->fg_params->accu_high_curr);
+                               di->bm->fg_params->accu_high_curr);
                        ab8500_fg_coulomb_counter(di, true);
                        ab8500_fg_discharge_state_to(di,
                                AB8500_FG_DISCHARGE_READOUT);
  
        case AB8500_FG_DISCHARGE_READOUT_INIT:
                di->fg_samples = SEC_TO_SAMPLE(
-                       di->bat->fg_params->accu_high_curr);
+                       di->bm->fg_params->accu_high_curr);
                ab8500_fg_coulomb_counter(di, true);
                ab8500_fg_discharge_state_to(di,
                                AB8500_FG_DISCHARGE_READOUT);
                        }
  
                        di->high_curr_cnt +=
-                               di->bat->fg_params->accu_high_curr;
+                               di->bm->fg_params->accu_high_curr;
                        if (di->high_curr_cnt >
-                               di->bat->fg_params->high_curr_time)
+                               di->bm->fg_params->high_curr_time)
                                di->recovery_needed = true;
  
                        ab8500_fg_calc_cap_discharge_fg(di);
                ab8500_fg_calc_cap_discharge_voltage(di, true);
  
                di->fg_samples = SEC_TO_SAMPLE(
-                       di->bat->fg_params->accu_high_curr);
+                       di->bm->fg_params->accu_high_curr);
                ab8500_fg_coulomb_counter(di, true);
                ab8500_fg_discharge_state_to(di,
                                AB8500_FG_DISCHARGE_READOUT);
@@@ -1721,7 -1721,7 +1721,7 @@@ static void ab8500_fg_low_bat_work(stru
        vbat = ab8500_fg_bat_voltage(di);
  
        /* Check if LOW_BAT still fulfilled */
-       if (vbat < di->bat->fg_params->lowbat_threshold) {
+       if (vbat < di->bm->fg_params->lowbat_threshold) {
                di->flags.low_bat = true;
                dev_warn(di->dev, "Battery voltage still LOW\n");
  
@@@ -1779,8 -1779,8 +1779,8 @@@ static int ab8500_fg_battok_init_hw_reg
        int ret;
        int new_val;
  
-       sel0 = di->bat->fg_params->battok_falling_th_sel0;
-       sel1 = di->bat->fg_params->battok_raising_th_sel1;
+       sel0 = di->bm->fg_params->battok_falling_th_sel0;
+       sel1 = di->bm->fg_params->battok_raising_th_sel1;
  
        cbp_sel0 = ab8500_fg_battok_calc(di, sel0);
        cbp_sel1 = ab8500_fg_battok_calc(di, sel1);
@@@ -1963,7 -1963,7 +1963,7 @@@ static int ab8500_fg_get_property(struc
                                di->bat_cap.max_mah);
                break;
        case POWER_SUPPLY_PROP_ENERGY_NOW:
-               if (di->flags.batt_unknown && !di->bat->chg_unknown_bat &&
+               if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
                                di->flags.batt_id_received)
                        val->intval = ab8500_fg_convert_mah_to_uwh(di,
                                        di->bat_cap.max_mah);
                val->intval = di->bat_cap.max_mah;
                break;
        case POWER_SUPPLY_PROP_CHARGE_NOW:
-               if (di->flags.batt_unknown && !di->bat->chg_unknown_bat &&
+               if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
                                di->flags.batt_id_received)
                        val->intval = di->bat_cap.max_mah;
                else
                        val->intval = di->bat_cap.prev_mah;
                break;
        case POWER_SUPPLY_PROP_CAPACITY:
-               if (di->flags.batt_unknown && !di->bat->chg_unknown_bat &&
+               if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
                                di->flags.batt_id_received)
                        val->intval = 100;
                else
                        val->intval = di->bat_cap.prev_percent;
                break;
        case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
-               if (di->flags.batt_unknown && !di->bat->chg_unknown_bat &&
+               if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
                                di->flags.batt_id_received)
                        val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
                else
@@@ -2078,7 -2078,7 +2078,7 @@@ static int ab8500_fg_get_ext_psy_data(s
                                if (!di->flags.batt_id_received) {
                                        const struct abx500_battery_type *b;
  
-                                       b = &(di->bat->bat_type[di->bat->batt_id]);
+                                       b = &(di->bm->bat_type[di->bm->batt_id]);
  
                                        di->flags.batt_id_received = true;
  
@@@ -2155,7 -2155,7 +2155,7 @@@ static int ab8500_fg_init_hw_registers(
                AB8500_SYS_CTRL2_BLOCK,
                AB8500_LOW_BAT_REG,
                ab8500_volt_to_regval(
-                       di->bat->fg_params->lowbat_threshold) << 1 |
+                       di->bm->fg_params->lowbat_threshold) << 1 |
                LOW_BAT_ENABLE);
        if (ret) {
                dev_err(di->dev, "%s write failed\n", __func__);
@@@ -2410,7 -2410,7 +2410,7 @@@ static int ab8500_fg_suspend(struct pla
  #define ab8500_fg_resume       NULL
  #endif
  
 -static int __devexit ab8500_fg_remove(struct platform_device *pdev)
 +static int ab8500_fg_remove(struct platform_device *pdev)
  {
        int ret = 0;
        struct ab8500_fg *di = platform_get_drvdata(pdev);
@@@ -2445,9 -2445,10 +2445,10 @@@ static char *supply_interface[] = 
        "ab8500_usb",
  };
  
 -static int __devinit ab8500_fg_probe(struct platform_device *pdev)
 +static int ab8500_fg_probe(struct platform_device *pdev)
  {
        struct device_node *np = pdev->dev.of_node;
+       struct abx500_bm_data *plat = pdev->dev.platform_data;
        struct ab8500_fg *di;
        int i, irq;
        int ret = 0;
                dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__);
                return -ENOMEM;
        }
-       di->bat = pdev->mfd_cell->platform_data;
-       if (!di->bat) {
-               if (np) {
-                       ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
-                       if (ret) {
-                               dev_err(&pdev->dev,
-                                       "failed to get battery information\n");
-                               return ret;
-                       }
-               } else {
-                       dev_err(&pdev->dev, "missing dt node for ab8500_fg\n");
-                       return -EINVAL;
+       if (!plat) {
+               dev_err(&pdev->dev, "no battery management data supplied\n");
+               return -EINVAL;
+       }
+       di->bm = plat;
+       if (np) {
+               ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to get battery information\n");
+                       return ret;
                }
-       } else {
-               dev_info(&pdev->dev, "falling back to legacy platform data\n");
        }
  
        mutex_init(&di->cc_lock);
        di->fg_psy.external_power_changed = ab8500_fg_external_power_changed;
  
        di->bat_cap.max_mah_design = MILLI_TO_MICRO *
-               di->bat->bat_type[di->bat->batt_id].charge_full_design;
+               di->bm->bat_type[di->bm->batt_id].charge_full_design;
  
        di->bat_cap.max_mah = di->bat_cap.max_mah_design;
  
-       di->vbat_nom = di->bat->bat_type[di->bat->batt_id].nominal_voltage;
+       di->vbat_nom = di->bm->bat_type[di->bm->batt_id].nominal_voltage;
  
        di->init_capacity = true;
  
                goto free_inst_curr_wq;
        }
  
-       di->fg_samples = SEC_TO_SAMPLE(di->bat->fg_params->init_timer);
+       di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer);
        ab8500_fg_coulomb_counter(di, true);
  
        /* Initialize completion used to notify completion of inst current */
@@@ -2615,7 -2614,7 +2614,7 @@@ static const struct of_device_id ab8500
  
  static struct platform_driver ab8500_fg_driver = {
        .probe = ab8500_fg_probe,
 -      .remove = __devexit_p(ab8500_fg_remove),
 +      .remove = ab8500_fg_remove,
        .suspend = ab8500_fg_suspend,
        .resume = ab8500_fg_resume,
        .driver = {
index 2970891460641177f53449dc1ff32b33ed26a375,a8acfe5b863fa85a5078a4b72dca229cc32803ee..8b69da0ae5af76ac983830db7e0427a7e638146a
@@@ -207,7 -207,7 +207,7 @@@ enum maxim_ret 
   * @chg_info:         information about connected charger types
   * @batt_data:                data of the battery
   * @susp_status:      current charger suspension status
-  * @bat:              pointer to the abx500_bm platform data
+  * @bm:               Platform specific battery management information
   * @chargalg_psy:     structure that holds the battery properties exposed by
   *                    the charging algorithm
   * @events:           structure for information about events triggered
@@@ -232,7 -232,7 +232,7 @@@ struct abx500_chargalg 
        struct abx500_chargalg_charger_info chg_info;
        struct abx500_chargalg_battery_data batt_data;
        struct abx500_chargalg_suspension_status susp_status;
-       struct abx500_bm_data *bat;
+       struct abx500_bm_data *bm;
        struct power_supply chargalg_psy;
        struct ux500_charger *ac_chg;
        struct ux500_charger *usb_chg;
@@@ -367,13 -367,13 +367,13 @@@ static void abx500_chargalg_start_safet
        case AC_CHG:
                timer_expiration =
                round_jiffies(jiffies +
-                       (di->bat->main_safety_tmr_h * 3600 * HZ));
+                       (di->bm->main_safety_tmr_h * 3600 * HZ));
                break;
  
        case USB_CHG:
                timer_expiration =
                round_jiffies(jiffies +
-                       (di->bat->usb_safety_tmr_h * 3600 * HZ));
+                       (di->bm->usb_safety_tmr_h * 3600 * HZ));
                break;
  
        default:
@@@ -638,32 -638,32 +638,32 @@@ static void abx500_chargalg_start_charg
   */
  static void abx500_chargalg_check_temp(struct abx500_chargalg *di)
  {
-       if (di->batt_data.temp > (di->bat->temp_low + di->t_hyst_norm) &&
-               di->batt_data.temp < (di->bat->temp_high - di->t_hyst_norm)) {
+       if (di->batt_data.temp > (di->bm->temp_low + di->t_hyst_norm) &&
+               di->batt_data.temp < (di->bm->temp_high - di->t_hyst_norm)) {
                /* Temp OK! */
                di->events.btemp_underover = false;
                di->events.btemp_lowhigh = false;
                di->t_hyst_norm = 0;
                di->t_hyst_lowhigh = 0;
        } else {
-               if (((di->batt_data.temp >= di->bat->temp_high) &&
+               if (((di->batt_data.temp >= di->bm->temp_high) &&
                        (di->batt_data.temp <
-                               (di->bat->temp_over - di->t_hyst_lowhigh))) ||
+                               (di->bm->temp_over - di->t_hyst_lowhigh))) ||
                        ((di->batt_data.temp >
-                               (di->bat->temp_under + di->t_hyst_lowhigh)) &&
-                       (di->batt_data.temp <= di->bat->temp_low))) {
+                               (di->bm->temp_under + di->t_hyst_lowhigh)) &&
+                       (di->batt_data.temp <= di->bm->temp_low))) {
                        /* TEMP minor!!!!! */
                        di->events.btemp_underover = false;
                        di->events.btemp_lowhigh = true;
-                       di->t_hyst_norm = di->bat->temp_hysteresis;
+                       di->t_hyst_norm = di->bm->temp_hysteresis;
                        di->t_hyst_lowhigh = 0;
-               } else if (di->batt_data.temp <= di->bat->temp_under ||
-                       di->batt_data.temp >= di->bat->temp_over) {
+               } else if (di->batt_data.temp <= di->bm->temp_under ||
+                       di->batt_data.temp >= di->bm->temp_over) {
                        /* TEMP major!!!!! */
                        di->events.btemp_underover = true;
                        di->events.btemp_lowhigh = false;
                        di->t_hyst_norm = 0;
-                       di->t_hyst_lowhigh = di->bat->temp_hysteresis;
+                       di->t_hyst_lowhigh = di->bm->temp_hysteresis;
                } else {
                /* Within hysteresis */
                dev_dbg(di->dev, "Within hysteresis limit temp: %d "
   */
  static void abx500_chargalg_check_charger_voltage(struct abx500_chargalg *di)
  {
-       if (di->chg_info.usb_volt > di->bat->chg_params->usb_volt_max)
+       if (di->chg_info.usb_volt > di->bm->chg_params->usb_volt_max)
                di->chg_info.usb_chg_ok = false;
        else
                di->chg_info.usb_chg_ok = true;
  
-       if (di->chg_info.ac_volt > di->bat->chg_params->ac_volt_max)
+       if (di->chg_info.ac_volt > di->bm->chg_params->ac_volt_max)
                di->chg_info.ac_chg_ok = false;
        else
                di->chg_info.ac_chg_ok = true;
@@@ -707,10 -707,10 +707,10 @@@ static void abx500_chargalg_end_of_char
        if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
                di->charge_state == STATE_NORMAL &&
                !di->maintenance_chg && (di->batt_data.volt >=
-               di->bat->bat_type[di->bat->batt_id].termination_vol ||
+               di->bm->bat_type[di->bm->batt_id].termination_vol ||
                di->events.usb_cv_active || di->events.ac_cv_active) &&
                di->batt_data.avg_curr <
-               di->bat->bat_type[di->bat->batt_id].termination_curr &&
+               di->bm->bat_type[di->bm->batt_id].termination_curr &&
                di->batt_data.avg_curr > 0) {
                if (++di->eoc_cnt >= EOC_COND_CNT) {
                        di->eoc_cnt = 0;
  static void init_maxim_chg_curr(struct abx500_chargalg *di)
  {
        di->ccm.original_iset =
-               di->bat->bat_type[di->bat->batt_id].normal_cur_lvl;
+               di->bm->bat_type[di->bm->batt_id].normal_cur_lvl;
        di->ccm.current_iset =
-               di->bat->bat_type[di->bat->batt_id].normal_cur_lvl;
-       di->ccm.test_delta_i = di->bat->maxi->charger_curr_step;
-       di->ccm.max_current = di->bat->maxi->chg_curr;
-       di->ccm.condition_cnt = di->bat->maxi->wait_cycles;
+               di->bm->bat_type[di->bm->batt_id].normal_cur_lvl;
+       di->ccm.test_delta_i = di->bm->maxi->charger_curr_step;
+       di->ccm.max_current = di->bm->maxi->chg_curr;
+       di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
        di->ccm.level = 0;
  }
  
@@@ -755,7 -755,7 +755,7 @@@ static enum maxim_ret abx500_chargalg_c
  {
        int delta_i;
  
-       if (!di->bat->maxi->ena_maxi)
+       if (!di->bm->maxi->ena_maxi)
                return MAXIM_RET_NOACTION;
  
        delta_i = di->ccm.original_iset - di->batt_data.inst_curr;
                if (di->ccm.wait_cnt == 0) {
                        dev_dbg(di->dev, "lowering current\n");
                        di->ccm.wait_cnt++;
-                       di->ccm.condition_cnt = di->bat->maxi->wait_cycles;
+                       di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
                        di->ccm.max_current =
                                di->ccm.current_iset - di->ccm.test_delta_i;
                        di->ccm.current_iset = di->ccm.max_current;
                if (di->ccm.current_iset == di->ccm.original_iset)
                        return MAXIM_RET_NOACTION;
  
-               di->ccm.condition_cnt = di->bat->maxi->wait_cycles;
+               di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
                di->ccm.current_iset = di->ccm.original_iset;
                di->ccm.level = 0;
  
                di->ccm.max_current) {
                if (di->ccm.condition_cnt-- == 0) {
                        /* Increse the iset with cco.test_delta_i */
-                       di->ccm.condition_cnt = di->bat->maxi->wait_cycles;
+                       di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
                        di->ccm.current_iset += di->ccm.test_delta_i;
                        di->ccm.level++;
                        dev_dbg(di->dev, " Maximization needed, increase"
                        return MAXIM_RET_NOACTION;
                }
        }  else {
-               di->ccm.condition_cnt = di->bat->maxi->wait_cycles;
+               di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
                return MAXIM_RET_NOACTION;
        }
  }
@@@ -838,7 -838,7 +838,7 @@@ static void handle_maxim_chg_curr(struc
                break;
        case MAXIM_RET_IBAT_TOO_HIGH:
                result = abx500_chargalg_update_chg_curr(di,
-                       di->bat->bat_type[di->bat->batt_id].normal_cur_lvl);
+                       di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
                if (result)
                        dev_err(di->dev, "failed to set chg curr\n");
                break;
@@@ -1210,7 -1210,7 +1210,7 @@@ static void abx500_chargalg_algorithm(s
         * this way
         */
        if (!charger_status ||
-               (di->events.batt_unknown && !di->bat->chg_unknown_bat)) {
+               (di->events.batt_unknown && !di->bm->chg_unknown_bat)) {
                if (di->charge_state != STATE_HANDHELD) {
                        di->events.safety_timer_expired = false;
                        abx500_chargalg_state_to(di, STATE_HANDHELD_INIT);
  
        case STATE_NORMAL_INIT:
                abx500_chargalg_start_charging(di,
-                       di->bat->bat_type[di->bat->batt_id].normal_vol_lvl,
-                       di->bat->bat_type[di->bat->batt_id].normal_cur_lvl);
+                       di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
+                       di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
                abx500_chargalg_state_to(di, STATE_NORMAL);
                abx500_chargalg_start_safety_timer(di);
                abx500_chargalg_stop_maintenance_timer(di);
                handle_maxim_chg_curr(di);
                if (di->charge_status == POWER_SUPPLY_STATUS_FULL &&
                        di->maintenance_chg) {
-                       if (di->bat->no_maintenance)
+                       if (di->bm->no_maintenance)
                                abx500_chargalg_state_to(di,
                                        STATE_WAIT_FOR_RECHARGE_INIT);
                        else
  
        case STATE_WAIT_FOR_RECHARGE:
                if (di->batt_data.volt <=
-                       di->bat->bat_type[di->bat->batt_id].recharge_vol) {
+                       di->bm->bat_type[di->bm->batt_id].recharge_vol) {
                        if (di->rch_cnt-- == 0)
                                abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
                } else
        case STATE_MAINTENANCE_A_INIT:
                abx500_chargalg_stop_safety_timer(di);
                abx500_chargalg_start_maintenance_timer(di,
-                       di->bat->bat_type[
-                               di->bat->batt_id].maint_a_chg_timer_h);
+                       di->bm->bat_type[
+                               di->bm->batt_id].maint_a_chg_timer_h);
                abx500_chargalg_start_charging(di,
-                       di->bat->bat_type[
-                               di->bat->batt_id].maint_a_vol_lvl,
-                       di->bat->bat_type[
-                               di->bat->batt_id].maint_a_cur_lvl);
+                       di->bm->bat_type[
+                               di->bm->batt_id].maint_a_vol_lvl,
+                       di->bm->bat_type[
+                               di->bm->batt_id].maint_a_cur_lvl);
                abx500_chargalg_state_to(di, STATE_MAINTENANCE_A);
                power_supply_changed(&di->chargalg_psy);
                /* Intentional fallthrough*/
  
        case STATE_MAINTENANCE_B_INIT:
                abx500_chargalg_start_maintenance_timer(di,
-                       di->bat->bat_type[
-                               di->bat->batt_id].maint_b_chg_timer_h);
+                       di->bm->bat_type[
+                               di->bm->batt_id].maint_b_chg_timer_h);
                abx500_chargalg_start_charging(di,
-                       di->bat->bat_type[
-                               di->bat->batt_id].maint_b_vol_lvl,
-                       di->bat->bat_type[
-                               di->bat->batt_id].maint_b_cur_lvl);
+                       di->bm->bat_type[
+                               di->bm->batt_id].maint_b_vol_lvl,
+                       di->bm->bat_type[
+                               di->bm->batt_id].maint_b_cur_lvl);
                abx500_chargalg_state_to(di, STATE_MAINTENANCE_B);
                power_supply_changed(&di->chargalg_psy);
                /* Intentional fallthrough*/
  
        case STATE_TEMP_LOWHIGH_INIT:
                abx500_chargalg_start_charging(di,
-                       di->bat->bat_type[
-                               di->bat->batt_id].low_high_vol_lvl,
-                       di->bat->bat_type[
-                               di->bat->batt_id].low_high_cur_lvl);
+                       di->bm->bat_type[
+                               di->bm->batt_id].low_high_vol_lvl,
+                       di->bm->bat_type[
+                               di->bm->batt_id].low_high_cur_lvl);
                abx500_chargalg_stop_maintenance_timer(di);
                di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
                abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH);
@@@ -1543,11 -1543,11 +1543,11 @@@ static void abx500_chargalg_periodic_wo
        if (di->chg_info.conn_chg)
                queue_delayed_work(di->chargalg_wq,
                        &di->chargalg_periodic_work,
-                       di->bat->interval_charging * HZ);
+                       di->bm->interval_charging * HZ);
        else
                queue_delayed_work(di->chargalg_wq,
                        &di->chargalg_periodic_work,
-                       di->bat->interval_not_charging * HZ);
+                       di->bm->interval_not_charging * HZ);
  }
  
  /**
@@@ -1614,7 -1614,7 +1614,7 @@@ static int abx500_chargalg_get_property
                if (di->events.batt_ovv) {
                        val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
                } else if (di->events.btemp_underover) {
-                       if (di->batt_data.temp <= di->bat->temp_under)
+                       if (di->batt_data.temp <= di->bm->temp_under)
                                val->intval = POWER_SUPPLY_HEALTH_COLD;
                        else
                                val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
@@@ -1782,7 -1782,7 +1782,7 @@@ static int abx500_chargalg_suspend(stru
  #define abx500_chargalg_resume       NULL
  #endif
  
 -static int __devexit abx500_chargalg_remove(struct platform_device *pdev)
 +static int abx500_chargalg_remove(struct platform_device *pdev)
  {
        struct abx500_chargalg *di = platform_get_drvdata(pdev);
  
@@@ -1803,9 -1803,10 +1803,10 @@@ static char *supply_interface[] = 
        "ab8500_fg",
  };
  
 -static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
 +static int abx500_chargalg_probe(struct platform_device *pdev)
  {
        struct device_node *np = pdev->dev.of_node;
+       struct abx500_bm_data *plat = pdev->dev.platform_data;
        struct abx500_chargalg *di;
        int ret = 0;
  
                dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__);
                return -ENOMEM;
        }
-       di->bat = pdev->mfd_cell->platform_data;
-       if (!di->bat) {
-               if (np) {
-                       ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
-                       if (ret) {
-                               dev_err(&pdev->dev,
-                                       "failed to get battery information\n");
-                               return ret;
-                       }
-               } else {
-                       dev_err(&pdev->dev, "missing dt node for ab8500_chargalg\n");
-                       return -EINVAL;
+       if (!plat) {
+               dev_err(&pdev->dev, "no battery management data supplied\n");
+               return -EINVAL;
+       }
+       di->bm = plat;
+       if (np) {
+               ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to get battery information\n");
+                       return ret;
                }
-       } else {
-               dev_info(&pdev->dev, "falling back to legacy platform data\n");
        }
  
        /* get device struct */
@@@ -1912,7 -1911,7 +1911,7 @@@ static const struct of_device_id ab8500
  
  static struct platform_driver abx500_chargalg_driver = {
        .probe = abx500_chargalg_probe,
 -      .remove = __devexit_p(abx500_chargalg_remove),
 +      .remove = abx500_chargalg_remove,
        .suspend = abx500_chargalg_suspend,
        .resume = abx500_chargalg_resume,
        .driver = {