EM/Battery: Compute battery health from fuel gauge
authorRamakrishna Pallala <ramakrishna.pallala@intel.com>
Tue, 24 Apr 2012 09:45:37 +0000 (15:15 +0530)
committerbuildbot <buildbot@intel.com>
Wed, 25 Apr 2012 18:54:20 +0000 (11:54 -0700)
BZ: 32795

This patch disables the power supply registration for
battery from smb347 charger driver and adds the capability
to compute battery health from max17042 fuel gauge driver.

Change-Id: I71150bbad8c914edfbae34d5ded0f7e744ce8568
Signed-off-by: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
Reviewed-on: http://android.intel.com:8080/44357
Reviewed-by: Tc, Jenny <jenny.tc@intel.com>
Reviewed-by: Jena, TapanX <tapanx.jena@intel.com>
Tested-by: Kallappa Manjanna, MadhukumarX <madhukumarx.kallappa.manjanna@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
arch/x86/platform/intel-mid/device_libs/platform_max17042.c
drivers/power/max17042_battery.c
drivers/power/smb347-charger.c
include/linux/power/max17042_battery.h
include/linux/power/smb347-charger.h

index b0f4b62..e799b29 100644 (file)
@@ -177,6 +177,10 @@ void *max17042_platform_data(void *info)
 #ifdef CONFIG_BOARD_REDRIDGE /* TODO: get rid of this */
        platform_data.enable_current_sense = true;
        platform_data.technology = POWER_SUPPLY_TECHNOLOGY_LION;
+       platform_data.temp_min_lim = 0;
+       platform_data.temp_max_lim = 60;
+       platform_data.volt_min_lim = 3200;
+       platform_data.volt_max_lim = 4500;
        platform_data.restore_config_data = mfld_fg_restore_config_data;
        platform_data.save_config_data = mfld_fg_save_config_data;
 #endif
index 2fc3d30..ec79d5c 100644 (file)
@@ -1287,6 +1287,45 @@ static void set_soc_intr_thresholds(struct max17042_chip *chip, int off)
                                "SOC threshold write to maxim fail:%d", ret);
 }
 
+static int max17042_get_batt_health(void)
+{
+       struct max17042_chip *chip = i2c_get_clientdata(max17042_client);
+       int vavg, temp, ret;
+
+       ret = read_batt_pack_temp(chip, &temp);
+       if (ret < 0) {
+               dev_err(&chip->client->dev,
+                       "battery pack temp read fail:%d", ret);
+               return POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+       }
+       if ((temp < chip->pdata->temp_min_lim) ||
+                       (temp > chip->pdata->temp_max_lim)) {
+               dev_info(&chip->client->dev,
+                       "Battery Over Temp condition Detected:%d\n", temp);
+               return POWER_SUPPLY_HEALTH_OVERHEAT;
+       }
+
+       ret = max17042_read_reg(chip->client, MAX17042_AvgVCELL);
+       if (ret < 0) {
+               dev_err(&chip->client->dev, "Vavg read fail:%d", ret);
+               return POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+       }
+       /* get the voltage to milli volts */
+       vavg = ((ret >> 3) * MAX17042_VOLT_CONV_FCTR) / 1000;
+       if (vavg < chip->pdata->volt_min_lim) {
+               dev_info(&chip->client->dev,
+                       "Low Battery condition Detected:%d\n", vavg);
+               return POWER_SUPPLY_HEALTH_DEAD;
+       }
+       if (vavg > chip->pdata->volt_max_lim) {
+               dev_info(&chip->client->dev,
+                       "Battery Over Voltage condition Detected:%d\n", vavg);
+               return POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+       }
+
+       return POWER_SUPPLY_HEALTH_GOOD;
+}
+
 static void max17042_evt_worker(struct work_struct *work)
 {
        struct max17042_chip *chip = container_of(work,
@@ -1302,12 +1341,13 @@ static void max17042_evt_worker(struct work_struct *work)
        /* get the battery health */
        if (chip->pdata->battery_health)
                health = chip->pdata->battery_health();
+       else
+               health = max17042_get_batt_health();
 
        mutex_lock(&chip->batt_lock);
        if (chip->pdata->battery_status)
                chip->status = status;
-       if (chip->pdata->battery_health)
-               chip->health = health;
+       chip->health = health;
        mutex_unlock(&chip->batt_lock);
 
        /* Init maxim chip if it is not already initialized */
index 6705779..08aeadf 100644 (file)
@@ -1125,7 +1125,8 @@ static irqreturn_t smb347_interrupt(int irq, void *data)
                        "error in charger, disabling charging\n");
 
                smb347_charging_disable(smb);
-               power_supply_changed(&smb->battery);
+               if (smb->pdata->show_battery)
+                       power_supply_changed(&smb->battery);
 
                ret = IRQ_HANDLED;
        }
