Merge branches 'pandora-3.2-aufs', 'pandora-3.2-mru', 'pandora-3.2-picks' and 'pandor...
authorGrazvydas Ignotas <notasas@gmail.com>
Sun, 15 Jan 2012 18:13:06 +0000 (20:13 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Sun, 15 Jan 2012 18:13:06 +0000 (20:13 +0200)
1  2  3  4 
drivers/power/bq27x00_battery.c
drivers/power/twl4030_charger.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
include/linux/i2c/twl.h

    
    #define BQ27000_REG_RSOC            0x0B /* Relative State-of-Charge */
    #define BQ27000_REG_ILMD            0x76 /* Initial last measured discharge */
-- -#define BQ27000_FLAG_CHGS           BIT(7)
++ +#define BQ27000_FLAG_EDVF           BIT(0) /* Final End-of-Discharge-Voltage flag */
++ +#define BQ27000_FLAG_EDV1           BIT(1) /* First End-of-Discharge-Voltage flag */
++ +#define BQ27000_FLAG_CI                     BIT(4) /* Capacity Inaccurate flag */
    #define BQ27000_FLAG_FC                     BIT(5)
++ +#define BQ27000_FLAG_CHGS           BIT(7) /* Charge state flag */
++ +
++ +#define BQ27000_FLAGS_IMPORTANT             (BQ27000_FLAG_FC|BQ27000_FLAG_CHGS|BIT(31))
    
    #define BQ27500_REG_SOC                     0x2C
    #define BQ27500_REG_DCAP            0x3C /* Design capacity */
    #define BQ27500_FLAG_DSC            BIT(0)
++ +#define BQ27500_FLAG_SOCF           BIT(1) /* State-of-Charge threshold final */
++ +#define BQ27500_FLAG_SOC1           BIT(2) /* State-of-Charge threshold 1 */
    #define BQ27500_FLAG_FC                     BIT(9)
    
++ +#define BQ27500_FLAGS_IMPORTANT             (BQ27500_FLAG_FC|BQ27500_FLAG_DSC|BIT(31))
++ +
    #define BQ27000_RS                  20 /* Resistor sense */
    
    struct bq27x00_device_info;
@@@@@ -79,9 -79,9 -88,8 -79,9 +88,8 @@@@@ struct bq27x00_reg_cache 
        int charge_full;
        int cycle_count;
        int capacity;
++ +    int energy;
        int flags;
-- -
-- -    int current_now;
    };
    
    struct bq27x00_device_info {
@@@@@ -108,6 -108,6 -116,7 -108,6 +116,7 @@@@@ static enum power_supply_property bq27x
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
        POWER_SUPPLY_PROP_CURRENT_NOW,
        POWER_SUPPLY_PROP_CAPACITY,
++ +    POWER_SUPPLY_PROP_CAPACITY_LEVEL,
        POWER_SUPPLY_PROP_TEMP,
        POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
        POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
@@@@@ -149,7 -149,7 -158,7 -149,7 +158,7 @@@@@ static int bq27x00_battery_read_rsoc(st
                rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true);
    
        if (rsoc < 0)
-- -            dev_err(di->dev, "error reading relative State-of-Charge\n");
++ +            dev_dbg(di->dev, "error reading relative State-of-Charge\n");
    
        return rsoc;
    }
