bci: some more code for testing
[pandora-kernel.git] / drivers / power / twl4030_bci_battery.c
index 6a55838..4415d7b 100644 (file)
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#define DEBUG
+/* Boot with automatic charge */
+#define CHARGE_MODE 1
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/device.h>
@@ -23,7 +27,6 @@
 #include <linux/platform_device.h>
 #include <linux/i2c/twl4030.h>
 #include <linux/power_supply.h>
-#include <mach/bci.h>
 #include <linux/i2c/twl4030-madc.h>
 
 #define T2_BATTERY_VOLT                0x04
@@ -42,8 +45,8 @@
 #define REG_PHY_CLK_CTRL_STS   0x0FF
 #define PHY_DPLL_CLK           0x01
 
-#define REG_BCICTL1            0x023
-#define REG_BCICTL2            0x024
+#define REG_BCICTL1            0x023
+#define REG_BCICTL2            0x024
 #define CGAIN                  0x020
 #define ITHEN                  0x010
 #define ITHSENS                        0x007
@@ -51,6 +54,7 @@
 /* Boot BCI flag bits */
 #define BCIAUTOWEN             0x020
 #define CONFIG_DONE            0x010
+#define CVENAC                 0x004
 #define BCIAUTOUSB             0x002
 #define BCIAUTOAC              0x001
 #define BCIMSTAT_MASK          0x03F
@@ -70,7 +74,7 @@
 #define REG_BCIMSTATEC         0x02
 #define REG_BCIMFSTS4          0x010
 #define REG_BCIMFSTS2          0x00E
-#define REG_BCIMFSTS3          0x00F
+#define REG_BCIMFSTS3          0x00F
 #define REG_BCIMFSTS1          0x001
 #define USBFASTMCHG            0x004
 #define BATSTSPCHG             0x004
 #define REG_BB_CFG             0x012
 #define BBCHEN                 0x010
 
+/* GPBR */
+#define REG_GPBR1              0x0c
+#define MADC_HFCLK_EN          0x80
+#define DEFAULT_MADC_CLK_EN    0x10
+
 /* Power supply charge interrupt */
 #define REG_PWR_ISR1           0x00
 #define REG_PWR_IMR1           0x01
 #define COR                    0x004
 
 /* interrupt status registers */
-#define REG_BCIISR1A           0x0
-#define REG_BCIISR2A           0x01
+#define REG_BCIISR1A           0x0
+#define REG_BCIISR2A           0x01
 
 /* Interrupt flags bits BCIISR1 */
 #define BATSTS_ISR1            0x080
 /* BCIEDR3 */
 #define        VBATLVL_EDRRISIN        0x02
 
+/* BCIIREF1 */
+#define REG_BCIIREF1           0x027
+#define REG_BCIIREF2           0x028
+
+/* BCIMFTH1 */
+#define REG_BCIMFTH1           0x016
+
+/* Key */
+#define KEY_IIREF              0xE7
+#define KEY_FTH1               0xD2
+#define REG_BCIMFKEY           0x011
+
 /* Step size and prescaler ratio */
 #define TEMP_STEP_SIZE         147
 #define TEMP_PSR_R             100
 #define ENABLE         1
 #define DISABLE                1
 