@@ -1136,7 +1137,8 @@ static irqreturn_t smb347_interrupt(int irq, void *data)
         * disabled by the hardware.
         */
        if (irqstat_c & (IRQSTAT_C_TERMINATION_IRQ | IRQSTAT_C_TAPER_IRQ)) {
-               if (irqstat_c & IRQSTAT_C_TERMINATION_STAT)
+               if ((irqstat_c & IRQSTAT_C_TERMINATION_STAT) &&
+                                               smb->pdata->show_battery)
                        power_supply_changed(&smb->battery);
                ret = IRQ_HANDLED;
        }
@@ -1541,18 +1543,21 @@ static int smb347_probe(struct i2c_client *client,
                }
        }
 
-       smb->battery.name = "smb347-battery";
-       smb->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-       smb->battery.get_property = smb347_battery_get_property;
-       smb->battery.properties = smb347_battery_properties;
-       smb->battery.num_properties = ARRAY_SIZE(smb347_battery_properties);
-       ret = power_supply_register(dev, &smb->battery);
-       if (ret < 0) {
-               if (smb->pdata->use_usb)
-                       power_supply_unregister(&smb->usb);
-               if (smb->pdata->use_mains)
-                       power_supply_unregister(&smb->mains);
-               return ret;
+       if (smb->pdata->show_battery) {
+               smb->battery.name = "smb347-battery";
+               smb->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+               smb->battery.get_property = smb347_battery_get_property;
+               smb->battery.properties = smb347_battery_properties;
+               smb->battery.num_properties =
+                               ARRAY_SIZE(smb347_battery_properties);
+               ret = power_supply_register(dev, &smb->battery);
+               if (ret < 0) {
+                       if (smb->pdata->use_usb)
+                               power_supply_unregister(&smb->usb);
+                       if (smb->pdata->use_mains)
+                               power_supply_unregister(&smb->mains);
+                       return ret;
+               }
        }
 
        /*
@@ -1610,7 +1615,8 @@ static int smb347_remove(struct i2c_client *client)
                }
        }
 
-       power_supply_unregister(&smb->battery);
+       if (smb->pdata->show_battery)
+               power_supply_unregister(&smb->battery);
        if (smb->pdata->use_usb)
                power_supply_unregister(&smb->usb);
        if (smb->pdata->use_mains)
index 38fab2c..2fa7d51 100644 (file)
@@ -76,6 +76,12 @@ struct max17042_platform_data {
        bool is_lowbatt_shutdown;
        int technology;
 
+       /* battery safety thresholds */
+       int temp_min_lim;       /* in degrees centigrade */
+       int temp_max_lim;       /* in degrees centigrade */
+       int volt_min_lim;       /* milli volts */
+       int volt_max_lim;       /* milli volts */
+
        int (*current_sense_enabled)(void);
        int (*battery_present)(void);
        int (*battery_health)(void);
index 70266fe..da6f119 100644 (file)
@@ -137,6 +137,7 @@ struct smb347_charger_platform_data {
        unsigned int    charge_current_compensation;
        bool            use_mains;
        bool            use_usb;
+       bool            show_battery;
        int             irq_gpio;
        enum smb347_chg_enable enable_control;
        enum smb347_otg_control otg_control;