@@@@@ -164,7 -164,7 -173,8 -164,7 +173,8 @@@@@ static int bq27x00_battery_read_charge(
    
        charge = bq27x00_read(di, reg, false);
        if (charge < 0) {
-- -            dev_err(di->dev, "error reading nominal available capacity\n");
++ +            dev_dbg(di->dev, "error reading charge register %02x: %d\n",
++ +                    reg, charge);
                return charge;
        }
    
@@@@@ -208,7 -208,7 -218,7 -208,7 +218,7 @@@@@ static int bq27x00_battery_read_ilmd(st
                ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
    
        if (ilmd < 0) {
-- -            dev_err(di->dev, "error reading initial last measured discharge\n");
++ +            dev_dbg(di->dev, "error reading initial last measured discharge\n");
                return ilmd;
        }
    
        return ilmd;
    }
    
++ +/*
++ + * Return the battery Available energy in µWh
++ + * Or < 0 if something fails.
++ + */
++ +static int bq27x00_battery_read_energy(struct bq27x00_device_info *di)
++ +{
++ +    int ae;
++ +
++ +    ae = bq27x00_read(di, BQ27x00_REG_AE, false);
++ +    if (ae < 0) {
++ +            dev_dbg(di->dev, "error reading available energy\n");
++ +            return ae;
++ +    }
++ +
++ +    if (di->chip == BQ27500)
++ +            ae *= 1000;
++ +    else
++ +            ae = ae * 29200 / BQ27000_RS;
++ +
++ +    return ae;
++ +}
++ +
++ +/*
++ + * Return the battery temperature in tenths of degree Celsius
++ + * Or < 0 if something fails.
++ + */
++ +static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di)
++ +{
++ +    int temp;
++ +
++ +    temp = bq27x00_read(di, BQ27x00_REG_TEMP, false);
++ +    if (temp < 0) {
++ +            dev_err(di->dev, "error reading temperature\n");
++ +            return temp;
++ +    }
++ +
++ +    if (di->chip == BQ27500)
++ +            temp -= 2731;
++ +    else
++ +            temp = ((temp * 5) - 5463) / 2;
++ +
++ +    return temp;
++ +}
++ +
    /*
     * Return the battery Cycle count total
     * Or < 0 if something fails.
@@@@@ -245,7 -245,7 -299,8 -245,7 +299,8 @@@@@ static int bq27x00_battery_read_time(st
    
        tval = bq27x00_read(di, reg, false);
        if (tval < 0) {
-- -            dev_err(di->dev, "error reading register %02x: %d\n", reg, tval);
++ +            dev_dbg(di->dev, "error reading time register %02x: %d\n",
++ +                    reg, tval);
                return tval;
        }
    
@@@@@ -259,31 -259,31 -314,42 -259,31 +314,42 @@@@@ static void bq27x00_update(struct bq27x
    {
        struct bq27x00_reg_cache cache = {0, };
        bool is_bq27500 = di->chip == BQ27500;
++ +    int flags_changed;
    
        cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500);
        if (cache.flags >= 0) {
-- -            cache.capacity = bq27x00_battery_read_rsoc(di);
-- -            cache.temperature = bq27x00_read(di, BQ27x00_REG_TEMP, false);
-- -            cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);
-- -            cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
-- -            cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
-- -            cache.charge_full = bq27x00_battery_read_lmd(di);
++ +            if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) {
++ +                    dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
++ +                    cache.capacity = -ENODATA;
++ +                    cache.energy = -ENODATA;
++ +                    cache.time_to_empty = -ENODATA;
++ +                    cache.time_to_empty_avg = -ENODATA;
++ +                    cache.time_to_full = -ENODATA;
++ +                    cache.charge_full = -ENODATA;
++ +            } else {
++ +                    cache.capacity = bq27x00_battery_read_rsoc(di);
++ +                    cache.energy = bq27x00_battery_read_energy(di);
++ +                    cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);
++ +                    cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
++ +                    cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
++ +                    cache.charge_full = bq27x00_battery_read_lmd(di);
++ +            }
++ +            cache.temperature = bq27x00_battery_read_temperature(di);
                cache.cycle_count = bq27x00_battery_read_cyct(di);
    
-- -            if (!is_bq27500)
-- -                    cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false);
-- -
                /* We only have to read charge design full once */
                if (di->charge_design_full <= 0)
                        di->charge_design_full = bq27x00_battery_read_ilmd(di);
        }
    
-- -    /* Ignore current_now which is a snapshot of the current battery state
-- -     * and is likely to be different even between two consecutive reads */
-- -    if (memcmp(&di->cache, &cache, sizeof(cache) - sizeof(int)) != 0) {
-- -            di->cache = cache;
++ +    flags_changed = di->cache.flags ^ cache.flags;
++ +    di->cache = cache;
++ +    if (is_bq27500)
++ +            flags_changed &= BQ27500_FLAGS_IMPORTANT;
++ +    else
++ +            flags_changed &= BQ27000_FLAGS_IMPORTANT;
++ +    if (flags_changed)
                power_supply_changed(&di->bat);
-- -    }
    
        di->last_update = jiffies;
    }
