power: pm8921-charger: BTC override fixes

- Monitor battery health when charger is not connected
- Add configurable temperature hysteresis and enable the
  same for BTC override
- Avoid releasing wakelock when charging is not in progress
  and BTC override is enabled
- check temperature thresholds when fully charged, to handle
  temperature restrictions while restarting charging

CRs-Fixed: 466525
Change-Id: I8cad3f8bcf65844fc1048625d9b387ede132d3e0
Signed-off-by: Anirudh Ghayal <aghayal@codeaurora.org>
This commit is contained in:
Anirudh Ghayal
2013-04-17 19:38:37 -07:00
committed by Gerrit - the friendly Code Review server
parent 96a4d97f60
commit d37bc1fb63
2 changed files with 46 additions and 7 deletions
+45 -7
View File
@@ -213,6 +213,8 @@ struct bms_notify {
* @alarm_high_mv: the battery alarm voltage high
* @cool_temp_dc: the cool temp threshold in deciCelcius
* @warm_temp_dc: the warm temp threshold in deciCelcius
* @hysteresis_temp_dc: the hysteresis between temp thresholds in
* deciCelcius
* @resume_voltage_delta: the voltage delta from vdd max at which the
* battery should resume charging
* @term_current: The charging based term current
@@ -235,6 +237,7 @@ struct pm8921_chg_chip {
unsigned int alarm_high_mv;
int cool_temp_dc;
int warm_temp_dc;
int hysteresis_temp_dc;
unsigned int temp_check_period;
unsigned int cool_bat_chg_current;
unsigned int warm_bat_chg_current;
@@ -308,6 +311,7 @@ static int charging_disabled;
static int thermal_mitigation;
static struct pm8921_chg_chip *the_chip;
static void check_temp_thresholds(struct pm8921_chg_chip *chip);
#define LPM_ENABLE_BIT BIT(2)
static int pm8921_chg_set_lpm(struct pm8921_chg_chip *chip, int enable)
@@ -3162,6 +3166,22 @@ static void update_heartbeat(struct work_struct *work)
struct delayed_work *dwork = to_delayed_work(work);
struct pm8921_chg_chip *chip = container_of(dwork,
struct pm8921_chg_chip, update_heartbeat_work);
bool chg_present = chip->usb_present || chip->dc_present;
/* for battery health when charger is not connected */
if (chip->btc_override && !chg_present)
schedule_delayed_work(&chip->btc_override_work,
round_jiffies_relative(msecs_to_jiffies
(chip->btc_delay_ms)));
/*
* check temp thresholds when charger is present and
* and battery is FULL. The temperature here can impact
* the charging restart conditions.
*/
if (chip->btc_override && chg_present &&
!wake_lock_active(&chip->eoc_wake_lock))
check_temp_thresholds(chip);
power_supply_changed(&chip->batt_psy);
if (chip->recent_reported_soc <= 20)
@@ -3317,7 +3337,7 @@ static void check_temp_thresholds(struct pm8921_chg_chip *chip)
if (chip->warm_temp_dc != INT_MIN) {
if (chip->is_bat_warm
&& temp < chip->warm_temp_dc - TEMP_HYSTERISIS_DECIDEGC)
&& temp < chip->warm_temp_dc - chip->hysteresis_temp_dc)
battery_warm(false);
else if (!chip->is_bat_warm && temp >= chip->warm_temp_dc)
battery_warm(true);
@@ -3325,7 +3345,7 @@ static void check_temp_thresholds(struct pm8921_chg_chip *chip)
if (chip->cool_temp_dc != INT_MIN) {
if (chip->is_bat_cool
&& temp > chip->cool_temp_dc + TEMP_HYSTERISIS_DECIDEGC)
&& temp > chip->cool_temp_dc + chip->hysteresis_temp_dc)
battery_cool(false);
else if (!chip->is_bat_cool && temp <= chip->cool_temp_dc)
battery_cool(true);
@@ -3543,7 +3563,8 @@ static void btc_override_worker(struct work_struct *work)
temp = pm_chg_get_rt_status(chip, BATTTEMP_HOT_IRQ);
if (temp) {
if (decidegc < chip->btc_override_hot_decidegc)
if (decidegc < chip->btc_override_hot_decidegc -
chip->hysteresis_temp_dc)
/* stop forcing batt hot */
rc = pm_chg_override_hot(chip, 0);
if (rc)
@@ -3558,7 +3579,8 @@ static void btc_override_worker(struct work_struct *work)
temp = pm_chg_get_rt_status(chip, BATTTEMP_COLD_IRQ);
if (temp) {
if (decidegc > chip->btc_override_cold_decidegc)
if (decidegc > chip->btc_override_cold_decidegc +
chip->hysteresis_temp_dc)
/* stop forcing batt cold */
rc = pm_chg_override_cold(chip, 0);
if (rc)
@@ -3622,7 +3644,8 @@ static void eoc_worker(struct work_struct *work)
end = is_charging_finished(chip, vbat_batt_terminal_uv, ichg_meas_ma);
if (end == CHG_NOT_IN_PROGRESS) {
if (end == CHG_NOT_IN_PROGRESS && (!chip->btc_override ||
!(chip->usb_present || chip->dc_present))) {
count = 0;
goto eoc_worker_stop;
}
@@ -3650,7 +3673,8 @@ static void eoc_worker(struct work_struct *work)
chgdone_irq_handler(chip->pmic_chg_irq[CHGDONE_IRQ], chip);
} else {
check_temp_thresholds(chip);
adjust_vdd_max_for_fastchg(chip, vbat_batt_terminal_uv);
if (end != CHG_NOT_IN_PROGRESS)
adjust_vdd_max_for_fastchg(chip, vbat_batt_terminal_uv);
pr_debug("EOC count = %d\n", count);
schedule_delayed_work(&chip->eoc_work,
round_jiffies_relative(msecs_to_jiffies
@@ -3659,9 +3683,9 @@ static void eoc_worker(struct work_struct *work)
}
eoc_worker_stop:
wake_unlock(&chip->eoc_wake_lock);
/* set the vbatdet back, in case it was changed to trigger charging */
set_appropriate_vbatdet(chip);
wake_unlock(&chip->eoc_wake_lock);
}
/**
@@ -3795,6 +3819,11 @@ static void __devinit determine_initial_state(struct pm8921_chg_chip *chip)
schedule_delayed_work(&chip->unplug_check_work,
msecs_to_jiffies(UNPLUG_CHECK_WAIT_PERIOD_MS));
pm8921_chg_enable_irq(chip, CHG_GONE_IRQ);
if (chip->btc_override)
schedule_delayed_work(&chip->btc_override_work,
round_jiffies_relative(msecs_to_jiffies
(chip->btc_delay_ms)));
}
pm8921_chg_enable_irq(chip, DCIN_VALID_IRQ);
@@ -4600,6 +4629,8 @@ static int pm8921_charger_resume(struct device *dev)
is_usb_chg_plugged_in(the_chip)))
schedule_delayed_work(&chip->btc_override_work, 0);
schedule_delayed_work(&chip->update_heartbeat_work, 0);
return 0;
}
@@ -4607,6 +4638,8 @@ static int pm8921_charger_suspend(struct device *dev)
{
struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
cancel_delayed_work_sync(&chip->update_heartbeat_work);
if (chip->btc_override)
cancel_delayed_work_sync(&chip->btc_override_work);
@@ -4663,6 +4696,11 @@ static int __devinit pm8921_charger_probe(struct platform_device *pdev)
else
chip->warm_temp_dc = INT_MIN;
if (pdata->hysteresis_temp)
chip->hysteresis_temp_dc = pdata->hysteresis_temp * 10;
else
chip->hysteresis_temp_dc = TEMP_HYSTERISIS_DECIDEGC;
chip->temp_check_period = pdata->temp_check_period;
chip->max_bat_chg_current = pdata->max_bat_chg_current;
/* Assign to corresponding module parameter */
@@ -165,6 +165,7 @@ struct pm8921_charger_platform_data {
unsigned int warm_bat_chg_current;
unsigned int cool_bat_voltage;
unsigned int warm_bat_voltage;
int hysteresis_temp;
unsigned int (*get_batt_capacity_percent) (void);
int64_t batt_id_min;
int64_t batt_id_max;