-/* Ptr to thermistor table */
-int *therm_tbl;
-
-static int twl4030_bci_battery_probe(struct platform_device *dev);
-static int twl4030_bci_battery_remove(struct platform_device *dev);
-#ifdef CONFIG_PM
-static int twl4030_bci_battery_suspend(struct platform_device *dev,
-                                       pm_message_t state);
-static int twl4030_bci_battery_resume(struct platform_device *dev);
-#endif
-
 struct twl4030_bci_device_info {
        struct device           *dev;
 
@@ -169,18 +179,8 @@ struct twl4030_bci_device_info {
        struct power_supply     bk_bat;
        struct delayed_work     twl4030_bci_monitor_work;
        struct delayed_work     twl4030_bk_bci_monitor_work;
-};
 
-static struct platform_driver twl4030_bci_battery_driver = {
-       .probe =        twl4030_bci_battery_probe,
-       .remove =       twl4030_bci_battery_remove,
-#ifdef CONFIG_PM
-       .suspend =      twl4030_bci_battery_suspend,
-       .resume =       twl4030_bci_battery_resume,
-#endif
-       .driver = {
-               .name = "twl4030-bci-battery",
-       },
+       struct twl4030_bci_platform_data *pdata;
 };
 
 static int usb_charger_flag;
@@ -204,14 +204,11 @@ static inline int twl4030charger_presence_evt(void)
        if (ret)
                return IRQ_NONE;
 
-       /* If the AC charger have been connected */
-       if (chg_sts & STS_CHG) {
+       if (chg_sts & STS_CHG) { /* If the AC charger have been connected */
                /* configuring falling edge detection for CHG_PRES */
                set = CHG_PRES_FALLING;
                clear = CHG_PRES_RISING;
-       }
-       /* If the AC charger have been disconnected */
-       else {
+       } else { /* If the AC charger have been disconnected */
                /* configuring rising edge detection for CHG_PRES */
                set = CHG_PRES_RISING;
                clear = CHG_PRES_FALLING;
@@ -230,9 +227,17 @@ static inline int twl4030charger_presence_evt(void)
  * USB_PRES (USB charger presence) CHG_PRES (AC charger presence) events
  *
  */
-static irqreturn_t twl4030charger_interrupt(int irq, void *dev_id)
+static irqreturn_t twl4030charger_interrupt(int irq, void *_di)
 {
-       struct twl4030_bci_device_info *di = dev_id;
+       struct twl4030_bci_device_info *di = _di;
+
+#ifdef CONFIG_LOCKDEP
+       /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
+        * we don't want and can't tolerate.  Although it might be
+        * friendlier not to borrow this thread context...
+        */
+       local_irq_enable();
+#endif
 
        twl4030charger_presence_evt();
        power_supply_changed(&di->bat);
@@ -264,17 +269,14 @@ static int twl4030battery_presence_evt(void)
         * REVISIT: Physically inserting/removing the batt
         * does not seem to generate an int on 3430ES2 SDP.
         */
-
-       /* In case of the battery insertion event */
        if ((batstspchg & BATSTSPCHG) || (batstsmchg & BATSTSMCHG)) {
+               /* In case of the battery insertion event */
                ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRRISIN,
                        BATSTS_EDRFALLING, REG_BCIEDR2);
                if (ret)
                        return ret;
-       }
-
-       /* In case of the battery removal event */
-       else {
+       } else {
+               /* In case of the battery removal event */
                ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRFALLING,
                        BATSTS_EDRRISIN, REG_BCIEDR2);
                if (ret)
@@ -298,18 +300,27 @@ static int twl4030battery_level_evt(void)
        if (ret)
                return ret;
 
+       /* REVISIT could use a bitmap */
        if (mfst & VBATOV4) {
                LVL_4 = 1;
-               LVL_3 = LVL_2 = LVL_1 = 0;
+               LVL_3 = 0;
+               LVL_2 = 0;
+               LVL_1 = 0;
        } else if (mfst & VBATOV3) {
+               LVL_4 = 0;
                LVL_3 = 1;
-               LVL_4 = LVL_2 = LVL_1 = 0;
+               LVL_2 = 0;
+               LVL_1 = 0;
        } else if (mfst & VBATOV2) {
+               LVL_4 = 0;
+               LVL_3 = 0;
                LVL_2 = 1;
-               LVL_4 = LVL_3 = LVL_1 = 0;
+               LVL_1 = 0;
        } else {
+               LVL_4 = 0;
+               LVL_3 = 0;
+               LVL_2 = 0;
                LVL_1 = 1;
-               LVL_4 = LVL_3 = LVL_2 = 0;
        }
 
        return 0;
@@ -323,10 +334,18 @@ static int twl4030battery_level_evt(void)
  * VBATOV (main battery voltage threshold) events
  *
  */
-static irqreturn_t twl4030battery_interrupt(int irq, void *dev_id)
+static irqreturn_t twl4030battery_interrupt(int irq, void *_di)
 {
-       int ret;
        u8 isr1a_val, isr2a_val, clear_2a, clear_1a;
+       int ret;
+
+#ifdef CONFIG_LOCKDEP
+       /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
+        * we don't want and can't tolerate.  Although it might be
+        * friendlier not to borrow this thread context...
+        */
+       local_irq_enable();
+#endif
 
        ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr1a_val,
                                REG_BCIISR1A);
@@ -338,8 +357,8 @@ static irqreturn_t twl4030battery_interrupt(int irq, void *dev_id)
        if (ret)
                return IRQ_NONE;
 
-       clear_2a = (isr2a_val & VBATLVL_ISR1)? (VBATLVL_ISR1): 0;
-       clear_1a = (isr1a_val & BATSTS_ISR1)? (BATSTS_ISR1): 0;
+       clear_2a = (isr2a_val & VBATLVL_ISR1) ? (VBATLVL_ISR1) : 0;
+       clear_1a = (isr1a_val & BATSTS_ISR1) ? (BATSTS_ISR1) : 0;
 
        /* cleaning BCI interrupt status flags */
        ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS,
@@ -427,15 +446,21 @@ static int twl4030battery_hw_presence_en(int enable)
 /*
  * Enable/Disable AC Charge funtionality.
  */
-static int twl4030charger_ac_en(int enable)
+static int twl4030charger_ac_en(int enable, int automatic)
 {
        int ret;
 
        if (enable) {
                /* forcing the field BCIAUTOAC (BOOT_BCI[0) to 1 */
-               ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
-                       (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC),
-                       REG_BOOT_BCI);
+               if(!automatic) {
+                       ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC | CVENAC,
+                               (CONFIG_DONE | BCIAUTOWEN),
+                               REG_BOOT_BCI);
+               } else {
+                       ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
+                               (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC | CVENAC),
+                               REG_BOOT_BCI);
+               }
                if (ret)
                        return ret;
        } else {
@@ -446,6 +471,7 @@ static int twl4030charger_ac_en(int enable)
                if (ret)
                        return ret;
        }
+
        return 0;
 }
 