@@@@@ -302,25 -302,25 -368,6 -302,25 +368,6 @@@@@ static void bq27x00_battery_poll(struc
        }
    }
    
-- -
-- -/*
-- - * Return the battery temperature in tenths of degree Celsius
-- - * Or < 0 if something fails.
-- - */
-- -static int bq27x00_battery_temperature(struct bq27x00_device_info *di,
-- -    union power_supply_propval *val)
-- -{
-- -    if (di->cache.temperature < 0)
-- -            return di->cache.temperature;
-- -
-- -    if (di->chip == BQ27500)
-- -            val->intval = di->cache.temperature - 2731;
-- -    else
-- -            val->intval = ((di->cache.temperature * 5) - 5463) / 2;
-- -
-- -    return 0;
-- -}
-- -
    /*
     * Return the battery average current in µA
     * Note that current can be negative signed as well
@@@@@ -330,20 -330,20 -377,20 -330,20 +377,20 @@@@@ static int bq27x00_battery_current(stru
        union power_supply_propval *val)
    {
        int curr;
++ +    int flags;
    
-- -    if (di->chip == BQ27500)
-- -        curr = bq27x00_read(di, BQ27x00_REG_AI, false);
-- -    else
-- -        curr = di->cache.current_now;
-- -
-- -    if (curr < 0)
++ +    curr = bq27x00_read(di, BQ27x00_REG_AI, false);
++ +    if (curr < 0) {
++ +            dev_err(di->dev, "error reading current\n");
                return curr;
++ +    }
    
        if (di->chip == BQ27500) {
                /* bq27500 returns signed value */
                val->intval = (int)((s16)curr) * 1000;
        } else {
-- -            if (di->cache.flags & BQ27000_FLAG_CHGS) {
++ +            flags = bq27x00_read(di, BQ27x00_REG_FLAGS, false);
++ +            if (flags & BQ27000_FLAG_CHGS) {
                        dev_dbg(di->dev, "negative current!\n");
                        curr = -curr;
                }
@@@@@ -382,50 -382,50 -429,56 -382,50 +429,56 @@@@@ static int bq27x00_battery_status(struc
        return 0;
    }
    
-- -/*
-- - * Return the battery Voltage in milivolts
-- - * Or < 0 if something fails.
-- - */
-- -static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
++ +static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di,
        union power_supply_propval *val)
    {
-- -    int volt;
++ +    int level;
    
-- -    volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
-- -    if (volt < 0)
-- -            return volt;
++ +    if (di->chip == BQ27500) {
++ +            if (di->cache.flags & BQ27500_FLAG_FC)
++ +                    level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
++ +            else if (di->cache.flags & BQ27500_FLAG_SOC1)
++ +                    level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
++ +            else if (di->cache.flags & BQ27500_FLAG_SOCF)
++ +                    level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
++ +            else
++ +                    level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
++ +    } else {
++ +            if (di->cache.flags & BQ27000_FLAG_FC)
++ +                    level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
++ +            else if (di->cache.flags & BQ27000_FLAG_EDV1)
++ +                    level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
++ +            else if (di->cache.flags & BQ27000_FLAG_EDVF)
++ +                    level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
++ +            else
++ +                    level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
++ +    }
    
-- -    val->intval = volt * 1000;
++ +    val->intval = level;
    
        return 0;
    }
    
    /*
-- - * Return the battery Available energy in µWh
++ + * Return the battery Voltage in milivolts
     * Or < 0 if something fails.
     */
-- -static int bq27x00_battery_energy(struct bq27x00_device_info *di,
++ +static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
        union power_supply_propval *val)
    {
-- -    int ae;
++ +    int volt;
    
-- -    ae = bq27x00_read(di, BQ27x00_REG_AE, false);
-- -    if (ae < 0) {
-- -            dev_err(di->dev, "error reading available energy\n");
-- -            return ae;
++ +    volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
++ +    if (volt < 0) {
++ +            dev_err(di->dev, "error reading voltage\n");
++ +            return volt;
        }
    
-- -    if (di->chip == BQ27500)
-- -            ae *= 1000;
-- -    else
-- -            ae = ae * 29200 / BQ27000_RS;
-- -
-- -    val->intval = ae;
++ +    val->intval = volt * 1000;
    
        return 0;
    }
    
-- -
    static int bq27x00_simple_value(int value,
        union power_supply_propval *val)
    {
@@@@@ -473,8 -473,8 -526,11 -473,8 +526,11 @@@@@ static int bq27x00_battery_get_property
        case POWER_SUPPLY_PROP_CAPACITY:
                ret = bq27x00_simple_value(di->cache.capacity, val);
                break;
++ +    case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
++ +            ret = bq27x00_battery_capacity_level(di, val);
++ +            break;
        case POWER_SUPPLY_PROP_TEMP:
-- -            ret = bq27x00_battery_temperature(di, val);
++ +            ret = bq27x00_simple_value(di->cache.temperature, val);
                break;
        case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
                ret = bq27x00_simple_value(di->cache.time_to_empty, val);
                ret = bq27x00_simple_value(di->cache.cycle_count, val);
                break;
        case POWER_SUPPLY_PROP_ENERGY_NOW:
-- -            ret = bq27x00_battery_energy(di, val);
++ +            ret = bq27x00_simple_value(di->cache.energy, val);
                break;
        default:
                return -EINVAL;
@@@@@ -515,7 -515,7 -571,7 -515,8 +571,8 @@@@@ static void bq27x00_external_power_chan
        struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
    
        cancel_delayed_work_sync(&di->work);
---     schedule_delayed_work(&di->work, 0);
+++     set_timer_slack(&di->work.timer, 2 * HZ);
+++     schedule_delayed_work(&di->work, 2 * HZ);
    }
    
    static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
    
    static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
    {
++ +    /*
++ +     * power_supply_unregister call bq27x00_battery_get_property which
++ +     * call bq27x00_battery_poll.
++ +     * Make sure that bq27x00_battery_poll will not call
++ +     * schedule_delayed_work again after unregister (which cause OOPS).
++ +     */
++ +    poll_interval = 0;
++ +
        cancel_delayed_work_sync(&di->work);
    
        power_supply_unregister(&di->bat);
    #include <linux/power_supply.h>
    #include <linux/notifier.h>
    #include <linux/usb/otg.h>
+++ #include <linux/ratelimit.h>
    
    #define TWL4030_BCIMSTATEC  0x02
    #define TWL4030_BCIICHG             0x08
    #define TWL4030_MSTATEC_COMPLETE1   0x0b
    #define TWL4030_MSTATEC_COMPLETE4   0x0e
    
--- static bool allow_usb;
+++ static bool allow_usb = 1;
    module_param(allow_usb, bool, 0644);
    MODULE_PARM_DESC(allow_usb, "Allow USB charge drawing default current");
    
@@@@@ -74,8 -74,8 -74,8 -75,11 +75,11 @@@@@ struct twl4030_bci 
        struct work_struct      work;
        int                     irq_chg;
        int                     irq_bci;
+++     bool                    ac_charge_enable;
+++     bool                    usb_charge_enable;
    
        unsigned long           event;
+++     struct ratelimit_state  ratelimit;
    };
    
    /*
@@@@@ -103,7 -103,7 -103,7 -107,7 +107,7 @@@@@ static int twl4030_bci_read(u8 reg, u8 
    
    static int twl4030_clear_set_boot_bci(u8 clear, u8 set)
    {
-- -    return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, 0,
++ +    return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, clear,
                        TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set,
                        TWL4030_PM_MASTER_BOOT_BCI);
    }
@@@@@ -151,13 -151,13 -151,13 -155,16 +155,16 @@@@@ static int twl4030_bci_have_vbus(struc
    }
    
    /*
-- - * Enable/Disable USB Charge funtionality.
++ + * Enable/Disable USB Charge functionality.
     */
    static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
    {
        int ret;
    
        if (enable) {
+++             if (!bci->usb_charge_enable)
+++                     return -EACCES;
+++ 
                /* Check for USB charger conneted */
                if (!twl4030_bci_have_vbus(bci))
                        return -ENODEV;
@@@@@ -243,21 -243,21 -243,21 -250,28 +250,28 @@@@@ static irqreturn_t twl4030_bci_interrup
        }
    
        /* various monitoring events, for now we just log them here */
---     if (irqs1 & (TWL4030_TBATOR2 | TWL4030_TBATOR1))
+++     if (irqs1 & (TWL4030_TBATOR2 | TWL4030_TBATOR1) &&
+++                     __ratelimit(&bci->ratelimit))
                dev_warn(bci->dev, "battery temperature out of range\n");
    
---     if (irqs1 & TWL4030_BATSTS)
+++     if (irqs1 & TWL4030_BATSTS && __ratelimit(&bci->ratelimit))
                dev_crit(bci->dev, "battery disconnected\n");
    
---     if (irqs2 & TWL4030_VBATOV)
+++     if (irqs2 & TWL4030_VBATOV && __ratelimit(&bci->ratelimit))
                dev_crit(bci->dev, "VBAT overvoltage\n");
    
---     if (irqs2 & TWL4030_VBUSOV)
+++     if (irqs2 & TWL4030_VBUSOV && __ratelimit(&bci->ratelimit))
                dev_crit(bci->dev, "VBUS overvoltage\n");
    
---     if (irqs2 & TWL4030_ACCHGOV)
+++     if (irqs2 & TWL4030_ACCHGOV && __ratelimit(&bci->ratelimit))
                dev_crit(bci->dev, "Ac charger overvoltage\n");
    
+++     /* ack the interrupts */
+++     twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, irqs1,
+++                      TWL4030_INTERRUPTS_BCIISR1A);
+++     twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, irqs2,
+++                      TWL4030_INTERRUPTS_BCIISR2A);
+++ 
        return IRQ_HANDLED;
    }
    
