diff options
Diffstat (limited to 'board/wmt/wmt_battery/gauge/upi/ug31xx_boot.c')
-rwxr-xr-x | board/wmt/wmt_battery/gauge/upi/ug31xx_boot.c | 804 |
1 files changed, 804 insertions, 0 deletions
diff --git a/board/wmt/wmt_battery/gauge/upi/ug31xx_boot.c b/board/wmt/wmt_battery/gauge/upi/ug31xx_boot.c new file mode 100755 index 0000000..b92ea75 --- /dev/null +++ b/board/wmt/wmt_battery/gauge/upi/ug31xx_boot.c @@ -0,0 +1,804 @@ +/** + * @filename ug31xx_boot.c + * + * uG31xx operation in bootloader + * + * @author AllenTeng <allen_teng@upi-semi.com> + */ + +#include <common.h> +#ifdef CONFIG_BATT_UPI +#include <asm/errno.h> +//#include <app.h> +//#include <debug.h> +//#include <arch/arm.h> +//#include <dev/udc.h> +//#include <linux/string.h> +//#include <kernel/thread.h> +//#include <arch/ops.h> +//#include <malloc.h> + +//#include <stdarg.h> + +#include "../../wmt_battery.h" + +#include "ug31xx_boot_i2c.h" +#include "ug31xx_boot.h" +#include "uG31xx_API.h" + +#define UG31XX_BOOT_VERSION (12) + +#define UG31XX_BOOT_STATUS_FCC_IS_0 (1<<0) +#define UG31XX_BOOT_STATUS_IC_IS_NOT_ACTIVE (1<<1) +#define UG31XX_BOOT_STATUS_WRONG_PRODUCT_TYPE (1<<2) +#define DPRINTF(x,args...) printf("UG31xx " x , ##args) + +extern void ug31xx_init_i2c(int i2c_dev); + +UG31xxDataType ug31_data; + +typedef struct UG31xxDataInternalST { + UG31xxDataType *info; + + CELL_PARAMETER ggbParameter; + CELL_TABLE ggbCellTable; + + OtpDataType otpData; + MeasDataType measData; + SystemDataType sysData; + + int tpTime; + int status; +} UG31xxDataInternalType; + +#undef bool +typedef enum _bool {false, true} bool; + +#include "ggb/ug31xx_ggb_data_uboot_wms8309_wm8_20130820_110949.h" +#include "ggb/ug31xx_ggb_data_uboot_wms8309_c7_20130725_164935.h" +#include "ggb/ug31xx_ggb_data_uboot_wms8309_c7_20130910_130553.h" +#include "ggb/ug31xx_ggb_data_uboot_wms7320_20130718_200031.h" +#include "ggb/ug31xx_ggb_data_uboot_cw500_20130801_103638.h" +#include "ggb/ug31xx_ggb_data_uboot_mp718_20131004_070110.h" +#include "ggb/ug31xx_ggb_data_uboot_t73v_20131120_001204.h" + +enum { + UG31XX_ID_3105, + UG31XX_ID_3102, +}; + +static int g_ug31xx_id; + +struct ggb_info { + char *name; + char *data; +}; + +/* Extern Function */ +static struct ggb_info ggb_arrays[] = { + { + .name = "wms8309wm8", + .data = FactoryGGBXFile_wms8309_wm8, + }, { + .name = "wms7320", + .data = FactoryGGBXFile_wms7320, + }, { + .name = "wms8309c7_3900mAh", + .data = FactoryGGBXFile_wms8309_c7_3900mAh, + }, { + .name = "wms8309c7_3000mAh", + .data = FactoryGGBXFile_wms8309_c7_3000mAh, + }, { + .name = "cw500", + .data = FactoryGGBXFile_cw500, + }, { + .name = "mp718", + .data = FactoryGGBXFile_mp718, + }, { + .name = "t73v", + .data = FactoryGGBXFile_t73v, + }, +}; + +struct ug31xx_param { + int i2c_adapter; + int external_temperature; + int charge_temperature_range[2]; + struct ggb_info *ggb; +}; + +static struct ug31xx_param ug31xx_param = { + .i2c_adapter = 1, + .external_temperature = 1, + .charge_temperature_range = { -150, 600 }, + .ggb = &ggb_arrays[0], +}; + +static int parse_battery_param(void) +{ + enum { + idx_i2c, + idx_et, + idx_temp0, + idx_temp1, + idx_max + }; + long ps[idx_max] = { 0, }; + char *p, *env; + char *endp; + int i = 0; + + env = p = getenv("wmt.battery.param"); + if (!p) + return -EINVAL; + + if (!prefixcmp(p, "ug3105")) + g_ug31xx_id = UG31XX_ID_3105; + else if (!prefixcmp(p, "ug3102")) + g_ug31xx_id = UG31XX_ID_3102; + else + return -EINVAL; + + p += 7; // skip "ug3105:" + + while (i < idx_max) { + ps[i++] = simple_strtol(p, &endp, 10); + if (*endp == '\0') + break; + p = endp + 1; + + if (*p == '\0') + break; + } + + ug31xx_param.i2c_adapter = ps[idx_i2c]; + ug31xx_param.external_temperature = ps[idx_et]; + if (ps[idx_temp1] > ps[idx_temp0]) { + ug31xx_param.charge_temperature_range[0] = ps[idx_temp0]; + ug31xx_param.charge_temperature_range[1] = ps[idx_temp1]; + } + + for (i = 0; i < ARRAY_SIZE(ggb_arrays); i++) { + if (strstr(env, ggb_arrays[i].name)) { + ug31xx_param.ggb = &ggb_arrays[i]; + break; + } + } + + printf("%s i2c%d, ggb %s, %s, charge temperature range [%d, %d]\n", + (g_ug31xx_id == UG31XX_ID_3105) ? "ug3105" : "ug3102", + ug31xx_param.i2c_adapter, + ug31xx_param.ggb->name, + ug31xx_param.external_temperature ? "ET" : "IT", + ug31xx_param.charge_temperature_range[0], + ug31xx_param.charge_temperature_range[1]); + return 0; +} + +/** + * @brief GetTickCount + * + * Get tick count in milli-second + * + * @return tick count + */ +_upi_u32_ GetTickCount(void) +{ + return (0); +} + +/** + * @brief GetSysTickCount + * + * Get system tick count in milli-second + * + * @return tick count + */ +_upi_u32_ GetSysTickCount(void) +{ + return (0); +} + +/** + * @brief ug31_dprintk + * + * print debug message + * + * @para level debug message level + * @para fmt debug message + * @return message length + */ +#if 0 +int ug31_dprintk(int level, const char *fmt, ...) +{ + va_list args; + int r; + + va_start(args, fmt); + //r = dprintk(level, fmt, args); + r = NULL; + va_end(args); + return (r); +} +#endif + + +#define TP_REACH_SOC (100) + +void CheckRsocBeforeTP(UG31xxDataInternalType *obj) +{ + int rm; + + if(obj->sysData.rsocFromIC >= TP_REACH_SOC) + { + obj->sysData.rsocFromIC = TP_REACH_SOC - 1; + + rm = (int)obj->sysData.rsocFromIC; + rm = rm*obj->sysData.fccFromIC/100; + obj->sysData.rmFromIC = (_sys_u16_)rm; + return; + } + + if(obj->sysData.rmFromIC > obj->sysData.fccFromIC) + { + obj->sysData.rmFromIC = obj->sysData.fccFromIC; + } +} + +/** + * @brief ResetFullCharge + * + * Reset full charge checking module + * + * @para obj address of UG31xxDataInternalType + * @return NULL + */ +void ResetFullCharge(UG31xxDataInternalType *obj) +{ + obj->tpTime = 0; + + CheckRsocBeforeTP(obj); +} + +#define TP_COUNT_INTERVAL (5) + +/** + * @brief FullChargeCheck + * + * Check full charge condition + * + * @para obj address of UG31xxDataInternalType + * @return NULL + */ +void FullChargeCheck(UG31xxDataInternalType *obj) +{ + if(obj->tpTime >= obj->ggbParameter.TPTime) + { + return; + } + + /// [AT-PM] : Check taper voltage ; 02/01/2013 + if(obj->measData.bat1Voltage < obj->ggbParameter.TPVoltage) + { + ResetFullCharge(obj); + return; + } + + /// [AT-PM] : Check taper current ; 02/01/2013 + if((obj->measData.curr < obj->ggbParameter.standbyCurrent) || + (obj->measData.curr > obj->ggbParameter.TPCurrent)) + { + ResetFullCharge(obj); + return; + } + + /// [AT-PM] : Check taper time ; 02/01/2013 + obj->tpTime = obj->tpTime + TP_COUNT_INTERVAL; + if(obj->tpTime < obj->ggbParameter.TPTime) + { + CheckRsocBeforeTP(obj); + return; + } + + /// [AT-PM] : Set full charge condition ; 02/01/2013 + obj->sysData.rsocFromIC = TP_REACH_SOC; + obj->sysData.rmFromIC = obj->sysData.fccFromIC; +} + +/** + * @brief SetMemoryMapping + * + * Set memory mapping + * + * @para data address of UG31xxDataType + * @para obj address of UG31xxDataInternalType pointer + * @return NULL + */ +void SetMemoryMapping(UG31xxDataType *data, UG31xxDataInternalType **obj) +{ + (*obj) = (UG31xxDataInternalType *)data->buf; + (*obj)->info = data; + (*obj)->measData.sysData = &((*obj)->sysData); + (*obj)->measData.otp = &((*obj)->otpData); + (*obj)->sysData.ggbXBuf = (GGBX_FILE_HEADER *)(ug31xx_param.ggb->data); + (*obj)->sysData.ggbParameter = &((*obj)->ggbParameter); + (*obj)->sysData.ggbCellTable = &((*obj)->ggbCellTable); + (*obj)->sysData.otpData = &((*obj)->otpData); + //printf("[SetMemoryMapping] ggb_tag (%d) = %d\n", sizeof((*obj)->sysData.ggbXBuf->ggb_tag), (*obj)->sysData.ggbXBuf->ggb_tag); + //printf("[SetMemoryMapping] sum16 (%d) = %d\n", sizeof((*obj)->sysData.ggbXBuf->sum16), (*obj)->sysData.ggbXBuf->sum16); + //printf("[SetMemoryMapping] time_stamp (%d) = %d\n", sizeof((*obj)->sysData.ggbXBuf->time_stamp), (*obj)->sysData.ggbXBuf->time_stamp); + //printf("[SetMemoryMapping] length (%d) = %d\n", sizeof((*obj)->sysData.ggbXBuf->length), (*obj)->sysData.ggbXBuf->length); + //printf("[SetMemoryMapping] num_ggb (%d) = %d\n", sizeof((*obj)->sysData.ggbXBuf->num_ggb), (*obj)->sysData.ggbXBuf->num_ggb); +} + +#define CURRENT_MAGIC_NUMBER (4) +#define OCV_TABLE_INDEX (1) + +static int OcvTableSoc[] = { + 100, + 95, + 90, + 85, + 80, + 75, + 70, + 65, + 60, + 55, + 50, + 45, + 40, + 35, + 30, + 25, + 20, + 15, + 10, + 5, + 0, +}; + +/** + * @brief InitCharge + * + * Look up initial charge from table + * + * @para obj address of UG31xxDataInternalType + * @return NULL + */ +void InitCharge(UG31xxDataInternalType *obj) +{ + int volt; + int tmp; + int idxTemp; + int idxSoc; + int ocv; + + /// [AT-PM] : FCC is equal to ILMD ; 02/24/2013 + obj->info->fcc = (int)obj->ggbParameter.ILMD; + + /// [AT-PM] : Real battery voltage ; 02/24/2013 + volt = (int)obj->measData.bat1Voltage; + tmp = (int)obj->measData.curr; + tmp = tmp/CURRENT_MAGIC_NUMBER; + if(tmp > 0) + { + volt = volt - tmp; + } + + /// [AT-PM] : Look up table ; 02/24/2013 + idxSoc = 0; + while(idxSoc < OCV_NUMS) + { + idxTemp = 0; + ocv = 0; + while(idxTemp < TEMPERATURE_NUMS) + { + ocv = ocv + obj->ggbCellTable.INIT_OCV[idxTemp][OCV_TABLE_INDEX][idxSoc]; + idxTemp = idxTemp + 1; + } + ocv = ocv/TEMPERATURE_NUMS; + + if(volt >= ocv) + { + break; + } + + idxSoc = idxSoc + 1; + } + if(idxSoc < OCV_NUMS) + { + obj->info->rsoc = OcvTableSoc[idxSoc]; + } + else + { + obj->info->rsoc = 0; + } + + /// [AT-PM] : Calculate RM ; 02/24/2013 + tmp = obj->info->rsoc; + tmp = tmp*obj->info->fcc/CONST_PERCENTAGE; + obj->info->rm = tmp; +} + +/// =========================================================================== +/// Extern region +/// =========================================================================== + +#define DEFAULT_ADC1_CONV_TIME (1250) +#define DEFAULT_TIME_TICK (0xFFFFFFFF) + +/** + * @brief UpiBootInitial + * + * Initialize uG31xx + * + * @para data address of UG31xxDataType + * @return UPI_BOOT_RTN + */ +int UpiBootInitial(UG31xxDataType *data) +{ + UG31xxDataInternalType *obj; + + //dprintf(INFO, "[UpiBootInitial] Version = %d\n", UG31XX_BOOT_VERSION); + printf("[UpiBootInitial] Version = %d\n", UG31XX_BOOT_VERSION); + + /// [AT-PM] : Create memory buffer ; 02/01/2013 + data->buf = (char *)malloc(sizeof(UG31xxDataInternalType)); + memset(data->buf, 0, sizeof(UG31xxDataInternalType)); + obj = _UPI_NULL_; + SetMemoryMapping(data, &obj); + + data->version = UG31XX_BOOT_VERSION; + obj->status = 0; + + //dprintf(INFO, "[UpiBootInitial] data->ug31xx_i2c_dev = %d\n",data->ug31xx_i2c_dev); + /// [AT-PM] : Initial I2C device ; 02/04/2013 + //ug31xx_init_i2c(data->ug31xx_i2c_dev); + + /// [AT-PM] : Load GGB data ; 02/24/2013 + UpiInitSystemData(&obj->sysData); + printf("[UPI Boot GGB]: %d (0x%04x)\n", obj->ggbCellTable.INIT_OCV[0][0][0], obj->ggbCellTable.INIT_OCV[0][0][0]); + printf("[UPI Boot GGB]: %d (0x%04x)\n", obj->ggbParameter.adc1_pgain, obj->ggbParameter.adc1_pgain); + printf("[UPI Boot GGB]: %d (0x%04x)\n", obj->ggbParameter.adc1_ngain, obj->ggbParameter.adc1_ngain); + printf("[UPI Boot GGB]: %d (0x%04x)\n", obj->ggbParameter.adc1_pos_offset, obj->ggbParameter.adc1_pos_offset); + printf("[UPI Boot GGB]: %d (0x%04x)\n", obj->ggbParameter.adc2_gain, obj->ggbParameter.adc2_gain); + printf("[UPI Boot GGB]: %d (0x%04x)\n", obj->ggbParameter.adc2_offset, obj->ggbParameter.adc2_offset); + + /// [AT-PM] : Get capacity information from IC ; 02/24/2013 + UpiLoadBatInfoFromIC(&obj->sysData); + if(obj->sysData.fccFromIC == 0) + { + //dprintf(CRITICAL, "[UpiBootInitial] Capacity in uG31xx is invalid.\n"); + printf("[UpiBootInitial] Capacity in uG31xx is invalid.\n"); + obj->status = obj->status | UG31XX_BOOT_STATUS_FCC_IS_0; + } + + /// [AT-PM] : Check IC is active or not ; 02/24/2013 + if(UpiCheckICActive() == _UPI_TRUE_) + { + //dprintf(CRITICAL, "[UpiBootInitial] uG31xx is not actived.\n"); + printf("[UpiBootInitial] uG31xx is not actived.\n"); + obj->status = obj->status | UG31XX_BOOT_STATUS_IC_IS_NOT_ACTIVE; + + /// [AT-PM] : Active uG31xx ; 02/24/2013 + if(UpiActiveUg31xx() != SYSTEM_RTN_PASS) + { + return (UPI_BOOT_RTN_UG31XX_NOT_ACTIVE); + } + + /// [AT-PM] : Initialize ADC ; 02/24/2013 + UpiSetupAdc(&obj->sysData); + + /// [AT-PM] : Initialize system ; 02/24/2013 + UpiSetupSystem(&obj->sysData); + } + + /// [AT-PM] : Get OTP data ; 02/24/2013 + API_I2C_Read(SECURITY, UG31XX_I2C_HIGH_SPEED_MODE, UG31XX_I2C_TEM_BITS_MODE, OTP1_BYTE1, OTP1_SIZE, obj->otpData.otp1); + API_I2C_Read(SECURITY, UG31XX_I2C_HIGH_SPEED_MODE, UG31XX_I2C_TEM_BITS_MODE, OTP2_BYTE1, OTP2_SIZE, obj->otpData.otp2); + API_I2C_Read(NORMAL, UG31XX_I2C_HIGH_SPEED_MODE, UG31XX_I2C_TEM_BITS_MODE, OTP6_BYTE1, OTP3_SIZE, obj->otpData.otp3); + #ifdef UPI_UBOOT_DEBUG_MSG + printf("[UpiBootInitial] %02x %02x %02x %02x\n", + obj->otpData.otp1[0], obj->otpData.otp1[1], obj->otpData.otp1[2], obj->otpData.otp1[3]); + printf("[UpiBootInitial] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + obj->otpData.otp2[0], obj->otpData.otp2[1], obj->otpData.otp2[2], obj->otpData.otp2[3], + obj->otpData.otp2[4], obj->otpData.otp2[5], obj->otpData.otp2[6], obj->otpData.otp2[7], + obj->otpData.otp2[8], obj->otpData.otp2[9], obj->otpData.otp2[10], obj->otpData.otp2[11], + obj->otpData.otp2[12], obj->otpData.otp2[13], obj->otpData.otp2[14], obj->otpData.otp2[15]); + printf("[UpiBootInitial] %02x %02x %02x %02x\n", + obj->otpData.otp3[0], obj->otpData.otp3[1], obj->otpData.otp3[2], obj->otpData.otp3[3]); + #endif ///< end of UPI_UBOOT_DEBUG_MSG + UpiConvertOtp(&obj->otpData); + if(obj->otpData.productType != UG31XX_PRODUCT_TYPE_0) + { + //dprintf(CRITICAL, "[UpiBootInitial] uG31xx product type is not %d (%d)\n", UG31XX_PRODUCT_TYPE_0, obj->otpData.productType); + printf("[UpiBootInitial] uG31xx product type is not %d (%d)\n", UG31XX_PRODUCT_TYPE_0, obj->otpData.productType); + obj->status = obj->status | UG31XX_BOOT_STATUS_WRONG_PRODUCT_TYPE; + return (UPI_BOOT_RTN_INVALID_PRODUCT_TYPE); + } + + /// [AT-PM] : Initialize UG31xxInternalDataType ; 02/24/2013 + if(obj->status & (UG31XX_BOOT_STATUS_FCC_IS_0 | UG31XX_BOOT_STATUS_IC_IS_NOT_ACTIVE)) + { + /// [AT-PM] : Data for IC not active ; 02/24/2013 + obj->measData.lastDeltaCap = 0; + obj->measData.adc1ConvertTime = DEFAULT_ADC1_CONV_TIME; + /// [AT-PM] : Do measurement ; 02/24/2013 + obj->measData.lastTimeTick = DEFAULT_TIME_TICK; + UpiMeasurement(&obj->measData); + data->volt = (int)obj->measData.bat1Voltage; + data->curr = (int)obj->measData.curr; + data->intTemp = (int)obj->measData.intTemperature; + data->extTemp = (int)obj->measData.extTemperature; + /// [AT-PM] : Look up initial capacity from table ; 02/24/2013 + InitCharge(obj); + obj->sysData.rmFromIC = (_sys_u16_)obj->info->rm; + obj->sysData.fccFromIC = (_sys_u16_)obj->info->fcc; + obj->sysData.rsocFromIC = (_sys_u8_)obj->info->rsoc; + //dprintf(INFO, "[UpiBootInitial] (Lookup Table) %d / %d / %d - %d / %d = %d\n", data->volt, data->curr, data->intTemp, data->rm, data->fcc, data->rsoc); + printf("[UpiBootInitial] (Lookup Table) %d / %d / %d - %d / %d = %d\n", data->volt, data->curr, data->intTemp, data->rm, data->fcc, data->rsoc); + } + else + { + /// [AT-PM] : Data for IC active ; 02/24/2013 + obj->measData.lastDeltaCap = obj->sysData.deltaCapFromIC; + obj->measData.adc1ConvertTime = obj->sysData.adc1ConvTime; + /// [AT-PM] : Do measurement ; 02/24/2013 + obj->measData.lastTimeTick = DEFAULT_TIME_TICK; + UpiMeasurement(&obj->measData); + data->volt = (int)obj->measData.bat1Voltage; + data->curr = (int)obj->measData.curr; + data->intTemp = (int)obj->measData.intTemperature; + data->extTemp = (int)obj->measData.extTemperature; + /// [AT-PM] : Set capacity information ; 02/24/2013 + obj->info->rm = (int)obj->sysData.rmFromIC; + obj->info->fcc = (int)obj->sysData.fccFromIC; + obj->info->rsoc = (int)obj->sysData.rsocFromIC; + //dprintf(INFO, "[UpiBootInitial] (Load From IC) %d / %d / %d - %d / %d = %d\n", data->volt, data->curr, data->intTemp, data->rm, data->fcc, data->rsoc); + printf("[UpiBootInitial] (Load From IC) %d / %d / %d - %d / %d = %d\n", data->volt, data->curr, data->intTemp, data->rm, data->fcc, data->rsoc); + } + return (UPI_BOOT_RTN_PASS); +} + +/** + * @brief UpiBootMain + * + * Main function of uG31xx + * + * @para data address of UG31xxDataType + * @return UPI_BOOT_RTN + */ +int UpiBootMain(UG31xxDataType *data) +{ + UG31xxDataInternalType *obj; + MEAS_RTN_CODE rtn; + + //dprintf(INFO, "[UpiBootMain]\n"); + //printf("[UpiBootMain]\n"); + obj = _UPI_NULL_; + SetMemoryMapping(data, &obj); + + /// [AT-PM] : Do measurement ; 02/24/2013 + obj->measData.lastTimeTick = DEFAULT_TIME_TICK; + rtn = UpiMeasurement(&obj->measData); + if(rtn != MEAS_RTN_PASS) + { + //dprintf(INFO, "[UpiBootMain] uG31xx measurement routine fail 0x%02x\n", rtn); + printf("[UpiBootMain] uG31xx measurement routine fail 0x%02x\n", rtn); + + data->rm = 0; + data->fcc = 0; + data->rsoc = 0; + return (rtn); + } + + /// [AT-PM] : Update capacity ; 02/13/2013 + obj->sysData.voltage = obj->measData.bat1Voltage; + if((obj->measData.curr < 0) && (obj->measData.stepCap > 0)) + { + obj->measData.stepCap = 0; + } + else if((obj->measData.curr > 0) && (obj->measData.stepCap < 0)) + { + obj->measData.stepCap = 0; + } + UpiUpdateBatInfoFromIC(&obj->sysData, obj->measData.stepCap); + + /// [AT-PM] : Reset coulomb counter ; 02/24/2013 + obj->measData.lastTimeTick = DEFAULT_TIME_TICK; + if(obj->measData.deltaCap > 10) + { + UpiResetCoulombCounter(&obj->measData); + } + + //dprintf(INFO, "[UpiBootMain] %d / %d / %d\n", obj->measData.codeBat1, obj->measData.codeCurrent, obj->measData.codeIntTemperature); + //dprintf(INFO, "[UpiBootMain] %d - %d / %d - %d\n", obj->measData.adc1Gain, obj->measData.adc1Offset, obj->measData.adc2Gain, obj->measData.adc2Offset); + //dprintf(INFO, "[UpiBootMain] Voltage : %d - %d\n", obj->ggbParameter.adc2_gain, obj->ggbParameter.adc2_offset); + //dprintf(INFO, "[UpiBootMain] Current : %d - %d - %d\n", obj->ggbParameter.adc1_pgain, obj->ggbParameter.adc1_ngain, obj->ggbParameter.adc1_pos_offset); + //dprintf(INFO, "[UpiBootMain] Int. T : %d\n", obj->ggbParameter.adc_d3); + + //printf("[UpiBootMain] %d / %d / %d\n", obj->measData.codeBat1, obj->measData.codeCurrent, obj->measData.codeIntTemperature); + //printf("[UpiBootMain] %d - %d / %d - %d\n", obj->measData.adc1Gain, obj->measData.adc1Offset, obj->measData.adc2Gain, obj->measData.adc2Offset); + //printf("[UpiBootMain] Voltage : %d - %d\n", obj->ggbParameter.adc2_gain, obj->ggbParameter.adc2_offset); + //printf("[UpiBootMain] Current : %d - %d - %d\n", obj->ggbParameter.adc1_pgain, obj->ggbParameter.adc1_ngain, obj->ggbParameter.adc1_pos_offset); + //printf("[UpiBootMain] Int. T : %d\n", obj->ggbParameter.adc_d3); + + data->volt = (int)obj->measData.bat1Voltage; + data->curr = (int)obj->measData.curr; + data->intTemp = (int)obj->measData.intTemperature; + data->extTemp = (int)obj->measData.extTemperature; + + /// [AT-PM] : Full charge determination ; 02/01/2013 + FullChargeCheck(obj); + + /// [AT-PM] : Refresh capacity information ; 02/24/2013 + data->rm = (int)obj->sysData.rmFromIC; + data->fcc = (int)obj->sysData.fccFromIC; + data->rsoc = (int)obj->sysData.rsocFromIC; + //dprintf(INFO, "[UpiBootMain] %d / %d / %d - %d / %d = %d\n", data->volt, data->curr, data->intTemp, data->rm, data->fcc, data->rsoc); + //printf("[UpiBootMain] %d / %d / %d - %d / %d = %d\n", data->volt, data->curr, data->intTemp, data->rm, data->fcc, data->rsoc); + + /// [AT-PM] : Save battery information back to IC ; 02/24/2013 + if(obj->status & (UG31XX_BOOT_STATUS_FCC_IS_0 | UG31XX_BOOT_STATUS_IC_IS_NOT_ACTIVE)) + { + obj->sysData.fccFromIC = 0; + } + UpiSaveBatInfoTOIC(&obj->sysData); + obj->sysData.fccFromIC = (_sys_u16_)data->fcc; +#if 0 + printf("battery volt = %d\n", data->volt); + printf("battery curr = %d\n", data->curr); + printf("battery intTemp = %d\n", data->intTemp); + printf("battery extTemp = %d\n", data->extTemp); + printf("battery rm = %d\n", data->rm); + printf("battery fcc = %d\n", data->fcc); + printf("battery rsoc = %d\n", data->rsoc); +#endif + return (UPI_BOOT_RTN_PASS); +} + +/** + * @brief UpiBootUnInitial + * + * Un-initialize uG31xx + * + * @para data address of UG31xxDataType + * @return UPI_BOOT_RTN + */ +int UpiBootUnInitial(UG31xxDataType *data) +{ + printf("[UpiBootUninitial]\n"); + + free(data->buf); + return (UPI_BOOT_RTN_PASS); +} + +/* + * WMT MCE: Use gpio3 on ug31xx as a switch to control charger. + */ +static void hw_charging_set(bool enable) +{ + if (g_ug31xx_id == UG31XX_ID_3105) { + API_I2C_SingleWrite(0, 0, 0, 0x16, enable ? 0x2 : 0x0); + } else if (g_ug31xx_id == UG31XX_ID_3102) { + u8 data = 0; + API_I2C_SingleRead(0, 0, 0 ,REG_CTRL1, &data); + if (enable) + data |= CTRL1_IO1DATA; + else + data &= ~CTRL1_IO1DATA; + API_I2C_SingleWrite(0, 0, 0, REG_CTRL1, data); + } +} + +static void inline hw_charging_disable(void) +{ + hw_charging_set(false); +} + +static void inline hw_charging_enable(void) +{ + hw_charging_set(true); +} + +static unsigned short percentage = -1; + +int upi_read_percentage(void) +{ + UpiBootMain(&ug31_data); + percentage = ug31_data.rsoc; + + if (g_ug31xx_id == UG31XX_ID_3105) { + printf("%s: percentage = %d, temperature %d\n", + __FUNCTION__, percentage, ug31_data.extTemp); + if (ug31xx_param.external_temperature) { + if (ug31_data.extTemp < ug31xx_param.charge_temperature_range[0] || + ug31_data.extTemp > ug31xx_param.charge_temperature_range[1]) { + hw_charging_disable(); + } else { + hw_charging_enable(); + } + printf("%s: percentage = %d, temperature %d\n", + __FUNCTION__, percentage, ug31_data.extTemp); + } + } else if (g_ug31xx_id == UG31XX_ID_3102) { + hw_charging_enable(); + } + + return percentage; +} + +int upi_read_voltage(void) +{ + int volt_mV; + + UpiBootMain(&ug31_data); + volt_mV = ug31_data.volt; + printf("voltage = %d mV\n", volt_mV); + + return volt_mV; +} + +int upi_read_current(void) +{ + int current; + + UpiBootMain(&ug31_data); + current = ug31_data.curr; + printf("current = %d mA\n", current); + + return current; +} + +int upi_boot_init(void) +{ + int ret; + + if (parse_battery_param()) + return -EINVAL; + + ug31xx_init_i2c(ug31xx_param.i2c_adapter); + + ret = UpiBootInitial(&ug31_data); + + hw_charging_enable(); + + return (ret == UPI_BOOT_RTN_PASS) ? 0 : -1; +} + +static int upi_check_bl(void) +{ + int ret; + + if (percentage < 0) { + upi_read_percentage(); + } + + ret = (percentage < 3); + printf("%s: percentage = %d, temperature %d, ret %d\n", + __FUNCTION__, ug31_data.rsoc, ug31_data.extTemp, ret); + + return ret; +} + +struct battery_dev ug31xx_battery_dev = { + .name = "ug3105", + .is_gauge = 1, + .init = upi_boot_init, + .get_capacity = upi_read_percentage, + .get_voltage = upi_read_voltage, + .get_current = upi_read_current, + .check_batlow = upi_check_bl, +}; + +struct battery_dev ug3102_battery_dev = { + .name = "ug3102", + .is_gauge = 1, + .init = upi_boot_init, + .get_capacity = upi_read_percentage, + .get_voltage = upi_read_voltage, + .get_current = upi_read_current, + .check_batlow = upi_check_bl, +}; +#endif |