From 151c951ecbd0148337a959e91ba0208084e4ff3c Mon Sep 17 00:00:00 2001 From: 1624952103 Date: Thu, 26 Mar 2026 15:59:03 +0800 Subject: [PATCH] =?utf8?q?=E4=BC=98=E5=8C=96=E5=85=85=E7=94=B5=E6=9B=B2?= =?utf8?q?=E7=BA=BF=EF=BC=8C=E5=A2=9E=E5=8A=A0SGM41562=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../config/target_config/brandy/config.py | 4 +- code/sdk/zhihui/drivers/CMakeLists.txt | 1 + code/sdk/zhihui/drivers/charge/CMakeLists.txt | 40 +- .../sdk/zhihui/drivers/charge/hp4570/hp4570.c | 2 +- .../drivers/charge/service/charge_at_cmd.c | 14 +- .../zhihui/drivers/charge/sgm41562/sgm41562.c | 1382 +++++++++++++++++ .../zhihui/drivers/charge/sgm41562/sgm41562.h | 263 ++++ .../battery/service/battery_driver.cpp | 67 +- .../battery/service/battery_service.cpp | 6 +- code/sdk/zhihui/utils/custom_utils.c | 2 +- 10 files changed, 1747 insertions(+), 34 deletions(-) create mode 100644 code/sdk/zhihui/drivers/charge/sgm41562/sgm41562.c create mode 100644 code/sdk/zhihui/drivers/charge/sgm41562/sgm41562.h diff --git a/code/sdk/build/config/target_config/brandy/config.py b/code/sdk/build/config/target_config/brandy/config.py index 8fedf75d8..f9a23f152 100644 --- a/code/sdk/build/config/target_config/brandy/config.py +++ b/code/sdk/build/config/target_config/brandy/config.py @@ -1161,6 +1161,8 @@ target = { # 'DOWNLOAD_GNSS_SWITCH', 'PPG_HX3695', 'ROTARYENCODER_HX3508', + 'ENABLE_HP4570', + # 'ENABLE_SGM41562', '-:SUPPORT_ALIPAY_SEC', ], #添加自定义应用 @@ -1205,12 +1207,12 @@ target = { # "mag_service", "cywee_dml", "cyweeBleService", - "charge_ic_hp4570", "gnss", "pgnss_sample", # "gnss_sample", "cyweeBleService", "aiMediaService", + "charge", ], 'image_analysis': False, 'fs_image_path':'fd272', diff --git a/code/sdk/zhihui/drivers/CMakeLists.txt b/code/sdk/zhihui/drivers/CMakeLists.txt index df1b70ebe..bdc2eeb57 100644 --- a/code/sdk/zhihui/drivers/CMakeLists.txt +++ b/code/sdk/zhihui/drivers/CMakeLists.txt @@ -17,5 +17,6 @@ add_subdirectory_if_exist(entest) add_subdirectory_if_exist(barometer) add_subdirectory_if_exist(charge) add_subdirectory_if_exist(charge/hp4570) +add_subdirectory_if_exist(charge/sgm41562) add_subdirectory_if_exist(gyro) add_subdirectory_if_exist(bp) diff --git a/code/sdk/zhihui/drivers/charge/CMakeLists.txt b/code/sdk/zhihui/drivers/charge/CMakeLists.txt index be09e97a4..f3cbc4de8 100644 --- a/code/sdk/zhihui/drivers/charge/CMakeLists.txt +++ b/code/sdk/zhihui/drivers/charge/CMakeLists.txt @@ -2,19 +2,48 @@ # @brief cmake file # Copyright (c) @CompanyNameMagicTag 2022-2023. All rights reserved. #=============================================================================== -set(COMPONENT_NAME "charge_ic_hp4570") +set(COMPONENT_NAME "charge") +if("ENABLE_HP4570" IN_LIST DEFINES) set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hp4570/hp4570.c ${CMAKE_CURRENT_SOURCE_DIR}/service/charge_at_cmd.c ${CMAKE_CURRENT_SOURCE_DIR}/service/charge_service.c ) +elseif("ENABLE_SGM41562" IN_LIST DEFINES) +set(SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/sgm41562/sgm41562.c + ${CMAKE_CURRENT_SOURCE_DIR}/service/charge_at_cmd.c + ${CMAKE_CURRENT_SOURCE_DIR}/service/charge_service.c +) + +else() +set(SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/service/charge_at_cmd.c + ${CMAKE_CURRENT_SOURCE_DIR}/service/charge_service.c +) +endif() + +if("ENABLE_HP4570" IN_LIST DEFINES) set(PUBLIC_HEADER - ${CMAKE_CURRENT_SOURCE_DIR}/hp4570/ - ${CMAKE_CURRENT_SOURCE_DIR}/service/ - + ${CMAKE_CURRENT_SOURCE_DIR}/hp4570 + ${CMAKE_CURRENT_SOURCE_DIR}/service ) +elseif("ENABLE_SGM41562" IN_LIST DEFINES) + +set(PUBLIC_HEADER + ${CMAKE_CURRENT_SOURCE_DIR}/sgm41562 + ${CMAKE_CURRENT_SOURCE_DIR}/service +) + +else() + +set(PUBLIC_HEADER + ${CMAKE_CURRENT_SOURCE_DIR}/service +) + +endif() set(PRIVATE_HEADER ) @@ -26,7 +55,6 @@ set(PRIVATE_DEFINES set(PUBLIC_DEFINES SUPPORT_AT_CHARGE -ENABLE_HP4570 ) # use this when you want to add ccflags like -include xxx @@ -44,4 +72,4 @@ set(MAIN_COMPONENT false ) -build_component() +build_component() \ No newline at end of file diff --git a/code/sdk/zhihui/drivers/charge/hp4570/hp4570.c b/code/sdk/zhihui/drivers/charge/hp4570/hp4570.c index 19e6fafc5..c7d8ab87e 100644 --- a/code/sdk/zhihui/drivers/charge/hp4570/hp4570.c +++ b/code/sdk/zhihui/drivers/charge/hp4570/hp4570.c @@ -105,7 +105,7 @@ bool hp4570n_init(uint8_t chip_ver){ hp4570n_set_ceb_en(true); // int ret = hp4570n_set_chrg_vbat_mV(4700.0); - int ret = hp4570n_set_chrg_vbat_mV(4440.0); + int ret = hp4570n_set_chrg_vbat_mV(4420.0); printf("hp4570n_set_chrg_vbat_mV ret:%d\n",ret); ret = hp4570n_set_high_chrg_ipre_mA(30); diff --git a/code/sdk/zhihui/drivers/charge/service/charge_at_cmd.c b/code/sdk/zhihui/drivers/charge/service/charge_at_cmd.c index 50d01872a..1c8e96f2e 100644 --- a/code/sdk/zhihui/drivers/charge/service/charge_at_cmd.c +++ b/code/sdk/zhihui/drivers/charge/service/charge_at_cmd.c @@ -9,7 +9,9 @@ #include "at_cmd_api.h" #include "pm_control.h" #include "debug_print.h" +#ifdef ENABLE_HP4570 #include "hp4570.h" +#endif #include "custom_utils.h" #include "battery_service.h" @@ -75,7 +77,10 @@ static uint32_t hp4570_test(uint8_t *para, uint32_t paraLen, char *strCommonCmd) // PRINT("SKIP CHARGEtest start, already started\r\n"); // return 0; // } +#ifdef ENABLE_HP4570 hp4570n_init(HP4570N); +#endif + g_charge_test_started = 1; }else if (start == 2){ if (g_charge_test_started == 0) @@ -85,11 +90,18 @@ static uint32_t hp4570_test(uint8_t *para, uint32_t paraLen, char *strCommonCmd) } // ots_stop(); g_charge_test_started = 0 ; - }else + }else if (start == 3) { batteryservice_set_test_bat_temp(start); } + else if (start == 4) + { +#ifdef ENABLE_SGM41562 + sgm41562_read_all_reg(); +#endif + } + return ERRCODE_SUCC; } diff --git a/code/sdk/zhihui/drivers/charge/sgm41562/sgm41562.c b/code/sdk/zhihui/drivers/charge/sgm41562/sgm41562.c new file mode 100644 index 000000000..aa757d77c --- /dev/null +++ b/code/sdk/zhihui/drivers/charge/sgm41562/sgm41562.c @@ -0,0 +1,1382 @@ + +#include "sgm41562.h" +#include "custom_utils.h" + +#undef pr_debug +#define pr_debug printf + +#if defined(BOARD_L22) || defined(BOARD_FD272) +#define I2C_BUS I2C_BUS_0 +#elif defined BOARD_U8 +#define I2C_BUS I2C_BUS_3 +#endif + +// static struct power_supply_desc sgm41562_power_supply_desc; + +enum SGM41562_PULLDOWN_PERIOD { + SGM41562_PN_TIMER_8S, + SGM41562_PN_TIMER_12S, + SGM41562_PN_TIMER_16S, + SGM41562_PN_TIMER_20S, + SGM41562_PN_TIMER_MAX = 4, +}; + +enum SGM41562_WDT_TIMER { + SGM41562_WDT_TIMER_DISABLE, + SGM41562_WDT_TIMER_40S, + SGM41562_WDT_TIMER_80S, + SGM41562_WDT_TIMER_160S, + SGM41562_WDT_TIMER_MAX = 4, +}; + +enum SGM41562_CHG_TIMER { + SGM41562_CHG_TIMER_3H, + SGM41562_CHG_TIMER_5H, + SGM41562_CHG_TIMER_8H, + SGM41562_CHG_TIMER_12H, + SGM41562_CHG_TIMER_MAX = 4, +}; + +enum SGM41562_TEMP_STATUS { + SGM41562_TEMP_HOT, + SGM41562_TEMP_WARM, + SGM41562_TEMP_COOL, + SGM41562_TEMP_COLD, + SGM41562_TEMP_MAX = 4, +}; + +enum SGM41562_EN_OPTION { + /* REG 01*/ + REG_BIT_RST_DUR, //0=2S,1=4S + REG_BIT_EN_HIZ, + REG_BIT_EN_CEB, //enable charge + /* REG 02*/ + REG_BIT_REG_RST, + REG_BIT_WD_RST, + /* REG 04*/ + REG_BIT_VBAT_PRE, + REG_BIT_VRECH, + /* REG 05*/ + REG_BIT_EN_WD_DISCHG, + REG_BIT_EN_TERM, + REG_BIT_EN_TIMER, + REG_BIT_TERM_TMR, + /* REG 06*/ + REG_BIT_EN_NTC, + REG_BIT_EN_TMR2X, + REG_BIT_FET_DIS, + REG_BIT_PG_INT_CTL, + REG_BIT_EOC_INT_CTL, + REG_BIT_CHG_STATUS_INT_CTL, + REG_BIT_NTC_INT_CTL, + REG_BIT_BATOVP_INT_CTL, + /* REG 07*/ + REG_BIT_EN_PCB_OTP, + REG_BIT_DIS_VINLOOP, + /* REG 08*/ + REG_BIT_VIN_OVP_SEL, + //REG_BIT_IIN_LIM_ADD200, + /* REG 0A*/ + REG_BIT_COLD_RESET, + REG_BIT_SWITCH_MODE, + REG_BIT_DIS_VDD, + REG_BIT_DIS_VINOVP, + REG_BIT_CC_FINE, + REG_BIT_DIS_INT, +}; + +/********************************************************** + * + * [I2C Function For Read/Write sgm41562_device] + * + *********************************************************/ +static int __sgm41562_read_byte( uint8_t reg, uint8_t *data) +{ + int32_t ret; + + // ret = i2c_smbus_read_byte_data(sgm->client, reg); + // if (ret < 0) { + // printf("i2c read fail: can't read from reg 0x%02X\n", reg); + // return ret; + // } + + custom_i2c_read_regs(0x03, reg, 1, data, 1, I2C_BUS); + + // *data = (uint8_t) ret; + + return 0; +} + +static int __sgm41562_write_byte( int reg, uint8_t val) +{ + int32_t ret; + + // ret = i2c_smbus_write_byte_data(sgm->client, reg, val); + // if (ret < 0) { + // printf("i2c write fail: can't write 0x%02X to reg 0x%02X: %d\n", + // val, reg, ret); + // return ret; + // } + + custom_i2c_write_reg(0x03, reg, 1, &val, 1, I2C_BUS); + + return 0; +} + +static int sgm41562_read_reg( uint8_t reg, uint8_t *data) +{ + int ret; + + // mutex_lock(&sgm->i2c_rw_lock); + ret = __sgm41562_read_byte( reg, data); + // mutex_unlock(&sgm->i2c_rw_lock); + + return ret; +} + +static int sgm41562_write_reg( uint8_t reg, uint8_t val) +{ + int ret; + + // mutex_lock(&sgm->i2c_rw_lock); + ret = __sgm41562_write_byte(reg, val); + // mutex_unlock(&sgm->i2c_rw_lock); + + if (ret) + printf("Failed: reg=%02X, ret=%d\n", reg, ret); + + return ret; +} + +static int sgm41562_update_bits( uint8_t reg, + uint8_t mask, uint8_t val) +{ + int ret; + uint8_t tmp; + + // mutex_lock(&sgm->i2c_rw_lock); + ret = __sgm41562_read_byte(reg, &tmp); + if (ret) { + printf("Failed: reg=%02X, ret=%d\n", reg, ret); + goto out; + } + + tmp &= ~mask; + tmp |= val & mask; + + ret = __sgm41562_write_byte(reg, tmp); + if (ret) + printf("Failed: reg=%02X, ret=%d\n", reg, ret); + +out: +// mutex_unlock(&sgm->i2c_rw_lock); + return ret; +} + +static int sgm41562_set_input_volt_lim(int vindpm) +{ + int ret; + int reg_val; + + if (vindpm < SGM41562_VINDPM_V_MIN_uV || vindpm > SGM41562_VINDPM_V_MAX_uV) + return -1; + + reg_val = (vindpm-SGM41562_VINDPM_V_MIN_uV) / SGM41562_VINDPM_STEP_uV; + reg_val = reg_val<< 4; + ret = sgm41562_update_bits(SGM41562_CHRG_REG_0, + SGM41562_VINDPM_V_MASK, reg_val); + pr_debug("%s ret %d,reg_val 0x%x\n",__func__,ret,reg_val); + return ret; +} + +static int sgm41562_get_input_volt_lim(void) +{ + int ret; + int vlim; + uint8_t temp; + + ret = sgm41562_read_reg(SGM41562_CHRG_REG_0, &temp); + if (ret) + return ret; + + vlim = temp>>4; + vlim = SGM41562_VINDPM_V_MIN_uV + vlim * SGM41562_VINDPM_STEP_uV; + return vlim; +} + +static int sgm41562_set_input_curr_lim( int iindpm) +{ + int ret; + int reg_val; + + if (iindpm < SGM41562_IINDPM_I_MIN_uA || iindpm > SGM41562_IINDPM_I_MAX_uA) + return -1; + + reg_val = (iindpm-SGM41562_IINDPM_I_MIN_uA) / SGM41562_IINDPM_STEP_uA; + reg_val = reg_val << 3; + ret = sgm41562_update_bits(SGM41562_CHRG_REG_C, + SGM41562_IINDPM_I_MASK, reg_val); + pr_debug("%s ret %d,reg_val 0x%x\n",__func__,ret,reg_val); + return ret; +} + +static int sgm41562_get_input_curr_lim(void) +{ + int ret; + uint8_t val; + uint32_t ilim; + + ret = sgm41562_read_reg(SGM41562_CHRG_REG_C, &val); + if (ret) + return ret; + + ilim = ((val & SGM41562_IINDPM_I_MASK) >> 3) * SGM41562_IINDPM_STEP_uA + SGM41562_IINDPM_I_MIN_uA; + + return ilim; +} + +static int sgm41562_set_pulldown_period(enum SGM41562_PULLDOWN_PERIOD time) +{ + int ret; + uint8_t reg_val; + + reg_val = time << 6; + ret = sgm41562_update_bits(SGM41562_CHRG_REG_1, + SGM41562_RST_DGL, reg_val); + + return ret; +} + +static int sgm41562_set_vbat_uvlo(int volt) +{ + int ret; + int reg_val; + + if (volt < SGM41562_VBAT_UVLO_MIN_uV || + volt > SGM41562_VBAT_UVLO_MAX_uV) + return -1; + + reg_val = (volt - SGM41562_VBAT_UVLO_MIN_uV) / SGM41562_VBAT_UVLO_STEP_uV; + + ret = sgm41562_update_bits(SGM41562_CHRG_REG_1, + SGM41562_VBAT_UVLO_MASK, reg_val); + pr_debug("%s ret %d,reg_val 0x%x\n",__func__,ret,reg_val); + return ret; +} + +static int sgm41562_set_fast_cc( int curr) +{ + int ret; + int reg_val; + + if (curr < SGM41562_FAST_ICC_MIN_uA || curr > SGM41562_FAST_ICC_MAX_uA) + return -1; + + reg_val = (curr - SGM41562_FAST_ICC_MIN_uA) / SGM41562_FAST_ICC_STEP_uA; + + ret = sgm41562_update_bits(SGM41562_CHRG_REG_2, + SGM41562_FAST_ICC_MASK, reg_val); + pr_debug("%s ret %d,reg_val 0x%x\n",__func__,ret,reg_val); + return ret; +} + +static int sgm41562_set_discharge_curr_limit(int curr) +{ + int ret; + int reg_val; + + if (curr < SGM41562_DSCHG_I_MIN_uA || curr > SGM41562_DSCHG_I_MAX_uA) + return -1; + + reg_val = (curr - SGM41562_DSCHG_I_MIN_uA) / SGM41562_DSCHG_I_STEP_uA; + if (0 == reg_val) + return -1; + reg_val = reg_val << 4; + ret = sgm41562_update_bits(SGM41562_CHRG_REG_3, + SGM41562_DSCHG_I_MASK, reg_val); + pr_debug("%s ret %d,reg_val 0x%x\n",__func__,ret,reg_val); + return ret; +} + +static int sgm41562_get_term_curr(void) +{ + int ret; + uint8_t reg_val; + uint32_t curr; + int offset = SGM41562_TERM_I_MIN_uA; + + ret = sgm41562_read_reg(SGM41562_CHRG_REG_3, ®_val); + if (ret) + return ret; + + reg_val &= SGM41562_TERM_I_MASK; + curr = reg_val * SGM41562_TERM_I_STEP_uA + offset; + return curr; +} + +static int sgm41562_set_term_curr( int term_curr) +{ + int ret = 0; + int reg_val; + int offset = SGM41562_TERM_I_MIN_uA; + + if (term_curr < SGM41562_TERM_I_MIN_uA) + term_curr = SGM41562_TERM_I_MIN_uA; + else if (term_curr > SGM41562_TERM_I_MAX_uA) + term_curr = SGM41562_TERM_I_MAX_uA; + + reg_val = (term_curr - offset) / SGM41562_TERM_I_STEP_uA; + + ret = sgm41562_update_bits(SGM41562_CHRG_REG_3, + SGM41562_TERM_I_MASK, reg_val); + + pr_debug("%s ret %d,reg_val 0x%x\n",__func__,ret,reg_val); + return ret; +} + +static int sgm41562_set_chrg_volt( int chrg_volt) +{ + int ret; + int reg_val; + + if (chrg_volt < SGM41562_VBAT_REG_MIN_uV) + chrg_volt = SGM41562_VBAT_REG_MIN_uV; + else if (chrg_volt > SGM41562_VBAT_REG_MAX_uV) + chrg_volt = SGM41562_VBAT_REG_MAX_uV; + + reg_val = (chrg_volt - SGM41562_VBAT_REG_MIN_uV) / SGM41562_VBAT_REG_STEP_uV; + reg_val = reg_val << 1; + ret = sgm41562_update_bits(SGM41562_CHRG_REG_4, + SGM41562_VBAT_REG_MASK, reg_val); + pr_debug("%s ret %d,reg_val 0x%x\n",__func__,ret,reg_val); + + return ret; +} + +static int sgm41562_get_chrg_volt(void) +{ + int ret; + uint8_t vreg_val; + uint32_t chrg_volt; + + ret = sgm41562_read_reg(SGM41562_CHRG_REG_4, &vreg_val); + if (ret) + return ret; + + vreg_val = vreg_val >> 1; + chrg_volt = vreg_val*SGM41562_VBAT_REG_STEP_uV + SGM41562_VBAT_REG_MIN_uV; + + return chrg_volt; +} + +static int sgm41562_set_watchdog_timer( enum SGM41562_WDT_TIMER time) +{ + int ret; + uint8_t reg_val; + + reg_val = time << 5; + ret = sgm41562_update_bits(SGM41562_CHRG_REG_5, + SGM41562_WD_TIMER_MASK, reg_val); + + return ret; +} + +static int sgm41562_set_chg_timer( enum SGM41562_CHG_TIMER time) +{ + int ret; + uint8_t reg_val; + + reg_val = time<<1; + ret = sgm41562_update_bits(SGM41562_CHRG_REG_5, + SGM41562_CHG_TIMER_MASK, reg_val); + + return ret; +} + +static int sgm41562_set_vsys_volt( int volt) +{ + int ret; + int reg_val; + + if (volt < SGM41562_VSYS_MIN_uV) + volt = SGM41562_VSYS_MIN_uV; + else if (volt > SGM41562_VSYS_MAX_uV) + volt = SGM41562_VSYS_MAX_uV; + + reg_val = (volt - SGM41562_VSYS_MIN_uV) / SGM41562_VSYS_STEP_uV; + + ret = sgm41562_update_bits(SGM41562_CHRG_REG_7, + SGM41562_VSYS_REG_MASK, reg_val); + pr_debug("%s ret %d,reg_val 0x%x\n",__func__,ret,reg_val); + + return ret; +} + +static int sgm41562_ctrl_setting(enum SGM41562_EN_OPTION options,bool en) +{ + int ret = 0; + int mask = 0; + int reg_addr = 0; + + switch (options) + { + case REG_BIT_RST_DUR: //0=2S,1=4S + reg_addr = SGM41562_CHRG_REG_1; + mask = SGM41562_RST_DUR; + break; + case REG_BIT_EN_HIZ: + reg_addr = SGM41562_CHRG_REG_1; + mask = SGM41562_HIZ_EN; + break; + case REG_BIT_EN_CEB: //enable charge + reg_addr = SGM41562_CHRG_REG_1; + mask = SGM41562_EN_CEB; + break; + case REG_BIT_REG_RST: + reg_addr = SGM41562_CHRG_REG_2; + mask = SGM41562_REG_RST; + break; + case REG_BIT_WD_RST: + reg_addr = SGM41562_CHRG_REG_C; + mask = SGM41562_WD_RST; + break; + case REG_BIT_VBAT_PRE: + reg_addr = SGM41562_CHRG_REG_C; + mask = SGM41562_VBAT_PRE_THRE_uV; + break; + case REG_BIT_VRECH: + reg_addr = SGM41562_CHRG_REG_4; + mask = SGM41562_VRECH_THRE_uV; + break; + case REG_BIT_EN_WD_DISCHG: + reg_addr = SGM41562_CHRG_REG_5; + mask = SGM41562_EN_WD_DISCHG; + break; + case REG_BIT_EN_TERM: + reg_addr = SGM41562_CHRG_REG_5; + mask = SGM41562_EN_TERM; + break; + case REG_BIT_EN_TIMER: + reg_addr = SGM41562_CHRG_REG_5; + mask = SGM41562_EN_SATETY_TIMER; + break; + case REG_BIT_TERM_TMR: + reg_addr = SGM41562_CHRG_REG_5; + mask = SGM41562_EN_TERM_TIMER; + break; + case REG_BIT_EN_NTC: + reg_addr = SGM41562_CHRG_REG_6; + mask = SGM41562_EN_NTC; + break; + case REG_BIT_EN_TMR2X: + reg_addr = SGM41562_CHRG_REG_6; + mask = SGM41562_EN_TMR2X; + break; + case REG_BIT_FET_DIS: + reg_addr = SGM41562_CHRG_REG_6; + mask = SGM41562_FET_DIS; + break; + case REG_BIT_PG_INT_CTL: + reg_addr = SGM41562_CHRG_REG_6; + mask = SGM41562_PG_INT_CTL; + break; + case REG_BIT_EOC_INT_CTL: + reg_addr = SGM41562_CHRG_REG_6; + mask = SGM41562_EOC_INT_CTL; + break; + case REG_BIT_CHG_STATUS_INT_CTL: + reg_addr = SGM41562_CHRG_REG_6; + mask = SGM41562_CHG_STATUS_INT_CTL; + break; + case REG_BIT_NTC_INT_CTL: + reg_addr = SGM41562_CHRG_REG_6; + mask = SGM41562_NTC_INT_CTL; + break; + case REG_BIT_BATOVP_INT_CTL: + reg_addr = SGM41562_CHRG_REG_6; + mask = SGM41562_BATOVP_INT_CTL; + break; + case REG_BIT_EN_PCB_OTP: + reg_addr = SGM41562_CHRG_REG_8; + mask = SGM41562_DIS_PCB_OTP; + break; + case REG_BIT_DIS_VINLOOP: + reg_addr = SGM41562_CHRG_REG_7; + mask = SGM41562_DIS_VINLOOP; + break; + case REG_BIT_VIN_OVP_SEL: + reg_addr = SGM41562_CHRG_REG_8; + mask = SGM41562_VIN_OVP_SEL; + break; +// case REG_BIT_IIN_LIM_ADD200: +// reg_addr = SGM41562_CHRG_REG_8; +// mask = SGM41562_IIN_LIM_ADD200; + break; + case REG_BIT_COLD_RESET: + reg_addr = SGM41562_CHRG_REG_A; + mask = SGM41562_COLD_RESET; + break; + case REG_BIT_SWITCH_MODE: + reg_addr = SGM41562_CHRG_REG_A; + mask = SGM41562_SWITCH_MODE; + break; + case REG_BIT_DIS_VDD: + reg_addr = SGM41562_CHRG_REG_A; + mask = SGM41562_DIS_VDD; + break; + case REG_BIT_DIS_VINOVP: + reg_addr = SGM41562_CHRG_REG_A; + mask = SGM41562_DIS_VINOVP; + break; + case REG_BIT_CC_FINE: + reg_addr = SGM41562_CHRG_REG_A; + mask = SGM41562_CC_FINE; + break; + case REG_BIT_DIS_INT: + reg_addr = SGM41562_CHRG_REG_C; + mask = SGM41562_DIS_INT; + break; + + } + if (en) + ret = sgm41562_update_bits(reg_addr,mask,mask); + else + ret = sgm41562_update_bits(reg_addr,mask,0); + if (ret < 0) { + printf("[%s] SET fail\n", __func__); + return ret; + } + printf("[%s] ret=0x%x\n", __func__,ret); + + return ret; +} + + +static int sgm41562_get_state( + struct sgm41562_state *state) +{ + uint8_t chrg_stat; + uint8_t fault; + int ret; + + ret = sgm41562_read_reg( SGM41562_CHRG_REG_8, &chrg_stat); + if (ret){ + ret = sgm41562_read_reg( SGM41562_CHRG_REG_8, &chrg_stat); + if (ret){ + printf("%s read SGM41562_CHRG_REG_8 fail\n",__func__); + return ret; + } + } + + state->chrg_stat = chrg_stat & SGM41562_CHG_STAT_MASK; + state->pg_stat = !!(chrg_stat & SGM41562_PG_STAT); + state->therm_stat = !!(chrg_stat & SGM41562_THERM_STAT); + state->ppm_stat = !!(chrg_stat & SGM41562_PPM_STAT); + + printf("%s chrg_stat =%d,pg_stat =%d ppm_stat = %d\n", + __func__,chrg_stat,state->pg_stat,state->ppm_stat); + + ret = sgm41562_read_reg( SGM41562_CHRG_REG_9, &fault); + if (ret){ + printf("%s read SGM41562_CHRG_REG_9 fail\n",__func__); + return ret; + } + state->ntc_fault_0 = !!(chrg_stat & SGM41562_NTC_COOL_FAULT); + state->ntc_fault_1 = !!(chrg_stat & SGM41562_NTC_HOT_FAULT); + state->bat_fault = !!(chrg_stat & SGM41562_BAT_FAULT); + + if (state->ntc_fault_0) + state->health = SGM41562_TEMP_COLD; + else if (state->ntc_fault_1) + state->health = SGM41562_TEMP_HOT; + else + state->health = SGM41562_TEMP_WARM; + return 0; +} + +// static int sgm41562_property_is_writeable(enum power_supply_property prop) +// { +// switch (prop) { +// // case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: +// // case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: +// // case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: +// // case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: +// // case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: +// // case POWER_SUPPLY_PROP_STATUS: +// // return true; +// default: +// return false; +// } +// } + +// static int sgm41562_charger_set_property( +// const union power_supply_propval *val) +// { +// void = power_supply_get_drvdata(psy); +// int ret = -1; + +// switch (prop) { +// case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: +// ret = sgm41562_set_input_curr_lim( val->intval); +// break; +// case POWER_SUPPLY_PROP_STATUS: +// if (val->intval) +// ret = sgm41562_ctrl_setting(REG_BIT_EN_CEB,1); +// else +// ret = sgm41562_ctrl_setting(REG_BIT_EN_CEB,0); +// break; +// /* case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: +// ret = sgm41562_set_input_volt_lim( val->intval); +// break;*/ +// default: +// return -1; +// } + +// return ret; +// } + +// static int sgm41562_charger_get_property(struct power_supply *psy, +// enum power_supply_property psp, +// union power_supply_propval *val) +// { +// void = power_supply_get_drvdata(psy); +// struct sgm41562_state state; +// int ret = 0; + +// mutex_lock(&sgm->lock); +// //ret = sgm41562_get_state( &state); +// state = sgm->state; +// mutex_unlock(&sgm->lock); +// if (ret) +// return ret; + +// switch (psp) { +// case POWER_SUPPLY_PROP_STATUS: +// if (!state.pg_stat) +// val->intval = POWER_SUPPLY_STATUS_DISCHARGING; +// else if (state.pg_stat && !state.chrg_stat) +// val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; +// else if (state.chrg_stat == SGM41562_TERM_CHRG) +// val->intval = POWER_SUPPLY_STATUS_FULL; +// else +// val->intval = POWER_SUPPLY_STATUS_CHARGING; +// break; +// case POWER_SUPPLY_PROP_CHARGE_TYPE: +// switch (state.chrg_stat) { +// case SGM41562_PRECHRG: +// val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; +// break; +// case SGM41562_FAST_CHRG: +// val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; +// break; +// case SGM41562_TERM_CHRG: +// val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; +// break; +// case SGM41562_NOT_CHRGING: +// val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; +// break; +// default: +// val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; +// } +// break; +// case POWER_SUPPLY_PROP_MANUFACTURER: +// val->strval = SGM41562_MANUFACTURER; +// break; + +// case POWER_SUPPLY_PROP_MODEL_NAME: +// val->strval = SGM41562_NAME; +// break; + +// case POWER_SUPPLY_PROP_ONLINE: +// val->intval = state.pg_stat; +// break; +// case POWER_SUPPLY_PROP_PRESENT: +// val->intval = state.pg_stat; +// break; +// case POWER_SUPPLY_PROP_TYPE: +// val->intval = sgm41562_power_supply_desc.type; +// break; +// case POWER_SUPPLY_PROP_USB_TYPE: +// break; + +// case POWER_SUPPLY_PROP_HEALTH: +// if (state.bat_fault) +// val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; +// else +// val->intval = POWER_SUPPLY_HEALTH_GOOD; + +// switch (state.health) { +// case SGM41562_TEMP_HOT: +// val->intval = POWER_SUPPLY_HEALTH_HOT; +// break; +// case SGM41562_TEMP_WARM: +// val->intval = POWER_SUPPLY_HEALTH_WARM; +// break; +// case SGM41562_TEMP_COOL: +// val->intval = POWER_SUPPLY_HEALTH_COOL; +// break; +// case SGM41562_TEMP_COLD: +// val->intval = POWER_SUPPLY_HEALTH_COLD; +// break; +// } +// break; + +// case POWER_SUPPLY_PROP_VOLTAGE_NOW: +// //val->intval = state.vbus_adc; +// break; + +// case POWER_SUPPLY_PROP_CURRENT_NOW: +// //val->intval = state.ibus_adc; +// break; + +// /* case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: +// ret = sgm41562_get_input_volt_lim(sgm); +// if (ret < 0) +// return ret; + +// val->intval = ret; +// break;*/ + +// case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: +// ret = sgm41562_get_input_curr_lim(); +// if (ret < 0) +// return ret; + +// val->intval = ret; +// break; + +// default: +// return -1; +// } + +// return ret; +// } + +#if 0 +static bool sgm41562_state_changed( + struct sgm41562_state *new_state) +{ + struct sgm41562_state old_state; + + mutex_lock(&sgm->lock); + old_state = sgm->state; + mutex_unlock(&sgm->lock); + + return (old_state.chrg_status != new_state->chrg_status || + old_state.chrg_fault != new_state->chrg_fault || + old_state.online != new_state->online || + old_state.health != new_state->health || + old_state.chrg_type != new_state->chrg_type + ); +} +#endif +static void sgm41562_dump_register(void) +{ + int i = 0; + uint8_t reg = 0; + + for(i=0; i<=SGM41562_CHRG_REG_D; i++) { + sgm41562_read_reg( i, ®); + printf("%s REG%x %X\n", __func__, i, reg); + } +} + +// static void charger_monitor_work_func(struct work_struct *work) +// { +// int ret = 0; + +// struct delayed_work *charge_monitor_work = NULL; +// struct sgm41562_state state; + +// charge_monitor_work = container_of(work, struct delayed_work, work); +// if(charge_monitor_work == NULL) { +// printf("Cann't get charge_monitor_work\n"); +// return ; +// } +// sgm = container_of(charge_monitor_work, struct sgm41562_device, charge_monitor_work); +// if(sgm == NULL) { +// printf("Cann't get sgm \n"); +// return ; +// } + +// ret = sgm41562_get_state( &state); +// mutex_lock(&sgm->lock); +// sgm->state = state; +// mutex_unlock(&sgm->lock); + +// if (!sgm->state.pg_stat) { +// printf("%s not present vbus_status \n",__func__); +// goto OUT; +// } +// sgm41562_dump_register(sgm); +// OUT: +// schedule_delayed_work(&sgm->charge_monitor_work, 10*HZ); +// } + +// static void charger_detect_work_func(struct work_struct *work) +// { +// struct delayed_work *charge_detect_delayed_work = NULL; +// void = NULL; +// struct sgm41562_state state; +// int ret; + +// charge_detect_delayed_work = container_of(work, struct delayed_work, work); +// if(charge_detect_delayed_work == NULL) { +// printf("Cann't get charge_detect_delayed_work\n"); +// goto err; +// } +// sgm = container_of(charge_detect_delayed_work, struct sgm41562_device, charge_detect_delayed_work); +// if(sgm == NULL) { +// printf("Cann't get sgm41562_device\n"); +// goto err; +// } + +// if (!sgm->charger_wakelock->active) +// __pm_stay_awake(sgm->charger_wakelock); + +// ret = sgm41562_get_state( &state); +// mutex_lock(&sgm->lock); +// sgm->state = state; +// mutex_unlock(&sgm->lock); + +// if(!sgm->state.pg_stat) { +// dev_err(sgm->dev, "Vbus not online disable charge\n"); +// sgm41562_ctrl_setting(REG_BIT_EN_CEB,0); +// goto err; +// } + +// //enable charge +// sgm41562_ctrl_setting(REG_BIT_EN_CEB,1); + +// sgm41562_dump_register(sgm); +// err: +// //release wakelock +// power_supply_changed(sgm->charger); +// dev_err(sgm->dev, "Relax wakelock\n"); +// __pm_relax(sgm->charger_wakelock); +// return; +// } + +// static irqreturn_t sgm41562_irq_handler_thread(int irq, void *private) +// { +// void = private; + +// //lock wakelock +// printf("%s entry\n",__func__); + +// schedule_delayed_work(&sgm->charge_detect_delayed_work, 100); +// //power_supply_changed(sgm->charger); + +// return IRQ_HANDLED; +// } + + +// static char *sgm41562_charger_supplied_to[] = { +// "battery", +// }; + +// static struct power_supply_desc sgm41562_power_supply_desc = { +// .name = "sgm41562-charger", +// .type = POWER_SUPPLY_TYPE_BATTERY, +// .usb_types = sgm41562_usb_type, +// .num_usb_types = ARRAY_SIZE(sgm41562_usb_type), +// .properties = sgm41562_power_supply_props, +// .num_properties = ARRAY_SIZE(sgm41562_power_supply_props), +// .get_property = sgm41562_charger_get_property, +// .set_property = sgm41562_charger_set_property, +// .property_is_writeable = sgm41562_property_is_writeable, +// }; + +// static int sgm41562_power_supply_init( +// struct device *dev) +// { +// struct power_supply_config psy_cfg = { .drv_data = +// .of_node = dev->of_node, }; + +// psy_cfg.supplied_to = sgm41562_charger_supplied_to; +// psy_cfg.num_supplicants = ARRAY_SIZE(sgm41562_charger_supplied_to); + +// sgm->charger = devm_power_supply_register(sgm->dev, +// &sgm41562_power_supply_desc, +// &psy_cfg); +// if (IS_ERR(sgm->charger)) +// return -1; + +// return 0; +// } + +// static int sgm41562_hw_init(void) +// { +// int ret = 0; +// // struct power_supply_battery_info bat_info = { }; + +// struct sgm41562_init_data { +// uint32_t ichg; /* 充电电流 (uA) */ +// uint32_t ilim; /* 输入限流 (uA) */ +// uint32_t vreg; /* 满电电压 (uV) */ +// uint32_t iterm; /* 截止电流 (uA) */ +// uint32_t iprechg; /* 预充电流 (uA) */ +// uint32_t vlim; /* 最小系统电压 (uV) */ +// uint32_t max_ichg; /* 最大充电电流 (uA) */ +// uint32_t max_vreg; /* 最大满电电压 (uV) */ +// }; + + +// struct sgm41562_init_data data = {0}; + + + + +// bat_info.constant_charge_current_max_ua = +// SGM41562_FAST_ICC_DEF_uA; +// sgm->init_data.ichg = bat_info.constant_charge_current_max_ua; + +// bat_info.constant_charge_voltage_max_uv = +// SGM41562_VBAT_REG_DEF_uV; +// sgm->init_data.max_vreg = bat_info.constant_charge_voltage_max_uv; + +// bat_info.charge_term_current_ua = +// SGM41562_TERM_I_DEF_uA; +// sgm->init_data.iterm = bat_info.charge_term_current_ua; + +// sgm->init_data.max_ichg = +// SGM41562_FAST_ICC_MAX_uA; +// sgm->init_data.vlim = +// SGM41562_VINDPM_DEF_uV; + +// sgm->init_data.max_vreg = +// SGM41562_VBAT_REG_MAX_uV; + +// ret = sgm41562_set_fast_cc( +// bat_info.constant_charge_current_max_ua); +// if (ret) +// goto err_out; + +// ret = sgm41562_set_chrg_volt( +// bat_info.constant_charge_voltage_max_uv); +// if (ret) +// goto err_out; + +// ret = sgm41562_ctrl_setting(REG_BIT_VBAT_PRE,1); //3.0v +// if (ret) +// goto err_out; + +// ret = sgm41562_ctrl_setting(REG_BIT_VRECH,1); //200mv +// if (ret) +// goto err_out; + +// ret = sgm41562_set_input_volt_lim( sgm->init_data.vlim); +// if (ret) +// goto err_out; + +// ret = sgm41562_set_input_curr_lim( sgm->init_data.ilim); +// if (ret) +// goto err_out; + +// printf("ichrg_curr:%d chrg_vol:%d,input_curr_lim:%d", +// bat_info.constant_charge_current_max_ua, +// bat_info.constant_charge_voltage_max_uv, +// sgm->init_data.ilim); + +// return 0; + +// err_out: +// return ret; +// } + + +static int sgm41562_hw_chipid_detect(void) +{ + int ret = 0; + uint8_t val = 0; + + ret = sgm41562_read_reg(SGM41562_CHRG_REG_B,&val); + if (ret < 0) { + printf("[%s] read SGM41562_CHRG_REG_B fail\n", __func__); + return ret; + } + printf("[%s] Reg[0x0B]=0x%x.\n", __func__,val); + + if (val == SGM41562S_DEV_ID){ + printf("[%s] device sgm41562S found !!!\n", __func__); + } else if (val == SGM41562SA_DEV_ID) { + printf("[%s] device sgm41562SA found !!!\n", __func__); + } else if (val == SGM41562_DEV_ID) { + printf("[%s] device sgm41562 found !!!\n", __func__); + }else { + printf("[%s] device not found !!!\n", __func__); + return -1; + } + + return ret; +} + + +int sgm41562_hw_init(void) +{ + int ret = 0; + + // struct sgm41562_init_data { + // uint32_t ichg; /* charge current */ + // uint32_t ilim; /* input current */ + // uint32_t vreg; /* regulation voltage */ + // uint32_t iterm; /* termination current */ + // uint32_t iprechg;/* precharge current */ + // uint32_t vlim; /* minimum system voltage limit */ + // uint32_t max_ichg; + // uint32_t max_vreg; + // }; + + custom_i2c_init(I2C_BUS); + + ret = sgm41562_hw_chipid_detect(); + if(ret){ + printf("[%s] device not found !!!\n", __func__); + return ret; + } + + printf("sgm41562_hw_chipid_detect successful\n"); + + struct sgm41562_init_data data = {0}; + + data.ichg = 256000; + data.vreg = SGM41562_VBAT_REG_DEF_uV; + data.iterm = SGM41562_TERM_I_DEF_uA; + data.vlim = SGM41562_VINDPM_DEF_uV; + data.max_ichg = SGM41562_FAST_ICC_MAX_uA; + data.max_vreg = SGM41562_VBAT_REG_MAX_uV; + data.ilim = SGM41562_IINDPM_DEF_uA; + + // ===================== 硬件寄存器配置 ===================== + ret = sgm41562_set_fast_cc(data.ichg); + if (ret) + goto err_out; + + ret = sgm41562_set_chrg_volt(data.vreg); + if (ret) + goto err_out; + + ret = sgm41562_ctrl_setting(REG_BIT_VBAT_PRE, 1); // 3.0V + if (ret) + goto err_out; + + ret = sgm41562_ctrl_setting(REG_BIT_VRECH, 1); // 200mV + if (ret) + goto err_out; + + ret = sgm41562_set_input_volt_lim(data.vlim); + if (ret) + goto err_out; + + ret = sgm41562_set_input_curr_lim(data.ilim); + if (ret) + goto err_out; + + ret = sgm41562_ctrl_setting(REG_BIT_EN_CEB, 0); + if (ret) + goto err_out; + + printf("ichrg:%d uA, chrg_vol:%d uV, input_limit:%d uA\n", + data.ichg, data.vreg, data.ilim); + + + // static int sgm41562_read_reg( uint8_t reg, uint8_t *data); + uint8_t reg_data = 0; + + sgm41562_read_reg(SGM41562_CHRG_REG_0,®_data); + printf("SGM41562_CHRG_REG_0 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_1,®_data); + printf("SGM41562_CHRG_REG_1 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_2,®_data); + printf("SGM41562_CHRG_REG_2 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_3,®_data); + printf("SGM41562_CHRG_REG_3 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_4,®_data); + printf("SGM41562_CHRG_REG_4 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_5,®_data); + printf("SGM41562_CHRG_REG_5 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_6,®_data); + printf("SGM41562_CHRG_REG_6 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_7,®_data); + printf("SGM41562_CHRG_REG_7 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_8,®_data); + printf("SGM41562_CHRG_REG_8 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_9,®_data); + printf("SGM41562_CHRG_REG_9 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_A,®_data); + printf("SGM41562_CHRG_REG_A :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_B,®_data); + printf("SGM41562_CHRG_REG_B :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_C,®_data); + printf("SGM41562_CHRG_REG_C :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_D,®_data); + printf("SGM41562_CHRG_REG_D :0x%x\n",reg_data); + + return 0; + +err_out: + return ret; +} + +// static int sgm41562_parse_dt(void) +// { +// int ret; + +// int irq_gpio = 0, irqn = 0; +// //int chg_en_gpio = 0; + +// ret = device_property_read_uint32_t(sgm->dev, +// "input-voltage-limit-microvolt", +// &sgm->init_data.vlim); +// if (ret) +// sgm->init_data.vlim = SGM41562_VINDPM_DEF_uV; + +// if (sgm->init_data.vlim > SGM41562_VINDPM_V_MAX_uV || +// sgm->init_data.vlim < SGM41562_VINDPM_V_MIN_uV) +// return -1; + +// ret = device_property_read_uint32_t(sgm->dev, +// "input-current-limit-microamp", +// &sgm->init_data.ilim); +// if (ret) +// sgm->init_data.ilim = SGM41562_IINDPM_DEF_uA; + +// if (sgm->init_data.ilim > SGM41562_IINDPM_I_MAX_uA || +// sgm->init_data.ilim < SGM41562_IINDPM_I_MIN_uA) +// return -1; + +// irq_gpio = of_get_named_gpio(sgm->dev->of_node, "irq-gpio", 0); +// if (!gpio_is_valid(irq_gpio)) +// { +// dev_err(sgm->dev, "%s: %d gpio get failed\n", __func__, irq_gpio); +// return -1; +// } +// ret = gpio_request(irq_gpio, "sgm41562 irq pin"); +// if (ret) { +// dev_err(sgm->dev, "%s: %d gpio request failed\n", __func__, irq_gpio); +// return ret; +// } +// gpio_direction_input(irq_gpio); +// irqn = gpio_to_irq(irq_gpio); +// if (irqn < 0) { +// dev_err(sgm->dev, "%s:%d gpio_to_irq failed\n", __func__, irqn); +// return irqn; +// } +// sgm->client->irq = irqn; +// #if 0 +// chg_en_gpio = of_get_named_gpio(sgm->dev->of_node, "chg-en-gpio", 0); +// if (!gpio_is_valid(chg_en_gpio)) +// { +// dev_err(sgm->dev, "%s: %d gpio get failed\n", __func__, chg_en_gpio); +// return -1; +// } +// ret = gpio_request(chg_en_gpio, "sgm chg en pin"); +// if (ret) { +// dev_err(sgm->dev, "%s: %d gpio request failed\n", __func__, chg_en_gpio); +// return ret; +// } +// gpio_direction_output(chg_en_gpio,0);//default enable charge +// #endif +// return 0; +// } + + +// static int sgm41562_suspend_notifier(struct notifier_block *nb, +// unsigned long event, +// void *dummy) +// { +// void = container_of(nb, struct sgm41562_device, pm_nb); + +// switch (event) { + +// case PM_SUSPEND_PREPARE: +// printf("sgm41562 PM_SUSPEND \n"); + +// cancel_delayed_work_sync(&sgm->charge_monitor_work); + +// sgm->sgm41562_suspend_flag = 1; + +// return NOTIFY_OK; + +// case PM_POST_SUSPEND: +// printf("sgm41562 PM_RESUME \n"); + +// schedule_delayed_work(&sgm->charge_monitor_work, 0); + +// sgm->sgm41562_suspend_flag = 0; + +// return NOTIFY_OK; + +// default: +// return NOTIFY_DONE; +// } +// } + +// static int sgm41562_probe(struct i2c_client *client, +// const struct i2c_device_id *id) +// { +// struct device *dev = &client->dev; +// void; +// int ret; +// char *name = NULL; + +// printf("%s enter\n",__func__); +// sgm = devm_kzalloc(dev, sizeof(*sgm), GFP_KERNEL); +// if (!sgm) +// return -ENOMEM; + +// sgm->client = client; +// sgm->dev = dev; + +// mutex_init(&sgm->lock); +// mutex_init(&sgm->i2c_rw_lock); + +// strncpy(sgm->model_name, id->name, I2C_NAME_SIZE); + +// i2c_set_clientdata(client, sgm); + +// // Customer customization +// ret = sgm41562_parse_dt(sgm); +// if (ret) { +// dev_err(dev, "Failed to read device tree properties%d\n", ret); +// return ret; +// } + +// ret = sgm41562_hw_chipid_detect(sgm); +// if(ret){ +// printf("[%s] device not found !!!\n", __func__); +// return ret; +// } + +// name = devm_kasprintf(sgm->dev, GFP_KERNEL, "%s", +// "sgm41562 suspend wakelock"); +// #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 9)) +// // 如果内核版本大于或等于 4.1.9,执行这里的代码 +// sgm->charger_wakelock = +// wakeup_source_register(dev,name); +// #else +// sgm->charger_wakelock = +// wakeup_source_register(name); +// #endif + +// INIT_DELAYED_WORK(&sgm->charge_detect_delayed_work, charger_detect_work_func); +// INIT_DELAYED_WORK(&sgm->charge_monitor_work, charger_monitor_work_func); +// sgm->pm_nb.notifier_call = sgm41562_suspend_notifier; +// register_pm_notifier(&sgm->pm_nb); + +// if (client->irq) { +// ret = devm_request_threaded_irq(dev, client->irq, NULL, +// sgm41562_irq_handler_thread, +// IRQF_TRIGGER_FALLING | +// IRQF_ONESHOT, +// dev_name(&client->dev), sgm); +// if (ret) +// goto error_out; +// enable_irq_wake(client->irq); +// } + +// ret = sgm41562_power_supply_init( dev); +// if (ret) { +// dev_err(dev, "Failed to register power supply\n"); +// goto error_out; +// } + +// ret = sgm41562_hw_init(sgm); +// if (ret) { +// dev_err(dev, "Cannot initialize the chip.\n"); +// goto error_out; +// } + +// schedule_delayed_work(&sgm->charge_monitor_work,100); +// printf("%s end \n",__func__); + +// error_out: +// return ret; +// } + +// static int sgm41562_charger_remove(struct i2c_client *client) +// { +// void= i2c_get_clientdata(client); + +// cancel_delayed_work_sync(&sgm->charge_monitor_work); + +// power_supply_unregister(sgm->charger); + +// mutex_destroy(&sgm->lock); +// mutex_destroy(&sgm->i2c_rw_lock); + + +// return 0; +// } + +static void sgm41562_charger_shutdown(void) +{ + int ret = 0; + + // void = i2c_get_clientdata(client); + ret = sgm41562_ctrl_setting(REG_BIT_EN_CEB,0); + if (ret) { + printf("Failed to disable charger, ret = %d\n", ret); + } + printf("sgm41562_charger_shutdown\n"); +} + +void sgm41562_read_all_reg(void) +{ + uint8_t reg_data = 0; + + sgm41562_read_reg(SGM41562_CHRG_REG_0,®_data); + printf("SGM41562_CHRG_REG_0 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_1,®_data); + printf("SGM41562_CHRG_REG_1 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_2,®_data); + printf("SGM41562_CHRG_REG_2 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_3,®_data); + printf("SGM41562_CHRG_REG_3 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_4,®_data); + printf("SGM41562_CHRG_REG_4 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_5,®_data); + printf("SGM41562_CHRG_REG_5 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_6,®_data); + printf("SGM41562_CHRG_REG_6 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_7,®_data); + printf("SGM41562_CHRG_REG_7 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_8,®_data); + printf("SGM41562_CHRG_REG_8 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_9,®_data); + printf("SGM41562_CHRG_REG_9 :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_A,®_data); + printf("SGM41562_CHRG_REG_A :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_B,®_data); + printf("SGM41562_CHRG_REG_B :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_C,®_data); + printf("SGM41562_CHRG_REG_C :0x%x\n",reg_data); + + sgm41562_read_reg(SGM41562_CHRG_REG_D,®_data); + printf("SGM41562_CHRG_REG_D :0x%x\n",reg_data); +} diff --git a/code/sdk/zhihui/drivers/charge/sgm41562/sgm41562.h b/code/sdk/zhihui/drivers/charge/sgm41562/sgm41562.h new file mode 100644 index 000000000..19460d672 --- /dev/null +++ b/code/sdk/zhihui/drivers/charge/sgm41562/sgm41562.h @@ -0,0 +1,263 @@ +#ifndef SGM41562_CHARGER_H +#define SGM41562_CHARGER_H + +#include +#include +#include "std_def.h" + +#ifndef GENMASK +#define GENMASK(h, l) (((uint8_t) -1 >> (7 - (h))) & ~((1U << (l)) - 1)) +#endif + +/*define register*/ +#define SGM41562_CHRG_REG_0 0x00 +#define SGM41562_CHRG_REG_1 0x01 +#define SGM41562_CHRG_REG_2 0x02 +#define SGM41562_CHRG_REG_3 0x03 +#define SGM41562_CHRG_REG_4 0x04 +#define SGM41562_CHRG_REG_5 0x05 +#define SGM41562_CHRG_REG_6 0x06 +#define SGM41562_CHRG_REG_7 0x07 +#define SGM41562_CHRG_REG_8 0x08 +#define SGM41562_CHRG_REG_9 0x09 +#define SGM41562_CHRG_REG_A 0x0A +#define SGM41562_CHRG_REG_B 0x0B +#define SGM41562_CHRG_REG_C 0x0C +#define SGM41562_CHRG_REG_D 0x0D + +/* REG00 vindpm voltage */ +#define SGM41562_VINDPM_V_MASK GENMASK(7, 4) +#define SGM41562_VINDPM_V_MIN_uV 3880000 +#define SGM41562_VINDPM_V_MAX_uV 5080000 +#define SGM41562_VINDPM_STEP_uV 80000 +#define SGM41562_VINDPM_DEF_uV 4600000 +#define SGM41562_PRE_TO BIT(3) +#define SGM41562_INT_EXIT_SHIP BIT(2) +#define SGM41562_VIN_EXIT_SHIP BIT(1) +#define SGM41562_ITERM_TIMER BIT(0) + + +/*REG01 charge setting */ +#define SGM41562_RST_DGL GENMASK(7, 6) +#define SGM41562_RST_DUR BIT(5) +#define SGM41562_HIZ_EN BIT(4) +#define SGM41562_EN_CEB BIT(3) + +/*REG01 VBAT UVLO THRESHOLD */ +#define SGM41562_VBAT_UVLO_MASK GENMASK(2, 0) +#define SGM41562_VBAT_UVLO_MIN_uV 2400000 +#define SGM41562_VBAT_UVLO_MAX_uV 3030000 +#define SGM41562_VBAT_UVLO_STEP_uV 90000 +#define SGM41562_VBAT_UVLO_DEF_uV 2760000 + +/*REG02 */ +#define SGM41562_REG_RST BIT(7) +#define SGM41562_FAST_ICC_MASK GENMASK(5, 0) +#define SGM41562_FAST_ICC_MIN_uA 8000 +#define SGM41562_FAST_ICC_MAX_uA 1024000 +#define SGM41562_FAST_ICC_STEP_uA 8000 +#define SGM41562_FAST_ICC_DEF_uA 128000 + +/* REG03 discharge current */ +#define SGM41562_DSCHG_I_MASK GENMASK(7, 4) +#define SGM41562_DSCHG_I_MIN_uA 400000 +#define SGM41562_DSCHG_I_MAX_uA 3200000 +#define SGM41562_DSCHG_I_STEP_uA 200000 +#define SGM41562_DSCHG_I_DEF_uA 2000000 + +/* REG03 termination current */ +#define SGM41562_TERM_I_MASK GENMASK(3, 0) +#define SGM41562_TERM_I_MIN_uA 1000 +#define SGM41562_TERM_I_MAX_uA 31000 +#define SGM41562_TERM_I_STEP_uA 2000 +#define SGM41562_TERM_I_DEF_uA 3000 + + +/* REG04 vbat */ +#define SGM41562_VBAT_REG_MASK GENMASK(7, 2) +#define SGM41562_VBAT_REG_MIN_uV 3500000 +#define SGM41562_VBAT_REG_MAX_uV 4770000 +#define SGM41562_VBAT_REG_STEP_uV 10000 +#define SGM41562_VBAT_REG_DEF_uV 4550000 +#define SGM41562_VRECH_THRE_uV BIT(0) + + +/* REG05 */ +#define SGM41562_EN_WD_DISCHG BIT(7) +#define SGM41562_WD_TIMER_MASK (BIT(6)| BIT(5)) +#define SGM41562_EN_TERM BIT(4) +#define SGM41562_EN_SATETY_TIMER BIT(3) +#define SGM41562_CHG_TIMER_MASK (BIT(2)| BIT(1)) +#define SGM41562_EN_TERM_TIMER BIT(0) + +/* REG06 */ +#define SGM41562_EN_NTC BIT(7) +#define SGM41562_EN_TMR2X BIT(6) +#define SGM41562_FET_DIS BIT(5) +#define SGM41562_PG_INT_CTL BIT(4) +#define SGM41562_EOC_INT_CTL BIT(3) +#define SGM41562_CHG_STATUS_INT_CTL BIT(2) +#define SGM41562_NTC_INT_CTL BIT(1) +#define SGM41562_BATOVP_INT_CTL BIT(0) + +/* REG07 */ +#define SGM41562_DIS_VINLOOP BIT(7) +#define SGM41562_TJ_REG_MASK GENMASK(6, 5) +#define SGM41562_VSYS_REG_MASK GENMASK(4, 0) +#define SGM41562_VSYS_MIN_uV 3600000 +#define SGM41562_VSYS_MAX_uV 5150000 +#define SGM41562_VSYS_STEP_uV 50000 +#define SGM41562_VSYS_DEF_uV 4550000 + +/* REG08 */ +#define SGM41562_WTD_FAULT BIT(7) +#define SGM41562_DIS_PCB_OTP BIT(6) +#define SGM41562_VIN_OVP_SEL BIT(5) +#define SGM41562_CHG_STAT_MASK GENMASK(4, 3) +#define SGM41562_NOT_CHRGING 0 +#define SGM41562_PRECHRG BIT(3) +#define SGM41562_FAST_CHRG BIT(4) +#define SGM41562_TERM_CHRG (BIT(3)| BIT(4)) +#define SGM41562_PPM_STAT BIT(2) +#define SGM41562_PG_STAT BIT(1) +#define SGM41562_THERM_STAT BIT(0) + + +/* REG09 */ +#define SGM41562_EN_SHIP_DGL_MASK GENMASK(7, 6) +#define SGM41562_VIN_FAULT BIT(5) +#define SGM41562_THEM_SD BIT(4) +#define SGM41562_BAT_FAULT BIT(3) +#define SGM41562_STMR_FAULT BIT(2) +#define SGM41562_NTC_HOT_FAULT BIT(1) +#define SGM41562_NTC_COOL_FAULT BIT(0) + + +/* REG0A */ +#define SGM41562_SLAVE_ADDR_MASK GENMASK(7, 5) +#define SGM41562_COLD_RESET BIT(4) +#define SGM41562_SWITCH_MODE BIT(3) +#define SGM41562_DIS_VDD BIT(2) +#define SGM41562_DIS_VINOVP BIT(1) +#define SGM41562_CC_FINE BIT(0) + +/* REG0B */ +#define SGM41562_DEV_ID_MASK GENMASK(7, 0) +#define SGM41562S_DEV_ID (BIT(3) | BIT(0)) +#define SGM41562SA_DEV_ID 0 + +#define SGM41562_DEV_ID 0x4 + +/* REG0C iindpm current */ +#define SGM41562_IINDPM_I_MASK GENMASK(7, 3) +#define SGM41562_IINDPM_I_MIN_uA 50000 +#define SGM41562_IINDPM_I_MAX_uA 980000 +#define SGM41562_IINDPM_STEP_uA 30000 +#define SGM41562_IINDPM_DEF_uA 500000 +#define SGM41562_DIS_INT BIT(2) +#define SGM41562_VBAT_PRE_THRE_uV BIT(1) +#define SGM41562_WD_RST BIT(0) + +/* REG0D iprechg current */ +#define SGM41562_PRE_ICHG_MASK GENMASK(7, 4) +#define SGM41562_PRE_ICHG_MIN_uA 1000 +#define SGM41562_PRE_ICHG_MAX_uA 31000 +#define SGM41562_PRE_ICHG_STEP_uA 2000 +#define SGM41562_PRE_ICHG_DEF_uA 3000 +#define SGM41562_PRE_ICHG_X6 BIT(3) +#define SGM41562_ITERM_X6 BIT(2) + +struct sgm41562_init_data { + uint32_t ichg; /* charge current */ + uint32_t ilim; /* input current */ + uint32_t vreg; /* regulation voltage */ + uint32_t iterm; /* termination current */ + uint32_t iprechg; /* precharge current */ + uint32_t vlim; /* minimum system voltage limit */ + uint32_t max_ichg; + uint32_t max_vreg; +}; + +typedef enum { + // 对齐原内核枚举的语义,数值从0开始自定义 + POWER_SUPPLY_PROP_MANUFACTURER = 0, // 制造商 + POWER_SUPPLY_PROP_MODEL_NAME, // 型号名称 + POWER_SUPPLY_PROP_STATUS, // 充电状态(充电/放电/空闲) + POWER_SUPPLY_PROP_ONLINE, // 是否在线(外接电源是否接入) + POWER_SUPPLY_PROP_HEALTH, // 电池健康状态 + POWER_SUPPLY_PROP_VOLTAGE_NOW, // 当前电压(mV) + POWER_SUPPLY_PROP_CURRENT_NOW, // 当前电流(mA) + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, // 输入限流(mA) + POWER_SUPPLY_PROP_CHARGE_TYPE, // 充电类型(恒流/恒压/快充等) + POWER_SUPPLY_PROP_USB_TYPE, // USB 类型(USB2.0/3.0/快充协议) + POWER_SUPPLY_PROP_PRESENT, // 电池是否在位 + POWER_SUPPLY_PROP_MAX // 枚举边界(用于数组遍历) +} power_supply_property; + +// 原数组直接复用,仅修改枚举类型定义(无需改数组内容) +static power_supply_property sgm41562_power_supply_props[] = { + POWER_SUPPLY_PROP_MANUFACTURER, + POWER_SUPPLY_PROP_MODEL_NAME, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, + POWER_SUPPLY_PROP_CHARGE_TYPE, + POWER_SUPPLY_PROP_USB_TYPE, + POWER_SUPPLY_PROP_PRESENT +}; + +struct sgm41562_state { + bool ppm_stat; + bool therm_stat; + bool pg_stat; + uint8_t chrg_stat; + + bool chrg_en; + bool hiz_en; + bool term_en; + bool bat_fault; + + uint8_t health; + uint8_t ntc_fault_0; + uint8_t ntc_fault_1; +}; + +// struct sgm41562_device { +// struct i2c_client *client; +// struct device *dev; +// struct power_supply *charger; +// struct mutex lock; +// struct mutex i2c_rw_lock; + +// struct usb_phy *usb2_phy; +// struct usb_phy *usb3_phy; +// struct notifier_block usb_nb; +// struct work_struct usb_work; +// unsigned long usb_event; +// struct regmap *regmap; + +// char model_name[I2C_NAME_SIZE]; +// int device_id; + +// struct sgm41562_init_data init_data; +// struct sgm41562_state state; +// #if defined(CONFIG_MTK_GAUGE_VERSION) && (CONFIG_MTK_GAUGE_VERSION == 30) +// struct charger_device *chg_dev; +// #endif + +// struct delayed_work charge_detect_delayed_work; +// struct delayed_work charge_monitor_work; +// struct notifier_block pm_nb; +// bool sgm41562_suspend_flag; + +// struct wakeup_source *charger_wakelock; +// }; + +int sgm41562_hw_init(void); + +void sgm41562_read_all_reg(void); + +#endif /* _SGM41562_CHARGER_H */ diff --git a/code/sdk/zhihui/services/battery/service/battery_driver.cpp b/code/sdk/zhihui/services/battery/service/battery_driver.cpp index f3e9bd994..cbd01b580 100644 --- a/code/sdk/zhihui/services/battery/service/battery_driver.cpp +++ b/code/sdk/zhihui/services/battery/service/battery_driver.cpp @@ -432,7 +432,7 @@ float battery_percent_map[][2]={ {3.397, 5}, {3.3, 0} #elif defined BOARD_FD272 - {4.374, 100}, + {4.4, 100}, {4.186, 95}, {4.167, 90}, {4.148, 85}, @@ -480,27 +480,48 @@ float battery_percent_map[][2]={ float battery_charge_percent_map[][2]={ #ifdef BOARD_FD272 - {4.375, 100}, - {4.255, 95}, - {4.155, 90}, - {4.069, 85}, - {3.996, 80}, - {3.933, 75}, - {3.877, 70}, - {3.828, 65}, - {3.784, 60}, - {3.744, 55}, - {3.708, 50}, - {3.674, 45}, - {3.643, 40}, - {3.614, 35}, - {3.586, 30}, - {3.560, 25}, - {3.535, 20}, - {3.510, 15}, - {3.480, 10}, - {3.415, 5}, - {3.300, 0} + // {4.374, 100}, + // {4.260, 95}, + // {4.155, 90}, + // {4.068, 85}, + // {3.995, 80}, + // {3.932, 75}, + // {3.877, 70}, + // {3.828, 65}, + // {3.784, 60}, + // {3.744, 55}, + // {3.715, 50}, + // {3.708, 45}, + // {3.705, 40}, + // {3.703, 35}, + // {3.702, 30}, + // {3.701, 25}, + // {3.700, 20}, + // {3.650, 15}, + // {3.600, 10}, + // {3.500, 5}, + // {3.300, 0} + {4.4, 100}, + {4.338, 95}, + {4.300, 90}, + {4.263, 85}, + {4.225, 80}, + {4.188, 75}, + {4.150, 70}, + {4.113, 65}, + {4.075, 60}, + {4.038, 55}, + {4.000, 50}, + {3.963, 45}, + {3.925, 40}, + {3.888, 35}, + {3.850, 30}, + {3.813, 25}, + {3.775, 20}, + {3.738, 15}, + {3.700, 10}, + {3.500, 5}, + {3.300, 0} #endif }; @@ -508,7 +529,7 @@ float battery_charge_percent_map[][2]={ #ifdef BOARD_LEINIAO #define batteryservice_VOLTAGE_MAX (4.2f) #elif defined BOARD_FD272 -#define batteryservice_VOLTAGE_MAX (4.374f) +#define batteryservice_VOLTAGE_MAX (4.4f) #else #define batteryservice_VOLTAGE_MAX (4.3f) #endif diff --git a/code/sdk/zhihui/services/battery/service/battery_service.cpp b/code/sdk/zhihui/services/battery/service/battery_service.cpp index f3d5fe7f0..bcce40618 100644 --- a/code/sdk/zhihui/services/battery/service/battery_service.cpp +++ b/code/sdk/zhihui/services/battery/service/battery_service.cpp @@ -43,6 +43,8 @@ extern "C" { #ifdef ENABLE_HP4570 #include "hp4570.h" +#elif defined ENABLE_SGM41562 +#include "sgm41562.h" #endif // #include "cat1_utils.h" @@ -809,8 +811,10 @@ errcode_t uapi_battery_init(void) #ifdef ENABLE_HP4570 hp4570n_init(HP4570N); +#elif defined ENABLE_SGM41562 + sgm41562_hw_init(); #endif - battery_restore_vol(); + // battery_restore_vol(); battery_check_voltage(); battery_percent_init(0); //先读历史电量 diff --git a/code/sdk/zhihui/utils/custom_utils.c b/code/sdk/zhihui/utils/custom_utils.c index 9445789ed..42c64cd96 100644 --- a/code/sdk/zhihui/utils/custom_utils.c +++ b/code/sdk/zhihui/utils/custom_utils.c @@ -436,7 +436,7 @@ void shutdown_reboot_prejobs_task(void) // 保存电量历史(关机、重启、升级前均会执行,保证下次开机有历史电量可对比) #ifdef SUPPORT_BATTERY_SERVICE PRINT("shutdown_reboot_prejobs_task: Calling battery_save_vol()\r\n"); - battery_save_vol(); + // battery_save_vol(); PRINT("shutdown_reboot_prejobs_task: battery_save_vol() completed\r\n"); #endif -- 2.17.1