forked from len0rd/rockbox
imx233/fuze+: implement power management(battery charger), add powermgmt debug info, add power debug info, move target specific powermgmt code to its own files, remove auto-slow setup which was forgotten for debugging
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31424 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
a1d3ed2534
commit
f7f1f7023f
8 changed files with 432 additions and 40 deletions
|
|
@ -21,30 +21,21 @@
|
|||
|
||||
#include "powermgmt.h"
|
||||
#include "power-imx233.h"
|
||||
#include "usb-target.h"
|
||||
#include "string.h"
|
||||
//#define LOGF_ENABLE
|
||||
#include "logf.h"
|
||||
|
||||
const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
|
||||
{
|
||||
3659
|
||||
};
|
||||
#if !defined(IMX233_CHARGE_CURRENT) || !defined(IMX233_STOP_CURRENT) \
|
||||
|| !defined(IMX233_CHARGING_TIMEOUT) || !defined(IMX233_TOPOFF_TIMEOUT)
|
||||
#error You must define IMX233_CHARGE_CURRENT, IMX233_STOP_CURRENT, \
|
||||
IMX233_CHARGING_TIMEOUT and IMX233_TOPOFF_TIMEOUT !
|
||||
#endif
|
||||
|
||||
const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
|
||||
{
|
||||
3630
|
||||
};
|
||||
|
||||
/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
|
||||
const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
|
||||
{
|
||||
/* Toshiba Gigabeat S Li Ion 700mAH figured from discharge curve */
|
||||
{ 3659, 3719, 3745, 3761, 3785, 3813, 3856, 3926, 3984, 4040, 4121 },
|
||||
};
|
||||
|
||||
/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
|
||||
const unsigned short percent_to_volt_charge[11] =
|
||||
{
|
||||
/* Toshiba Gigabeat S Li Ion 700mAH figured from charge curve */
|
||||
4028, 4063, 4087, 4111, 4135, 4156, 4173, 4185, 4194, 4202, 4208
|
||||
};
|
||||
/* charger state is maintained in charge_state (see powermgmt.h) */
|
||||
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_4p2_ilimit_increase; /* timeout before increasing 4p2 ilimit */
|
||||
|
||||
/* Returns battery voltage from ADC [millivolts] */
|
||||
unsigned int battery_adc_voltage(void)
|
||||
|
|
@ -55,12 +46,115 @@ unsigned int battery_adc_voltage(void)
|
|||
|
||||
void powermgmt_init_target(void)
|
||||
{
|
||||
imx233_power_set_charge_current(IMX233_CHARGE_CURRENT);
|
||||
imx233_power_set_stop_current(IMX233_STOP_CURRENT);
|
||||
/* assume that adc_init was called and battery monitoring via LRADC setup */
|
||||
__REG_SET(HW_POWER_BATTMONITOR) = HW_POWER_BATTMONITOR__ENBATADJ;
|
||||
/* make sure we are in a known state: disable charger and 4p2 */
|
||||
__REG_SET(HW_POWER_CHARGE) = HW_POWER_CHARGE__PWD_BATTCHRG;
|
||||
__REG_CLR(HW_POWER_DCDC4P2) = HW_POWER_DCDC4P2__ENABLE_DCDC |
|
||||
HW_POWER_DCDC4P2__ENABLE_4P2;
|
||||
__REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;
|
||||
charge_state = DISCHARGING;
|
||||
}
|
||||
|
||||
void charging_algorithm_step(void)
|
||||
{
|
||||
bool is_5v_present = usb_plugged();
|
||||
|
||||
/* initial state & 5v -> battery transition */
|
||||
if(!is_5v_present && charge_state != DISCHARGING)
|
||||
{
|
||||
logf("pwrmgmt: * -> discharging");
|
||||
logf("pwrmgmt: disable charger and 4p2");
|
||||
/* 5V has been lost: disable 4p2 power rail */
|
||||
__REG_SET(HW_POWER_CHARGE) = HW_POWER_CHARGE__PWD_BATTCHRG;
|
||||
__REG_CLR(HW_POWER_DCDC4P2) = HW_POWER_DCDC4P2__ENABLE_DCDC |
|
||||
HW_POWER_DCDC4P2__ENABLE_4P2;
|
||||
__REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;
|
||||
charge_state = DISCHARGING;
|
||||
}
|
||||
/* battery -> 5v transition */
|
||||
else if(is_5v_present && charge_state == DISCHARGING)
|
||||
{
|
||||
logf("pwrmgmt: discharging -> trickle");
|
||||
logf("pwrmgmt: begin charging 4p2");
|
||||
/* 5V has been detected: prepare 4.2V power rail for activation */
|
||||
__REG_SET(HW_POWER_DCDC4P2) = HW_POWER_DCDC4P2__ENABLE_4P2;
|
||||
__REG_SET(HW_POWER_CHARGE) = HW_POWER_CHARGE__ENABLE_LOAD;
|
||||
__FIELD_SET(HW_POWER_5VCTRL, CHARGE_4P2_ILIMIT, 1);
|
||||
__REG_CLR(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;// FIXME: manual error ?
|
||||
__REG_SET(HW_POWER_DCDC4P2) = HW_POWER_DCDC4P2__ENABLE_DCDC;
|
||||
timeout_4p2_ilimit_increase = current_tick + HZ / 100;
|
||||
charge_state = TRICKLE;
|
||||
}
|
||||
else if(charge_state == TRICKLE && TIME_AFTER(current_tick, timeout_4p2_ilimit_increase))
|
||||
{
|
||||
/* if 4.2V current limit has not reached 780mA, increase it slowly to
|
||||
* charge the 4.2V capacitance */
|
||||
if(__XTRACT(HW_POWER_5VCTRL, CHARGE_4P2_ILIMIT) != 0x3f)
|
||||
{
|
||||
//logf("pwrmgmt: incr 4.2 ilimit");
|
||||
HW_POWER_5VCTRL += 1 << HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT_BP;
|
||||
timeout_4p2_ilimit_increase = current_tick + HZ / 100;
|
||||
}
|
||||
/* we've reached the maximum, take action */
|
||||
else
|
||||
{
|
||||
logf("pwrmgmt: enable dcdc and charger");
|
||||
logf("pwrmgmt: trickle -> charging");
|
||||
/* adjust arbitration between 4.2 and battery */
|
||||
__FIELD_SET(HW_POWER_DCDC4P2, CMPTRIP, 0); /* 85% */
|
||||
__FIELD_SET(HW_POWER_DCDC4P2, DROPOUT_CTRL, 0xe); /* select greater, 200 mV drop */
|
||||
__REG_CLR(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__DCDC_XFER;
|
||||
__REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__ENABLE_DCDC;
|
||||
/* enable battery charging */
|
||||
__REG_CLR(HW_POWER_CHARGE) = HW_POWER_CHARGE__PWD_BATTCHRG;
|
||||
charge_state = CHARGING;
|
||||
timeout_charging = current_tick + IMX233_CHARGING_TIMEOUT;
|
||||
}
|
||||
}
|
||||
else if(charge_state == CHARGING && TIME_AFTER(current_tick, timeout_charging))
|
||||
{
|
||||
/* we have charged for a too long time, declare charger broken */
|
||||
logf("pwrmgmt: charging timeout exceeded!");
|
||||
logf("pwrmgmt: charging -> error");
|
||||
/* stop charging */
|
||||
__REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;
|
||||
/* goto error state */
|
||||
charge_state = CHARGE_STATE_ERROR;
|
||||
}
|
||||
else if(charge_state == CHARGING && !(HW_POWER_STS & HW_POWER_STS__CHRGSTS))
|
||||
{
|
||||
logf("pwrmgmt: topping off");
|
||||
logf("pwrmgmt: charging -> topoff");
|
||||
charge_state = TOPOFF;
|
||||
timeout_topping_off = current_tick + IMX233_TOPOFF_TIMEOUT;
|
||||
}
|
||||
else if(charge_state == TOPOFF && TIME_AFTER(current_tick, timeout_topping_off))
|
||||
{
|
||||
logf("pwrmgmt: charging finished");
|
||||
logf("pwrmgmt: topoff -> disabled");
|
||||
/* stop charging */
|
||||
__REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;
|
||||
charge_state = CHARGE_STATE_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
void charging_algorithm_close(void)
|
||||
{
|
||||
}
|
||||
|
||||
struct imx233_powermgmt_info_t imx233_powermgmt_get_info(void)
|
||||
{
|
||||
struct imx233_powermgmt_info_t info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.state = charge_state;
|
||||
info.charging_timeout =
|
||||
charge_state == CHARGING ? timeout_charging - current_tick : 0;
|
||||
info.topoff_timeout =
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue