summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAlex Gonzalez <alex.gonzalez@digi.com>2012-02-03 18:18:07 +0100
committerAlex Gonzalez <alex.gonzalez@digi.com>2012-02-06 14:34:13 +0100
commit940f65c7309cba35dae51daa12f1a0d13d1d80a1 (patch)
tree3403730917f712e52368d04e316be3c644500405 /drivers
parent0e01b35db88924d161cf6652d5f21d2d612addd4 (diff)
ccxmx51: mc13892 battery, Fix driver to work without battery.
The mc13892 driver from the BSP assumed that the battery was always connected. Otherwise the battery driver would not be loaded. This fix allows for the driver to work even when booting without a battery. It modifies the battery status function to use the charger current measured via the ADC to detect the presence of a battery and its charging status instead of the sense bit. Also, because now the driver can tell whether a battery is present or not, it fixes some of the places where the driver assumed the battery would always be connected. This fixes 42033. Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com> (cherry picked from commit 093ee454469036f25f104c2d544ba144d9a1ed37)
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mxc/pmic/mc13892/pmic_battery.c88
1 files changed, 63 insertions, 25 deletions
diff --git a/drivers/mxc/pmic/mc13892/pmic_battery.c b/drivers/mxc/pmic/mc13892/pmic_battery.c
index 1b6c41a08cc2..ea0e38baab62 100644
--- a/drivers/mxc/pmic/mc13892/pmic_battery.c
+++ b/drivers/mxc/pmic/mc13892/pmic_battery.c
@@ -349,6 +349,7 @@ struct mc13892_dev_info {
unsigned short current_raw;
int current_uA;
int battery_status;
+ int battery_present;
int full_counter;
int charger_online;
int charger_voltage_uV;
@@ -387,13 +388,16 @@ s32 mc13892_get_bat_level(struct mc13892_dev_info *di)
static int bat_capacity_old;
int retval;
- retval = pmic_get_batt_voltage(&(di->voltage_raw));
- if (retval == 0)
- di->voltage_uV = di->voltage_raw * BAT_VOLTAGE_UNIT_UV;
- else
- pr_debug("Unable to update battery voltage measurement.\n");
+ if( di->battery_status != POWER_SUPPLY_STATUS_UNKNOWN &&
+ di->battery_status != POWER_SUPPLY_STATUS_FULL) {
+ retval = pmic_get_batt_voltage(&(di->voltage_raw));
+ if (retval == 0)
+ di->voltage_uV = di->voltage_raw * BAT_VOLTAGE_UNIT_UV;
+ else
+ pr_debug("Unable to update battery voltage measurement.\n");
- vbat = di->voltage_uV/1000;
+ vbat = di->voltage_uV/1000;
+ }
switch(di->battery_status){
case POWER_SUPPLY_STATUS_DISCHARGING:
@@ -580,6 +584,17 @@ static void chg_thread(struct work_struct *work)
}
}
+static int mc13892_is_charger_online(struct mc13892_dev_info *di){
+ int ret;
+ unsigned int value;
+
+ ret = pmic_read_reg(REG_INT_SENSE0, &value, BITFMASK(BIT_CHG_DETS));
+ if (ret == 0){
+ di->charger_online = BITFEXT(value, BIT_CHG_DETS);
+ }
+ return di->charger_online;
+}
+
static int mc13892_charger_update_status(struct mc13892_dev_info *di)
{
int ret;
@@ -600,17 +615,20 @@ static int mc13892_charger_update_status(struct mc13892_dev_info *di)
queue_delayed_work(di->monitor_wqueue,
&di->monitor_work, monitor_work_interval);
if (online) {
- pmic_start_coulomb_counter();
- pmic_restart_charging();
+ if(di->battery_present){
+ pmic_start_coulomb_counter();
+ pmic_restart_charging();
+ }
queue_delayed_work(chg_wq, &chg_work, chg_work_interval);
chg_wa_timer = 1;
} else {
cancel_delayed_work(&chg_work);
chg_wa_timer = 0;
- pmic_stop_coulomb_counter();
+ if(di->battery_present)
+ pmic_stop_coulomb_counter();
+ }
}
}
- }
return ret;
}
@@ -636,6 +654,10 @@ static int mc13892_battery_read_status(struct mc13892_dev_info *di)
{
int retval;
int coulomb;
+
+ if( !di->battery_present)
+ return -EINVAL;
+
retval = pmic_get_batt_voltage(&(di->voltage_raw));
if (retval == 0)
di->voltage_uV = di->voltage_raw * BAT_VOLTAGE_UNIT_UV;
@@ -660,33 +682,49 @@ static int mc13892_battery_read_status(struct mc13892_dev_info *di)
static void mc13892_battery_update_status(struct mc13892_dev_info *di)
{
unsigned int value;
- int retval;
+ int ret;
int old_battery_status = di->battery_status;
if (di->battery_status == POWER_SUPPLY_STATUS_UNKNOWN)
di->full_counter = 0;
- if (di->charger_online) {
- retval = pmic_read_reg(REG_INT_SENSE0,
- &value, BITFMASK(BIT_CHG_CURRS));
-
- if (retval == 0) {
- value = BITFEXT(value, BIT_CHG_CURRS);
- if (value)
- di->battery_status =
- POWER_SUPPLY_STATUS_CHARGING;
- else
- di->battery_status =
- POWER_SUPPLY_STATUS_NOT_CHARGING;
+ if ( mc13892_is_charger_online(di) ) {
+ if( (ret = pmic_get_chg_value(&value)) == 0 ) {
+ pr_debug("Charger current value %d\n",value);
+ if( value > CHG_CURRENT_THRESHOLD ){
+ di->battery_present = 1;
+ di->battery_status = POWER_SUPPLY_STATUS_CHARGING;
+ pr_debug("Present and charging, %d\n",di->cal_capacity);
+ }
+ else{
+ // Need to distinguish full battery from not present
+ if( di->cal_capacity >= 95 ){
+ di->battery_present = 1;
+ di->battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ pr_debug("Present and NOT charging, %d\n",di->cal_capacity);
+ }
+ else{
+ di->battery_present = 0;
+ di->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
+ pr_debug("NOT Present and Unknown, %d\n",di->cal_capacity);
+ }
}
+ }
+ else{
+ di->battery_present = 0;
+ di->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
+ pr_debug("NOT Present and Unknown, %d\n",di->cal_capacity);
+ }
if (di->battery_status == POWER_SUPPLY_STATUS_NOT_CHARGING)
di->full_counter++;
else
di->full_counter = 0;
} else {
+ di->battery_present = 1;
di->battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
di->full_counter = 0;
+ pr_debug("Present and Discharging, %d\n",di->cal_capacity);
}
dev_dbg(di->bat.dev, "bat status: %d\n",
@@ -728,13 +766,13 @@ static int mc13892_battery_get_property(struct power_supply *psy,
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
if (di->battery_status == POWER_SUPPLY_STATUS_UNKNOWN) {
- mc13892_charger_update_status(di);
mc13892_battery_update_status(di);
+ mc13892_charger_update_status(di);
}
val->intval = di->battery_status;
return 0;
case POWER_SUPPLY_PROP_PRESENT:
- val->intval = !di->charger_online;
+ val->intval = di->battery_present;
return 0;
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = di->cal_capacity;