@@ -519,11 +545,15 @@ int twl4030charger_usb_en(int enable)
  * Return battery temperature
  * Or < 0 on failure.
  */
-static int twl4030battery_temperature(void)
+static int twl4030battery_temperature(struct twl4030_bci_device_info *di)
 {
        u8 val;
        int temp, curr, volt, res, ret;
 
+       /* Is a temperature table specified? */
+       if (!di->pdata->tblsize)
+               return 0;
+
        /* Getting and calculating the thermistor voltage */
        ret = read_bci_val(T2_BATTERY_TEMP);
        if (ret < 0)
@@ -544,7 +574,7 @@ static int twl4030battery_temperature(void)
 
        /*calculating temperature*/
        for (temp = 58; temp >= 0; temp--) {
-               int actual = therm_tbl [temp];
+               int actual = di->pdata->battery_tmp_tbl[temp];
                if ((actual - res) >= 0)
                        break;
        }
@@ -599,9 +629,8 @@ static int twl4030battery_current(void)
  */
 static int twl4030backupbatt_voltage(void)
 {
-       int ret, temp;
-       u8 volt;
        struct twl4030_madc_request req;
+       int temp;
 
        req.channels = (1 << 9);
        req.do_avg = 0;
@@ -631,12 +660,12 @@ static int twl4030charger_presence(void)
        ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts,
                REG_STS_HW_CONDITIONS);
        if (ret) {
-               pr_err("BATTERY DRIVER: error reading STS_HW_CONDITIONS \n");
+               pr_err("twl4030_bci: error reading STS_HW_CONDITIONS\n");
                return ret;
        }
 
-       ret = (hwsts & STS_CHG)? AC_PW_CONN: NO_PW_CONN;
-       ret += (hwsts & STS_VBUS)? USB_PW_CONN: NO_PW_CONN;
+       ret = (hwsts & STS_CHG) ? AC_PW_CONN : NO_PW_CONN;
+       ret += (hwsts & STS_VBUS) ? USB_PW_CONN : NO_PW_CONN;
 
        if (ret & USB_PW_CONN)
                usb_charger_flag = 1;
@@ -659,10 +688,18 @@ static int twl4030bci_status(void)
        ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
                &status, REG_BCIMSTATEC);
        if (ret) {
-               pr_err("BATTERY DRIVER: error reading BCIMSTATEC \n");
+               pr_err("twl4030_bci: error reading BCIMSTATEC\n");
                return ret;
        }
 
