diff options
Diffstat (limited to 'drivers/power/wmt_battery/gauge/ug31xx/uG31xx_API.c')
-rwxr-xr-x | drivers/power/wmt_battery/gauge/ug31xx/uG31xx_API.c | 2307 |
1 files changed, 2307 insertions, 0 deletions
diff --git a/drivers/power/wmt_battery/gauge/ug31xx/uG31xx_API.c b/drivers/power/wmt_battery/gauge/ug31xx/uG31xx_API.c new file mode 100755 index 00000000..e4752190 --- /dev/null +++ b/drivers/power/wmt_battery/gauge/ug31xx/uG31xx_API.c @@ -0,0 +1,2307 @@ +/// ===========================================
+/// uG31xx_API.cpp
+/// ===========================================
+
+#include "stdafx.h" //windows need this??
+#include "uG31xx_API.h"
+
+static _upi_bool_ Ug31DebugEnable;
+static _upi_s32_ dsg_charge_before_suspend;
+static _upi_s32_ delta_cap_during_suspend;
+static _upi_u8_ wakeup_predict_rsoc;
+static _upi_u8_ fix_et_at_initial_cnt;
+#if defined (uG31xx_OS_WINDOWS)
+
+ #ifdef DEBUG_LOG
+
+ unsigned int debugViewLines = 0;
+ CString debugViewFileName = _T("uG3100-1");
+ CString BackupFile;
+
+ #endif
+
+#elif defined (uG31xx_OS_ANDROID)
+
+ _upi_u32_ GetTickCount(void)
+ {
+ return jiffies_to_msecs(jiffies); //20121121/jacky
+ }
+
+ _upi_u32_ GetSysTickCount(void)
+ {
+
+ struct timeval current_tick;
+
+ do_gettimeofday(¤t_tick);
+
+ return current_tick.tv_sec * 1000 + current_tick.tv_usec/1000;
+ }
+
+#endif
+
+#if defined(uG31xx_OS_ANDROID)
+
+ int ug31_printk(int level, const char *fmt, ...)
+ {
+ #ifdef UG31XX_DEBUG_ENABLE
+ va_list args;
+ int r;
+
+ r = 0;
+ if(Ug31DebugEnable == _UPI_TRUE_)
+ {
+ va_start(args, fmt);
+ r = vprintk(fmt, args);
+ va_end(args);
+ }
+ return (r);
+ #else ///< else of UG31XX_DEBUG_ENABLE
+ return (0);
+ #endif ///< end of UG31XX_DEBUG_ENABLE
+ }
+
+#endif ///< end of defined(uG31xx_OS_ANDROID)
+
+
+
+/// ===========================================
+/// uG31xx_API.cpp (VAR)
+/// ===========================================
+
+
+/* uPI ug31xx hardware control interface */
+struct ug31xx_data {
+
+ /// [AT-PM] : Following variables are used for uG31xx operation ; 11/01/2012
+ _upi_u8_ totalCellNums;
+ _upi_bool_ bFirstData;
+
+ // Global variable
+ CELL_TABLE cellTable; // data from .GGB file
+ CELL_PARAMETER cellParameter; // data from .GGB file
+ GG_BATTERY_INFO batteryInfo;
+ GG_DEVICE_INFO deviceInfo;
+ GG_USER_REG userReg; //user register 0x00 ~0x10
+ GG_USER2_REG user2Reg; //user register 0x40 ~0x4f
+ GG_TI_BQ27520 bq27520Cmd;
+
+ OtpDataType otpData;
+ MeasDataType measData;
+ CapacityDataType capData;
+ SystemDataType sysData;
+ BackupDataType backupData;
+
+ _upi_u8_ EncriptTableStatus;
+ _upi_u16_ PreviousITAve;
+};
+
+/// ===========================================
+/// End of uG31xx_API.cpp (VAR)
+/// ===========================================
+
+/**
+ * @brief upiGG_GetAlarmStatus
+ *
+ * Get alarm status
+ *
+ * @para pAlarmStatus address of alarm status
+ * @return UG_READ_DEVICE_ALARM_SUCCESS if success
+ */
+GGSTATUS upiGG_GetAlarmStatus(char *pObj, _upi_u8_ *pAlarmStatus)
+{
+ struct ug31xx_data *pUg31xx;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+
+ UpiMeasAlarmThreshold(&pUg31xx->measData);
+ *pAlarmStatus = UpiAlarmStatus(&pUg31xx->sysData);
+
+ pUg31xx->userReg.regAlarm1Status = (_upi_u8_)(pUg31xx->sysData.alarmSts & 0x00ff);
+ pUg31xx->userReg.regAlarm2Status = (_upi_u8_)(pUg31xx->sysData.alarmSts >> 8);
+
+ return (UG_READ_DEVICE_ALARM_SUCCESS);
+}
+
+// Read GG_USER_REG from device to global variable and output
+GGSTATUS upiGG_ReadAllRegister(char *pObj, GG_USER_REG* pUserReg, GG_USER2_REG* pUser2Reg)
+{
+ struct ug31xx_data *pUg31xx;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+
+ if(!API_I2C_Read(NORMAL,
+ UG31XX_I2C_HIGH_SPEED_MODE,
+ UG31XX_I2C_TEM_BITS_MODE,
+ REG_MODE,
+ sizeof(GG_USER_REG),
+ &pUg31xx->userReg.regMode))
+ {
+ return (UG_READ_REG_FAIL);
+ }
+ if(!API_I2C_Read(NORMAL,
+ UG31XX_I2C_HIGH_SPEED_MODE,
+ UG31XX_I2C_TEM_BITS_MODE,
+ REG_VBAT2_LOW,
+ sizeof(GG_USER2_REG),
+ (_upi_u8_* )&pUg31xx->user2Reg.regVbat2)) //read
+ {
+ return (UG_READ_REG_FAIL);
+ }
+
+ return (UG_READ_REG_SUCCESS);
+}
+
+// 07/04/1022/Jacky
+_upi_u16_ CalculateVoltageFromUserReg(struct ug31xx_data *pUg31xx, _upi_s16_ voltageAdcCode, _upi_s16_ curr, _upi_u16_ offsetR, _upi_u16_ deltaR)
+{
+ _upi_u16_ voltage_return;
+
+ voltage_return = (_upi_u16_)voltageAdcCode;
+ if(curr < 0) {
+ voltage_return = voltage_return + offsetR*abs(curr)/1000 + deltaR;
+ } else{
+ voltage_return = voltage_return - offsetR*abs(curr)/1000 + deltaR;
+ }
+ return (voltage_return);
+}
+
+// Read GG_USER_REG from device and calculate GG_DEVICE_INFO, then write to global variable and output
+// TODO: offsetR and deltaR will input from .GGB in the future modify
+GGSTATUS upiGG_ReadDeviceInfo(char *pObj, GG_DEVICE_INFO* pExtDeviceInfo)
+{
+ // Get current user register data
+ GGSTATUS status = UG_READ_DEVICE_INFO_SUCCESS;
+ struct ug31xx_data *pUg31xx;
+ _upi_s32_ tmp;
+ MEAS_RTN_CODE rtn;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+
+ if(!API_I2C_Read(NORMAL,
+ UG31XX_I2C_HIGH_SPEED_MODE,
+ UG31XX_I2C_TEM_BITS_MODE,
+ REG_MODE,
+ REG_AVE_RID_HIGH - REG_MODE + 1,
+ &pUg31xx->userReg.regMode))
+ {
+ status = UG_READ_ADC_FAIL;
+ }
+ else
+ {
+ if(!API_I2C_Read(NORMAL,
+ UG31XX_I2C_HIGH_SPEED_MODE,
+ UG31XX_I2C_TEM_BITS_MODE,
+ REG_INTR_STATUS,
+ REG_CTRL2 - REG_INTR_STATUS + 1,
+ &pUg31xx->userReg.regIntrStatus))
+ {
+ status = UG_READ_ADC_FAIL;
+ }
+ else
+ {
+ if(!API_I2C_Read(NORMAL,
+ UG31XX_I2C_HIGH_SPEED_MODE,
+ UG31XX_I2C_TEM_BITS_MODE,
+ REG_VBAT2_LOW,
+ sizeof(GG_USER2_REG),
+ (_upi_u8_* )&pUg31xx->user2Reg.regVbat2)) //read
+ {
+ status = UG_READ_ADC_FAIL;
+ }
+ }
+ }
+
+ /// [AT-PM] : Check IT AVE code, which should be continuous ; 12/28/2012
+ if(pUg31xx->PreviousITAve != 0)
+ {
+ tmp = (_upi_s32_)pUg31xx->PreviousITAve;
+ tmp = tmp - pUg31xx->userReg.regITAve;
+ if((tmp > 1000) || (tmp < -1000))
+ {
+ #ifdef DEBUG_LOG
+ wDebug::LOGE(debugViewFileName.GetBuffer(),debugViewLines++,_T("[%s]: IT AVE Code abnormal -> %d/%d"),
+ _L(__FUNCTION__), pUg31xx->userReg.regITAve, pUg31xx->PreviousITAve);
+ debugViewFileName.ReleaseBuffer();
+ #endif
+ pUg31xx->userReg.regITAve = pUg31xx->PreviousITAve;
+ }
+ }
+ pUg31xx->PreviousITAve = pUg31xx->userReg.regITAve;
+
+ /// [AT-PM] : Check OTP is empty or not ; 01/25/2013
+ if(pUg31xx->otpData.empty == OTP_IS_EMPTY)
+ {
+ return (UG_OTP_ISEMPTY);
+ }
+
+ /// [AT-PM] : Check product type ; 01/25/2013
+ if(pUg31xx->otpData.productType != UG31XX_PRODUCT_TYPE_0)
+ {
+ return (UG_OTP_PRODUCT_DISMATCH);
+ }
+
+ pUg31xx->measData.sysData = &pUg31xx->sysData;
+ pUg31xx->measData.otp = &pUg31xx->otpData;
+ rtn = UpiMeasurement(&pUg31xx->measData);
+ if(rtn != MEAS_RTN_PASS)
+ {
+ return ((GGSTATUS)(rtn + UG_MEAS_FAIL));
+ }
+
+ pUg31xx->deviceInfo.chargeRegister = pUg31xx->userReg.regCharge; //coulomb counter
+ pUg31xx->deviceInfo.AdcCounter = pUg31xx->userReg.regCounter; //adc1 convert counter
+ pUg31xx->deviceInfo.aveCurrentRegister = pUg31xx->userReg.regCurrentAve; //2012/07/11
+ pUg31xx->deviceInfo.current_mA = pUg31xx->measData.curr;
+ pUg31xx->deviceInfo.AveCurrent_mA = pUg31xx->measData.curr;
+ pUg31xx->deviceInfo.IT = pUg31xx->measData.intTemperature;
+ pUg31xx->deviceInfo.ET = pUg31xx->measData.extTemperature;
+ pUg31xx->deviceInfo.v1_mV = pUg31xx->measData.bat1Voltage;
+ pUg31xx->deviceInfo.vCell1_mV = pUg31xx->measData.bat1Voltage;
+ pUg31xx->deviceInfo.vBat1Average_mV = CalculateVoltageFromUserReg(pUg31xx,
+ pUg31xx->measData.bat1Voltage,
+ pUg31xx->measData.curr,
+ pUg31xx->cellParameter.offsetR,
+ pUg31xx->cellParameter.deltaR);
+ pUg31xx->deviceInfo.voltage_mV = pUg31xx->deviceInfo.vBat1Average_mV;
+ pUg31xx->deviceInfo.chargeData_mAh = pUg31xx->measData.deltaCap;
+
+ pUg31xx->sysData.otpData = &pUg31xx->otpData;
+ UpiCalibrationOsc(&pUg31xx->sysData); //osc calibration
+
+ UpiAdcStatus(&pUg31xx->sysData);
+
+ if(fix_et_at_initial_cnt > 0)
+ {
+ fix_et_at_initial_cnt = fix_et_at_initial_cnt - 1;
+
+ if(pUg31xx->deviceInfo.ET > UG31XX_MAX_TEMPERATURE_BEFORE_READY)
+ {
+ pUg31xx->deviceInfo.ET = UG31XX_MAX_TEMPERATURE_BEFORE_READY;
+ }
+ if(pUg31xx->deviceInfo.ET < UG31XX_MIN_TEMPERATURE_BEFORE_READY)
+ {
+ pUg31xx->deviceInfo.ET = UG31XX_MIN_TEMPERATURE_BEFORE_READY;
+ }
+ }
+ memcpy(pExtDeviceInfo, &pUg31xx->deviceInfo, sizeof(GG_DEVICE_INFO));
+ return (status);
+}
+
+void dumpInfo(struct ug31xx_data *pUg31xx)
+{
+ int i=0;
+ int j;
+ int k;
+
+/// dump parameter setting
+ UG31_LOGI("/// 2012/12/16/1611====================================\n");
+ UG31_LOGI("/// CELL_PARAMETER\n");
+ UG31_LOGI("/// ====================================2012/12/16/1611\n");
+ UG31_LOGI("Total struct size: %d\n", pUg31xx->cellParameter.totalSize);
+ UG31_LOGI("firmware version: 0x%02X\n", pUg31xx->cellParameter.fw_ver)
+ UG31_LOGI("customer: %s\n", pUg31xx->cellParameter.customer)
+ UG31_LOGI("project: %s\n", pUg31xx->cellParameter.project)
+ UG31_LOGI("ggb version: 0x%02X\n", pUg31xx->cellParameter.ggb_version)
+ UG31_LOGI("customer self-define: %s\n", pUg31xx->cellParameter.customerSelfDef)
+ UG31_LOGI("project self-define: %s\n", pUg31xx->cellParameter.projectSelfDef)
+ UG31_LOGI("cell type : 0x%04X\n", pUg31xx->cellParameter.cell_type_code);
+ UG31_LOGI("ICType: 0x%02X\n", pUg31xx->cellParameter.ICType);
+ UG31_LOGI("gpio1: 0x%02X\n", pUg31xx->cellParameter.gpio1);
+ UG31_LOGI("gpio2: 0x%02X\n", pUg31xx->cellParameter.gpio2);
+ UG31_LOGI("gpio34: 0x%02X\n", pUg31xx->cellParameter.gpio34);
+ UG31_LOGI("Chop control ?? : 0x%02X\n", pUg31xx->cellParameter.chopCtrl);
+ UG31_LOGI("ADC1 offset ?? : %d\n", pUg31xx->cellParameter.adc1Offset);
+ UG31_LOGI("Cell number ?? : %d\n", pUg31xx->cellParameter.cellNumber);
+ UG31_LOGI("Assign cell one to: %d\n", pUg31xx->cellParameter.assignCellOneTo);
+ UG31_LOGI("Assign cell two to: %d\n", pUg31xx->cellParameter.assignCellTwoTo);
+ UG31_LOGI("Assign cell three to: %d\n", pUg31xx->cellParameter.assignCellThreeTo);
+ UG31_LOGI("I2C Address: : 0x%02X\n", pUg31xx->cellParameter.i2cAddress);
+ UG31_LOGI("I2C 10bit address: : 0x%02X\n", pUg31xx->cellParameter.tenBitAddressMode);
+ UG31_LOGI("I2C high speed: 0x%02X\n", pUg31xx->cellParameter.highSpeedMode);
+ UG31_LOGI("clock(kHz): %d\n", pUg31xx->cellParameter.clock);
+ UG31_LOGI("RSense(m ohm): %d\n", pUg31xx->cellParameter.rSense);
+ UG31_LOGI("ILMD(mAH) ?? : %d\n", pUg31xx->cellParameter.ILMD);
+ UG31_LOGI("EDV1 Voltage(mV): %d\n", pUg31xx->cellParameter.edv1Voltage);
+ UG31_LOGI("Standby current ?? : %d\n", pUg31xx->cellParameter.standbyCurrent);
+ UG31_LOGI("TP Current(mA)?? : %d\n", pUg31xx->cellParameter.TPCurrent);
+ UG31_LOGI("TP Voltage(mV)?? : %d\n", pUg31xx->cellParameter.TPVoltage);
+ UG31_LOGI("TP Time ?? : %d\n", pUg31xx->cellParameter.TPTime);
+ UG31_LOGI("Offset R ?? : %d\n", pUg31xx->cellParameter.offsetR);
+ UG31_LOGI("Delta R ?? : %d\n", pUg31xx->cellParameter.deltaR);
+ UG31_LOGI("max delta Q(%%) ?? : %d\n", pUg31xx->cellParameter.maxDeltaQ);
+ UG31_LOGI("TP Bypass Current ?? : %d\n", pUg31xx->cellParameter.TpBypassCurrent); //20121029/Jacky
+ UG31_LOGI("time interval (s) : %d\n", pUg31xx->cellParameter.timeInterval);
+ UG31_LOGI("ADC1 pgain: %d\n", pUg31xx->cellParameter.adc1_pgain);
+ UG31_LOGI("ADC1 ngain: %d\n", pUg31xx->cellParameter.adc1_ngain);
+ UG31_LOGI("ADC1 pos. offset: %d\n", pUg31xx->cellParameter.adc1_pos_offset);
+ UG31_LOGI("ADC2 gain: %d\n", pUg31xx->cellParameter.adc2_gain);
+ UG31_LOGI("ADC2 offset: %d\n", pUg31xx->cellParameter.adc2_offset);
+ UG31_LOGI("R ?? : %d\n", pUg31xx->cellParameter.R);
+ for (i=0; i<sizeof(pUg31xx->cellParameter.rtTable)/sizeof(_upi_u16_); i++) {
+ UG31_LOGI("RTTable[%02d]: %d\n", i, pUg31xx->cellParameter.rtTable[i]);
+ }
+ for (i=0; i<sizeof(pUg31xx->cellParameter.SOV_TABLE)/sizeof(_upi_u16_); i++) {
+ UG31_LOGI("SOV Table[%02d]: %d\n", i, pUg31xx->cellParameter.SOV_TABLE[i]/10);
+ }
+ UG31_LOGI("ADC d1: %d\n", pUg31xx->cellParameter.adc_d1);
+ UG31_LOGI("ADC d2: %d\n", pUg31xx->cellParameter.adc_d2);
+ UG31_LOGI("ADC d3: %d\n", pUg31xx->cellParameter.adc_d3);
+ UG31_LOGI("ADC d4: %d\n", pUg31xx->cellParameter.adc_d4);
+ UG31_LOGI("ADC d5: %d\n", pUg31xx->cellParameter.adc_d5);
+ UG31_LOGI("NacLmdAdjustCfg: %d\n", pUg31xx->cellParameter.NacLmdAdjustCfg); //20121124
+
+ /// [AT-PM] : Dump NAC table ; 01/27/2013
+ i = 0;
+ while(i < TEMPERATURE_NUMS)
+ {
+ j = 0;
+ while(j < C_RATE_NUMS)
+ {
+ k = 0;
+ while(k < SOV_NUMS)
+ {
+ UG31_LOGI("NAC Table [%d][%d][%d] = %d\n", i, j, k, pUg31xx->cellTable.CELL_NAC_TABLE[i][j][k]);
+ k = k + 1;
+ }
+ j = j + 1;
+ }
+ i = i + 1;
+ }
+}
+
+/// count Time Elapsed in suspend/power Off
+_upi_u32_ CountTotalTime(_upi_u32_ savedTimeTag)
+{
+ _upi_u32_ totalTime;
+ _upi_u32_ currentTime;
+
+ totalTime = 0;
+#if defined(uG31xx_OS_ANDROID)
+ currentTime = GetSysTickCount();
+#else ///< else of defined(uG31xx_OS_ANDROID)
+ currentTime = GetTickCount();
+#endif ///< end of defined(uG31xx_OS_ANDROID)
+ if(currentTime > savedTimeTag)
+ {
+ totalTime = currentTime - savedTimeTag; //count the delta Time
+ }
+ else
+ {
+ totalTime = currentTime;
+ }
+ UG31_LOGE("[%s]current time/save Time/totalTime = %d/%d/%d \n",
+ __func__,
+ currentTime,
+ savedTimeTag,
+ totalTime
+ );
+ return(totalTime);
+}
+
+#define MS_IN_A_DAY (86400000)
+#define INIT_CAP_FROM_CC_FACTOR (10)
+
+/**
+ * @brief CheckInitCapacityFromCC
+ *
+ * Check the initial capacity from coulomb counter with time interval
+ * The delta RSOC should be less than n days x 0.1%
+ *
+ * @para pUg31xx address of struct ug31xx_data
+ * @para lastRsoc last RSOC before employ coulomb counter value
+ * @return _UPI_NULL_
+ */
+void CheckInitCapacityFromCC(struct ug31xx_data *pUg31xx, _sys_u8_ lastRsoc)
+{
+ _upi_s32_ tmp32;
+
+ tmp32 = (_upi_s16_)pUg31xx->sysData.rsocFromIC;
+ tmp32 = tmp32 - lastRsoc;
+ if(tmp32 < 0)
+ {
+ tmp32 = (_upi_s32_)CountTotalTime(pUg31xx->sysData.timeTagFromIC)/MS_IN_A_DAY/INIT_CAP_FROM_CC_FACTOR;
+ tmp32 = tmp32*(-1) + lastRsoc;
+ if(tmp32 < 0)
+ {
+ tmp32 = 1;
+ }
+ UG31_LOGI("[%s]: RSOC should be limited to %d (%d <-> %d)\n", __func__,
+ tmp32, lastRsoc, pUg31xx->sysData.rsocFromIC);
+ pUg31xx->sysData.rsocFromIC = (_sys_u8_)tmp32;
+ tmp32 = tmp32*pUg31xx->sysData.fccFromIC/CONST_PERCENTAGE;
+ pUg31xx->sysData.rmFromIC = (_sys_u16_)tmp32;
+ }
+}
+
+#define MAX_DELTA_RSOC_THRESHOLD_FOR_WAKEUP (25)
+#define MIN_DELTA_RSOC_THRESHOLD_FOR_WAKEUP (-25)
+#define MAX_DELTA_TIME_THRESHOLD_FOR_WAKEUP (MS_IN_A_DAY*5)
+#define MAX_DELTA_RSOC_THRESHOLD_FOR_TABLE (0)
+#define MIN_DELTA_RSOC_THRESHOLD_FOR_TABLE (-5)
+
+// Read GGB file and initial
+#ifdef uG31xx_OS_WINDOWS
+GGSTATUS upiGG_Initial(char **pObj,const wchar_t* GGBFilename,const wchar_t* OtpFileName, const wchar_t* BackupFileName, char ForceReset, unsigned char MaxETFixCnt)
+#elif defined(uG31xx_OS_ANDROID)
+GGSTATUS upiGG_Initial(char **pObj,GGBX_FILE_HEADER *pGGBXBuf, char ForceReset, unsigned char MaxETFixCnt)
+#endif
+{
+ _upi_bool_ firstPowerOn;
+ struct ug31xx_data *pUg31xx;
+ SYSTEM_RTN_CODE rtn;
+ _upi_s16_ deltaQC = 0;
+ _upi_s32_ tmp32;
+ MEAS_RTN_CODE rtnMeas;
+ _sys_u8_ lastRsocFromIC;
+
+ UG31_LOGI("[%s]: uG31xx API Version = %d.%08x.%04x\n", __func__,
+ UG31XX_API_MAIN_VERSION, UG31XX_API_OTP_VERSION, UG31XX_API_SUB_VERSION);
+
+ Ug31DebugEnable = _UPI_TRUE_;
+ firstPowerOn = _UPI_FALSE_;
+ #if defined(uG31xx_OS_ANDROID)
+ #ifdef uG31xx_BOOT_LOADER
+ *pObj = (char *)malloc(sizeof(struct ug31xx_data));
+ #else ///< else of uG31xx_BOOT_LOADER
+ *pObj = (char *)kmalloc(sizeof(struct ug31xx_data),GFP_KERNEL);
+ #endif ///< end of uG31xx_BOOT_LOADER
+ #else ///< else of defined(uG31xx_OS_ANDROID)
+ *pObj = (char *)malloc(sizeof(struct ug31xx_data));
+ #endif ///< end of defined(uG31xx_OS_ANDROID)
+ pUg31xx = (struct ug31xx_data *)(*pObj);
+
+ memset(pUg31xx, 0, sizeof(struct ug31xx_data));
+
+ #ifdef uG31xx_OS_WINDOWS
+ pUg31xx->sysData.ggbFilename = GGBFilename;
+ pUg31xx->sysData.otpFileName = OtpFileName;
+ pUg31xx->sysData.backupFileName = BackupFileName;
+ BackupFile = BackupFileName;
+ #elif defined(uG31xx_OS_ANDROID)
+ pUg31xx->sysData.ggbXBuf = pGGBXBuf;
+ #endif
+ pUg31xx->sysData.ggbParameter = &pUg31xx->cellParameter;
+ pUg31xx->sysData.ggbCellTable = &pUg31xx->cellTable;
+ rtn = UpiInitSystemData(&pUg31xx->sysData);
+ if(rtn != SYSTEM_RTN_PASS)
+ {
+ if(rtn == SYSTEM_RTN_READ_GGB_FAIL)
+ {
+ return (UG_READ_GGB_FAIL);
+ }
+ return (UG_NOT_DEF);
+ }
+
+ // Initial I2C and Open HID
+ #if defined(uG31xx_OS_WINDOWS)
+
+ if(!API_I2C_Init(pUg31xx->cellParameter.clock, pUg31xx->cellParameter.i2cAddress))
+ {
+ return UG_I2C_INIT_FAIL;
+ }
+
+ #endif ///< end of defined(uG31xx_OS_WINDOWS)
+ UpiLoadBatInfoFromIC(&pUg31xx->sysData);
+
+ pUg31xx->capData.ggbTable = &pUg31xx->cellTable;
+ pUg31xx->capData.ggbParameter = &pUg31xx->cellParameter;
+ pUg31xx->capData.measurement = &pUg31xx->measData;
+ UpiInitNacTable(&pUg31xx->capData);
+
+ /// [AT-PM] : Check IC is active or not ; 01/28/2013
+ #ifdef UG31XX_RESET_DATABASE
+ firstPowerOn = _UPI_TRUE_;
+ #else ///< else of UG31XX_RESET_DATABASE
+ if(ForceReset == 0)
+ {
+ firstPowerOn = UpiCheckICActive();
+ }
+ else
+ {
+ firstPowerOn = _UPI_TRUE_;
+ UG31_LOGI("[%s]: Force to reset uG3105 driver. (%d)\n", __func__, ForceReset);
+ }
+ #endif ///< end of UG31XX_RESET_DATABASE
+ if(firstPowerOn == _UPI_TRUE_)
+ {
+ UG31_LOGE("[%s]#####firstPowerOn= %d \n",__func__,firstPowerOn);
+ rtn = UpiActiveUg31xx();
+ if(rtn != SYSTEM_RTN_PASS)
+ {
+ return (UG_ACTIVE_FAIL);
+ }
+
+ UpiSetupAdc(&pUg31xx->sysData);
+ UpiSetupSystem(&pUg31xx->sysData);
+
+ pUg31xx->backupData.icDataAvailable = BACKUP_BOOL_FALSE;
+ }
+ else
+ {
+ UG31_LOGE("[%s]#####Last time tag = %d\n", __func__, pUg31xx->sysData.timeTagFromIC);
+ pUg31xx->measData.lastTimeTick = pUg31xx->sysData.timeTagFromIC;
+ pUg31xx->measData.lastDeltaCap = pUg31xx->sysData.deltaCapFromIC;
+ pUg31xx->measData.adc1ConvertTime = pUg31xx->sysData.adc1ConvTime;
+
+ pUg31xx->backupData.icDataAvailable = BACKUP_BOOL_TRUE;
+ }
+
+ /// [AT-PM] : Load OTP data ; 01/31/2013
+ API_I2C_Read(SECURITY, UG31XX_I2C_HIGH_SPEED_MODE, UG31XX_I2C_TEM_BITS_MODE, OTP1_BYTE1, OTP1_SIZE, pUg31xx->otpData.otp1);
+ API_I2C_Read(SECURITY, UG31XX_I2C_HIGH_SPEED_MODE, UG31XX_I2C_TEM_BITS_MODE, OTP2_BYTE1, OTP2_SIZE, pUg31xx->otpData.otp2);
+ API_I2C_Read(NORMAL, UG31XX_I2C_HIGH_SPEED_MODE, UG31XX_I2C_TEM_BITS_MODE, OTP6_BYTE1, OTP3_SIZE, pUg31xx->otpData.otp3);
+ UpiConvertOtp(&pUg31xx->otpData);
+
+ /// [AT-PM] : Check product type ; 01/25/2013
+ if(pUg31xx->otpData.productType != UG31XX_PRODUCT_TYPE_0)
+ {
+ return (UG_OTP_PRODUCT_DISMATCH);
+ }
+
+ if(firstPowerOn == _UPI_TRUE_)
+ {
+ SleepMiniSecond(1000);
+ fix_et_at_initial_cnt = MaxETFixCnt;
+ }
+
+ UG31_LOGI("[%s]: Do measurement\n", __func__);
+
+ pUg31xx->measData.sysData = &pUg31xx->sysData;
+ pUg31xx->measData.otp = &pUg31xx->otpData;
+ rtnMeas = UpiMeasurement(&pUg31xx->measData);
+ if(rtnMeas != MEAS_RTN_PASS)
+ {
+ return ((GGSTATUS)(rtnMeas + UG_MEAS_FAIL));
+ }
+ if(firstPowerOn == _UPI_TRUE_)
+ {
+ /// [AT-PM] : Initialize alarm function ; 04/08/2013
+ UpiMeasAlarmThreshold(&pUg31xx->measData);
+ UpiInitAlarm(&pUg31xx->sysData);
+ }
+
+ UG31_LOGI("[%s]: Current Status = %d mV / %d mA / %d 0.1oC\n", __func__,
+ pUg31xx->measData.bat1Voltage, pUg31xx->measData.curr, pUg31xx->measData.intTemperature);
+
+ UpiInitCapacity(&pUg31xx->capData);
+ pUg31xx->capData.rsoc = CalculateRsoc(pUg31xx->capData.rm, pUg31xx->capData.fcc);
+ if((firstPowerOn == _UPI_TRUE_) || (pUg31xx->sysData.fccFromIC == 0))
+ {
+ pUg31xx->batteryInfo.NAC = (_upi_u16_)pUg31xx->capData.rm;
+ pUg31xx->batteryInfo.LMD = (_upi_u16_)pUg31xx->capData.fcc;
+ pUg31xx->batteryInfo.RSOC = (_upi_u16_)pUg31xx->capData.rsoc;
+ UG31_LOGI("[%s]: Init data from table -> %d/%d = %d\n", __func__,
+ pUg31xx->batteryInfo.NAC, pUg31xx->batteryInfo.LMD, pUg31xx->batteryInfo.RSOC);
+ }
+ else
+ {
+ pUg31xx->capData.tableUpdateIdx = pUg31xx->sysData.tableUpdateIdxFromIC;
+
+ /// [AT-PM] : Calculate the RSOC/NAC/LMD from coulomb counter ; 01/27/2013
+ deltaQC = (_upi_s16_)pUg31xx->measData.stepCap;
+ pUg31xx->sysData.voltage = pUg31xx->measData.bat1Voltage;
+ lastRsocFromIC = pUg31xx->sysData.rsocFromIC;
+ UpiUpdateBatInfoFromIC(&pUg31xx->sysData, deltaQC);
+ if(CountTotalTime(pUg31xx->sysData.timeTagFromIC) > MAX_DELTA_TIME_THRESHOLD_FOR_WAKEUP)
+ {
+ /// [AT-PM] : Check the data accuracy ; 01/27/2013
+ deltaQC = (_upi_s16_)pUg31xx->sysData.rsocFromIC;
+ deltaQC = deltaQC - pUg31xx->capData.rsoc;
+ if((deltaQC > MAX_DELTA_RSOC_THRESHOLD_FOR_WAKEUP) || (deltaQC < MIN_DELTA_RSOC_THRESHOLD_FOR_WAKEUP))
+ {
+ deltaQC = (_upi_s16_)pUg31xx->capData.rsoc;
+ deltaQC = deltaQC - pUg31xx->sysData.rsocFromICBackup;
+ if((deltaQC > MAX_DELTA_RSOC_THRESHOLD_FOR_TABLE) || (deltaQC < MIN_DELTA_RSOC_THRESHOLD_FOR_TABLE))
+ {
+ if(deltaQC > MAX_DELTA_RSOC_THRESHOLD_FOR_TABLE)
+ {
+ deltaQC = MAX_DELTA_RSOC_THRESHOLD_FOR_TABLE;
+ }
+ if(deltaQC < MIN_DELTA_RSOC_THRESHOLD_FOR_TABLE)
+ {
+ deltaQC = MIN_DELTA_RSOC_THRESHOLD_FOR_TABLE;
+ }
+ deltaQC = deltaQC + pUg31xx->sysData.rsocFromICBackup;
+ pUg31xx->capData.rsoc = (_cap_u8_)deltaQC;
+
+ }
+ pUg31xx->capData.fcc = pUg31xx->sysData.fccFromIC;
+ tmp32 = (_upi_s32_)pUg31xx->capData.fcc;
+ tmp32 = tmp32*pUg31xx->capData.rsoc/CONST_PERCENTAGE;
+ pUg31xx->capData.rm = (_cap_u16_)tmp32;
+ UG31_LOGI("[%s]: Coulomb counter is not available -> Use data from table (%d/%d = %d)\n", __func__,
+ pUg31xx->capData.rm, pUg31xx->capData.fcc, pUg31xx->capData.rsoc);
+ }
+ else
+ {
+ CheckInitCapacityFromCC(pUg31xx, lastRsocFromIC);
+ pUg31xx->capData.rm = (_cap_u16_)pUg31xx->sysData.rmFromIC;
+ pUg31xx->capData.fcc = (_cap_u16_)pUg31xx->sysData.fccFromIC;
+ pUg31xx->capData.rsoc = (_cap_u8_)pUg31xx->sysData.rsocFromIC;
+ UG31_LOGI("[%s]: Use data from coulomb counter (%d/%d = %d)\n", __func__,
+ pUg31xx->capData.rm, pUg31xx->capData.fcc, pUg31xx->capData.rsoc);
+ }
+ }
+ else
+ {
+ CheckInitCapacityFromCC(pUg31xx, lastRsocFromIC);
+ pUg31xx->capData.rm = (_cap_u16_)pUg31xx->sysData.rmFromIC;
+ pUg31xx->capData.fcc = (_cap_u16_)pUg31xx->sysData.fccFromIC;
+ pUg31xx->capData.rsoc = (_cap_u8_)pUg31xx->sysData.rsocFromIC;
+ UG31_LOGI("[%s]: Use data from coulomb counter (%d/%d = %d)\n", __func__,
+ pUg31xx->capData.rm, pUg31xx->capData.fcc, pUg31xx->capData.rsoc);
+ }
+ pUg31xx->batteryInfo.NAC = (_upi_u16_)pUg31xx->capData.rm;
+ pUg31xx->batteryInfo.LMD = (_upi_u16_)pUg31xx->capData.fcc;
+ pUg31xx->batteryInfo.RSOC = (_upi_u16_)pUg31xx->capData.rsoc;
+ UpiResetCoulombCounter(&pUg31xx->measData);
+ }
+ UpiInitDsgCharge(&pUg31xx->capData);
+
+ /// [AT-PM] : Save battery information to IC ; 01/31/2013
+ pUg31xx->sysData.rmFromIC = pUg31xx->batteryInfo.NAC;
+ pUg31xx->sysData.fccFromIC = pUg31xx->batteryInfo.LMD;
+ pUg31xx->sysData.rsocFromIC = (_sys_u8_)pUg31xx->batteryInfo.RSOC;
+ pUg31xx->sysData.tableUpdateIdxFromIC = pUg31xx->capData.tableUpdateIdx;
+ pUg31xx->sysData.deltaCapFromIC = pUg31xx->measData.lastDeltaCap;
+ pUg31xx->sysData.adc1ConvTime = pUg31xx->measData.adc1ConvertTime;
+ UpiSaveBatInfoTOIC(&pUg31xx->sysData);
+
+ UG31_LOGI("[%s]: Driver version = %d\n", __func__, UG31XX_API_RELEASE_VERSION);
+ pUg31xx->backupData.targetFileVer = UG31XX_API_RELEASE_VERSION;
+ pUg31xx->backupData.backupDataIdx = BACKUP_MAX_LOG_SUSPEND_DATA;
+ while(pUg31xx->backupData.backupDataIdx)
+ {
+ pUg31xx->backupData.backupDataIdx = pUg31xx->backupData.backupDataIdx - 1;
+ pUg31xx->backupData.logData[pUg31xx->backupData.backupDataIdx] = (BackupSuspendDataType *)kmalloc(sizeof(BackupSuspendDataType), GFP_KERNEL);
+ memset(pUg31xx->backupData.logData[pUg31xx->backupData.backupDataIdx], 0, sizeof(BackupSuspendDataType));
+ }
+
+ dumpInfo(pUg31xx);
+ return (UG_INIT_SUCCESS);
+}
+
+GGSTATUS upiGG_PreSuspend(char *pObj)
+{
+ GGSTATUS Status = UG_READ_DEVICE_INFO_SUCCESS;
+ struct ug31xx_data *pUg31xx;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+ UG31_LOGE("[%s]:*****upiGG_PreSuspend *****\n", __func__);
+
+ UpiResetCoulombCounter(&pUg31xx->measData);
+
+ /// [AT-PM] : Save battery information to IC ; 01/31/2013
+ pUg31xx->sysData.rmFromIC = pUg31xx->batteryInfo.NAC;
+ pUg31xx->sysData.fccFromIC = pUg31xx->batteryInfo.LMD;
+ pUg31xx->sysData.rsocFromIC = (_sys_u8_)pUg31xx->batteryInfo.RSOC;
+ pUg31xx->sysData.tableUpdateIdxFromIC = pUg31xx->capData.tableUpdateIdx;
+ pUg31xx->sysData.deltaCapFromIC = pUg31xx->measData.lastDeltaCap;
+ pUg31xx->sysData.adc1ConvTime = pUg31xx->measData.adc1ConvertTime;
+ pUg31xx->sysData.voltage = pUg31xx->measData.bat1Voltage;
+ UpiUpdateBatInfoFromIC(&pUg31xx->sysData, (_sys_s16_) pUg31xx->measData.stepCap);
+ UpiSaveBatInfoTOIC(&pUg31xx->sysData);
+
+ /// [AT-PM] : Save dsgCharge before suspend ; 08/14/2013
+ dsg_charge_before_suspend = (_upi_s32_)pUg31xx->capData.dsgCharge;
+ if(dsg_charge_before_suspend < 0)
+ {
+ dsg_charge_before_suspend = (_upi_s32_)pUg31xx->sysData.fccFromIC;
+ dsg_charge_before_suspend = dsg_charge_before_suspend - pUg31xx->sysData.rmFromIC;
+ }
+ UG31_LOGI("[%s]: dsg_charge_before_suspend = %d\n", __func__, dsg_charge_before_suspend);
+
+ pUg31xx->backupData.capData = &pUg31xx->capData;
+ pUg31xx->backupData.sysData = &pUg31xx->sysData;
+ pUg31xx->backupData.measData = &pUg31xx->measData;
+ UpiUpdateSuspendData(&pUg31xx->backupData, _UPI_FALSE_);
+
+ /// [AT-PM] : Set CAP_STS_NAC_UPDATE_DISQ ; 11/08/2013
+ pUg31xx->capData.status = pUg31xx->capData.status | 0x0400;
+
+ #ifdef DEBUG_LOG
+ wDebug::LOGE(debugViewFileName.GetBuffer(),debugViewLines++,_T("[%s]:Reset Coulumb counter"), _L(__FUNCTION__));
+ debugViewFileName.ReleaseBuffer();
+ #endif
+ return(Status);
+}
+
+//====================================================
+//API Call to get the Battery Capacity
+// charge full condition:
+// if((Iav <TP current) && (Voltage >= TP Voltage))
+//====================================================
+void upiGG_ReadCapacity(char *pObj, GG_CAPACITY *pExtCapacity)
+{
+ struct ug31xx_data *pUg31xx;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+
+ pUg31xx->capData.ggbTable = &pUg31xx->cellTable;
+ pUg31xx->capData.ggbParameter = &pUg31xx->cellParameter;
+ pUg31xx->capData.measurement = &pUg31xx->measData;
+ UpiReadCapacity(&pUg31xx->capData);
+ pUg31xx->capData.tableUpdateDelayCnt = 1;
+ pUg31xx->batteryInfo.NAC = (_upi_u16_)pUg31xx->capData.rm;
+ pUg31xx->batteryInfo.LMD = (_upi_u16_)pUg31xx->capData.fcc;
+ pUg31xx->batteryInfo.RSOC = (_upi_u16_)pUg31xx->capData.rsoc;
+
+ // Output result by assign value from global variable
+ pExtCapacity->LMD = pUg31xx->batteryInfo.LMD;
+ pExtCapacity->NAC = pUg31xx->batteryInfo.NAC;
+ pExtCapacity->RSOC = pUg31xx->batteryInfo.RSOC;
+
+ /// [AT-PM] : If fully charged and keeps charging, reset coulomb counter ; 02/11/2013
+ if((pUg31xx->batteryInfo.RSOC == 100) && (pUg31xx->measData.curr >= pUg31xx->cellParameter.standbyCurrent))
+ {
+ pUg31xx->measData.sysData = &pUg31xx->sysData;
+ pUg31xx->measData.otp = &pUg31xx->otpData;
+ UpiResetCoulombCounter(&pUg31xx->measData);
+ }
+
+ /// [AT-PM] : Save battery information to IC ; 01/31/2013
+ pUg31xx->sysData.rmFromIC = pUg31xx->batteryInfo.NAC;
+ pUg31xx->sysData.fccFromIC = pUg31xx->batteryInfo.LMD;
+ pUg31xx->sysData.rsocFromIC = (_sys_u8_)pUg31xx->batteryInfo.RSOC;
+ pUg31xx->sysData.tableUpdateIdxFromIC = pUg31xx->capData.tableUpdateIdx;
+ pUg31xx->sysData.deltaCapFromIC = pUg31xx->measData.lastDeltaCap;
+ pUg31xx->sysData.adc1ConvTime = pUg31xx->measData.adc1ConvertTime;
+ UpiSaveBatInfoTOIC(&pUg31xx->sysData);
+
+ /// [AT-PM] : Check data from IC and file ; 06/19/2013
+ if((pUg31xx->backupData.backupFileSts == BACKUP_FILE_STS_EXIST) &&
+ (pUg31xx->backupData.icDataAvailable == BACKUP_BOOL_FALSE))
+ {
+ pUg31xx->backupData.icDataAvailable = BACKUP_BOOL_TRUE;
+ pUg31xx->sysData.timeTagFromIC = pUg31xx->measData.lastTimeTick;
+ pUg31xx->sysData.deltaCapFromIC = pUg31xx->measData.lastDeltaCap;
+ UpiSaveBatInfoTOIC(&pUg31xx->sysData);
+ pUg31xx->capData.rm = (_cap_u16_)pUg31xx->sysData.rmFromIC;
+ pUg31xx->capData.fcc = (_cap_u16_)pUg31xx->sysData.fccFromIC;
+ pUg31xx->capData.rsoc = (_cap_u8_)pUg31xx->sysData.rsocFromIC;
+ pUg31xx->capData.tableUpdateIdx = pUg31xx->sysData.tableUpdateIdxFromIC;
+ UpiSaveNacTable(&pUg31xx->capData);
+ pUg31xx->batteryInfo.NAC = (_upi_u16_)pUg31xx->capData.rm;
+ pUg31xx->batteryInfo.LMD = (_upi_u16_)pUg31xx->capData.fcc;
+ pUg31xx->batteryInfo.RSOC = (_upi_u16_)pUg31xx->capData.rsoc;
+ UpiInitDsgCharge(&pUg31xx->capData);
+ pUg31xx->measData.adc1ConvertTime = pUg31xx->sysData.adc1ConvTime;
+ UG31_LOGI("[%s]: Refresh driver information from file\n", __func__);
+ }
+
+ if(pUg31xx->backupData.icDataAvailable == BACKUP_BOOL_TRUE)
+ {
+ pExtCapacity->Ready = UG_CAP_DATA_READY;
+ }
+ else
+ {
+ pExtCapacity->Ready = UG_CAP_DATA_NOT_READY;
+ }
+}
+
+_upi_u8_ upiGG_CheckBackupFile(char *pObj)
+{
+ struct ug31xx_data *pUg31xx;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+
+ pUg31xx->capData.ggbTable = &pUg31xx->cellTable;
+ pUg31xx->capData.ggbParameter = &pUg31xx->cellParameter;
+ pUg31xx->capData.measurement = &pUg31xx->measData;
+ pUg31xx->measData.sysData = &pUg31xx->sysData;
+ pUg31xx->measData.otp = &pUg31xx->otpData;
+
+ pUg31xx->sysData.rmFromIC = pUg31xx->batteryInfo.NAC;
+ pUg31xx->sysData.fccFromIC = pUg31xx->batteryInfo.LMD;
+ pUg31xx->sysData.rsocFromIC = (_sys_u8_)pUg31xx->batteryInfo.RSOC;
+ pUg31xx->sysData.tableUpdateIdxFromIC = pUg31xx->capData.tableUpdateIdx;
+ pUg31xx->sysData.deltaCapFromIC = pUg31xx->measData.lastDeltaCap;
+ pUg31xx->sysData.adc1ConvTime = pUg31xx->measData.adc1ConvertTime;
+
+ /// [AT-PM] : Backup data to file routine ; 02/21/2013
+ pUg31xx->backupData.capData = &pUg31xx->capData;
+ pUg31xx->backupData.sysData = &pUg31xx->sysData;
+ pUg31xx->backupData.measData = &pUg31xx->measData;
+ #ifdef uG31xx_OS_WINDOWS
+ pUg31xx->sysData.backupFileName = BackupFile.GetBuffer();
+ #endif ///< end of uG31xx_OS_WINDOWS
+ UpiBackupData(&pUg31xx->backupData);
+ #ifdef uG31xx_OS_WINDOWS
+ BackupFile.ReleaseBuffer();
+ #endif ///< end of uG31xx_OS_WINDOWS
+
+ if(pUg31xx->backupData.backupFileSts == BACKUP_FILE_STS_CHECKING)
+ {
+ UG31_LOGI("[%s]: Backup File check fail\n", __func__);
+ return (UPI_CHECK_BACKUP_FILE_FAIL);
+ }
+ if(pUg31xx->backupData.backupFileSts == BACKUP_FILE_STS_COMPARE)
+ {
+ UG31_LOGI("[%s]: Backup File Version = %d\n", __func__, pUg31xx->backupData.backupFileVer);
+ if(pUg31xx->backupData.backupFileVer != UG31XX_API_RELEASE_VERSION)
+ {
+ return (UPI_CHECK_BACKUP_FILE_MISMATCH);
+ }
+ return (UPI_CHECK_BACKUP_FILE_EXIST);
+ }
+ return (UPI_CHECK_BACKUP_FILE_FAIL);
+}
+
+//system wakeup
+// to read back the preSuspend information from uG31xx RAM area
+// re-calculate the deltaQmax( the charge/discharge) during the suspend time
+GGSTATUS upiGG_Wakeup(char *pObj, int dc_in_before)
+{
+ GGSTATUS Status = UG_READ_DEVICE_INFO_SUCCESS;
+ _upi_s16_ deltaQC = 0; //coulomb counter's deltaQ
+ _upi_u32_ totalTime;
+ _upi_s32_ tmp32;
+ MEAS_RTN_CODE rtn;
+ _upi_u16_ rmBefore;
+ _upi_u16_ fccBefore;
+ _upi_u16_ rsocBefore;
+
+ struct ug31xx_data *pUg31xx;
+ pUg31xx = (struct ug31xx_data *)pObj;
+
+ ///Load the Saved time tag NAC LMD
+ UpiLoadBatInfoFromIC(&pUg31xx->sysData);
+ rmBefore = (_upi_u16_)pUg31xx->sysData.rmFromIC;
+ fccBefore = (_upi_u16_)pUg31xx->sysData.fccFromIC;
+ rsocBefore = (_upi_u16_)pUg31xx->sysData.rsocFromIC;
+
+ /// Count total Time
+ totalTime = CountTotalTime(pUg31xx->sysData.timeTagFromIC);
+ /// count the deltaQ during suspend
+ pUg31xx->measData.sysData = &pUg31xx->sysData;
+ pUg31xx->measData.otp = &pUg31xx->otpData;
+ pUg31xx->measData.lastTimeTick = pUg31xx->sysData.timeTagFromIC;
+ pUg31xx->measData.lastDeltaCap = pUg31xx->sysData.deltaCapFromIC;
+ pUg31xx->measData.adc1ConvertTime = pUg31xx->sysData.adc1ConvTime;
+ rtn = UpiMeasurement(&pUg31xx->measData);
+ pUg31xx->measData.adc1ConvertTime = pUg31xx->sysData.adc1ConvTime;
+ if(rtn != MEAS_RTN_PASS)
+ {
+ pUg31xx->backupData.capData = &pUg31xx->capData;
+ pUg31xx->backupData.sysData = &pUg31xx->sysData;
+ pUg31xx->backupData.measData = &pUg31xx->measData;
+ UpiUpdateSuspendData(&pUg31xx->backupData, _UPI_TRUE_);
+ return ((GGSTATUS)(rtn + UG_MEAS_FAIL));
+ }
+
+ /// [AT-PM] : Calculate delta capacity; 08/13/2013
+ tmp32 = (_upi_s32_)pUg31xx->measData.deltaCap;
+ tmp32 = tmp32*(pUg31xx->sysData.adc1ConvTime)/(pUg31xx->measData.adc1ConvertTime);
+ pUg31xx->measData.deltaCap = (_upi_s16_)tmp32;
+ pUg31xx->measData.lastDeltaCap = pUg31xx->measData.deltaCap;
+ tmp32 = tmp32 - pUg31xx->sysData.deltaCapFromIC;
+ pUg31xx->measData.stepCap = (_upi_s16_)tmp32;
+ deltaQC = (_upi_s16_)pUg31xx->measData.stepCap;
+ delta_cap_during_suspend = (_upi_s32_)deltaQC;
+
+ /// [AT-PM] : Calculate the RSOC/NAC/LMD from coulomb counter ; 01/27/2013
+ pUg31xx->sysData.voltage = pUg31xx->measData.bat1Voltage;
+ UpiUpdateBatInfoFromIC(&pUg31xx->sysData, deltaQC);
+ UG31_LOGE("[%s]: suspend time = %d ms,deltaQ = %d mAh, RSOC =%d, LMD = %d mAh, NAC=%d mAh\n",
+ __func__,
+ totalTime,
+ deltaQC,
+ pUg31xx->sysData.rsocFromIC,
+ pUg31xx->sysData.fccFromIC,
+ pUg31xx->sysData.rmFromIC);
+ /// [AT-PM] : Calculate the RSOC/NAC/LMD from table ; 01/28/2013
+ pUg31xx->capData.ggbTable = &pUg31xx->cellTable;
+ pUg31xx->capData.ggbParameter = &pUg31xx->cellParameter;
+ pUg31xx->capData.measurement = &pUg31xx->measData;
+ pUg31xx->capData.tableUpdateIdx = pUg31xx->sysData.tableUpdateIdxFromIC;
+ UpiTableCapacity(&pUg31xx->capData);
+ pUg31xx->capData.rsoc = CalculateRsoc(pUg31xx->capData.rm, pUg31xx->capData.fcc);
+ wakeup_predict_rsoc = (_upi_u8_)pUg31xx->capData.rsoc;
+ /// [AT-PM] : Check the data accuracy ; 01/27/2013
+ if(totalTime > MAX_DELTA_TIME_THRESHOLD_FOR_WAKEUP)
+ {
+ deltaQC = (_upi_s16_)pUg31xx->sysData.rsocFromIC;
+ deltaQC = deltaQC - pUg31xx->capData.rsoc;
+ if((deltaQC > MAX_DELTA_RSOC_THRESHOLD_FOR_WAKEUP) || (deltaQC < MIN_DELTA_RSOC_THRESHOLD_FOR_WAKEUP))
+ {
+ deltaQC = (_upi_s16_)pUg31xx->capData.rsoc;
+ deltaQC = deltaQC - pUg31xx->sysData.rsocFromICBackup;
+ if((deltaQC > MAX_DELTA_RSOC_THRESHOLD_FOR_TABLE) || (deltaQC < MIN_DELTA_RSOC_THRESHOLD_FOR_TABLE))
+ {
+ if(deltaQC > MAX_DELTA_RSOC_THRESHOLD_FOR_TABLE)
+ {
+ deltaQC = MAX_DELTA_RSOC_THRESHOLD_FOR_TABLE;
+ }
+ if(deltaQC < MIN_DELTA_RSOC_THRESHOLD_FOR_TABLE)
+ {
+ deltaQC = MIN_DELTA_RSOC_THRESHOLD_FOR_TABLE;
+ }
+ deltaQC = deltaQC + pUg31xx->sysData.rsocFromICBackup;
+ pUg31xx->capData.rsoc = (_cap_u8_)deltaQC;
+
+ }
+ pUg31xx->capData.fcc = pUg31xx->sysData.fccFromIC;
+ tmp32 = (_upi_s32_)pUg31xx->capData.fcc;
+ tmp32 = tmp32*pUg31xx->capData.rsoc/CONST_PERCENTAGE;
+ pUg31xx->capData.rm = (_cap_u16_)tmp32;
+ UG31_LOGI("[%s]: Coulomb counter is not available -> Use data from table (%d/%d = %d)\n", __func__,
+ pUg31xx->capData.rm, pUg31xx->capData.fcc, pUg31xx->capData.rsoc);
+ }
+ else
+ {
+ pUg31xx->capData.rm = (_cap_u16_)pUg31xx->sysData.rmFromIC;
+ pUg31xx->capData.fcc = (_cap_u16_)pUg31xx->sysData.fccFromIC;
+ pUg31xx->capData.rsoc = (_cap_u8_)pUg31xx->sysData.rsocFromIC;
+ UG31_LOGI("[%s]: Use data from coulomb counter (%d/%d = %d)\n", __func__,
+ pUg31xx->capData.rm, pUg31xx->capData.fcc, pUg31xx->capData.rsoc);
+ }
+ }
+ else
+ {
+ pUg31xx->capData.rm = (_cap_u16_)pUg31xx->sysData.rmFromIC;
+ pUg31xx->capData.fcc = (_cap_u16_)pUg31xx->sysData.fccFromIC;
+ pUg31xx->capData.rsoc = (_cap_u8_)pUg31xx->sysData.rsocFromIC;
+ UG31_LOGI("[%s]: Use data from coulomb counter (%d/%d = %d)\n", __func__,
+ pUg31xx->capData.rm, pUg31xx->capData.fcc, pUg31xx->capData.rsoc);
+ }
+
+ /// [AT-PM] : Check dc in before suspend ; 10/22/2013
+ if(dc_in_before == 0)
+ {
+ if(pUg31xx->batteryInfo.RSOC < pUg31xx->capData.rsoc)
+ {
+ UG31_LOGI("[%s]: Fix the RSOC the same value before suspend = %d (%d)\n", __func__, rsocBefore, pUg31xx->capData.rsoc);
+ pUg31xx->capData.rm = (_cap_u16_)rmBefore;
+ pUg31xx->capData.fcc = (_cap_u16_)fccBefore;
+ pUg31xx->capData.rsoc = (_cap_u16_)rsocBefore;
+ }
+
+ tmp32 = (_upi_s32_)totalTime;
+ tmp32 = tmp32/1000*(pUg31xx->cellParameter.standbyCurrent)/2/3600*(-1);
+ UG31_LOGI("[%s]: Estimated capacity = %d\n", __func__, tmp32);
+
+ if(deltaQC >= tmp32)
+ {
+ UG31_LOGI("[%s]: Apply static discharging current\n", __func__);
+
+ tmp32 = tmp32 + deltaQC;
+ tmp32 = tmp32/2;
+ tmp32 = tmp32 + rmBefore;
+ if(tmp32 < 0)
+ {
+ tmp32 = 0;
+ }
+ UG31_LOGI("[%s]: New RM = %d (%d)\n", __func__, tmp32, rmBefore);
+
+ pUg31xx->capData.rm = (_cap_u16_)tmp32;
+ pUg31xx->capData.rsoc = CalculateRsoc(pUg31xx->capData.rm, pUg31xx->capData.fcc);
+ UG31_LOGI("[%s]: Battery status -> %d / %d = %d\n", __func__, pUg31xx->capData.rm, pUg31xx->capData.fcc, pUg31xx->capData.rsoc);
+ }
+
+ if(pUg31xx->measData.rawCodeCharge > 0)
+ {
+ pUg31xx->measData.ccOffsetAdj = pUg31xx->measData.ccOffsetAdj + 1;
+ if(pUg31xx->measData.ccOffsetAdj > pUg31xx->cellParameter.standbyCurrent)
+ {
+ pUg31xx->measData.ccOffsetAdj = pUg31xx->cellParameter.standbyCurrent;
+ }
+ UG31_LOGI("[%s]: Adjust ADC1 offset = %d\n", __func__, pUg31xx->measData.ccOffsetAdj);
+ }
+ }
+
+ pUg31xx->batteryInfo.NAC = (_upi_u16_)pUg31xx->capData.rm;
+ pUg31xx->batteryInfo.LMD = (_upi_u16_)pUg31xx->capData.fcc;
+ pUg31xx->batteryInfo.RSOC = (_upi_u16_)pUg31xx->capData.rsoc;
+ UpiInitDsgCharge(&pUg31xx->capData);
+
+ UpiResetCoulombCounter(&pUg31xx->measData);
+
+ /// [AT-PM] : Save battery information to IC ; 01/31/2013
+ pUg31xx->sysData.rmFromIC = pUg31xx->batteryInfo.NAC;
+ pUg31xx->sysData.fccFromIC = pUg31xx->batteryInfo.LMD;
+ pUg31xx->sysData.rsocFromIC = (_sys_u8_)pUg31xx->batteryInfo.RSOC;
+ pUg31xx->sysData.tableUpdateIdxFromIC = pUg31xx->capData.tableUpdateIdx;
+ pUg31xx->sysData.deltaCapFromIC = pUg31xx->measData.lastDeltaCap;
+ pUg31xx->sysData.adc1ConvTime = pUg31xx->measData.adc1ConvertTime;
+ UpiSaveBatInfoTOIC(&pUg31xx->sysData);
+
+ pUg31xx->backupData.capData = &pUg31xx->capData;
+ pUg31xx->backupData.sysData = &pUg31xx->sysData;
+ pUg31xx->backupData.measData = &pUg31xx->measData;
+ UpiUpdateSuspendData(&pUg31xx->backupData, _UPI_TRUE_);
+
+#if 0
+ /// [AT-PM] : Backup data to file routine ; 02/21/2013
+ pUg31xx->backupData.capData = &pUg31xx->capData;
+ pUg31xx->backupData.sysData = &pUg31xx->sysData;
+ pUg31xx->backupData.measData = &pUg31xx->measData;
+ UpiBackupData(&pUg31xx->backupData);
+#endif
+ return (Status);
+}
+
+/**
+ * @brief upiGG_AccessMeasurementParameter
+ *
+ * Access measurement parameter
+ *
+ * @para read set _UPI_TRUE_ to read data from API
+ * @para pMeasPara pointer of GG_MEAS_PARA_TYPE
+ * @return GGSTATUS
+ */
+GGSTATUS upiGG_AccessMeasurementParameter(char *pObj, _upi_bool_ read, GG_MEAS_PARA_TYPE *pMeasPara)
+{
+ struct ug31xx_data *pUg31xx;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+
+ /// [AT-PM] : Read data ; 08/29/2012
+ if(read == _UPI_TRUE_)
+ {
+ pMeasPara->Adc1Gain = pUg31xx->cellParameter.adc1_ngain;
+ pMeasPara->Adc1Offset = pUg31xx->cellParameter.adc1_pos_offset;
+ pMeasPara->Adc2Gain = pUg31xx->cellParameter.adc2_gain;
+ pMeasPara->Adc2Offset = pUg31xx->cellParameter.adc2_offset;
+ pMeasPara->ITOffset = pUg31xx->cellParameter.adc_d5;
+ pMeasPara->ETOffset = pUg31xx->cellParameter.adc_d4;
+ pMeasPara->ProductType = pUg31xx->otpData.productType;
+ return (UG_SUCCESS);
+ }
+
+ /// [AT-PM] : Write data ; 08/29/2012
+ pUg31xx->cellParameter.adc1_ngain = pMeasPara->Adc1Gain;
+ pUg31xx->cellParameter.adc1_pos_offset = pMeasPara->Adc1Offset;
+ pUg31xx->cellParameter.adc2_gain = pMeasPara->Adc2Gain;
+ pUg31xx->cellParameter.adc2_offset = pMeasPara->Adc2Offset;
+ pUg31xx->cellParameter.adc_d5 = pMeasPara->ITOffset;
+ pUg31xx->cellParameter.adc_d4 = pMeasPara->ETOffset;
+ return (UG_SUCCESS);
+}
+
+#ifdef ENABLE_BQ27520_SW_CMD
+
+/**
+ * @brief TI_Cntl
+ *
+ * Control() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Cntl(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_u16_ CntlData;
+
+ CntlData = *pData;
+ switch(CntlData)
+ {
+ case UG_STD_CMD_CNTL_CONTROL_STATUS:
+ *pData = pUg31xx->bq27520Cmd.CntlControlStatus;
+ break;
+ case UG_STD_CMD_CNTL_DEVICE_TYPE:
+ *pData = 0x3103;
+ break;
+ case UG_STD_CMD_CNTL_FW_VERSION:
+ *pData = 0x0001;
+ break;
+ case UG_STD_CMD_CNTL_PREV_MACWRITE:
+ *pData = pUg31xx->bq27520Cmd.CntlPrevMacWrite;
+ break;
+ case UG_STD_CMD_CNTL_CHEM_ID:
+ *pData = 0x0001;
+ break;
+ case UG_STD_CMD_CNTL_OCV_CMD:
+ break;
+ case UG_STD_CMD_CNTL_BAT_INSERT:
+ if(!(pUg31xx->bq27520Cmd.Opcfg & UG_STD_CMD_OPCFG_BIE))
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags | UG_STD_CMD_FLAGS_BAT_DET;
+ }
+ break;
+ case UG_STD_CMD_CNTL_BAT_REMOVE:
+ if(!(pUg31xx->bq27520Cmd.Opcfg & UG_STD_CMD_OPCFG_BIE))
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags & (~UG_STD_CMD_FLAGS_BAT_DET);
+ }
+ break;
+ case UG_STD_CMD_CNTL_SET_HIBERNATE:
+ pUg31xx->bq27520Cmd.CntlControlStatus = pUg31xx->bq27520Cmd.CntlControlStatus | UG_STD_CMD_CNTL_CONTROL_STATUS_HIBERNATE;
+ break;
+ case UG_STD_CMD_CNTL_CLEAR_HIBERNATE:
+ pUg31xx->bq27520Cmd.CntlControlStatus = pUg31xx->bq27520Cmd.CntlControlStatus & (~UG_STD_CMD_CNTL_CONTROL_STATUS_HIBERNATE);
+ break;
+ case UG_STD_CMD_CNTL_SET_SLEEP_PLUS:
+ pUg31xx->bq27520Cmd.CntlControlStatus = pUg31xx->bq27520Cmd.CntlControlStatus | UG_STD_CMD_CNTL_CONTROL_STATUS_SNOOZE;
+ break;
+ case UG_STD_CMD_CNTL_CLEAR_SLEEP_PLUS:
+ pUg31xx->bq27520Cmd.CntlControlStatus = pUg31xx->bq27520Cmd.CntlControlStatus & (~UG_STD_CMD_CNTL_CONTROL_STATUS_SNOOZE);
+ break;
+ case UG_STD_CMD_CNTL_FACTORY_RESTORE:
+ break;
+ case UG_STD_CMD_CNTL_ENABLE_DLOG:
+ pUg31xx->bq27520Cmd.CntlControlStatus = pUg31xx->bq27520Cmd.CntlControlStatus | UG_STD_CMD_CNTL_CONTROL_STATUS_DLOGEN;
+ break;
+ case UG_STD_CMD_CNTL_DISABLE_DLOG:
+ pUg31xx->bq27520Cmd.CntlControlStatus = pUg31xx->bq27520Cmd.CntlControlStatus & (~UG_STD_CMD_CNTL_CONTROL_STATUS_DLOGEN);
+ break;
+ case UG_STD_CMD_CNTL_DF_VERSION:
+ *pData = 0x0000;
+ break;
+ case UG_STD_CMD_CNTL_SEALED:
+ pUg31xx->bq27520Cmd.CntlControlStatus = pUg31xx->bq27520Cmd.CntlControlStatus | UG_STD_CMD_CNTL_CONTROL_STATUS_SS;
+ break;
+ case UG_STD_CMD_CNTL_RESET:
+ if(!(pUg31xx->bq27520Cmd.CntlControlStatus & UG_STD_CMD_CNTL_CONTROL_STATUS_SS))
+ {
+ }
+ break;
+ default:
+ *pData = 0x0000;
+ break;
+ }
+
+ pUg31xx->bq27520Cmd.CntlPrevMacWrite = ((CntlData) > UG_STD_CMD_CNTL_PREV_MACWRITE) ? UG_STD_CMD_CNTL_PREV_MACWRITE : CntlData;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_AR
+ *
+ * AtRate() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_AR(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_s16_ AR;
+
+ AR = (_upi_s16_)(*pData);
+ if(AR != pUg31xx->bq27520Cmd.AR)
+ {
+ pUg31xx->bq27520Cmd.AR = AR;
+ }
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Artte
+ *
+ * AtRateTimeToEmpty() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Artte(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_s32_ Artte;
+
+ if(pUg31xx->bq27520Cmd.AR >= 0)
+ {
+ *pData = 65535;
+ }
+
+ Artte = (_upi_s32_)pUg31xx->batteryInfo.NAC;
+ Artte = Artte*60*(-1)/pUg31xx->bq27520Cmd.AR;
+ *pData = (_upi_u16_)Artte;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Temp
+ *
+ * Temperature() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Temp(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ if(pUg31xx->bq27520Cmd.Opcfg & UG_STD_CMD_OPCFG_WRTEMP)
+ {
+ /// [AT-PM] : Temperature is from host ; 10/11/2012
+ pUg31xx->bq27520Cmd.Temp = *pData;
+ }
+ else
+ {
+ /// [AT-PM] : Temperature is measured by uG31xx ; 10/11/2012
+ if(pUg31xx->bq27520Cmd.Opcfg & UG_STD_CMD_OPCFG_TEMPS)
+ {
+ /// [AT-PM] : Report external temperature ; 10/11/2012
+ *pData = pUg31xx->deviceInfo.ET;
+ }
+ else
+ {
+ /// [AT-PM] : Report internal temperature ; 10/11/2012
+ *pData = pUg31xx->deviceInfo.IT;
+ }
+ }
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Volt
+ *
+ * Voltage() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Volt(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = pUg31xx->deviceInfo.voltage_mV;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Flags
+ *
+ * Flags() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Flags(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ /// [AT-PM] : OTC - Overtemperature in charge ; 10/11/2012
+
+ /// [AT-PM] : OTD - Overtemperature in discharge ; 10/11/2012
+
+ /// [AT-PM] : CHG_INH - Charge inhibit ; 10/11/2012
+
+ /// [AT-PM] : XCHG - Charge suspend alert ; 10/11/2012
+
+ /// [AT-PM] : FC - Full-charged ; 10/11/2012
+ if(pUg31xx->batteryInfo.RSOC < pUg31xx->bq27520Cmd.FCClear)
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags & (~UG_STD_CMD_FLAGS_FC);
+ }
+ if(pUg31xx->bq27520Cmd.FCSet < 0)
+ {
+ if(pUg31xx->batteryInfo.RSOC == 100)
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags | UG_STD_CMD_FLAGS_FC;
+ }
+ }
+ else
+ {
+ if(pUg31xx->batteryInfo.RSOC > pUg31xx->bq27520Cmd.FCSet)
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags | UG_STD_CMD_FLAGS_FC;
+ }
+ }
+
+ /// [AT-PM] : CHG - (Fast) charging allowed ; 10/11/2012
+ if(pUg31xx->bq27520Cmd.Flags & UG_STD_CMD_FLAGS_FC)
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags & (~UG_STD_CMD_FLAGS_CHG);
+ }
+ else
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags | UG_STD_CMD_FLAGS_CHG;
+ }
+
+ /// [AT-PM] : OCV_GD - Good OCV measurement taken ; 10/11/2012
+
+ /// [AT-PM] : WAIT_ID - Waiting to identify inserted battery ; 10/11/2012
+
+ /// [AT-PM] : BAT_DET - Battery detected ; 10/11/2012
+ if(pUg31xx->userReg.regAlarm2Status & ALARM2_STATUS_OV1_ALARM)
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags | UG_STD_CMD_FLAGS_BAT_DET;
+ }
+ else
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags & (~UG_STD_CMD_FLAGS_BAT_DET);
+ }
+
+ /// [AT-PM] : SOC1 - State-of-charge threshold 1 (SOC1 Set) reached ; 10/11/2012
+ if(pUg31xx->batteryInfo.NAC > pUg31xx->bq27520Cmd.Soc1Clear)
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags & (~UG_STD_CMD_FLAGS_SOC1);
+ }
+ if(pUg31xx->batteryInfo.NAC < pUg31xx->bq27520Cmd.Soc1Set)
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags | UG_STD_CMD_FLAGS_SOC1;
+ }
+
+ /// [AT-PM] : SYSDOWN - System should shut down ; 10/11/2012
+
+ /// [AT-PM] : DSG - Discharging detected ; 10/11/2012
+ if(pUg31xx->deviceInfo.AveCurrent_mA <= 0)
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags | UG_STD_CMD_FLAGS_DSG;
+ }
+ else
+ {
+ pUg31xx->bq27520Cmd.Flags = pUg31xx->bq27520Cmd.Flags & (~UG_STD_CMD_FLAGS_DSG);
+ }
+
+ *pData = pUg31xx->bq27520Cmd.Flags;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Nac
+ *
+ * NominalAvailableCapacity() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Nac(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = pUg31xx->batteryInfo.NAC;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Fac
+ *
+ * FullAvailableCapacity() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Fac(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = pUg31xx->batteryInfo.LMD;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_RM
+ *
+ * RemainingCapacity() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_RM(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = pUg31xx->batteryInfo.NAC;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Fcc
+ *
+ * FullChargeCapacity() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Fcc(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = pUg31xx->batteryInfo.LMD;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_AI
+ *
+ * AverageCurrent() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_AI(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = pUg31xx->deviceInfo.AveCurrent_mA;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Tte
+ *
+ * TimeToEmpty() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Tte(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_s32_ Tte;
+
+ if(pUg31xx->deviceInfo.AveCurrent_mA >= 0)
+ {
+ *pData = 65535;
+ return (UG_SUCCESS);
+ }
+
+ Tte = (_upi_s32_)pUg31xx->batteryInfo.NAC;
+ Tte = Tte*60*(-1)/pUg31xx->deviceInfo.AveCurrent_mA;
+ *pData = (_upi_u16_)Tte;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Ttf
+ *
+ * TimeToFull() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Ttf(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_s32_ Ttf;
+
+ if(pUg31xx->deviceInfo.AveCurrent_mA <= 0)
+ {
+ *pData = 65535;
+ return (UG_SUCCESS);
+ }
+
+ Ttf = (_upi_s32_)pUg31xx->batteryInfo.LMD;
+ Ttf = Ttf - pUg31xx->batteryInfo.NAC;
+ Ttf = Ttf*90/pUg31xx->deviceInfo.AveCurrent_mA;
+ *pData = (_upi_u16_)Ttf;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_SI
+ *
+ * StandbyCurrent() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_SI(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_s16_ LowerBound;
+ _upi_s32_ NewSI;
+
+ /// [AT-PM] : Set initial SI ; 10/11/2012
+ if(pUg31xx->bq27520Cmd.SINow == 0)
+ {
+ pUg31xx->bq27520Cmd.SINow = pUg31xx->bq27520Cmd.InitSI;
+ }
+
+ LowerBound = pUg31xx->bq27520Cmd.InitSI*2;
+ if(LowerBound > 0)
+ {
+ LowerBound = LowerBound*(-1);
+ }
+
+ /// [AT-PM] : SI criteria - 2 x InitSI < Current < 0 ; 10/11/2012
+ if((pUg31xx->deviceInfo.AveCurrent_mA < 0) && (pUg31xx->deviceInfo.AveCurrent_mA > LowerBound))
+ {
+ /// [AT-PM] : Update SI every 1 minute ; 10/11/2012
+ if((pUg31xx->bq27520Cmd.SIWindow >= 60) && (pUg31xx->bq27520Cmd.SISample > 0))
+ {
+ NewSI = pUg31xx->bq27520Cmd.SIBuf/pUg31xx->bq27520Cmd.SISample;
+ NewSI = NewSI*7 + pUg31xx->bq27520Cmd.SINow*93;
+ NewSI = NewSI/100;
+ pUg31xx->bq27520Cmd.SINow = (_upi_s16_)NewSI;
+ pUg31xx->bq27520Cmd.SISample = -1;
+ pUg31xx->bq27520Cmd.SIBuf = 0;
+ pUg31xx->bq27520Cmd.SIWindow = 0;
+ }
+ else
+ {
+ pUg31xx->bq27520Cmd.SISample = pUg31xx->bq27520Cmd.SISample + 1;
+ pUg31xx->bq27520Cmd.SIWindow = pUg31xx->bq27520Cmd.SIWindow + pUg31xx->bq27520Cmd.DeltaSec;
+
+ /// [AT-PM] : Ignore the first sample ; 10/11/2012
+ if(pUg31xx->bq27520Cmd.SISample > 0)
+ {
+ pUg31xx->bq27520Cmd.SIBuf = pUg31xx->bq27520Cmd.SIBuf + pUg31xx->deviceInfo.AveCurrent_mA;
+ }
+ }
+ }
+ else
+ {
+ /// [AT-PM] : Ignore the last sample ; 10/11/2012
+ if(pUg31xx->bq27520Cmd.SISample > 0)
+ {
+ NewSI = pUg31xx->bq27520Cmd.SIBuf/pUg31xx->bq27520Cmd.SISample;
+ NewSI = NewSI*7 + pUg31xx->bq27520Cmd.SINow*93;
+ NewSI = NewSI/100;
+ pUg31xx->bq27520Cmd.SINow = (_upi_s16_)NewSI;
+ }
+ pUg31xx->bq27520Cmd.SISample = -1;
+ pUg31xx->bq27520Cmd.SIBuf = 0;
+ pUg31xx->bq27520Cmd.SIWindow = 0;
+ }
+
+ *pData = pUg31xx->bq27520Cmd.SINow;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Stte
+ *
+ * StandbyTimeToEmpty() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Stte(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_s32_ Stte;
+
+ if(pUg31xx->bq27520Cmd.SINow >= 0)
+ {
+ *pData = 65535;
+ return (UG_SUCCESS);
+ }
+
+ Stte = (_upi_s32_)pUg31xx->batteryInfo.NAC;
+ Stte = Stte*60*(-1)/pUg31xx->bq27520Cmd.SINow;
+ *pData = (_upi_u16_)Stte;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Mli
+ *
+ * MaxLoadCurrent() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Mli(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_s32_ NewMli;
+
+ /// [AT-PM] : Set initial MLI ; 10/11/2012
+ if(pUg31xx->bq27520Cmd.Mli == 0)
+ {
+ pUg31xx->bq27520Cmd.Mli = pUg31xx->bq27520Cmd.InitMaxLoadCurrent;
+ }
+
+ /// [AT-PM] : Get the start charging SOC ; 10/11/2012
+ if(pUg31xx->bq27520Cmd.Flags & UG_STD_CMD_FLAGS_DSG)
+ {
+ pUg31xx->bq27520Cmd.MliDsgSoc = (_upi_u8_)pUg31xx->batteryInfo.RSOC;
+ }
+
+ /// [AT-PM] : MLI criteria - Current < MLI ; 10/11/2012
+ if(pUg31xx->deviceInfo.AveCurrent_mA < pUg31xx->bq27520Cmd.Mli)
+ {
+ pUg31xx->bq27520Cmd.Mli = pUg31xx->deviceInfo.AveCurrent_mA;
+ }
+
+ /// [AT-PM] : Reduce MLI at FC ; 10/11/2012
+ if((pUg31xx->bq27520Cmd.Flags & UG_STD_CMD_FLAGS_FC) && (pUg31xx->bq27520Cmd.MliDsgSoc < 50))
+ {
+ NewMli = (_upi_s32_)pUg31xx->bq27520Cmd.InitMaxLoadCurrent;
+ NewMli = NewMli + pUg31xx->bq27520Cmd.Mli;
+ NewMli = NewMli/2;
+ pUg31xx->bq27520Cmd.Mli = (_upi_s16_)NewMli;
+ }
+
+ *pData = (_upi_u16_)pUg31xx->bq27520Cmd.Mli;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Stte
+ *
+ * MaxLoadTimeToEmpty() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Mltte(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_s32_ Mltte;
+
+ if(pUg31xx->deviceInfo.AveCurrent_mA >= 0)
+ {
+ *pData = 65535;
+ return (UG_SUCCESS);
+ }
+
+ Mltte = (_upi_s32_)pUg31xx->batteryInfo.NAC;
+ Mltte = Mltte*60*(-1)/pUg31xx->bq27520Cmd.Mli;
+ *pData = (_upi_u16_)Mltte;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_AE
+ *
+ * AvailableEnergy() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_AE(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_u32_ AE;
+
+ AE = (_upi_u32_)pUg31xx->batteryInfo.NAC;
+ AE = AE*pUg31xx->deviceInfo.voltage_mV/1000;
+ pUg31xx->bq27520Cmd.AE = (_upi_u16_)AE;
+ *pData = pUg31xx->bq27520Cmd.AE;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_AP
+ *
+ * AveragePower() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_AP(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_s32_ AP;
+
+ if((pUg31xx->deviceInfo.AveCurrent_mA == 0) || (pUg31xx->bq27520Cmd.APDsgTime == 0))
+ {
+ pUg31xx->bq27520Cmd.AP = 0;
+ *pData = 0;
+ return (UG_SUCCESS);
+ }
+
+ AP = (_upi_s32_)pUg31xx->batteryInfo.NAC;
+ AP = AP*pUg31xx->deviceInfo.voltage_mV/1000;
+
+ /// [AT-PM] : Average discharging power ; 10/11/2012
+ if(pUg31xx->deviceInfo.AveCurrent_mA > 0)
+ {
+ pUg31xx->bq27520Cmd.APStartDsgE = AP;
+ pUg31xx->bq27520Cmd.APDsgTime = 0;
+
+ pUg31xx->bq27520Cmd.APChgTime = pUg31xx->bq27520Cmd.APChgTime + pUg31xx->bq27520Cmd.DeltaSec;
+ AP = AP - pUg31xx->bq27520Cmd.APStartChgE;
+ AP = AP*3600/pUg31xx->bq27520Cmd.APChgTime;
+ pUg31xx->bq27520Cmd.AP = (_upi_s16_)AP;
+ }
+
+ /// [AT-PM] : Average charging power ; 10/11/2012
+ if(pUg31xx->deviceInfo.AveCurrent_mA < 0)
+ {
+ pUg31xx->bq27520Cmd.APStartChgE = AP;
+ pUg31xx->bq27520Cmd.APChgTime = 0;
+
+ pUg31xx->bq27520Cmd.APDsgTime = pUg31xx->bq27520Cmd.APDsgTime + pUg31xx->bq27520Cmd.DeltaSec;
+ AP = AP - pUg31xx->bq27520Cmd.APStartDsgE;
+ AP = AP*3600/pUg31xx->bq27520Cmd.APDsgTime;
+ pUg31xx->bq27520Cmd.AP = (_upi_s16_)AP;
+ }
+
+ *pData = (_upi_u16_)pUg31xx->bq27520Cmd.AP;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Ttecp
+ *
+ * TimeToEmptyAtConstantPower() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Ttecp(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_s32_ Ttecp;
+
+ if(pUg31xx->bq27520Cmd.AP >= 0)
+ {
+ *pData = 65535;
+ return (UG_SUCCESS);
+ }
+
+ Ttecp = (_upi_s32_)pUg31xx->bq27520Cmd.AE;
+ Ttecp = Ttecp*60*(-1)/pUg31xx->bq27520Cmd.AP;
+ *pData = (_upi_u16_)Ttecp;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Soh
+ *
+ * StateOfHealth() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Soh(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ _upi_u32_ Soh;
+
+ Soh = (_upi_u32_)pUg31xx->batteryInfo.LMD;
+ Soh = Soh*100/pUg31xx->bq27520Cmd.Dcap;
+
+ Soh = Soh & UG_STD_CMD_SOH_VALUE_MASK;
+ Soh = Soh | UG_STD_CMD_SOH_STATUS_READY;
+ *pData = (_upi_u16_)Soh;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_CC
+ *
+ * CycleCount() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_CC(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ if(pUg31xx->deviceInfo.AveCurrent_mA < 0)
+ {
+ pUg31xx->bq27520Cmd.CCBuf = pUg31xx->bq27520Cmd.CCBuf + pUg31xx->bq27520Cmd.CCLastNac - pUg31xx->batteryInfo.NAC;
+ }
+ pUg31xx->bq27520Cmd.CCLastNac = pUg31xx->batteryInfo.NAC;
+
+ if(pUg31xx->bq27520Cmd.CCBuf >= pUg31xx->bq27520Cmd.CCThreshold)
+ {
+ pUg31xx->bq27520Cmd.CC = pUg31xx->bq27520Cmd.CC + 1;
+ pUg31xx->bq27520Cmd.CCBuf = pUg31xx->bq27520Cmd.CCBuf - pUg31xx->bq27520Cmd.CCThreshold;
+ }
+
+ *pData = pUg31xx->bq27520Cmd.CC;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Soc
+ *
+ * StateOfCharge() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Soc(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = pUg31xx->batteryInfo.RSOC;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Nic
+ *
+ * NormalizedImpedanceCal() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Nic(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = 0;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Icr
+ *
+ * InstantaneousCurrentReading() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Icr(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = pUg31xx->deviceInfo.current_mA;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Dli
+ *
+ * DataLogIndex() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Dli(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = pUg31xx->bq27520Cmd.Dli;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Dlb
+ *
+ * DataLogBuffer() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Dlb(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = pUg31xx->bq27520Cmd.Dlb;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Itemp
+ *
+ * InternalTemperature() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Itemp(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = pUg31xx->deviceInfo.IT;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Opcfg
+ *
+ * OperationConfiguration() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Opcfg(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = (_upi_u16_)pUg31xx->bq27520Cmd.Opcfg;
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief TI_Dcap
+ *
+ * DesignCapacity() command
+ *
+ * @para pData address of data
+ * @return GGSTATUS
+ */
+GGSTATUS TI_Dcap(struct ug31xx_data *pUg31xx, _upi_u16_ *pData)
+{
+ *pData = pUg31xx->bq27520Cmd.Dcap;
+ return (UG_SUCCESS);
+}
+
+typedef GGSTATUS (*TIBq27520FuncPtr)(struct ug31xx_data *pUg31xx, _upi_u16_ *pData);
+typedef struct TIBq27520FuncTableST {
+ TIBq27520FuncPtr pFunc;
+ _upi_u8_ CmdCode;
+} TIBq27520FuncTableType;
+
+
+TIBq27520FuncTableType TI_Command[] = {
+ { TI_Cntl, UG_STD_CMD_CNTL, },
+ { TI_AR, UG_STD_CMD_AR, },
+ { TI_Artte, UG_STD_CMD_ARTTE, },
+ { TI_Temp, UG_STD_CMD_TEMP, },
+ { TI_Volt, UG_STD_CMD_VOLT, },
+ { TI_Flags, UG_STD_CMD_FLAGS, },
+ { TI_Nac, UG_STD_CMD_NAC, },
+ { TI_Fac, UG_STD_CMD_FAC, },
+ { TI_RM, UG_STD_CMD_RM, },
+ { TI_Fcc, UG_STD_CMD_FCC, },
+ { TI_AI, UG_STD_CMD_AI, },
+ { TI_Tte, UG_STD_CMD_TTE, },
+ { TI_Ttf, UG_STD_CMD_TTF, },
+ { TI_SI, UG_STD_CMD_SI, },
+ { TI_Stte, UG_STD_CMD_STTE, },
+ { TI_Mli, UG_STD_CMD_MLI, },
+ { TI_Mltte, UG_STD_CMD_MLTTE, },
+ { TI_AE, UG_STD_CMD_AE, },
+ { TI_AP, UG_STD_CMD_AP, },
+ { TI_Ttecp, UG_STD_CMD_TTECP, },
+ { TI_Soh, UG_STD_CMD_SOH, },
+ { TI_CC, UG_STD_CMD_CC, },
+ { TI_Soc, UG_STD_CMD_SOC, },
+ { TI_Nic, UG_STD_CMD_NIC, },
+ { TI_Icr, UG_STD_CMD_ICR, },
+ { TI_Dli, UG_STD_CMD_DLI, },
+ { TI_Dlb, UG_STD_CMD_DLB, },
+ { TI_Itemp, UG_STD_CMD_ITEMP, },
+ { TI_Opcfg, UG_STD_CMD_OPCFG, },
+ { TI_Dcap, UG_EXT_CMD_DCAP, },
+};
+
+/**
+ * @brief upiGG_FetchDataCommand
+ *
+ * Read the gas gauge status following TI bq27520's interface
+ *
+ * @para CommandCode command code
+ * @para pData address of returned data
+ * @return GGSTATUS
+ */
+GGSTATUS upiGG_FetchDataCommand(char *pObj, _upi_u8_ CommandCode, _upi_u16_ *pData)
+{
+ GGSTATUS Rtn;
+ int TotalCmd;
+ GG_DEVICE_INFO DevInfo;
+ GG_CAPACITY CapData;
+ _upi_u32_ DeltaT;
+ int CmdIdx;
+ struct ug31xx_data *pUg31xx;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+
+ Rtn = upiGG_ReadDeviceInfo(pObj, &DevInfo);
+ if(Rtn != UG_READ_DEVICE_INFO_SUCCESS)
+ {
+ return (Rtn);
+ }
+
+ DeltaT = pUg31xx->measData.deltaTime;
+ if(DeltaT >= 5000000)
+ {
+ upiGG_ReadCapacity(pObj, &CapData);
+ }
+
+ DeltaT = GetTickCount();
+ DeltaT = DeltaT - pUg31xx->bq27520Cmd.LastTime;
+ pUg31xx->bq27520Cmd.LastTime = GetTickCount();
+ pUg31xx->bq27520Cmd.DeltaSec = (_upi_u16_)(DeltaT/1000);
+
+ Rtn = UG_SUCCESS;
+ TotalCmd = sizeof(TI_Command)/sizeof(TIBq27520FuncTableType);
+ CmdIdx = 0;
+ while(1)
+ {
+ if(TI_Command[CmdIdx].CmdCode == CommandCode)
+ {
+ Rtn = (*TI_Command[CmdIdx].pFunc)(pUg31xx, pData);
+ break;
+ }
+
+ CmdIdx = CmdIdx + 1;
+ if(CmdIdx >= TotalCmd)
+ {
+ Rtn = UG_TI_CMD_OVERFLOW;
+ }
+ }
+
+ return (Rtn);
+}
+
+/**
+ * @brief upiGG_FetchDataParameter
+ *
+ * Set the parameter for bq27520 like command
+ *
+ * @para data parameters of GG_FETCH_DATA_PARA_TYPE
+ * @return GGSTATUS
+ */
+GGSTATUS upiGG_FetchDataParameter(char *pObj, GG_FETCH_DATA_PARA_TYPE data)
+{
+ GGSTATUS Rtn;
+ struct ug31xx_data *pUg31xx;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+
+ Rtn = UG_SUCCESS;
+
+ pUg31xx->bq27520Cmd.FCSet = data.FCSet;
+ pUg31xx->bq27520Cmd.FCClear = data.FCClear;
+ pUg31xx->bq27520Cmd.Soc1Set = data.Soc1Set;
+ pUg31xx->bq27520Cmd.Soc1Clear = data.Soc1Clear;
+ pUg31xx->bq27520Cmd.InitSI = data.InitSI;
+ pUg31xx->bq27520Cmd.InitMaxLoadCurrent = data.InitMaxLoadCurrent;
+ pUg31xx->bq27520Cmd.CCThreshold = data.CCThreshold;
+ pUg31xx->bq27520Cmd.Opcfg = data.Opcfg;
+ pUg31xx->bq27520Cmd.Dcap = data.Dcap;
+ return (Rtn);
+}
+
+#endif ///< end of ENABLE_BQ27520_SW_CMD
+
+/**
+ * @brief upiGG_DumpRegister
+ *
+ * Dump whole register value
+ *
+ * @para pBuf address of register value buffer
+ * @return data size
+ */
+_upi_u16_ upiGG_DumpRegister(char *pObj, _upi_u8_ * pBuf)
+{
+ _upi_u16_ idx;
+ struct ug31xx_data *pUg31xx;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+
+ idx = 0;
+ memcpy(pBuf + idx, pUg31xx->otpData.otp1, OTP1_SIZE);
+ idx = idx + OTP1_SIZE;
+ memcpy(pBuf + idx, pUg31xx->otpData.otp2, OTP2_SIZE);
+ idx = idx + OTP2_SIZE;
+ memcpy(pBuf + idx, pUg31xx->otpData.otp3, OTP3_SIZE);
+ idx = idx + OTP3_SIZE;
+ memcpy(pBuf + idx, &pUg31xx->userReg, sizeof(GG_USER_REG));
+ idx = idx + sizeof(GG_USER_REG);
+ memcpy(pBuf + idx, &pUg31xx->user2Reg, sizeof(GG_USER2_REG));
+ idx = idx + sizeof(GG_USER2_REG);
+ return (idx);
+}
+
+/**
+ * @brief upiGG_DumpCellTable
+ *
+ * Dump cell NAC table
+ *
+ * @para pTable address of cell table
+ * @return _UPI_NULL_
+ */
+void upiGG_DumpCellTable(char *pObj, CELL_TABLE *pTable)
+{
+ struct ug31xx_data *pUg31xx;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+ memcpy(pTable, &pUg31xx->cellTable, sizeof(CELL_TABLE));
+}
+
+/**
+ * @brief upiGG_UnInitial
+ *
+ * Un-initialize uG31xx
+ *
+ * @para pObj address of memory buffer allocated for uG31xx
+ * @return GGSTATUS
+ */
+GGSTATUS upiGG_UnInitial(char **pObj)
+{
+ struct ug31xx_data *pUg31xx;
+ pUg31xx = (struct ug31xx_data *)(*pObj);
+
+ UG31_LOGE("[%s]***** upiGG_UnInitial() to free memory ***** \n", __func__);
+
+ pUg31xx->backupData.backupDataIdx = BACKUP_MAX_LOG_SUSPEND_DATA;
+ while(pUg31xx->backupData.backupDataIdx)
+ {
+ pUg31xx->backupData.backupDataIdx = pUg31xx->backupData.backupDataIdx - 1;
+ kfree(pUg31xx->backupData.logData[pUg31xx->backupData.backupDataIdx]);
+ }
+
+ #if defined(uG31xx_OS_ANDROID)
+ #ifdef uG31xx_BOOT_LOADER
+ free(*pObj);
+ #else ///< else of uG31xx_BOOT_LOADER
+ kfree(*pObj);
+ #endif ///< end of uG31xx_BOOT_LOADER
+ #else ///< else of defined(uG31xx_OS_ANDROID)
+ free(*pObj);
+ #endif ///< end of defined(uG31xx_OS_ANDROID)
+ return (UG_SUCCESS);
+}
+
+/**
+ * @brief upiGG_DumpParameter
+ *
+ * Dump all parameter setting
+ *
+ * @para pTable address of cell parameter
+ * @return _UPI_NULL_
+ */
+void upiGG_DumpParameter(char *pObj, CELL_PARAMETER *pTable)
+{
+ struct ug31xx_data *pUg31xx;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+ memcpy(pTable, &pUg31xx->cellParameter, sizeof(CELL_PARAMETER));
+
+ // memcpy(&pTable->CELL_NAC_TABLE, &pUg31xx->realData, sizeof(GG_REAL_DATA));
+}
+
+/**
+ * @brief upiGG_FetchDebugData
+ *
+ * Fetch debug information data
+ *
+ * @para pObj address of memory buffer
+ * @para data address of GG_FETCH_CAP_DATA_TYPE
+ * @return _UPI_NULL_
+ */
+void upiGG_FetchDebugData(char *pObj, GG_FETCH_DEBUG_DATA_TYPE *data)
+{
+ struct ug31xx_data *pUg31xx;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+
+ data->versionMain = UG31XX_API_MAIN_VERSION;
+ data->versionOtp = UG31XX_API_OTP_VERSION;
+ data->versionSub = UG31XX_API_SUB_VERSION;
+
+ data->capDelta = pUg31xx->measData.stepCap;
+ data->capDsgCharge = pUg31xx->capData.dsgCharge;
+ data->capDsgChargeStart = pUg31xx->capData.dsgChargeStart;
+ data->capDsgChargeTime = pUg31xx->capData.dsgChargeTime;
+ data->capPreDsgCharge = pUg31xx->capData.preDsgCharge;
+ data->capSelfHour = pUg31xx->capData.selfDsgHour;
+ data->capSelfMilliSec = pUg31xx->capData.selfDsgMilliSec;
+ data->capSelfMin = pUg31xx->capData.selfDsgMin;
+ data->capSelfSec = pUg31xx->capData.selfDsgSec;
+ data->capStatus = pUg31xx->capData.status;
+ data->capTableUpdateIdx = pUg31xx->capData.tableUpdateIdx;
+ data->capTPTime = pUg31xx->capData.tpTime;
+
+ data->measAdc1ConvertTime = pUg31xx->measData.adc1ConvertTime;
+ data->measAdc1Gain = pUg31xx->measData.adc1Gain;
+ data->measAdc1Offset = pUg31xx->measData.adc1Offset;
+ data->measAdc2Gain = pUg31xx->measData.adc2Gain;
+ data->measAdc2Offset = pUg31xx->measData.adc2Offset;
+ data->measCCOffset = pUg31xx->measData.ccOffset;
+ data->measCharge = pUg31xx->measData.codeCharge;
+ data->measCodeBat1 = pUg31xx->measData.codeBat1;
+ data->measCodeCurrent = pUg31xx->measData.codeCurrent;
+ data->measCodeET = pUg31xx->measData.codeExtTemperature;
+ data->measCodeIT = pUg31xx->measData.codeIntTemperature;
+ data->measLastCounter = pUg31xx->measData.lastCounter;
+ data->measLastDeltaQ = pUg31xx->measData.lastDeltaCap;
+ data->measLastTimeTick = pUg31xx->measData.lastTimeTick;
+}
+
+/**
+ * @brief upiGG_DebugSwitch
+ *
+ * Enable/disable debug information to UART
+ *
+ * @para Enable set _UPI_TRUE_ to enable it
+ * @return NULL
+ */
+void upiGG_DebugSwitch(_upi_bool_ enable)
+{
+ Ug31DebugEnable = enable;
+}
+
+/**
+ * @brief upiGG_ForceTaper
+ *
+ * Force taper condition reached
+ *
+ * @para pObj address of memory buffer
+ * @para charger_full 1 if charger detects full
+ * @para dc_in_before 1 if dc in before suspend mode
+ * @para dc_in_now 1 if dc in after suspend mode
+ * @return NULL
+ */
+void upiGG_ForceTaper(char *pObj, int charger_full, int dc_in_before, int dc_in_now)
+{
+ struct ug31xx_data *pUg31xx;
+ _meas_s16_ now_step_cap;
+ _meas_s16_ now_current;
+ _meas_u16_ now_voltage;
+ _meas_u32_ now_delta_time;
+ _upi_u8_ cnt;
+ _upi_s32_ tmp32;
+
+ pUg31xx = (struct ug31xx_data *)pObj;
+ pUg31xx->capData.ggbTable = &pUg31xx->cellTable;
+ pUg31xx->capData.ggbParameter = &pUg31xx->cellParameter;
+ pUg31xx->capData.measurement = &pUg31xx->measData;
+ pUg31xx->capData.status = pUg31xx->capData.status | 0x0100;
+
+ if(dc_in_before == 0)
+ {
+ UG31_LOGI("[%s]: Enter suspend without charger -> no force taper\n", __func__);
+ return;
+ }
+
+ tmp32 = dsg_charge_before_suspend - delta_cap_during_suspend;
+ if(dc_in_now == 0)
+ {
+ now_current = pUg31xx->measData.curr;
+ now_current = now_current/10;
+ now_voltage = pUg31xx->measData.bat1Voltage;
+ now_voltage = now_voltage - now_current;
+
+ UG31_LOGI("[%s]: No dc in now (%d)\n", __func__, now_voltage);
+ tmp32 = tmp32*100;
+ if((pUg31xx->capData.status & 0x0000000c) == 0x00000008) ///< [AT-PM] : Check current status is dischargign ; 10/11/2013
+ {
+ if((wakeup_predict_rsoc < 95) &&
+ (tmp32 > pUg31xx->cellParameter.ILMD) &&
+ (now_voltage < pUg31xx->cellParameter.TPVoltage))
+ {
+ UG31_LOGI("[%s]: Predicted RSOC < 95 and charged capacity is not enough (%d < %d) and voltage is low (%d < %d ) in discharging -> no force taper\n",
+ __func__, delta_cap_during_suspend, dsg_charge_before_suspend, now_voltage, pUg31xx->cellParameter.TPVoltage);
+ return;
+ }
+ }
+ else
+ {
+ if((wakeup_predict_rsoc < 98) && (tmp32 > pUg31xx->cellParameter.ILMD))
+ {
+ UG31_LOGI("[%s]: Predicted RSOC (%d) < 98 and charged capacity is not enough (%d < %d) -> no force taper\n",
+ __func__, wakeup_predict_rsoc, delta_cap_during_suspend, dsg_charge_before_suspend);
+ return;
+ }
+ }
+ }
+ else
+ {
+ UG31_LOGI("[%s]: DC in now\n", __func__);
+ if(charger_full == 0)
+ {
+ UG31_LOGI("[%s]: No charger detect full event -> no force taper\n", __func__);
+ return;
+ }
+ if(wakeup_predict_rsoc < 90)
+ {
+ UG31_LOGI("[%s]: Predicted RSOC (%d) < 90 -> no force taper\n", __func__, wakeup_predict_rsoc);
+ return;
+ }
+ }
+
+ now_step_cap = pUg31xx->measData.stepCap;
+ now_current = pUg31xx->measData.curr;
+ now_voltage = pUg31xx->measData.bat1Voltage;
+ now_delta_time = pUg31xx->measData.deltaTime;
+
+ UG31_LOGI("[%s]: Force to taper START\n", __func__);
+
+ cnt = 100;
+ while(cnt)
+ {
+ /// [AT-PM] : Enter charging mode ; 08/14/2013
+ pUg31xx->measData.stepCap = 0;
+ pUg31xx->measData.deltaTime = 0;
+ pUg31xx->measData.curr = (_meas_s16_)pUg31xx->cellParameter.TPCurrent - 1;
+
+ UpiReadCapacity(&pUg31xx->capData);
+ pUg31xx->capData.tableUpdateDelayCnt = 1;
+ pUg31xx->batteryInfo.NAC = (_upi_u16_)pUg31xx->capData.rm;
+ pUg31xx->batteryInfo.LMD = (_upi_u16_)pUg31xx->capData.fcc;
+ pUg31xx->batteryInfo.RSOC = (_upi_u16_)pUg31xx->capData.rsoc;
+
+ /// [AT-PM] : Force to TP ; 08/14/2013
+ pUg31xx->measData.bat1Voltage = (_meas_u16_)pUg31xx->cellParameter.TPVoltage + 1;
+ pUg31xx->capData.tpTime = (_cap_u32_)pUg31xx->cellParameter.TPTime + 1;
+ pUg31xx->capData.tpTime = pUg31xx->capData.tpTime*1000;
+
+ UpiReadCapacity(&pUg31xx->capData);
+ pUg31xx->capData.tableUpdateDelayCnt = 1;
+ pUg31xx->capData.rm = pUg31xx->capData.fcc;
+ pUg31xx->capData.rsoc = 100;
+ pUg31xx->batteryInfo.NAC = (_upi_u16_)pUg31xx->capData.rm;
+ pUg31xx->batteryInfo.LMD = (_upi_u16_)pUg31xx->capData.fcc;
+ pUg31xx->batteryInfo.RSOC = (_upi_u16_)pUg31xx->capData.rsoc;
+
+ /// [AT-PM] : Recover to initial state ; 08/14/2013
+ pUg31xx->measData.curr = now_current;
+ pUg31xx->measData.bat1Voltage = now_voltage;
+ pUg31xx->measData.deltaTime = now_delta_time;
+
+ UpiReadCapacity(&pUg31xx->capData);
+ pUg31xx->capData.tableUpdateDelayCnt = 1;
+ pUg31xx->batteryInfo.NAC = (_upi_u16_)pUg31xx->capData.rm;
+ pUg31xx->batteryInfo.LMD = (_upi_u16_)pUg31xx->capData.fcc;
+ pUg31xx->batteryInfo.RSOC = (_upi_u16_)pUg31xx->capData.rsoc;
+
+ UG31_LOGI("[%s]: Force to taper loop %d -> %d / %d = %d\n", __func__,
+ cnt, pUg31xx->batteryInfo.NAC, pUg31xx->batteryInfo.LMD, pUg31xx->batteryInfo.RSOC);
+ if(pUg31xx->capData.rsoc >= 100)
+ {
+ break;
+ }
+
+ cnt = cnt - 1;
+ }
+
+ pUg31xx->measData.stepCap = now_step_cap;
+
+ UG31_LOGI("[%s]: Force to taper END (%d / %d = %d)\n", __func__,
+ pUg31xx->batteryInfo.NAC, pUg31xx->batteryInfo.LMD, pUg31xx->batteryInfo.RSOC);
+}
+
+/// ===========================================
+/// End of uG31xx_API.cpp
+/// ===========================================
+
|