mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 10:37:38 -04:00
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
|
@ -1382,6 +1382,7 @@ target/arm/imx233/sansa-fuzeplus/power-fuzeplus.c
|
||||||
target/arm/imx233/sansa-fuzeplus/adc-fuzeplus.c
|
target/arm/imx233/sansa-fuzeplus/adc-fuzeplus.c
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
target/arm/imx233/sansa-fuzeplus/audio-fuzeplus.c
|
target/arm/imx233/sansa-fuzeplus/audio-fuzeplus.c
|
||||||
|
target/arm/imx233/sansa-fuzeplus/powermgmt-fuzeplus.c
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -90,5 +90,6 @@
|
||||||
|
|
||||||
#define __XTRACT(reg, field) ((reg & reg##__##field##_BM) >> reg##__##field##_BP)
|
#define __XTRACT(reg, field) ((reg & reg##__##field##_BM) >> reg##__##field##_BP)
|
||||||
#define __XTRACT_EX(val, field) (((val) & field##_BM) >> field##_BP)
|
#define __XTRACT_EX(val, field) (((val) & field##_BM) >> field##_BP)
|
||||||
|
#define __FIELD_SET(reg, field, val) reg = (reg & ~reg##__##field##_BM) | (val << reg##__##field##_BP)
|
||||||
|
|
||||||
#endif /* __IMX233_H__ */
|
#endif /* __IMX233_H__ */
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include "adc-imx233.h"
|
#include "adc-imx233.h"
|
||||||
#include "power-imx233.h"
|
#include "power-imx233.h"
|
||||||
#include "clkctrl-imx233.h"
|
#include "clkctrl-imx233.h"
|
||||||
#include "powermgmt.h"
|
#include "powermgmt-imx233.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
|
@ -107,11 +107,22 @@ bool dbg_hw_info_power(void)
|
||||||
lcd_clear_display();
|
lcd_clear_display();
|
||||||
|
|
||||||
struct imx233_power_info_t info = imx233_power_get_info(POWER_INFO_ALL);
|
struct imx233_power_info_t info = imx233_power_get_info(POWER_INFO_ALL);
|
||||||
lcd_putsf(0, 0, "VDDD: %d mV linreg: %d", info.vddd, info.vddd_linreg);
|
lcd_putsf(0, 0, "VDDD: %d mV linreg: %d offset: %d", info.vddd, info.vddd_linreg,
|
||||||
lcd_putsf(0, 1, "VDDA: %d mV linreg: %d", info.vdda, info.vdda_linreg);
|
info.vddd_linreg_offset);
|
||||||
lcd_putsf(0, 2, "VDDIO: %d mV", info.vddio);
|
lcd_putsf(0, 1, "VDDA: %d mV linreg: %d offset: %d", info.vdda, info.vdda_linreg,
|
||||||
|
info.vdda_linreg_offset);
|
||||||
|
lcd_putsf(0, 2, "VDDIO: %d mV offset: %d", info.vddio, info.vddio_linreg_offset);
|
||||||
lcd_putsf(0, 3, "VDDMEM: %d mV linreg: %d", info.vddmem, info.vddmem_linreg);
|
lcd_putsf(0, 3, "VDDMEM: %d mV linreg: %d", info.vddmem, info.vddmem_linreg);
|
||||||
lcd_putsf(0, 4, "DC-DC: pll: %d freq: %d", info.dcdc_sel_pllclk, info.dcdc_freqsel);
|
lcd_putsf(0, 4, "DC-DC: pll: %d freq: %d", info.dcdc_sel_pllclk, info.dcdc_freqsel);
|
||||||
|
lcd_putsf(0, 5, "charge: %d mA stop: %d mA", info.charge_current, info.stop_current);
|
||||||
|
lcd_putsf(0, 6, "charging: %d bat_adj: %d", info.charging, info.batt_adj);
|
||||||
|
lcd_putsf(0, 7, "4.2: en: %d dcdc: %d", info._4p2_enable, info._4p2_dcdc);
|
||||||
|
lcd_putsf(0, 8, "4.2: cmptrip: %d dropout: %d", info._4p2_cmptrip, info._4p2_dropout);
|
||||||
|
lcd_putsf(0, 9, "5V: pwd_4.2_charge: %d", info._5v_pwd_charge_4p2);
|
||||||
|
lcd_putsf(0, 10, "5V: chargelim: %d mA", info._5v_charge_4p2_limit);
|
||||||
|
lcd_putsf(0, 11, "5V: dcdc: %d xfer: %d", info._5v_enable_dcdc, info._5v_dcdc_xfer);
|
||||||
|
lcd_putsf(0, 12, "5V: thr: %d mV use: %d cmps: %d", info._5v_vbusvalid_thr,
|
||||||
|
info._5v_vbusvalid_detect, info._5v_vbus_cmps);
|
||||||
|
|
||||||
lcd_update();
|
lcd_update();
|
||||||
yield();
|
yield();
|
||||||
|
@ -194,12 +205,6 @@ static struct
|
||||||
bool dbg_hw_info_clkctrl(void)
|
bool dbg_hw_info_clkctrl(void)
|
||||||
{
|
{
|
||||||
lcd_setfont(FONT_SYSFIXED);
|
lcd_setfont(FONT_SYSFIXED);
|
||||||
imx233_enable_auto_slow_monitor(AS_CPU_INSTR, true);
|
|
||||||
imx233_enable_auto_slow_monitor(AS_CPU_DATA, true);
|
|
||||||
imx233_enable_auto_slow_monitor(AS_TRAFFIC, true);
|
|
||||||
imx233_enable_auto_slow_monitor(AS_TRAFFIC_JAM, true);
|
|
||||||
imx233_enable_auto_slow_monitor(AS_APBXDMA, true);
|
|
||||||
imx233_enable_auto_slow_monitor(AS_APBHDMA, true);
|
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
|
@ -269,10 +274,49 @@ bool dbg_hw_info_clkctrl(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dbg_hw_info_powermgmt(void)
|
||||||
|
{
|
||||||
|
lcd_setfont(FONT_SYSFIXED);
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
int button = get_action(CONTEXT_STD, HZ / 10);
|
||||||
|
switch(button)
|
||||||
|
{
|
||||||
|
case ACTION_STD_NEXT:
|
||||||
|
case ACTION_STD_PREV:
|
||||||
|
case ACTION_STD_OK:
|
||||||
|
case ACTION_STD_MENU:
|
||||||
|
lcd_setfont(FONT_UI);
|
||||||
|
return true;
|
||||||
|
case ACTION_STD_CANCEL:
|
||||||
|
lcd_setfont(FONT_UI);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lcd_clear_display();
|
||||||
|
struct imx233_powermgmt_info_t info = imx233_powermgmt_get_info();
|
||||||
|
|
||||||
|
lcd_putsf(0, 0, "state: %s",
|
||||||
|
info.state == CHARGE_STATE_DISABLED ? "disabled" :
|
||||||
|
info.state == CHARGE_STATE_ERROR ? "error" :
|
||||||
|
info.state == DISCHARGING ? "discharging" :
|
||||||
|
info.state == TRICKLE ? "trickle" :
|
||||||
|
info.state == TOPOFF ? "topoff" :
|
||||||
|
info.state == CHARGING ? "charging" : "<unknown>");
|
||||||
|
lcd_putsf(0, 1, "charging tmo: %d", info.charging_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();
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool dbg_hw_info(void)
|
bool dbg_hw_info(void)
|
||||||
{
|
{
|
||||||
return dbg_hw_info_clkctrl() && dbg_hw_info_dma() && dbg_hw_info_adc() && dbg_hw_info_power() &&
|
return dbg_hw_info_clkctrl() && dbg_hw_info_dma() && dbg_hw_info_adc() &&
|
||||||
dbg_hw_target_info();
|
dbg_hw_info_power() && dbg_hw_info_powermgmt() && dbg_hw_target_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dbg_ports(void)
|
bool dbg_ports(void)
|
||||||
|
|
|
@ -26,6 +26,43 @@
|
||||||
#include "system-target.h"
|
#include "system-target.h"
|
||||||
#include "usb-target.h"
|
#include "usb-target.h"
|
||||||
|
|
||||||
|
struct current_step_bit_t
|
||||||
|
{
|
||||||
|
unsigned current;
|
||||||
|
uint32_t bit;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* in decreasing order */
|
||||||
|
static struct current_step_bit_t g_charger_current_bits[] =
|
||||||
|
{
|
||||||
|
{ 400, HW_POWER_CHARGE__BATTCHRG_I__400mA },
|
||||||
|
{ 200, HW_POWER_CHARGE__BATTCHRG_I__200mA },
|
||||||
|
{ 100, HW_POWER_CHARGE__BATTCHRG_I__100mA },
|
||||||
|
{ 50, HW_POWER_CHARGE__BATTCHRG_I__50mA },
|
||||||
|
{ 20, HW_POWER_CHARGE__BATTCHRG_I__20mA },
|
||||||
|
{ 10, HW_POWER_CHARGE__BATTCHRG_I__10mA }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* in decreasing order */
|
||||||
|
static struct current_step_bit_t g_charger_stop_current_bits[] =
|
||||||
|
{
|
||||||
|
{ 100, HW_POWER_CHARGE__STOP_ILIMIT__100mA },
|
||||||
|
{ 50, HW_POWER_CHARGE__STOP_ILIMIT__50mA },
|
||||||
|
{ 20, HW_POWER_CHARGE__STOP_ILIMIT__20mA },
|
||||||
|
{ 10, HW_POWER_CHARGE__STOP_ILIMIT__10mA }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* in decreasing order */
|
||||||
|
static struct current_step_bit_t g_4p2_charge_limit_bits[] =
|
||||||
|
{
|
||||||
|
{ 400, HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__400mA },
|
||||||
|
{ 200, HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__200mA },
|
||||||
|
{ 100, HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__100mA },
|
||||||
|
{ 50, HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__50mA },
|
||||||
|
{ 20, HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__20mA },
|
||||||
|
{ 10, HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__10mA }
|
||||||
|
};
|
||||||
|
|
||||||
void INT_VDD5V(void)
|
void INT_VDD5V(void)
|
||||||
{
|
{
|
||||||
if(HW_POWER_CTRL & HW_POWER_CTRL__VBUSVALID_IRQ)
|
if(HW_POWER_CTRL & HW_POWER_CTRL__VBUSVALID_IRQ)
|
||||||
|
@ -43,6 +80,12 @@ void INT_VDD5V(void)
|
||||||
|
|
||||||
void power_init(void)
|
void power_init(void)
|
||||||
{
|
{
|
||||||
|
/* setup vbusvalid parameters: set threshold to 4v and power up comparators */
|
||||||
|
__REG_CLR(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__VBUSVALID_TRSH_BM;
|
||||||
|
__REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__VBUSVALID_TRSH_4V |
|
||||||
|
HW_POWER_5VCTRL__PWRUP_VBUS_CMPS;
|
||||||
|
/* enable vbusvalid detection method for the dcdc (improves efficiency) */
|
||||||
|
__REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__VBUSVALID_5VDETECT;
|
||||||
/* clear vbusvalid irq and set correct polarity */
|
/* clear vbusvalid irq and set correct polarity */
|
||||||
__REG_CLR(HW_POWER_CTRL) = HW_POWER_CTRL__VBUSVALID_IRQ;
|
__REG_CLR(HW_POWER_CTRL) = HW_POWER_CTRL__VBUSVALID_IRQ;
|
||||||
if(HW_POWER_STS & HW_POWER_STS__VBUSVALID)
|
if(HW_POWER_STS & HW_POWER_STS__VBUSVALID)
|
||||||
|
@ -51,6 +94,11 @@ void power_init(void)
|
||||||
__REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__POLARITY_VBUSVALID;
|
__REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__POLARITY_VBUSVALID;
|
||||||
__REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__ENIRQ_VBUS_VALID;
|
__REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__ENIRQ_VBUS_VALID;
|
||||||
imx233_enable_interrupt(INT_SRC_VDD5V, true);
|
imx233_enable_interrupt(INT_SRC_VDD5V, true);
|
||||||
|
/* setup linear regulator offsets to 25 mV below to prevent contention between
|
||||||
|
* linear regulators and DCDC */
|
||||||
|
__FIELD_SET(HW_POWER_VDDDCTRL, LINREG_OFFSET, 2);
|
||||||
|
__FIELD_SET(HW_POWER_VDDACTRL, LINREG_OFFSET, 2);
|
||||||
|
__FIELD_SET(HW_POWER_VDDIOCTRL, LINREG_OFFSET, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void power_off(void)
|
void power_off(void)
|
||||||
|
@ -64,12 +112,42 @@ void power_off(void)
|
||||||
|
|
||||||
unsigned int power_input_status(void)
|
unsigned int power_input_status(void)
|
||||||
{
|
{
|
||||||
return POWER_INPUT_NONE;
|
return usb_plugged() ? POWER_INPUT_MAIN_CHARGER : POWER_INPUT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool charging_state(void)
|
bool charging_state(void)
|
||||||
{
|
{
|
||||||
return false;
|
return HW_POWER_STS & HW_POWER_STS__CHRGSTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void imx233_power_set_charge_current(unsigned current)
|
||||||
|
{
|
||||||
|
__REG_CLR(HW_POWER_CHARGE) = HW_POWER_CHARGE__BATTCHRG_I_BM;
|
||||||
|
/* find closest current LOWER THAN OR EQUAL TO the expected current */
|
||||||
|
for(unsigned i = 0; i < ARRAYLEN(g_charger_current_bits); i++)
|
||||||
|
if(current >= g_charger_current_bits[i].current)
|
||||||
|
{
|
||||||
|
current -= g_charger_current_bits[i].current;
|
||||||
|
__REG_SET(HW_POWER_CHARGE) = g_charger_current_bits[i].bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void imx233_power_set_stop_current(unsigned current)
|
||||||
|
{
|
||||||
|
__REG_CLR(HW_POWER_CHARGE) = HW_POWER_CHARGE__STOP_ILIMIT_BM;
|
||||||
|
/* find closest current GREATHER THAN OR EQUAL TO the expected current */
|
||||||
|
unsigned sum = 0;
|
||||||
|
for(unsigned i = 0; i < ARRAYLEN(g_charger_stop_current_bits); i++)
|
||||||
|
sum += g_charger_stop_current_bits[i].current;
|
||||||
|
for(unsigned i = 0; i < ARRAYLEN(g_charger_stop_current_bits); i++)
|
||||||
|
{
|
||||||
|
sum -= g_charger_stop_current_bits[i].current;
|
||||||
|
if(current > sum)
|
||||||
|
{
|
||||||
|
current -= g_charger_stop_current_bits[i].current;
|
||||||
|
__REG_SET(HW_POWER_CHARGE) = g_charger_stop_current_bits[i].bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct imx233_power_info_t imx233_power_get_info(unsigned flags)
|
struct imx233_power_info_t imx233_power_get_info(unsigned flags)
|
||||||
|
@ -91,14 +169,22 @@ struct imx233_power_info_t imx233_power_get_info(unsigned flags)
|
||||||
{
|
{
|
||||||
s.vddd = HW_POWER_VDDDCTRL__TRG_MIN + HW_POWER_VDDDCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDDCTRL, TRG);
|
s.vddd = HW_POWER_VDDDCTRL__TRG_MIN + HW_POWER_VDDDCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDDCTRL, TRG);
|
||||||
s.vddd_linreg = HW_POWER_VDDDCTRL & HW_POWER_VDDDCTRL__ENABLE_LINREG;
|
s.vddd_linreg = HW_POWER_VDDDCTRL & HW_POWER_VDDDCTRL__ENABLE_LINREG;
|
||||||
|
s.vddd_linreg_offset = __XTRACT(HW_POWER_VDDDCTRL, LINREG_OFFSET) == 0 ? 0 :
|
||||||
|
__XTRACT(HW_POWER_VDDDCTRL, LINREG_OFFSET) == 1 ? 25 : -25;
|
||||||
}
|
}
|
||||||
if(flags & POWER_INFO_VDDA)
|
if(flags & POWER_INFO_VDDA)
|
||||||
{
|
{
|
||||||
s.vdda = HW_POWER_VDDACTRL__TRG_MIN + HW_POWER_VDDACTRL__TRG_STEP * __XTRACT(HW_POWER_VDDACTRL, TRG);
|
s.vdda = HW_POWER_VDDACTRL__TRG_MIN + HW_POWER_VDDACTRL__TRG_STEP * __XTRACT(HW_POWER_VDDACTRL, TRG);
|
||||||
s.vdda_linreg = HW_POWER_VDDACTRL & HW_POWER_VDDACTRL__ENABLE_LINREG;
|
s.vdda_linreg = HW_POWER_VDDACTRL & HW_POWER_VDDACTRL__ENABLE_LINREG;
|
||||||
|
s.vdda_linreg_offset = __XTRACT(HW_POWER_VDDACTRL, LINREG_OFFSET) == 0 ? 0 :
|
||||||
|
__XTRACT(HW_POWER_VDDACTRL, LINREG_OFFSET) == 1 ? 25 : -25;
|
||||||
}
|
}
|
||||||
if(flags & POWER_INFO_VDDIO)
|
if(flags & POWER_INFO_VDDIO)
|
||||||
|
{
|
||||||
s.vddio = HW_POWER_VDDIOCTRL__TRG_MIN + HW_POWER_VDDIOCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDIOCTRL, TRG);
|
s.vddio = HW_POWER_VDDIOCTRL__TRG_MIN + HW_POWER_VDDIOCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDIOCTRL, TRG);
|
||||||
|
s.vddio_linreg_offset = __XTRACT(HW_POWER_VDDIOCTRL, LINREG_OFFSET) == 0 ? 0 :
|
||||||
|
__XTRACT(HW_POWER_VDDIOCTRL, LINREG_OFFSET) == 1 ? 25 : -25;
|
||||||
|
}
|
||||||
if(flags & POWER_INFO_VDDMEM)
|
if(flags & POWER_INFO_VDDMEM)
|
||||||
{
|
{
|
||||||
s.vddmem = HW_POWER_VDDMEMCTRL__TRG_MIN + HW_POWER_VDDMEMCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDMEMCTRL, TRG);
|
s.vddmem = HW_POWER_VDDMEMCTRL__TRG_MIN + HW_POWER_VDDMEMCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDMEMCTRL, TRG);
|
||||||
|
@ -109,5 +195,38 @@ struct imx233_power_info_t imx233_power_get_info(unsigned flags)
|
||||||
s.dcdc_sel_pllclk = HW_POWER_MISC & HW_POWER_MISC__SEL_PLLCLK;
|
s.dcdc_sel_pllclk = HW_POWER_MISC & HW_POWER_MISC__SEL_PLLCLK;
|
||||||
s.dcdc_freqsel = dcdc_freqsel[__XTRACT(HW_POWER_MISC, FREQSEL)];
|
s.dcdc_freqsel = dcdc_freqsel[__XTRACT(HW_POWER_MISC, FREQSEL)];
|
||||||
}
|
}
|
||||||
|
if(flags & POWER_INFO_CHARGE)
|
||||||
|
{
|
||||||
|
for(unsigned i = 0; i < ARRAYLEN(g_charger_current_bits); i++)
|
||||||
|
if(HW_POWER_CHARGE & g_charger_current_bits[i].bit)
|
||||||
|
s.charge_current += g_charger_current_bits[i].current;
|
||||||
|
for(unsigned i = 0; i < ARRAYLEN(g_charger_stop_current_bits); i++)
|
||||||
|
if(HW_POWER_CHARGE & g_charger_stop_current_bits[i].bit)
|
||||||
|
s.stop_current += g_charger_stop_current_bits[i].current;
|
||||||
|
s.charging = HW_POWER_STS & HW_POWER_STS__CHRGSTS;
|
||||||
|
s.batt_adj = HW_POWER_BATTMONITOR & HW_POWER_BATTMONITOR__ENBATADJ;
|
||||||
|
}
|
||||||
|
if(flags & POWER_INFO_4P2)
|
||||||
|
{
|
||||||
|
s._4p2_enable = HW_POWER_DCDC4P2 & HW_POWER_DCDC4P2__ENABLE_4P2;
|
||||||
|
s._4p2_dcdc = HW_POWER_DCDC4P2 & HW_POWER_DCDC4P2__ENABLE_DCDC;
|
||||||
|
s._4p2_cmptrip = __XTRACT(HW_POWER_DCDC4P2, CMPTRIP);
|
||||||
|
s._4p2_dropout = __XTRACT(HW_POWER_DCDC4P2, DROPOUT_CTRL);
|
||||||
|
}
|
||||||
|
if(flags & POWER_INFO_5V)
|
||||||
|
{
|
||||||
|
s._5v_pwd_charge_4p2 = HW_POWER_5VCTRL & HW_POWER_5VCTRL__PWD_CHARGE_4P2;
|
||||||
|
s._5v_dcdc_xfer = HW_POWER_5VCTRL & HW_POWER_5VCTRL__DCDC_XFER;
|
||||||
|
s._5v_enable_dcdc = HW_POWER_5VCTRL & HW_POWER_5VCTRL__ENABLE_DCDC;
|
||||||
|
for(unsigned i = 0; i < ARRAYLEN(g_4p2_charge_limit_bits); i++)
|
||||||
|
if(HW_POWER_5VCTRL & g_4p2_charge_limit_bits[i].bit)
|
||||||
|
s._5v_charge_4p2_limit += g_4p2_charge_limit_bits[i].current;
|
||||||
|
s._5v_vbusvalid_detect = HW_POWER_5VCTRL & HW_POWER_5VCTRL__VBUSVALID_5VDETECT;
|
||||||
|
s._5v_vbus_cmps = HW_POWER_5VCTRL & HW_POWER_5VCTRL__PWRUP_VBUS_CMPS;
|
||||||
|
s._5v_vbusvalid_thr =
|
||||||
|
__XTRACT(HW_POWER_5VCTRL, VBUSVALID_TRSH) == 0 ?
|
||||||
|
2900
|
||||||
|
: 3900 + __XTRACT(HW_POWER_5VCTRL, VBUSVALID_TRSH) * 100;
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,25 +33,52 @@
|
||||||
#define HW_POWER_CTRL__POLARITY_VBUSVALID (1 << 5)
|
#define HW_POWER_CTRL__POLARITY_VBUSVALID (1 << 5)
|
||||||
|
|
||||||
#define HW_POWER_5VCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x10))
|
#define HW_POWER_5VCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x10))
|
||||||
|
#define HW_POWER_5VCTRL__ENABLE_DCDC (1 << 0)
|
||||||
|
#define HW_POWER_5VCTRL__PWRUP_VBUS_CMPS (1 << 1)
|
||||||
#define HW_POWER_5VCTRL__VBUSVALID_5VDETECT (1 << 4)
|
#define HW_POWER_5VCTRL__VBUSVALID_5VDETECT (1 << 4)
|
||||||
|
#define HW_POWER_5VCTRL__DCDC_XFER (1 << 5)
|
||||||
#define HW_POWER_5VCTRL__VBUSVALID_TRSH_BP 8
|
#define HW_POWER_5VCTRL__VBUSVALID_TRSH_BP 8
|
||||||
#define HW_POWER_5VCTRL__VBUSVALID_TRSH_BM (0x7 << 8)
|
#define HW_POWER_5VCTRL__VBUSVALID_TRSH_BM (0x7 << 8)
|
||||||
|
#define HW_POWER_5VCTRL__VBUSVALID_TRSH_2p9 (0 << 8)
|
||||||
|
#define HW_POWER_5VCTRL__VBUSVALID_TRSH_4V (1 << 8)
|
||||||
|
#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT_BP 12
|
||||||
|
#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT_BM (0x3f << 12)
|
||||||
|
#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__10mA (1 << 12)
|
||||||
|
#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__20mA (1 << 13)
|
||||||
|
#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__50mA (1 << 14)
|
||||||
|
#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__100mA (1 << 15)
|
||||||
|
#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__200mA (1 << 16)
|
||||||
|
#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__400mA (1 << 17)
|
||||||
|
#define HW_POWER_5VCTRL__PWD_CHARGE_4P2 (1 << 20)
|
||||||
|
|
||||||
#define HW_POWER_MINPWR (*(volatile uint32_t *)(HW_POWER_BASE + 0x20))
|
#define HW_POWER_MINPWR (*(volatile uint32_t *)(HW_POWER_BASE + 0x20))
|
||||||
|
|
||||||
#define HW_POWER_CHARGE (*(volatile uint32_t *)(HW_POWER_BASE + 0x30))
|
#define HW_POWER_CHARGE (*(volatile uint32_t *)(HW_POWER_BASE + 0x30))
|
||||||
#define HW_POWER_CHARGE__BATTCHRG_I_BP 0
|
#define HW_POWER_CHARGE__BATTCHRG_I_BP 0
|
||||||
#define HW_POWER_CHARGE__BATTCHRG_I_BM 0x3f
|
#define HW_POWER_CHARGE__BATTCHRG_I_BM 0x3f
|
||||||
|
#define HW_POWER_CHARGE__BATTCHRG_I__10mA (1 << 0)
|
||||||
|
#define HW_POWER_CHARGE__BATTCHRG_I__20mA (1 << 1)
|
||||||
|
#define HW_POWER_CHARGE__BATTCHRG_I__50mA (1 << 2)
|
||||||
|
#define HW_POWER_CHARGE__BATTCHRG_I__100mA (1 << 3)
|
||||||
|
#define HW_POWER_CHARGE__BATTCHRG_I__200mA (1 << 4)
|
||||||
|
#define HW_POWER_CHARGE__BATTCHRG_I__400mA (1 << 5)
|
||||||
#define HW_POWER_CHARGE__STOP_ILIMIT_BP 8
|
#define HW_POWER_CHARGE__STOP_ILIMIT_BP 8
|
||||||
#define HW_POWER_CHARGE__STOP_ILIMIT_BM 0xf00
|
#define HW_POWER_CHARGE__STOP_ILIMIT_BM 0xf00
|
||||||
|
#define HW_POWER_CHARGE__STOP_ILIMIT__10mA (1 << 8)
|
||||||
|
#define HW_POWER_CHARGE__STOP_ILIMIT__20mA (1 << 9)
|
||||||
|
#define HW_POWER_CHARGE__STOP_ILIMIT__50mA (1 << 10)
|
||||||
|
#define HW_POWER_CHARGE__STOP_ILIMIT__100mA (1 << 11)
|
||||||
#define HW_POWER_CHARGE__PWD_BATTCHRG (1 << 16)
|
#define HW_POWER_CHARGE__PWD_BATTCHRG (1 << 16)
|
||||||
#define HW_POWER_CHARGE__CHRG_STS_OFF (1 << 19)
|
#define HW_POWER_CHARGE__CHRG_STS_OFF (1 << 19)
|
||||||
|
#define HW_POWER_CHARGE__ENABLE_LOAD (1 << 22)
|
||||||
|
|
||||||
#define HW_POWER_VDDDCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x40))
|
#define HW_POWER_VDDDCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x40))
|
||||||
#define HW_POWER_VDDDCTRL__TRG_BP 0
|
#define HW_POWER_VDDDCTRL__TRG_BP 0
|
||||||
#define HW_POWER_VDDDCTRL__TRG_BM 0x1f
|
#define HW_POWER_VDDDCTRL__TRG_BM 0x1f
|
||||||
#define HW_POWER_VDDDCTRL__TRG_STEP 25 /* mV */
|
#define HW_POWER_VDDDCTRL__TRG_STEP 25 /* mV */
|
||||||
#define HW_POWER_VDDDCTRL__TRG_MIN 800 /* mV */
|
#define HW_POWER_VDDDCTRL__TRG_MIN 800 /* mV */
|
||||||
|
#define HW_POWER_VDDDCTRL__LINREG_OFFSET_BP 16
|
||||||
|
#define HW_POWER_VDDDCTRL__LINREG_OFFSET_BM (0x3 << 16)
|
||||||
#define HW_POWER_VDDDCTRL__ENABLE_LINREG (1 << 21)
|
#define HW_POWER_VDDDCTRL__ENABLE_LINREG (1 << 21)
|
||||||
|
|
||||||
#define HW_POWER_VDDACTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x50))
|
#define HW_POWER_VDDACTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x50))
|
||||||
|
@ -59,6 +86,8 @@
|
||||||
#define HW_POWER_VDDACTRL__TRG_BM 0x1f
|
#define HW_POWER_VDDACTRL__TRG_BM 0x1f
|
||||||
#define HW_POWER_VDDACTRL__TRG_STEP 25 /* mV */
|
#define HW_POWER_VDDACTRL__TRG_STEP 25 /* mV */
|
||||||
#define HW_POWER_VDDACTRL__TRG_MIN 1500 /* mV */
|
#define HW_POWER_VDDACTRL__TRG_MIN 1500 /* mV */
|
||||||
|
#define HW_POWER_VDDACTRL__LINREG_OFFSET_BP 12
|
||||||
|
#define HW_POWER_VDDACTRL__LINREG_OFFSET_BM (0x3 << 12)
|
||||||
#define HW_POWER_VDDACTRL__ENABLE_LINREG (1 << 17)
|
#define HW_POWER_VDDACTRL__ENABLE_LINREG (1 << 17)
|
||||||
|
|
||||||
#define HW_POWER_VDDIOCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x60))
|
#define HW_POWER_VDDIOCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x60))
|
||||||
|
@ -66,6 +95,8 @@
|
||||||
#define HW_POWER_VDDIOCTRL__TRG_BM 0x1f
|
#define HW_POWER_VDDIOCTRL__TRG_BM 0x1f
|
||||||
#define HW_POWER_VDDIOCTRL__TRG_STEP 25 /* mV */
|
#define HW_POWER_VDDIOCTRL__TRG_STEP 25 /* mV */
|
||||||
#define HW_POWER_VDDIOCTRL__TRG_MIN 2800 /* mV */
|
#define HW_POWER_VDDIOCTRL__TRG_MIN 2800 /* mV */
|
||||||
|
#define HW_POWER_VDDIOCTRL__LINREG_OFFSET_BP 12
|
||||||
|
#define HW_POWER_VDDIOCTRL__LINREG_OFFSET_BM (0x3 << 12)
|
||||||
|
|
||||||
#define HW_POWER_VDDMEMCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x70))
|
#define HW_POWER_VDDMEMCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x70))
|
||||||
#define HW_POWER_VDDMEMCTRL__TRG_BP 0
|
#define HW_POWER_VDDMEMCTRL__TRG_BP 0
|
||||||
|
@ -74,6 +105,17 @@
|
||||||
#define HW_POWER_VDDMEMCTRL__TRG_MIN 1700 /* mV */
|
#define HW_POWER_VDDMEMCTRL__TRG_MIN 1700 /* mV */
|
||||||
#define HW_POWER_VDDMEMCTRL__ENABLE_LINREG (1 << 8)
|
#define HW_POWER_VDDMEMCTRL__ENABLE_LINREG (1 << 8)
|
||||||
|
|
||||||
|
#define HW_POWER_DCDC4P2 (*(volatile uint32_t *)(HW_POWER_BASE + 0x80))
|
||||||
|
#define HW_POWER_DCDC4P2__CMPTRIP_BP 0
|
||||||
|
#define HW_POWER_DCDC4P2__CMPTRIP_BM 0x1f
|
||||||
|
#define HW_POWER_DCDC4P2__CMPTRIP__0p85 0
|
||||||
|
#define HW_POWER_DCDC4P2__ENABLE_DCDC (1 << 22)
|
||||||
|
#define HW_POWER_DCDC4P2__ENABLE_4P2 (1 << 23)
|
||||||
|
#define HW_POWER_DCDC4P2__DROPOUT_CTRL_BP 28
|
||||||
|
#define HW_POWER_DCDC4P2__DROPOUT_CTRL_BM (0xf << 28)
|
||||||
|
#define HW_POWER_DCDC4P2__DROPOUT_CTRL__200mV (3 << 30)
|
||||||
|
#define HW_POWER_DCDC4P2__DROPOUT_CTRL__HIGHER (2 << 28)
|
||||||
|
|
||||||
#define HW_POWER_MISC (*(volatile uint32_t *)(HW_POWER_BASE + 0x90))
|
#define HW_POWER_MISC (*(volatile uint32_t *)(HW_POWER_BASE + 0x90))
|
||||||
#define HW_POWER_MISC__SEL_PLLCLK 1
|
#define HW_POWER_MISC__SEL_PLLCLK 1
|
||||||
#define HW_POWER_MISC__FREQSEL_BP 4
|
#define HW_POWER_MISC__FREQSEL_BP 4
|
||||||
|
@ -89,10 +131,12 @@
|
||||||
|
|
||||||
#define HW_POWER_STS (*(volatile uint32_t *)(HW_POWER_BASE + 0xc0))
|
#define HW_POWER_STS (*(volatile uint32_t *)(HW_POWER_BASE + 0xc0))
|
||||||
#define HW_POWER_STS__VBUSVALID (1 << 1)
|
#define HW_POWER_STS__VBUSVALID (1 << 1)
|
||||||
|
#define HW_POWER_STS__CHRGSTS (1 << 11)
|
||||||
#define HW_POWER_STS__PSWITCH_BP 20
|
#define HW_POWER_STS__PSWITCH_BP 20
|
||||||
#define HW_POWER_STS__PSWITCH_BM (3 << 20)
|
#define HW_POWER_STS__PSWITCH_BM (3 << 20)
|
||||||
|
|
||||||
#define HW_POWER_BATTMONITOR (*(volatile uint32_t *)(HW_POWER_BASE + 0xe0))
|
#define HW_POWER_BATTMONITOR (*(volatile uint32_t *)(HW_POWER_BASE + 0xe0))
|
||||||
|
#define HW_POWER_BATTMONITOR__ENBATADJ (1 << 10)
|
||||||
#define HW_POWER_BATTMONITOR__BATT_VAL_BP 16
|
#define HW_POWER_BATTMONITOR__BATT_VAL_BP 16
|
||||||
#define HW_POWER_BATTMONITOR__BATT_VAL_BM (0x3ff << 16)
|
#define HW_POWER_BATTMONITOR__BATT_VAL_BM (0x3ff << 16)
|
||||||
|
|
||||||
|
@ -100,17 +144,39 @@
|
||||||
#define HW_POWER_RESET__UNLOCK 0x3E770000
|
#define HW_POWER_RESET__UNLOCK 0x3E770000
|
||||||
#define HW_POWER_RESET__PWD 0x1
|
#define HW_POWER_RESET__PWD 0x1
|
||||||
|
|
||||||
|
void imx233_power_set_charge_current(unsigned current); /* in mA */
|
||||||
|
void imx233_power_set_stop_current(unsigned current); /* in mA */
|
||||||
|
void imx233_power_enable_batadj(bool enable);
|
||||||
|
|
||||||
struct imx233_power_info_t
|
struct imx233_power_info_t
|
||||||
{
|
{
|
||||||
int vddd; /* in mV */
|
int vddd; /* in mV */
|
||||||
bool vddd_linreg; /* VDDD source: linreg from VDDA or DC-DC */
|
bool vddd_linreg; /* VDDD source: linreg from VDDA or DC-DC */
|
||||||
|
int vddd_linreg_offset;
|
||||||
int vdda; /* in mV */
|
int vdda; /* in mV */
|
||||||
bool vdda_linreg; /* VDDA source: linreg from VDDIO or DC-DC */
|
bool vdda_linreg; /* VDDA source: linreg from VDDIO or DC-DC */
|
||||||
|
int vdda_linreg_offset;
|
||||||
int vddio; /* in mV */
|
int vddio; /* in mV */
|
||||||
|
int vddio_linreg_offset;
|
||||||
int vddmem; /* in mV */
|
int vddmem; /* in mV */
|
||||||
bool vddmem_linreg; /* VDDMEM source: linreg from VDDIO or off */
|
bool vddmem_linreg; /* VDDMEM source: linreg from VDDIO or off */
|
||||||
bool dcdc_sel_pllclk; /* clock source of DC-DC: pll or 24MHz xtal */
|
bool dcdc_sel_pllclk; /* clock source of DC-DC: pll or 24MHz xtal */
|
||||||
int dcdc_freqsel;
|
int dcdc_freqsel;
|
||||||
|
int charge_current;
|
||||||
|
int stop_current;
|
||||||
|
bool charging;
|
||||||
|
bool batt_adj;
|
||||||
|
bool _4p2_enable;
|
||||||
|
bool _4p2_dcdc;
|
||||||
|
int _4p2_cmptrip;
|
||||||
|
int _4p2_dropout;
|
||||||
|
bool _5v_pwd_charge_4p2;
|
||||||
|
int _5v_charge_4p2_limit;
|
||||||
|
bool _5v_dcdc_xfer;
|
||||||
|
bool _5v_enable_dcdc;
|
||||||
|
int _5v_vbusvalid_thr;
|
||||||
|
bool _5v_vbusvalid_detect;
|
||||||
|
bool _5v_vbus_cmps;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define POWER_INFO_VDDD (1 << 0)
|
#define POWER_INFO_VDDD (1 << 0)
|
||||||
|
@ -118,7 +184,10 @@ struct imx233_power_info_t
|
||||||
#define POWER_INFO_VDDIO (1 << 2)
|
#define POWER_INFO_VDDIO (1 << 2)
|
||||||
#define POWER_INFO_VDDMEM (1 << 3)
|
#define POWER_INFO_VDDMEM (1 << 3)
|
||||||
#define POWER_INFO_DCDC (1 << 4)
|
#define POWER_INFO_DCDC (1 << 4)
|
||||||
#define POWER_INFO_ALL 0x1f
|
#define POWER_INFO_CHARGE (1 << 5)
|
||||||
|
#define POWER_INFO_4P2 (1 << 6)
|
||||||
|
#define POWER_INFO_5V (1 << 7)
|
||||||
|
#define POWER_INFO_ALL 0xff
|
||||||
|
|
||||||
struct imx233_power_info_t imx233_power_get_info(unsigned flags);
|
struct imx233_power_info_t imx233_power_get_info(unsigned flags);
|
||||||
|
|
||||||
|
|
|
@ -21,30 +21,21 @@
|
||||||
|
|
||||||
#include "powermgmt.h"
|
#include "powermgmt.h"
|
||||||
#include "power-imx233.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] =
|
#if !defined(IMX233_CHARGE_CURRENT) || !defined(IMX233_STOP_CURRENT) \
|
||||||
{
|
|| !defined(IMX233_CHARGING_TIMEOUT) || !defined(IMX233_TOPOFF_TIMEOUT)
|
||||||
3659
|
#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] =
|
/* charger state is maintained in charge_state (see powermgmt.h) */
|
||||||
{
|
static int timeout_charging; /* timeout before charging will be declared broken */
|
||||||
3630
|
static int timeout_topping_off; /* timeout before stopping charging after topping off */
|
||||||
};
|
static int timeout_4p2_ilimit_increase; /* timeout before increasing 4p2 ilimit */
|
||||||
|
|
||||||
/* 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
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Returns battery voltage from ADC [millivolts] */
|
/* Returns battery voltage from ADC [millivolts] */
|
||||||
unsigned int battery_adc_voltage(void)
|
unsigned int battery_adc_voltage(void)
|
||||||
|
@ -55,12 +46,115 @@ unsigned int battery_adc_voltage(void)
|
||||||
|
|
||||||
void powermgmt_init_target(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)
|
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)
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 by Amaury Pouly
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
#include "config.h"
|
||||||
|
#include "powermgmt-target.h"
|
||||||
|
|
||||||
|
const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
|
||||||
|
{
|
||||||
|
3659
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
|
@ -22,9 +22,27 @@
|
||||||
#define POWERMGMT_TARGET_H
|
#define POWERMGMT_TARGET_H
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "powermgmt-imx233.h"
|
||||||
|
|
||||||
void powermgmt_init_target(void);
|
/* Fuze+ OF settings:
|
||||||
void charging_algorithm_step(void);
|
* - current ramp slope: 50 mA/s
|
||||||
void charging_algorithm_close(void);
|
* - conditioning threshold voltage: 3 V
|
||||||
|
* - conditioning max voltage: 3.1 V
|
||||||
|
* - conditioning current: 60 mA
|
||||||
|
* - conditioning timeout: 1 h
|
||||||
|
* - charging voltage: 4.2 V
|
||||||
|
* - charging current: 200 mA
|
||||||
|
* - charging threshold current: 30 mA
|
||||||
|
* - charging timeout: 4 h
|
||||||
|
* - top off period: 30 min
|
||||||
|
* - high die temperature: 71 °C
|
||||||
|
* - low die temperature: 56 °C
|
||||||
|
* - safe temperature current: 30 mA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IMX233_CHARGE_CURRENT 200
|
||||||
|
#define IMX233_STOP_CURRENT 30
|
||||||
|
#define IMX233_TOPOFF_TIMEOUT (30 * 60 * HZ)
|
||||||
|
#define IMX233_CHARGING_TIMEOUT (4 * 3600 * HZ)
|
||||||
|
|
||||||
#endif /* POWERMGMT_TARGET_H */
|
#endif /* POWERMGMT_TARGET_H */
|
Loading…
Add table
Add a link
Reference in a new issue