+#ifdef DEBUG
+       {
+               static int oldstatus = -1;
+               if (status != oldstatus)
+                       printk("BCI DEBUG: BCIMSTATEC Charge state is 0x%x\n", status);
+               oldstatus = status;
+       }
+#endif
        return (int) (status & BCIMSTAT_MASK);
 }
 
@@ -709,16 +746,47 @@ static int twl4030backupbatt_voltage_setup(void)
  * Settup the twl4030 BCI module to measure battery
  * temperature
  */
-static int twl4030battery_temp_setup(void)
+static int twl4030battery_temp_setup(int dump)
 {
-       int ret;
+#ifdef DEBUG
+       u8 i;
+#endif
+       u8 ret;
 
        /* Enabling thermistor current */
-       ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
+       ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, 0x1B,
                REG_BCICTL1);
        if (ret)
                return ret;
 
+       if (!dump)
+               return 0;
+#ifdef DEBUG
+       twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_BOOT_BCI);
+       printk("BCI DEBUG: BOOT_BCI Value is 0x%x\n", ret);
+
+       twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_STS_HW_CONDITIONS);
+       printk("BCI DEBUG: STS_HW_CONDITIONS Value is 0x%x\n", ret);
+
+       twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL1);
+       printk("BCI DEBUG: BCICTL1 Value is 0x%x\n", ret);
+
+       twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL2);
+       printk("BCI DEBUG: BCICTL2 Value is 0x%x\n", ret);
+
+       twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, 0x0);
+       printk("BCI DEBUG: BCIMDEN Value is 0x%x\n", ret);
+
+       twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &ret, REG_GPBR1);
+       printk("BCI DEBUG: GPBR1 Value is 0x%x\n", ret);
+
+       for(i = 0x0; i <= 0x32; i++)
+       {
+               twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, i);
+               printk("BCI DEBUG: BCI 0x%x Value is 0x%x\n", i, ret);
+       }
+#endif
+
        return 0;
 }
 
@@ -734,7 +802,6 @@ static inline int clear_n_set(u8 mod_no, u8 clear, u8 set, u8 reg)
        ret = twl4030_i2c_read_u8(mod_no, &val, reg);
        if (ret)
                return ret;
-
        /* Clearing all those bits to clear */
        val &= ~(clear);
 
@@ -774,13 +841,14 @@ static void twl4030_bk_bci_battery_work(struct work_struct *work)
                struct twl4030_bci_device_info,
                twl4030_bk_bci_monitor_work.work);
 
-       twl4030_bk_bci_battery_read_status(di);
+       if(!di->pdata->no_backup_battery)
+               twl4030_bk_bci_battery_read_status(di);
        schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
 }
 
 static void twl4030_bci_battery_read_status(struct twl4030_bci_device_info *di)
 {
-       di->temp_C = twl4030battery_temperature();
+       di->temp_C = twl4030battery_temperature(di);
        di->voltage_uV = twl4030battery_voltage();
        di->current_uA = twl4030battery_current();
 }
@@ -821,6 +889,111 @@ static void twl4030_bci_battery_external_power_changed(struct power_supply *psy)
 #define to_twl4030_bk_bci_device_info(x) container_of((x), \
                struct twl4030_bci_device_info, bk_bat);
 