@@@@@ -318,6 -318,6 -318,6 -332,80 +332,80 @@@@@ static int twl4030_charger_get_current(
        return ret;
    }
    
+++ static ssize_t twl4030_bci_ac_show_enable(struct device *dev,
+++                                       struct device_attribute *attr,
+++                                       char *buf)
+++ {
+++     u8 boot_bci;
+++     int ret;
+++ 
+++     ret = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &boot_bci,
+++                           TWL4030_PM_MASTER_BOOT_BCI);
+++     if (ret)
+++             return ret;
+++ 
+++     return sprintf(buf, "%d\n", (boot_bci & TWL4030_BCIAUTOAC) ? 1 : 0);
+++ }
+++ 
+++ static ssize_t twl4030_bci_ac_store_enable(struct device *dev,
+++                                        struct device_attribute *attr,
+++                                        const char *buf, size_t count)
+++ {
+++     struct power_supply *psy = dev_get_drvdata(dev);
+++     struct twl4030_bci *bci = container_of(psy, struct twl4030_bci, ac);
+++     unsigned long enable;
+++     int ret;
+++ 
+++     ret = strict_strtoul(buf, 10, &enable);
+++     if (ret || enable > 1)
+++             return -EINVAL;
+++ 
+++     bci->ac_charge_enable = enable;
+++     twl4030_charger_enable_ac(enable);
+++ 
+++     return count;
+++ }
+++ static const struct device_attribute dev_attr_enable_ac =
+++     __ATTR(enable, S_IRUGO | S_IWUSR, twl4030_bci_ac_show_enable,
+++     twl4030_bci_ac_store_enable);
+++ 
+++ static ssize_t twl4030_bci_usb_show_enable(struct device *dev,
+++                                        struct device_attribute *attr,
+++                                        char *buf)
+++ {
+++     u8 boot_bci;
+++     int ret;
+++ 
+++     ret = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &boot_bci,
+++                           TWL4030_PM_MASTER_BOOT_BCI);
+++     if (ret)
+++             return ret;
+++ 
+++     return sprintf(buf, "%d\n", (boot_bci & TWL4030_BCIAUTOUSB) ? 1 : 0);
+++ }
+++ 
+++ static ssize_t twl4030_bci_usb_store_enable(struct device *dev,
+++                                         struct device_attribute *attr,
+++                                         const char *buf, size_t count)
+++ {
+++     struct power_supply *psy = dev_get_drvdata(dev);
+++     struct twl4030_bci *bci = container_of(psy, struct twl4030_bci, usb);
+++     unsigned long enable;
+++     int ret;
+++ 
+++     ret = strict_strtoul(buf, 10, &enable);
+++     if (ret || enable > 1)
+++             return -EINVAL;
+++ 
+++     bci->usb_charge_enable = enable;
+++     twl4030_charger_enable_usb(bci, enable);
+++ 
+++     return count;
+++ }
+++ static const struct device_attribute dev_attr_enable_usb =
+++     __ATTR(enable, S_IRUGO | S_IWUSR, twl4030_bci_usb_show_enable,
+++     twl4030_bci_usb_store_enable);
+++ 
    /*
     * Returns the main charge FSM state
     * Or < 0 on failure.
@@@@@ -423,10 -423,10 -423,10 -511,16 +511,16 @@@@@ static enum power_supply_property twl40
    
    static int __init twl4030_bci_probe(struct platform_device *pdev)
    {
+++     const struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
        struct twl4030_bci *bci;
        int ret;
        u32 reg;
    
+++     if (pdata == NULL) {
+++             dev_err(&pdev->dev, "No platform data\n");
+++             return -EINVAL;
+++     }
+++ 
        bci = kzalloc(sizeof(*bci), GFP_KERNEL);
        if (bci == NULL)
                return -ENOMEM;
    
        platform_set_drvdata(pdev, bci);
    
+++     ratelimit_state_init(&bci->ratelimit, HZ, 2);
+++ 
        bci->ac.name = "twl4030_ac";
        bci->ac.type = POWER_SUPPLY_TYPE_MAINS;
        bci->ac.properties = twl4030_charger_props;
        bci->ac.num_properties = ARRAY_SIZE(twl4030_charger_props);
        bci->ac.get_property = twl4030_bci_get_property;
+++     bci->ac.supplied_to = pdata->supplied_to;
+++     bci->ac.num_supplicants = pdata->num_supplicants;
    
        ret = power_supply_register(&pdev->dev, &bci->ac);
        if (ret) {
        bci->usb.properties = twl4030_charger_props;
        bci->usb.num_properties = ARRAY_SIZE(twl4030_charger_props);
        bci->usb.get_property = twl4030_bci_get_property;
+++     bci->usb.supplied_to = pdata->supplied_to;
+++     bci->usb.num_supplicants = pdata->num_supplicants;
    
        ret = power_supply_register(&pdev->dev, &bci->usb);
        if (ret) {
                otg_register_notifier(bci->transceiver, &bci->otg_nb);
        }
    
+++     ret = device_create_file(bci->ac.dev, &dev_attr_enable_ac);
+++     if (ret) {
+++             dev_err(&pdev->dev, "failed to create sysfs file: %d\n", ret);
+++             goto fail_sysfs1;
+++     }
+++ 
+++     ret = device_create_file(bci->usb.dev, &dev_attr_enable_usb);
+++     if (ret) {
+++             dev_err(&pdev->dev, "failed to create sysfs file: %d\n", ret);
+++             goto fail_sysfs2;
+++     }
+++ 
        /* Enable interrupts now. */
        reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 |
                TWL4030_TBATOR1 | TWL4030_BATSTS);
        if (ret < 0)
                dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
    
