--- a/drivers/power/twl4030_bci_battery.c 2010-01-16 13:48:46.745838675 -0800 +++ b/drivers/power/twl4030_bci_battery.c 2010-01-16 13:41:47.317595764 -0800 @@ -598,11 +598,31 @@ static int twl4030battery_voltage(void) { int volt = read_bci_val(T2_BATTERY_VOLT); - return (volt * VOLT_STEP_SIZE) / VOLT_PSR_R; } /* + * Get latest battery voltage (using MADC) + * + * When the BCI is not charging, the BCI voltage registers are not + * updated and are 'frozen' but the data can be read through the + * MADC. + */ +static int twl4030battery_voltage_madc(void) +{ + struct twl4030_madc_request req; + + req.channels = (1 << 12); + req.do_avg = 0; + req.method = TWL4030_MADC_SW1; + req.active = 0; + req.func_cb = NULL; + twl4030_madc_conversion(&req); + + return (((int) req.rbuf[12]) * VOLT_STEP_SIZE) / VOLT_PSR_R; +} + +/* * Return the battery current * Or < 0 on failure. */ @@ -840,21 +860,21 @@ static void twl4030_bci_battery_read_status(struct twl4030_bci_device_info *di) { - di->temp_C = twl4030battery_temperature(di); - di->voltage_uV = twl4030battery_voltage(); - di->current_uA = twl4030battery_current(); + if(di->charge_status != POWER_SUPPLY_STATUS_DISCHARGING) { + di->temp_C = twl4030battery_temperature(di); + di->voltage_uV = twl4030battery_voltage(); + di->current_uA = twl4030battery_current(); + } } static void twl4030_bci_battery_update_status(struct twl4030_bci_device_info *di) { - twl4030_bci_battery_read_status(di); - di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN; - if (power_supply_am_i_supplied(&di->bat)) di->charge_status = POWER_SUPPLY_STATUS_CHARGING; else di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING; + twl4030_bci_battery_read_status(di); } static void twl4030_bci_battery_work(struct work_struct *work) @@ -960,7 +980,15 @@ return count; } + +static ssize_t +show_voltage(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", twl4030battery_voltage_madc()); +} + static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUGO, show_charge_current, set_charge_current); +static DEVICE_ATTR(voltage_now_madc, S_IRUGO, show_voltage, NULL); static int twl4030_bk_bci_battery_get_property(struct power_supply *psy, enum power_supply_property psp, @@ -998,10 +1026,23 @@ switch (psp) { case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = di->voltage_uV; + { + /* Get latest data from MADC -- not done periodically by + worker as this is more expensive, so only do it when we + are actually asked for the data... */ + if(di->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) + val->intval = twl4030battery_voltage_madc(); + else + val->intval = di->voltage_uV; + break; + } case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = di->current_uA; + /* FIXME: Get from MADC */ + if(di->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) + val->intval = 0; + else + val->intval = di->current_uA; break; case POWER_SUPPLY_PROP_TEMP: val->intval = di->temp_C; @@ -1016,6 +1057,12 @@ val->intval = 0; break; case POWER_SUPPLY_PROP_CAPACITY: + /* Get latest data from MADC -- not done periodically by + worker as this is more expensive, so only do it when we + are actually asked for the data... */ + if(di->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) + di->voltage_uV = twl4030battery_voltage_madc(); + /* * need to get the correct percentage value per the * battery characteristics. Approx values for now. @@ -1145,6 +1192,7 @@ } } + ret = device_create_file(di->bat.dev, &dev_attr_voltage_now_madc); ret = device_create_file(di->bat.dev, &dev_attr_charge_current); if (ret) { dev_err(&pdev->dev, "failed to create sysfs entries\n");