+static ssize_t
+show_charge_current(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       u8  ctl;
+       int ret = read_bci_val(REG_BCIIREF1) & 0x1FF;
+       twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ctl, REG_BCICTL1);
+
+       if (ctl & CGAIN)
+               ret |= 0x200;
+
+#ifdef DEBUG
+       /* Dump debug */
+       twl4030battery_temp_setup(1);
+#endif
+
+       return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t
+set_charge_current(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       unsigned long newCurrent;
+       int ret;
+
+       ret = strict_strtoul(buf, 10, &newCurrent);
+       if (ret)
+               return -EINVAL;
+
+       ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
+       if (ret)
+               return ret;
+
+       ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, newCurrent & 0xff, REG_BCIIREF1);
+       if (ret)
+               return ret;
+
+       ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
+       if (ret)
+               return ret;
+
+       ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x1, REG_BCIIREF2);
+       if (ret)
+               return ret;
+
+       /* Set software-controlled charge */
+       twl4030charger_ac_en(ENABLE, 0);
+
+       /* Set CGAIN = 0 or 1 */
+       if(newCurrent > 511) {
+               u8 tmp;
+
+               /* Set CGAIN = 1 -- need to wait until automatic charge turns off */
+               while(!ret) {
+                       clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, CGAIN | 0x1B, REG_BCICTL1);
+                       twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
+
+                       ret = tmp & CGAIN;
+                       if(!ret)
+                               mdelay(50);
+               }
+       } else {
+               u8 tmp;
+
+               /* Set CGAIN = 0 -- need to wait until automatic charge turns off */
+               while(!ret) {
+                       clear_n_set(TWL4030_MODULE_MAIN_CHARGE, CGAIN, 0x1B, REG_BCICTL1);
+                       twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
+
+                       ret = !(tmp & CGAIN);
+                       if(!ret)
+                               mdelay(50);
+               }
+       }
+
+       /* Set automatic charge (CGAIN = 0/1 persists) */
+       twl4030charger_ac_en(ENABLE, 1);
+
+       return count;
+}
+static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUSR, show_charge_current, set_charge_current);
+
+static ssize_t
+show_current2(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       int ret, curr = read_bci_val(T2_BATTERY_CUR);
+       u8 val;
+
+       ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
+               REG_BCICTL1);
+       if (ret)
+               return ret;
+
+       if (val & CGAIN)
+               //ret = (int)((float)curr * 1.6617790811339199f * 2.0f - 1.7f);
+               ret = curr * 16618 * 2 - 1700 * 10000;
+       else
+               //ret = (int)((float)curr * 1.6617790811339199f - 0.85f);
+               ret = curr * 16618 - 850 * 10000;
+       ret /= 10000;
+
+       return sprintf(buf, "%d (BCIICHG2 = 0x%02x, BCIICHG1 = 0x%02x, CGAIN = %d)\n",
+               ret, curr >> 8, curr & 0xff, (val & CGAIN) ? 1 : 0);
+}
+static DEVICE_ATTR(current_now2, S_IRUGO | S_IWUSR, show_current2, NULL);
+
 static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
                                        enum power_supply_property psp,
                                        union power_supply_propval *val)
