459 lines
16 KiB
C
459 lines
16 KiB
C
/*-----------------------------------------------------------------------------------------------------------------
|
|
dm_charge.c
|
|
This file implements the demo that ONLY illustrates the procedure that monitor charging to battery.
|
|
This demo call function that is not defined in ningbo.c/guilin.c.etc, but defined in ningbo_dm.c/guilin_dm.c.etc
|
|
Customer could directly use this demo to monitor charging procedure, OR overwrite this demo and call function
|
|
that is defined in ningbo.c/guilin.c.etc to adapt customer's charging procedure
|
|
|
|
Note:
|
|
1.For ningbo, too large capacity(exceed 2000mAh~3000mAh) of battery is NOT recommended to use, due to cccv timer(
|
|
90/144/192/240min) and max current setting(1000mA), which cause that battery cannot be charge full.
|
|
If customer thinks that it's necessary to use large capacity of battery, customer need to reset cccv timer in
|
|
some proper ponit during charging procedure by force to change FSM, to avoid to entry Fault status(FSM) due to
|
|
expire of cccv timer.
|
|
-------------------------------------------------------------------------------------------------------------------*/
|
|
#include "dm_i2c.h"
|
|
#include "dm_charge.h"
|
|
|
|
#define chargeManagerPrintf(fmt, args...) do { uart_printf("[chargeManager]"fmt"\r\n", ##args); } while(0)
|
|
|
|
static BOOL charging = FALSE;
|
|
//map : family -- name
|
|
// GUILIN -- guilin
|
|
// PM812 -- pm812
|
|
// NINGBO -- ningbo
|
|
static char *pmicName[8] = {"guilin", "pm812", "ningbo"};
|
|
/** support 8 power manage ic **/
|
|
struct chargeManagerT chargeManager[8] = {0};
|
|
|
|
static BOOL batteryConnectCheck(UINT8 index)
|
|
{
|
|
if (chargeManager[index].batteryConnectCheck) {
|
|
return chargeManager[index].batteryConnectCheck();
|
|
} else {
|
|
chargeManagerPrintf("batteryConnectCheck func is NULL, pmicName %s", pmicName[index]);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static BOOL usbConnectCheck(UINT8 index)
|
|
{
|
|
if (chargeManager[index].usbConnectCheck) {
|
|
return chargeManager[index].usbConnectCheck();
|
|
} else {
|
|
chargeManagerPrintf("usbConnectCheck func is NULL, pmicName %s", pmicName[index]);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static enum powerUpTypeE wakeUpCheck(UINT8 index, BOOL batConnectState)
|
|
{
|
|
if (chargeManager[index].wakeUpCheck) {
|
|
return chargeManager[index].wakeUpCheck(batConnectState);
|
|
} else {
|
|
chargeManagerPrintf("wakeUpCheck func is NULL, pmicName %s", pmicName[index]);
|
|
return PowerUP_Unkown;
|
|
}
|
|
}
|
|
|
|
static BOOL powerOnKeyCheck(UINT8 index, UINT8 timeOutValue)
|
|
{
|
|
if (chargeManager[index].powerOnKeyCheck) {
|
|
return chargeManager[index].powerOnKeyCheck(timeOutValue);
|
|
} else {
|
|
chargeManagerPrintf("powerOnKeyCheck func is NULL, pmicName %s", pmicName[index]);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static UINT16 batInstantVoltGet(UINT8 index, BOOL usbStatus)
|
|
{
|
|
if (chargeManager[index].batInstantVoltGet) {
|
|
return chargeManager[index].batInstantVoltGet(usbStatus);
|
|
} else {
|
|
chargeManagerPrintf("batInstantVoltGet func is NULL, pmicName %s", pmicName[index]);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static UINT16 batStableVoltGet(UINT8 index, UINT8 *pPercent)
|
|
{
|
|
if (chargeManager[index].batStableVoltGet) {
|
|
return chargeManager[index].batStableVoltGet(pPercent);
|
|
} else {
|
|
chargeManagerPrintf("batStableVoltGet func is NULL, pmicName %s", pmicName[index]);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static void systemPowerOff(UINT8 index)
|
|
{
|
|
if (chargeManager[index].systemPowerOff) {
|
|
chargeManager[index].systemPowerOff();
|
|
} else {
|
|
chargeManagerPrintf("systemPowerOff func is NULL, pmicName %s", pmicName[index]);
|
|
}
|
|
}
|
|
|
|
static BOOL chargerFull(UINT8 index)
|
|
{
|
|
if (chargeManager[index].chargerFull) {
|
|
return (chargeManager[index].chargerFull());
|
|
} else {
|
|
chargeManagerPrintf("chargerFull func is NULL, pmicName %s", pmicName[index]);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static BOOL chargerCC(UINT8 index)
|
|
{
|
|
if (chargeManager[index].chargerCC) {
|
|
return (chargeManager[index].chargerCC());
|
|
} else {
|
|
chargeManagerPrintf("chargerCC func is NULL, pmicName %s", pmicName[index]);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static BOOL setMPP(UINT8 index, UINT16 limit)
|
|
{
|
|
if (chargeManager[index].setMPP) {
|
|
return (chargeManager[index].setMPP(limit));
|
|
} else {
|
|
chargeManagerPrintf("setMPP func is NULL, pmicName %s", pmicName[index]);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static BOOL getChargeStatus(UINT8 index)
|
|
{
|
|
if (chargeManager[index].getChargeStatus) {
|
|
return (chargeManager[index].getChargeStatus());
|
|
} else {
|
|
chargeManagerPrintf("getChargeStatus func is NULL, pmicName %s", pmicName[index]);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static UINT32 getChargeCurrent(UINT8 index)
|
|
{
|
|
if (chargeManager[index].getChargeCurrent) {
|
|
return (chargeManager[index].getChargeCurrent());
|
|
} else {
|
|
chargeManagerPrintf("getChargeCurrent func is NULL, pmicName %s", pmicName[index]);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static void closeCharge(UINT8 index)
|
|
{
|
|
if (chargeManager[index].closeCharge) {
|
|
chargeManager[index].closeCharge();
|
|
} else {
|
|
chargeManagerPrintf("closeCharge func is NULL, pmicName %s", pmicName[index]);
|
|
}
|
|
}
|
|
|
|
static void openCharge(UINT8 index)
|
|
{
|
|
if (chargeManager[index].openCharge) {
|
|
chargeManager[index].openCharge();
|
|
} else {
|
|
chargeManagerPrintf("openCharge func is NULL, pmicName %s", pmicName[index]);
|
|
}
|
|
}
|
|
|
|
// handle charger abnormal that can defer, eg:abnormal that shutdown charge due to high temperature
|
|
// this type of abnormal is periodically handled, because they can defer.
|
|
static void handleChargerAbnormal(UINT8 index)
|
|
{
|
|
if (chargeManager[index].handleChargerAbnormal) {
|
|
chargeManager[index].handleChargerAbnormal();
|
|
} else {
|
|
chargeManagerPrintf("handleChargerAbnormal func is NULL, pmicName %s", pmicName[index]);
|
|
}
|
|
}
|
|
|
|
static UINT8 chargeICIDGet(void)
|
|
{
|
|
UINT8 i = 0, regVal;
|
|
|
|
for (i = 0; i < sizeof(chargeManager)/sizeof(struct chargeManagerT); i++) {
|
|
if ((chargeManager[i].chargeICIDGet != NULL) && ((chargeManager[i].chargeICIDGet() & 0xF0) >> 4 == chargeManager[i].id)) {
|
|
regVal = chargeManager[i].id;
|
|
chargeManagerPrintf("pmicId : %x", regVal);
|
|
}
|
|
}
|
|
|
|
return regVal;
|
|
}
|
|
|
|
static BOOL chargeICSubIDGet(void) // sub id for ningbo: A1 A3
|
|
{
|
|
UINT8 i = 0, regVal;
|
|
|
|
for (i = 0; i < sizeof(chargeManager)/sizeof(struct chargeManagerT); i++) {
|
|
if ((chargeManager[i].subId != 0)
|
|
&& (chargeManager[i].chargeICIDGet != NULL)
|
|
&& ((regVal = (chargeManager[i].chargeICIDGet())) == chargeManager[i].subId)) {
|
|
break;
|
|
}
|
|
}
|
|
chargeManagerPrintf("pmicSubId : %x", regVal);
|
|
return regVal;
|
|
}
|
|
|
|
static BOOL checkPowerOnOrPowerOff(UINT8 index)
|
|
{
|
|
/*
|
|
* 1, the charger/USB might not be plugged out after the battery is full charged,
|
|
* and the charger/USB is wakeup source, if OBM power down the system after
|
|
* full charged, it will wake up the system again...
|
|
*
|
|
* 2, if the charge function is disabled after full charged, the system power will
|
|
* be supplied from battery, it's not acceptable since the battery power will be
|
|
* exhausted...
|
|
*
|
|
* 3, the charger/USB can supply power to system too, and the charge function uses
|
|
* the same HW line connection as power supply function on Nezha LET MIFI 2.0,
|
|
* so, OBM will keep charge function, and let the charger/USB supply the system power.
|
|
*/
|
|
chargeManagerPrintf("charging is done!");
|
|
|
|
while (1) {
|
|
/*
|
|
* Normal power supply of USB/charger is controlled by the host with the t32s timer
|
|
* running to ensure that the host is alive. When the timer times out, the power
|
|
* supply is terminated.
|
|
*/
|
|
// resetTimer();
|
|
|
|
if (powerOnKeyCheck(index, 3)) {
|
|
chargeManagerPrintf("onkey pressed, boot");
|
|
return TRUE;
|
|
}
|
|
|
|
if (!usbConnectCheck(index)) {
|
|
chargeManagerPrintf("charger is plugged out!");
|
|
systemPowerOff(index);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void batteryCharge(UINT8 index)
|
|
{
|
|
UINT16 vBat;
|
|
UINT32 chargeCurrent;
|
|
BOOL batConnectState, usbConnectState, chargerSkipped = FALSE, mpptDone = FALSE;
|
|
|
|
uudelay(1000 * 100);
|
|
|
|
while (!chargerSkipped) {
|
|
batConnectState = batteryConnectCheck(index);
|
|
// batConnectState = TRUE;
|
|
usbConnectState = usbConnectCheck(index);
|
|
vBat = batInstantVoltGet(index, usbConnectState);
|
|
chargeManagerPrintf("vBat : %d", vBat);
|
|
chargeCurrent = getChargeCurrent(index);
|
|
chargeManagerPrintf("chargeCurrent : %d", chargeCurrent);
|
|
|
|
// periodically handle charger abnormal
|
|
handleChargerAbnormal(index);
|
|
|
|
// if USB is not connectted when charge is in process, power down system
|
|
if (usbConnectState) {
|
|
if (batConnectState) {
|
|
charging = TRUE;
|
|
if (vBat < Battery_Low_Voltage) {
|
|
/*
|
|
* System is forbidden to boot up if battery voltage is lower than power up voltage,
|
|
* it has to wait for OBM charging battery to enough voltage
|
|
*/
|
|
chargeManagerPrintf("battery low voltage");
|
|
|
|
if (!mpptDone && chargerCC(index)) {
|
|
if (setMPP(index, 1000)) {
|
|
mpptDone = TRUE;
|
|
}
|
|
}
|
|
|
|
if (getChargeStatus(index)) { // do mmpt when vbus re_plug, ov or uv
|
|
setMPP(index, 1000);
|
|
}
|
|
|
|
uudelay(1000 * 1000);
|
|
continue;
|
|
} else {
|
|
if (!(chargerFull(index))) {
|
|
/*
|
|
* Battery voltage is enough for system requirement, and system is permitted to boot up
|
|
* if ONKey press longer than 3s
|
|
*/
|
|
chargeManagerPrintf("battery not full, please long press onKey to wakeup");
|
|
if (!mpptDone && chargerCC(index)) {
|
|
if (setMPP(index, 1000)) {
|
|
mpptDone = TRUE;
|
|
}
|
|
}
|
|
|
|
if (getChargeStatus(index)) { // do mmpt when vbus re_plug, ov or uv
|
|
setMPP(index, 1000);
|
|
}
|
|
|
|
chargerSkipped = powerOnKeyCheck(index, 3);
|
|
} else {
|
|
// Once the battery is charged full, no charge any more, check if boot and if power off
|
|
chargeManagerPrintf("battery full, please long press onKey to wakeup");
|
|
chargerSkipped = checkPowerOnOrPowerOff(index);
|
|
}
|
|
uudelay(1000 * 1000);
|
|
}
|
|
} else {
|
|
chargerSkipped = TRUE;
|
|
chargeManagerPrintf("battery is plugged out!");
|
|
}
|
|
} else {
|
|
chargeManagerPrintf("charger is plugged out!");
|
|
if (charging) {
|
|
systemPowerOff(index);
|
|
} else {
|
|
if (vBat >= Battery_Low_Voltage) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (chargerSkipped) {
|
|
continue;
|
|
}
|
|
|
|
uudelay(1000 * 100);
|
|
}
|
|
}
|
|
|
|
static void chargeProcess(UINT8 index)
|
|
{
|
|
UINT16 vBat;
|
|
BOOL batConnectState, usbConnectState;
|
|
enum powerUpTypeE powerUpType = PowerUP_Unkown;
|
|
|
|
mdelay(10);
|
|
batConnectState = batteryConnectCheck(index); // no implement in status register 1
|
|
// batConnectState = TRUE;
|
|
chargeManagerPrintf("batConnectState %d", batConnectState);
|
|
usbConnectState = usbConnectCheck(index);
|
|
chargeManagerPrintf("usbConnectState %d", usbConnectState);
|
|
powerUpType = wakeUpCheck(index, batConnectState);
|
|
chargeManagerPrintf("powerUpType %d", powerUpType);
|
|
vBat = batInstantVoltGet(index, usbConnectState);
|
|
|
|
if (batConnectState) {
|
|
if (powerUpType == PowerUP_Battery) {
|
|
if (vBat < Battery_Low_Voltage) {
|
|
systemPowerOff(index);
|
|
}
|
|
chargeManagerPrintf("powerOn that is woken up by battery");
|
|
} else if (powerUpType == PowerUP_ONKEY) {
|
|
if (vBat < Battery_Low_Voltage) {
|
|
if (!usbConnectState) {
|
|
systemPowerOff(index);
|
|
}
|
|
chargeManagerPrintf("powerOn that is woken up by onKey on usb");
|
|
} else {
|
|
if (powerOnKeyCheck(index, 3)) {
|
|
chargeManagerPrintf("powerOn that is woken up by onKey on battery or usb");
|
|
return;
|
|
}
|
|
}
|
|
} else if (powerUpType == PowerUP_USB) {
|
|
if (!usbConnectState) {
|
|
if (vBat < Battery_Low_Voltage) {
|
|
systemPowerOff(index);
|
|
}
|
|
chargeManagerPrintf("powerOn that is woken up by usb on battery");
|
|
} else {
|
|
chargeManagerPrintf("powerOn that is woken up by usb");
|
|
}
|
|
} else {
|
|
chargeManagerPrintf("invalid resource which wakeup pmic");
|
|
}
|
|
|
|
charging = FALSE;
|
|
batteryCharge(index);
|
|
} else {
|
|
if (powerUpType == PowerUP_Battery) {
|
|
systemPowerOff(index); // can go here (powerup by battery and battery disconnect) ??
|
|
} else if (powerUpType == PowerUP_ONKEY) {
|
|
if (!usbConnectState) {
|
|
systemPowerOff(index);
|
|
} else {
|
|
if (powerOnKeyCheck(index, 3)) {
|
|
chargeManagerPrintf("powerOn that is woken up by onKey on usb");
|
|
} else {
|
|
systemPowerOff(index);
|
|
}
|
|
}
|
|
} else if (powerUpType == PowerUP_USB) {
|
|
if (!usbConnectState) {
|
|
systemPowerOff(index); // can go here (powerup by usb and usb disconnect) ??
|
|
}
|
|
chargeManagerPrintf("powerOn that is woken up by usb");
|
|
} else {
|
|
chargeManagerPrintf("invalid resource which wakeup pmic");
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void guiLinICRegister(void);
|
|
extern void pm812ICRegister(void);
|
|
extern void ningBoICRegister(void);
|
|
|
|
static void chargeICRegister(void)
|
|
{
|
|
// guiLinICRegister();
|
|
// pm812ICRegister();
|
|
ningBoICRegister();
|
|
}
|
|
|
|
void DM_CHARGE_Manager(void)
|
|
{
|
|
UINT8 i = 0;
|
|
UINT8 chargeICIndex = 0;
|
|
BOOL initDone = FALSE;
|
|
|
|
chargeICRegister();
|
|
|
|
// i2cInit(); // init is done in pmic.c, so donot init again
|
|
|
|
UINT8 chargeICID = chargeICIDGet();
|
|
UINT8 chargeICSubID = chargeICSubIDGet();
|
|
|
|
for (i = 0; i < sizeof(chargeManager)/sizeof(struct chargeManagerT); i++) {
|
|
if (chargeManager[i].id == chargeICID) {
|
|
if (chargeManager[i].subId != 0) {
|
|
if (chargeManager[i].subId == chargeICSubID) {
|
|
if (chargeManager[i].init != NULL) {
|
|
chargeManager[i].init();
|
|
initDone = TRUE;
|
|
chargeICIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
if (chargeManager[i].init != NULL) {
|
|
chargeManager[i].init();
|
|
chargeICIndex = i;
|
|
initDone = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (initDone) {
|
|
chargeProcess(chargeICIndex);
|
|
} else {
|
|
chargeManagerPrintf("charge init failed");
|
|
}
|
|
}
|