imx233: speedup charging trickle phase

Per Freescale recommandation, we need to ramp up the 4.2V rail before enabling
charging. Ramping should be done at 1 step/10ms, but the old code did 1 step/1s
because the powermgmt_step() function is called once every second. Use a tick
task to ramp up much faster.

Change-Id: I9a52bdd0c2ba5426d83ed42db8db7ecce2fea1f7
This commit is contained in:
Amaury Pouly 2016-05-02 21:49:13 +01:00
parent d245b7a2a1
commit 941ac165d8
3 changed files with 27 additions and 20 deletions

View file

@ -407,7 +407,6 @@ bool dbg_hw_info_powermgmt(void)
"<unknown>"); "<unknown>");
lcd_putsf(0, 1, "charging tmo: %d", info.charging_timeout); lcd_putsf(0, 1, "charging tmo: %d", info.charging_timeout);
lcd_putsf(0, 2, "topoff tmo: %d", info.topoff_timeout); lcd_putsf(0, 2, "topoff tmo: %d", info.topoff_timeout);
lcd_putsf(0, 3, "4p2ilimit tmo: %d", info.incr_4p2_ilimit_timeout);
lcd_update(); lcd_update();
yield(); yield();

View file

@ -39,7 +39,6 @@
/* charger state is maintained in charge_state (see powermgmt.h) */ /* charger state is maintained in charge_state (see powermgmt.h) */
static int timeout_charging; /* timeout before charging will be declared broken */ static int timeout_charging; /* timeout before charging will be declared broken */
static int timeout_topping_off; /* timeout before stopping charging after topping off */ static int timeout_topping_off; /* timeout before stopping charging after topping off */
static int timeout_4p2_ilimit_increase; /* timeout before increasing 4p2 ilimit */
/* Returns battery voltage from ADC [millivolts] */ /* Returns battery voltage from ADC [millivolts] */
int _battery_voltage(void) int _battery_voltage(void)
@ -69,9 +68,24 @@ void imx233_powermgmt_init(void)
#endif #endif
} }
#define MAX_4P2_ILIMIT 0x3f
/* The code below assumes HZ = 100 so that it runs every 10ms */
#if HZ != 100
#warning The ramp_up_4p2_rail() tick task assumes HZ = 100, this may break charging
#endif
static void ramp_up_4p2_rail(void)
{
/* only ramp up in the TRICKLE state and if we haven't reached the maximum yet */
if(charge_state == TRICKLE && BF_RD(POWER_5VCTRL, CHARGE_4P2_ILIMIT) < MAX_4P2_ILIMIT)
HW_POWER_5VCTRL += BF_POWER_5VCTRL_CHARGE_4P2_ILIMIT(1);
}
void powermgmt_init_target(void) void powermgmt_init_target(void)
{ {
charge_state = DISCHARGING; charge_state = DISCHARGING;
tick_add_task(&ramp_up_4p2_rail);
} }
void charging_algorithm_step(void) void charging_algorithm_step(void)
@ -84,15 +98,15 @@ void charging_algorithm_step(void)
{ {
logf("pwrmgmt: * -> discharging"); logf("pwrmgmt: * -> discharging");
logf("pwrmgmt: disable charger and 4p2"); logf("pwrmgmt: disable charger and 4p2");
charge_state = DISCHARGING;
/* 5V has been lost: disable 4p2 power rail */ /* 5V has been lost: disable 4p2 power rail */
BF_SET(POWER_CHARGE, PWD_BATTCHRG); BF_SET(POWER_CHARGE, PWD_BATTCHRG);
#if IMX233_SUBTARGET >= 3780 #if IMX233_SUBTARGET >= 3780
BF_WR(POWER_DCDC4P2, ENABLE_DCDC(0)); BF_WR(POWER_DCDC4P2, ENABLE_DCDC(0));
BF_WR(POWER_DCDC4P2, ENABLE_4P2(0)); BF_WR(POWER_DCDC4P2, ENABLE_4P2(0));
BF_WR(POWER_5VCTRL, CHARGE_4P2_ILIMIT(1)); BF_WR(POWER_5VCTRL, CHARGE_4P2_ILIMIT(0));
BF_SET(POWER_5VCTRL, PWD_CHARGE_4P2); BF_SET(POWER_5VCTRL, PWD_CHARGE_4P2);
#endif #endif
charge_state = DISCHARGING;
} }
/* battery -> 5v transition */ /* battery -> 5v transition */
else if(is_5v_present && charge_state == DISCHARGING) else if(is_5v_present && charge_state == DISCHARGING)
@ -108,26 +122,22 @@ void charging_algorithm_step(void)
* limit on the 4P2 rail. */ * limit on the 4P2 rail. */
BF_WR(POWER_DCDC4P2, ENABLE_4P2(1)); BF_WR(POWER_DCDC4P2, ENABLE_4P2(1));
BF_SET(POWER_CHARGE, ENABLE_LOAD); BF_SET(POWER_CHARGE, ENABLE_LOAD);
BF_WR(POWER_5VCTRL, CHARGE_4P2_ILIMIT(1)); /* start by drawing 10mA only */ BF_WR(POWER_5VCTRL, CHARGE_4P2_ILIMIT(0)); /* start by drawing 0mA */
BF_CLR(POWER_5VCTRL, PWD_CHARGE_4P2);// FIXME: manual error ? BF_CLR(POWER_5VCTRL, PWD_CHARGE_4P2);// FIXME: manual error ?
BF_WR(POWER_DCDC4P2, ENABLE_DCDC(1)); BF_WR(POWER_DCDC4P2, ENABLE_DCDC(1));
/* the tick task will take care of slowly ramping up the current in the rail
* every 10ms (since it runs at HZ and HZ=100) */
#endif #endif
timeout_4p2_ilimit_increase = current_tick + HZ / 100;
charge_state = TRICKLE; charge_state = TRICKLE;
} }
else if(charge_state == TRICKLE && TIME_AFTER(current_tick, timeout_4p2_ilimit_increase)) /* trickle -> charging transition */
else if(charge_state == TRICKLE)
{ {
#if IMX233_SUBTARGET >= 3780 #if IMX233_SUBTARGET >= 3780
/* if 4.2V current limit has not reached 780mA, increase it slowly to /* If 4.2V current limit has not reached 780mA, don't do anything, the
* charge the 4.2V capacitance */ * DPC is still running */
if(BF_RD(POWER_5VCTRL, CHARGE_4P2_ILIMIT) != 0x3f) /* If we've reached the maximum, take action */
{ if(BF_RD(POWER_5VCTRL, CHARGE_4P2_ILIMIT) == MAX_4P2_ILIMIT)
//logf("pwrmgmt: incr 4.2 ilimit");
HW_POWER_5VCTRL += BF_POWER_5VCTRL_CHARGE_4P2_ILIMIT(1);
timeout_4p2_ilimit_increase = current_tick + HZ / 100;
}
/* we've reached the maximum, take action */
else
#endif #endif
{ {
logf("pwrmgmt: enable dcdc and charger"); logf("pwrmgmt: enable dcdc and charger");
@ -181,6 +191,7 @@ void charging_algorithm_step(void)
void charging_algorithm_close(void) void charging_algorithm_close(void)
{ {
tick_remove_task(&ramp_up_4p2_rail);
} }
struct imx233_powermgmt_info_t imx233_powermgmt_get_info(void) struct imx233_powermgmt_info_t imx233_powermgmt_get_info(void)
@ -192,7 +203,5 @@ struct imx233_powermgmt_info_t imx233_powermgmt_get_info(void)
charge_state == CHARGING ? timeout_charging - current_tick : 0; charge_state == CHARGING ? timeout_charging - current_tick : 0;
info.topoff_timeout = info.topoff_timeout =
charge_state == TOPOFF ? timeout_topping_off - current_tick : 0; charge_state == TOPOFF ? timeout_topping_off - current_tick : 0;
info.incr_4p2_ilimit_timeout =
charge_state == TRICKLE ? timeout_4p2_ilimit_increase - current_tick : 0;
return info; return info;
} }

View file

@ -31,7 +31,6 @@ struct imx233_powermgmt_info_t
enum charge_state_type state; enum charge_state_type state;
int charging_timeout; /* time in tick before timeout, -1 if n/a */ int charging_timeout; /* time in tick before timeout, -1 if n/a */
int topoff_timeout; /* ditto */ int topoff_timeout; /* ditto */
int incr_4p2_ilimit_timeout; /* ditto */
}; };
struct imx233_powermgmt_info_t imx233_powermgmt_get_info(void); struct imx233_powermgmt_info_t imx233_powermgmt_get_info(void);