@@ -842,9 +1015,11 @@ static int twl4030_bci_battery_get_property(struct power_supply *psy,
                                        enum power_supply_property psp,
                                        union power_supply_propval *val)
 {
-       struct twl4030_bci_device_info *di = to_twl4030_bci_device_info(psy);
+       struct twl4030_bci_device_info *di;
        int status = 0;
 
+       di = to_twl4030_bci_device_info(psy);
+
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
                val->intval = di->charge_status;
@@ -905,21 +1080,18 @@ static char *twl4030_bci_supplied_to[] = {
        "twl4030_bci_battery",
 };
 
-static int twl4030_bci_battery_probe(struct  platform_device *dev)
+static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
 {
+       struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
        struct twl4030_bci_device_info *di;
+       int irq;
        int ret;
-       struct twl4030_bci_platform_data *pdata = dev->dev.platform_data;
-
-       therm_tbl = pdata->battery_tmp_tbl;
 
        di = kzalloc(sizeof(*di), GFP_KERNEL);
        if (!di)
                return -ENOMEM;
 
-       platform_set_drvdata(dev, di);
-
-       di->dev = &dev->dev;
+       di->dev = &pdev->dev;
        di->bat.name = "twl4030_bci_battery";
        di->bat.supplied_to = twl4030_bci_supplied_to;
        di->bat.num_supplicants = ARRAY_SIZE(twl4030_bci_supplied_to);
@@ -938,44 +1110,57 @@ static int twl4030_bci_battery_probe(struct  platform_device *dev)
        di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
        di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
        di->bk_bat.external_power_changed = NULL;
+       di->pdata = pdata;
+
+       /* Set up clocks */
+       twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, MADC_HFCLK_EN | DEFAULT_MADC_CLK_EN, REG_GPBR1);
 
-       twl4030charger_ac_en(ENABLE);
+       twl4030charger_ac_en(ENABLE, CHARGE_MODE);
        twl4030charger_usb_en(ENABLE);
        twl4030battery_hw_level_en(ENABLE);
        twl4030battery_hw_presence_en(ENABLE);
 
+       platform_set_drvdata(pdev, di);
+
        /* settings for temperature sensing */
-       ret = twl4030battery_temp_setup();
+       ret = twl4030battery_temp_setup(0);
        if (ret)
                goto temp_setup_fail;
 
        /* enabling GPCH09 for read back battery voltage */
-       ret = twl4030backupbatt_voltage_setup();
-       if (ret)
-               goto voltage_setup_fail;
+       if(!di->pdata->no_backup_battery)
+       {
+               ret = twl4030backupbatt_voltage_setup();
+               if (ret)
+                       goto voltage_setup_fail;
+       }
+
+       /* REVISIT do we need to request both IRQs ?? */
 
        /* request BCI interruption */
        ret = request_irq(TWL4030_MODIRQ_BCI, twl4030battery_interrupt,
-               IRQF_DISABLED, dev->name, NULL);
+               0, pdev->name, NULL);
        if (ret) {
-               pr_err("BATTERY DRIVER: (BCI) IRQ%d is not free.\n",
-                       TWL4030_MODIRQ_PWR);
+               dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
+                       TWL4030_MODIRQ_BCI, ret);
                goto batt_irq_fail;
        }
 
+       irq = platform_get_irq(pdev, 0);
+
        /* request Power interruption */
-       ret = request_irq(TWL4030_PWRIRQ_CHG_PRES, twl4030charger_interrupt,
-               0, dev->name, di);
+       ret = request_irq(irq, twl4030charger_interrupt,
+               0, pdev->name, di);
 
        if (ret) {
-               pr_err("BATTERY DRIVER: (POWER) IRQ%d is not free.\n",
-                       TWL4030_MODIRQ_PWR);
+               dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
+                       irq, ret);
                goto chg_irq_fail;
        }
 
-       ret = power_supply_register(&dev->dev, &di->bat);
+       ret = power_supply_register(&pdev->dev, &di->bat);
        if (ret) {
-               pr_err("BATTERY DRIVER: failed to register main battery\n");
+               dev_dbg(&pdev->dev, "failed to register main battery\n");
                goto batt_failed;
        }
 
@@ -983,11 +1168,21 @@ static int twl4030_bci_battery_probe(struct  platform_device *dev)
                                twl4030_bci_battery_work);
        schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
 
-       ret = power_supply_register(&dev->dev, &di->bk_bat);
+       if(!pdata->no_backup_battery)
+       {
+               ret = power_supply_register(&pdev->dev, &di->bk_bat);
+               if (ret) {
+                       dev_dbg(&pdev->dev, "failed to register backup battery\n");
+                       goto bk_batt_failed;
+               }
+       }
+
+       ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
        if (ret) {
-               pr_err("BATTERY DRIVER: failed to register backup battery\n");
+               dev_err(&pdev->dev, "failed to create sysfs entries\n");
                goto bk_batt_failed;
        }
+       device_create_file(di->bat.dev, &dev_attr_current_now2);
 
        INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bk_bci_monitor_work,
                                twl4030_bk_bci_battery_work);