+++     bci->ac_charge_enable = true;
+++     bci->usb_charge_enable = true;
        twl4030_charger_enable_ac(true);
        twl4030_charger_enable_usb(bci, true);
    
        return 0;
    
    fail_unmask_interrupts:
+++     device_remove_file(bci->usb.dev, &dev_attr_enable_usb);
+++ fail_sysfs2:
+++     device_remove_file(bci->ac.dev, &dev_attr_enable_ac);
+++ fail_sysfs1:
        if (bci->transceiver != NULL) {
                otg_unregister_notifier(bci->transceiver, &bci->otg_nb);
                otg_put_transceiver(bci->transceiver);
@@@@@ -529,6 -529,6 -529,6 -647,9 +647,9 @@@@@ static int __exit twl4030_bci_remove(st
    {
        struct twl4030_bci *bci = platform_get_drvdata(pdev);
    
+++     device_remove_file(bci->usb.dev, &dev_attr_enable_usb);
+++     device_remove_file(bci->ac.dev, &dev_attr_enable_ac);
+++ 
        twl4030_charger_enable_ac(false);
        twl4030_charger_enable_usb(bci, false);
    
@@@@@ -654,6 -654,6 -654,6 -654,15 +654,15 @@@@@ static irqreturn_t musb_stage0_irq(stru
                        musb->is_active = 0;
                        break;
                }
+++ 
+++             switch (musb->xceiv->state) {
+++             case OTG_STATE_B_IDLE:
+++             case OTG_STATE_B_PERIPHERAL:
+++                     cancel_delayed_work(&musb->vbus_workaround_work);
+++                     schedule_delayed_work(&musb->vbus_workaround_work, HZ / 2);
+++             default:
+++                     break;
+++             }
        }
    
        if (int_usb & MUSB_INTR_CONNECT) {
@@@@@ -982,6 -982,6 -982,9 -991,6 +991,9 @@@@@ static void musb_shutdown(struct platfo
        unsigned long   flags;
    
        pm_runtime_get_sync(musb->controller);
++ +
++ +    musb_gadget_cleanup(musb);
++ +
        spin_lock_irqsave(&musb->lock, flags);
        musb_platform_disable(musb);
        musb_generic_disable(musb);
        musb_platform_exit(musb);
    
        pm_runtime_put(musb->controller);
+++ 
+++     cancel_delayed_work(&musb->vbus_workaround_work);
+++ 
        /* FIXME power down */
    }
    
@@@@@ -1770,6 -1770,6 -1773,6 -1782,41 +1785,41 @@@@@ static void musb_irq_work(struct work_s
        }
    }
    
+++ #include <linux/usb/ulpi.h>
+++ 
+++ static void musb_vbus_workaround_work(struct work_struct *work)
+++ {
+++     struct musb *musb = container_of(work, struct musb, vbus_workaround_work.work);
+++     u8 devctl;
+++     int ret;
+++ 
+++     if (musb_ulpi_access.write == NULL)
+++             return;
+++ 
+++     devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+++ 
+++     /*
+++      * I don't really know why but VBUS sometimes gets stuck and
+++      * causes session to never end. It would look like some pullup
+++      * is enabled when it shouldn't be on certain PHY states.
+++      * Turning on pulldowns magically drains VBUS to zero and allows
+++      * session to end, so let's do that here.
+++      *
+++      * XXX: probably better check VBUS on TWL?
+++      * beagle sometimes has session bit set but no VBUS on twl?
+++      */
+++     if ((musb->xceiv->state == OTG_STATE_B_PERIPHERAL ||
+++          musb->xceiv->state == OTG_STATE_B_IDLE) &&
+++         (devctl & MUSB_DEVCTL_VBUS) != (3 << MUSB_DEVCTL_VBUS_SHIFT) &&
+++         (devctl & MUSB_DEVCTL_VBUS) != (0 << MUSB_DEVCTL_VBUS_SHIFT)) {
+++             dev_dbg(musb->controller, "VBUS workaround..\n");
+++             ret = musb_ulpi_access.write(musb->xceiv, ULPI_SET(ULPI_OTG_CTRL),
+++                     ULPI_OTG_CTRL_DM_PULLDOWN | ULPI_OTG_CTRL_DP_PULLDOWN);
+++             //if (ret)
+++             //      dev_err(musb->controller, "VBUS workaround error\n");
+++     }
+++ }
+++ 
    /* --------------------------------------------------------------------------
     * Init support
     */
@@@@@ -1827,8 -1827,8 -1830,6 -1874,8 +1877,6 @@@@@ static void musb_free(struct musb *musb
        sysfs_remove_group(&musb->controller->kobj, &musb_attr_group);
    #endif
    
-- -    musb_gadget_cleanup(musb);
-- -
        if (musb->nIrq >= 0) {
                if (musb->irq_wake)
                        disable_irq_wake(musb->nIrq);
@@@@@ -1941,6 -1941,6 -1942,6 -1988,8 +1989,8 @@@@@ musb_init_controller(struct device *dev
        /* Init IRQ workqueue before request_irq */
        INIT_WORK(&musb->irq_work, musb_irq_work);
    
+++     INIT_DELAYED_WORK(&musb->vbus_workaround_work, musb_vbus_workaround_work);
+++ 
        /* attach to the IRQ */
        if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) {
                dev_err(dev, "request_irq %d failed!\n", nIrq);
        if (status < 0)
                goto fail3;
    
++ +    pm_runtime_put(musb->controller);
++ +
        status = musb_init_debugfs(musb);
        if (status < 0)
                goto fail4;
@@@@@ -2111,11 -2111,11 -2114,9 -2160,11 +2163,9 @@@@@ static int __exit musb_remove(struct pl
         *  - Peripheral mode: peripheral is deactivated (or never-activated)
         *  - OTG mode: both roles are deactivated (or never-activated)
         */
-- -    pm_runtime_get_sync(musb->controller);
        musb_exit_debugfs(musb);
        musb_shutdown(pdev);
    
-- -    pm_runtime_put(musb->controller);
        musb_free(musb);
        iounmap(ctrl_base);
        device_init_wakeup(&pdev->dev, 0);
@@@@@ -2156,6 -2156,6 -2157,7 -2205,6 +2206,7 @@@@@ static void musb_save_context(struct mu
                if (!epio)
                        continue;
    
++ +            musb_writeb(musb_base, MUSB_INDEX, i);
                musb->context.index_regs[i].txmaxp =
                        musb_readw(epio, MUSB_TXMAXP);
                musb->context.index_regs[i].txcsr =
@@@@@ -2231,6 -2231,6 -2233,7 -2280,6 +2282,7 @@@@@ static void musb_restore_context(struc
                if (!epio)
                        continue;
    
++ +            musb_writeb(musb_base, MUSB_INDEX, i);
                musb_writew(epio, MUSB_TXMAXP,
                        musb->context.index_regs[i].txmaxp);
                musb_writew(epio, MUSB_TXCSR,
@@@@@ -311,6 -311,6 -311,7 -311,6 +311,7 @@@@@ struct musb_context_registers 
        u8 index, testmode;
    
        u8 devctl, busctl, misc;
++ +    u32 otg_interfsel;
    
        struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
    };
@@@@@ -454,6 -454,6 -455,6 -454,7 +455,7 @@@@@ struct musb 
    #ifdef MUSB_CONFIG_PROC_FS
        struct proc_dir_entry *proc_entry;
    #endif
+++     struct delayed_work     vbus_workaround_work;
    };
    
    static inline struct musb *gadget_to_musb(struct usb_gadget *g)
diff --combined include/linux/i2c/twl.h
@@@@@ -557,6 -557,6 -557,6 -557,8 +557,8 @@@@@ struct twl4030_clock_init_data 
    struct twl4030_bci_platform_data {
        int *battery_tmp_tbl;
        unsigned int tblsize;
+++     char **supplied_to;
+++     size_t num_supplicants;
    };
    
    /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
@@@@@ -652,10 -652,10 -652,12 -654,10 +654,12 @@@@@ struct twl4030_power_data 
        unsigned num;
        struct twl4030_resconfig *resource_config;
    #define TWL4030_RESCONFIG_UNDEF     ((u8)-1)
++ +    bool use_poweroff;      /* Board is wired for TWL poweroff */
    };
    
    extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
    extern int twl4030_remove_script(u8 flags);
++ +extern void twl4030_power_off(void);
    
    struct twl4030_codec_data {
        unsigned int digimic_delay; /* in ms */