Only ask the charger for current steps it can supply

This reduces oscillations in the charging algorithm.  This change also adds
more debug output so it's easier to see what the charging state machine is
doing.

BUG=chrome-os-partner:9572
BRANCH=link
TEST=discharge battery; charge battery; note infrequent but useful debug output

Change-Id: I4c8609c2ca8a6cab3eae151ecf2bb1520103fece
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/33811
Reviewed-by: Rong Chang <rongchang@chromium.org>
This commit is contained in:
Randall Spangler
2012-09-21 14:48:47 -07:00
committed by Gerrit
parent 3c4f66648d
commit 8b592052ce
3 changed files with 53 additions and 14 deletions

View File

@@ -346,8 +346,14 @@ static enum power_state state_idle(struct power_state_context *ctx)
ctx->trickle_charging_time = get_time();
} else {
/* Normal charging */
int want_current =
charger_closest_current(batt->desired_current);
CPRINTF("[%T Charge start %dmV %dmA]\n",
batt->desired_voltage, want_current);
if (charger_set_voltage(batt->desired_voltage) ||
charger_set_current(batt->desired_current))
charger_set_current(want_current))
return PWR_STATE_ERROR;
}
update_charger_time(ctx, get_time());
@@ -367,6 +373,7 @@ static enum power_state state_charge(struct power_state_context *ctx)
struct batt_params *batt = &ctx->curr.batt;
const struct charger_info *c_info = ctx->charger;
int debounce = 0;
int want_current;
timestamp_t now;
if (curr->error)
@@ -394,24 +401,36 @@ static enum power_state state_charge(struct power_state_context *ctx)
now = get_time();
if (batt->desired_voltage != curr->charging_voltage) {
CPRINTF("[%T Charge voltage %dmV]\n", batt->desired_voltage);
if (charger_set_voltage(batt->desired_voltage))
return PWR_STATE_ERROR;
update_charger_time(ctx, now);
}
if (batt->desired_current == curr->charging_current) {
/*
* Adjust desired current to one the charger can actually supply before
* we do debouncing, or else we'll keep asking for a current the
* charger can't actually supply.
*/
want_current = charger_closest_current(batt->desired_current);
if (want_current == curr->charging_current) {
/* Tick charger watchdog */
if (!is_charger_expired(ctx, now))
return PWR_STATE_UNCHANGE;
} else if (batt->desired_current > curr->charging_current) {
} else if (want_current > curr->charging_current) {
if (!timestamp_expired(ctx->voltage_debounce_time, &now))
return PWR_STATE_UNCHANGE;
} else {
/* Debounce charging current on falling edge */
debounce = 1;
}
if (charger_set_current(batt->desired_current))
if (want_current != curr->charging_current) {
CPRINTF("[%T Charge current %dmA @ %dmV]\n",
want_current, batt->desired_voltage);
}
if (charger_set_current(want_current))
return PWR_STATE_ERROR;
/* Update charger watchdog timer and debounce timer */

View File

@@ -134,17 +134,28 @@ int charger_get_current(int *current)
return EC_SUCCESS;
}
int charger_closest_current(int current)
{
const struct charger_info * const info = charger_get_info();
/*
* If the requested current is non-zero but below our minimum,
* return the minimum. See crosbug.com/p/8662.
*/
if (current > 0 && current < info->current_min)
return info->current_min;
/* Clip to max */
if (current > info->current_max)
return info->current_max;
/* Otherwise round down to nearest current step */
return current - (current % info->current_step);
}
int charger_set_current(int current)
{
const struct charger_info *info = charger_get_info();
/* Clip the charge current to the range the charger can supply. This
* is a temporary workaround for the battery requesting a very small
* current for trickle-charging. See crosbug.com/p/8662. */
if (current > 0 && current < info->current_min)
current = info->current_min;
if (current > info->current_max)
current = info->current_max;
current = charger_closest_current(current);
return sbc_write(SB_CHARGING_CURRENT, CURRENT_TO_REG(current, R_SNS));
}

View File

@@ -44,6 +44,15 @@ int charger_get_status(int *status);
*/
int charger_set_mode(int mode);
/**
* Return the closest match the charger can supply to the requested current.
*
* @param current Requested current in mA.
*
* @return Current the charger will actually supply if <current> is requested.
*/
int charger_closest_current(int current);
/* Get/set charge current limit in mA */
int charger_get_current(int *current);
int charger_set_current(int current);