@@ -996,16 +1191,16 @@ static int twl4030_bci_battery_probe(struct  platform_device *dev)
        return 0;
 
 bk_batt_failed:
-       power_supply_unregister(&di->bat);
+       if(!pdata->no_backup_battery)
+               power_supply_unregister(&di->bat);
 batt_failed:
-       free_irq(TWL4030_MODIRQ_PWR, di);
+       free_irq(irq, di);
 chg_irq_fail:
-prev_setup_err:
        free_irq(TWL4030_MODIRQ_BCI, NULL);
 batt_irq_fail:
 voltage_setup_fail:
 temp_setup_fail:
-       twl4030charger_ac_en(DISABLE);
+       twl4030charger_ac_en(DISABLE, CHARGE_MODE);
        twl4030charger_usb_en(DISABLE);
        twl4030battery_hw_level_en(DISABLE);
        twl4030battery_hw_presence_en(DISABLE);
@@ -1014,32 +1209,33 @@ temp_setup_fail:
        return ret;
 }
 
-static int twl4030_bci_battery_remove(struct  platform_device *dev)
+static int __exit twl4030_bci_battery_remove(struct platform_device *pdev)
 {
-       struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
+       struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
+       int irq = platform_get_irq(pdev, 0);
 
-       twl4030charger_ac_en(DISABLE);
+       twl4030charger_ac_en(DISABLE, CHARGE_MODE);
        twl4030charger_usb_en(DISABLE);
        twl4030battery_hw_level_en(DISABLE);
        twl4030battery_hw_presence_en(DISABLE);
 
        free_irq(TWL4030_MODIRQ_BCI, NULL);
-       free_irq(TWL4030_MODIRQ_PWR, di);
+       free_irq(irq, di);
 
        flush_scheduled_work();
        power_supply_unregister(&di->bat);
        power_supply_unregister(&di->bk_bat);
-       platform_set_drvdata(dev, NULL);
+       platform_set_drvdata(pdev, NULL);
        kfree(di);
 
        return 0;
 }
 
 #ifdef CONFIG_PM
-static int twl4030_bci_battery_suspend(struct platform_device *dev,
+static int twl4030_bci_battery_suspend(struct platform_device *pdev,
        pm_message_t state)
 {
-       struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
+       struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
 
        di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
        cancel_delayed_work(&di->twl4030_bci_monitor_work);
@@ -1047,37 +1243,42 @@ static int twl4030_bci_battery_suspend(struct platform_device *dev,
        return 0;
 }
 
-static int twl4030_bci_battery_resume(struct platform_device *dev)
+static int twl4030_bci_battery_resume(struct platform_device *pdev)
 {
-       struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
+       struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
 
        schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
        schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 50);
        return 0;
 }
+#else
+#define twl4030_bci_battery_suspend    NULL
+#define twl4030_bci_battery_resume     NULL
 #endif /* CONFIG_PM */
 
-/*
- * Battery driver module initializer function
- * registers battery driver structure
- */
+static struct platform_driver twl4030_bci_battery_driver = {
+       .probe          = twl4030_bci_battery_probe,
+       .remove         = __exit_p(twl4030_bci_battery_remove),
+       .suspend        = twl4030_bci_battery_suspend,
+       .resume         = twl4030_bci_battery_resume,
+       .driver         = {
+               .name   = "twl4030_bci",
+       },
+};
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl4030_bci");
+MODULE_AUTHOR("Texas Instruments Inc");
+
 static int __init twl4030_battery_init(void)
 {
        return platform_driver_register(&twl4030_bci_battery_driver);
-
 }
+module_init(twl4030_battery_init);
 
-/*
- * Battery driver module exit function
- * unregister battery driver structure
- */
 static void __exit twl4030_battery_exit(void)
 {
        platform_driver_unregister(&twl4030_bci_battery_driver);
 }
-
-module_init(twl4030_battery_init);
 module_exit(twl4030_battery_exit);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("twl4030_bci_battery");
-MODULE_AUTHOR("Texas Instruments Inc");
+