int asus_battery_register_proc_fs_test(void)
{
	struct battery_info_reply tmp_batt_info;
	struct proc_dir_entry *entry=NULL;

        mutex_lock(&batt_info_mutex);
        tmp_batt_info = batt_info;
        mutex_unlock(&batt_info_mutex);

	static struct file_operations asus_battery_info_fop = {
		.read = asus_battery_info_proc_read,
		//.write = asus_battery_info_proc_write,
	};
	entry = proc_create("asus_battery_info", 0666,NULL, &asus_battery_info_fop);
	if(!entry)
	{
		BAT_DBG_E("create /proc/asus_battery_info fail\n");
	}

	static struct file_operations asus_battery_profile_fop = {
	    	.read = asus_battery_profile_read,
	};
	entry = proc_create(PROCFS_BATTERY, 0666,NULL, &asus_battery_profile_fop);
	if(!entry)
	{
		BAT_DBG_E("create /proc/%s fail\n", PROCFS_BATTERY);
	}

        return 0;
}
int asus_battery_register_proc_fs_test(void)
{
        struct proc_dir_entry *entry=NULL;
        struct battery_info_reply tmp_batt_info;

        mutex_lock(&batt_info_mutex);
        tmp_batt_info = batt_info;
        mutex_unlock(&batt_info_mutex);

#if 0
        if (tmp_batt_info.test_flag & TEST_INFO_PROC_DUMP) {
#endif
                entry = create_proc_entry("asus_battery_info", 0666, NULL);
                if (!entry) {
                        BAT_DBG_E("Unable to create asus_battery_info\n");
                        return -EINVAL;
                }
                entry->read_proc = asus_battery_info_proc_read;
                entry->write_proc = asus_battery_info_proc_write;
#if 0
        }
#endif

        entry = create_proc_entry(PROCFS_BATTERY, 0666, NULL);
        if (!entry) {
                BAT_DBG_E("Unable to create %s\n", PROCFS_BATTERY);
                return -EINVAL;
        }
        entry->read_proc = asus_battery_profile_read;

        return 0;
}
int asus_charging_for_gague_toggle_write(struct file *file, const char *buffer, unsigned long count, void *data)
{
    struct battery_info_reply tmp_batt_info;
    //bool eng_charging_limit = true;

    BAT_DBG(" %s:\n", __func__);

    mutex_lock(&batt_info_mutex);
    tmp_batt_info = batt_info;
    mutex_unlock(&batt_info_mutex);

    //eng_charging_limit = tmp_batt_info.eng_charging_limit;

    if (buffer[0] == '0') {
        /* turn on charging limit in eng mode */
        //eng_charging_limit = true;
        BAT_DBG_E(" disable charging:\n");
        smb347_charging_toggle(false);
    }
    else if (buffer[0] == '1') {
        /* turn off charging limit in eng mode */
        //eng_charging_limit = false;
        BAT_DBG_E(" enable charging:\n");
        smb347_charging_toggle(true);
    }

    //tmp_batt_info.eng_charging_limit = eng_charging_limit;

    mutex_lock(&batt_info_mutex);
    batt_info = tmp_batt_info;
    mutex_unlock(&batt_info_mutex);

    return count;
}
int bq27520_exit_rom_mode() 
{
    int retry = RETRY_COUNT;
    struct i2c_client *i2c = NULL;
    struct i2c_client *client = NULL;
    int val=0;
    int ret=0;

    mutex_lock(&batt_dev_upt_mutex);    
    i2c = batt_upt_dev_info.i2c;
    mutex_unlock(&batt_dev_upt_mutex);

    BAT_DBG_E("[%s] enter \n", __func__);

    while (retry--) {
        ret = bq27520_write_i2c(i2c, 0x00, 0x0F, 1);
        if (ret < 0) continue;

        ret = bq27520_write_i2c(i2c, 0x64, 0x0F, 1);
        if (ret < 0) continue;

        ret = bq27520_write_i2c(i2c, 0x65, 0x00, 1);
        if (ret < 0) continue;

        break;
    };
    if (!retry) {
        BAT_DBG_E("Exit ROM mode FAIL \n");
        return ret;
    }

    /* 
     * verify it's NOT ROM node.
     * Yes if read registers FAIL from now on.
     */
    ret = bq27520_read_i2c(i2c, 0x00, &val, 1);
    if (!ret)  {
        BAT_DBG_E("Exit ROM Mode verification FAIL.\n");
        return -EACCES;
    }

    /* 
     * wait 1s and send IT_ENABLE command 
     * (battery team request)
     */
    msleep(1000);

    mutex_lock(&bq27520_dev_info_mutex);    
    client = bq27520_dev_info.i2c;
    mutex_unlock(&bq27520_dev_info_mutex);

    ret = bq27520_send_subcmd(client, NULL, BQ27520_SUBCMD_ENABLE_IT);
    if (ret)
        return ret;

    return 0;
}
//++Sewell+++ charging toggle interface for thermal
int thermal_charging_toggle_read(char *page, char **start, off_t off, int count, int *eof, void *date)
{
    int len = 0;

    BAT_DBG_E(" %s:\n", __func__);
    return len;
}
int bq27520_rom_mode_cmp(int reg_off, int value)
{
    int retry = RETRY_COUNT;
    struct i2c_client *i2c = NULL;
    int val=0;
    int ret=0;

    mutex_lock(&batt_dev_upt_mutex);    
    i2c = batt_upt_dev_info.i2c;
    mutex_unlock(&batt_dev_upt_mutex);

    BAT_DBG_E("[%s] enter \n", __func__);

    while (retry--) {
        ret = bq27520_read_i2c(i2c, reg_off, &val, 1);
        if (ret < 0) continue;

        break;
    };
    if (!retry && ret < 0) {
        return ret;
    }

    return val == value ? PROC_TRUE : PROC_FALSE;
}
void asus_cancel_work()
{
    if (battery_work_queue) {
        BAT_DBG_E(" %s:\n", __func__);
        cancel_delayed_work_sync(&battery_poll_data_work);
        cancel_delayed_work_sync(&detect_cable_work);
    }
}
int bq27520_rom_mode_wait(int m_secs)
{
    BAT_DBG_E("[%s] enter \n", __func__);

    if (m_secs < 1) return -EINVAL;

    msleep(m_secs);

    return 0;
}
int bq27520_enter_rom_mode()
{
    int retry = RETRY_COUNT;
    struct i2c_client *i2c = NULL;
    int val=0;
    int ret=0;

    BAT_DBG_E("[%s] enter \n", __func__);

    if (bq27520_is_rom_mode()) {
        return 0;
    }

    mutex_lock(&bq27520_dev_info_mutex);    
    i2c = bq27520_dev_info.i2c;
    mutex_unlock(&bq27520_dev_info_mutex);

    while (retry--) {
        ret = bq27520_write_i2c(i2c, 0x00, 0x0F00, 0);
        if (ret < 0) continue;

        break;
    };
    if (ret < 0) {
        BAT_DBG_E("Enter ROM mode FAIL \n");
        return ret;
    }

    /* 
     * verify it's ROM node.
     * Yes if read registers FAIL from now on.
     */
    ret = bq27520_read_i2c(i2c, 0x00, &val, 1);
    if (!ret)  {
        BAT_DBG_E("Exit ROM Mode verification FAIL.\n");
        return -EACCES;
    }

    return 0;
}
static int asus_battery_update_status_no_mutex(int percentage)
{
    int status;
    int temperature;
    struct battery_info_reply tmp_batt_info;
    u32 cable_status;

    tmp_batt_info = batt_info;
    cable_status = tmp_batt_info.cable_status;

    if (cable_status == USB_ADAPTER || cable_status == USB_PC) {
        status = POWER_SUPPLY_STATUS_CHARGING;

        /* ME371MG, ME302C, ME372CG
            stop charging to protect battery from damaged when
            battery temperature is too low or too high
        */
        temperature = asus_battery_update_temp_no_mutex();
        if (temperature != ERROR_CODE_I2C_FAILURE) {

            if (tmp_batt_info.tbl_chgr &&
                    tmp_batt_info.tbl_chgr->soc_control_float_vol)
                tmp_batt_info.tbl_chgr->soc_control_float_vol(temperature);

            if (temperature < LOW_TEMPERATURE_TO_STOP_CHARGING) {
                if (tmp_batt_info.tbl_chgr && tmp_batt_info.tbl_chgr->charging_toggle)
                    tmp_batt_info.tbl_chgr->charging_toggle(JEITA, false);
                status = POWER_SUPPLY_STATUS_DISCHARGING;
                BAT_DBG_E("*Error*: Force stop charging due to that battery temperature(%d) is lower than 0 (0.1C)", temperature);
                goto final;
            } else if (temperature > HIGH_TEMPERATURE_TO_STOP_CHARGING) {
                if (tmp_batt_info.tbl_chgr &&
                        tmp_batt_info.tbl_chgr->charging_toggle)
                    tmp_batt_info.tbl_chgr->charging_toggle(JEITA, false);
                status = POWER_SUPPLY_STATUS_DISCHARGING;
                BAT_DBG_E("*Error*: Force stop charging due to that battery temperature(%d) is higher than 500 (0.1C)", temperature);
                goto final;
            }
        }
static int asus_battery_update_percentage(void)
{
    int percentage = -EINVAL;
    drv_status_t drv_status;
    struct battery_info_reply tmp_batt_info;

    mutex_lock(&batt_info_mutex);
    tmp_batt_info = batt_info;
    drv_status = batt_info.drv_status;
    mutex_unlock(&batt_info_mutex);

    if (tmp_batt_info.tbl && tmp_batt_info.tbl->read_percentage) {
        percentage = tmp_batt_info.tbl->read_percentage();

        if (percentage == ERROR_CODE_I2C_FAILURE)
            return -EINVAL;

        if (percentage >= 0 && percentage <= 3) {
            percentage = 0;
            drv_status = DRV_SHUTDOWN;
        }

        /* illegal RSOC check for UPI gauge IC */
        if (percentage < 0) {
            BAT_DBG_E("*** Wrong battery percentage = %d ***\n", percentage);
            percentage = 0;
        }
        if (percentage > 100) {
            BAT_DBG_E("*** Wrong battery percentage = %d ***\n", percentage);
            percentage = 100;
        }

        mutex_lock(&batt_info_mutex);
        batt_info.drv_status = drv_status;
        mutex_unlock(&batt_info_mutex);
    }

    return percentage;
}
//<--Carlisle add for ATD querying charge status end
//-->Carlisle add for ATD querying gauge IC fw flash identify
int check_gauge_fw_status(void)
{
    struct proc_dir_entry *entry=NULL;

    entry = create_proc_entry("gauge_fw_status", 0666, NULL);
    if (!entry) {
        BAT_DBG_E("Unable to create gauge_fw_status\n");
        return -EINVAL;
    }
    entry->read_proc = check_gauge_fw_status_read;

    return 0;
}
int init_asus_charging_toggle(void)
{
    struct proc_dir_entry *entry=NULL;

    entry = create_proc_entry("charger_limit_enable", 0666, NULL);
    if (!entry) {
        BAT_DBG_E("Unable to create asus_charging_toggle\n");
        return -EINVAL;
    }
    entry->read_proc = asus_charging_toggle_read;
    entry->write_proc = asus_charging_toggle_write;

    return 0;
}
int init_thermal_charging_toggle(void)
{
    struct proc_dir_entry *entry=NULL;

    entry = create_proc_entry("thermal_charging_limit", 0600, NULL);
    if (!entry) {
        BAT_DBG_E("Unable to create thermal_charging_toggle\n");
        return -EINVAL;
    }
    entry->read_proc = thermal_charging_toggle_read;
    entry->write_proc = thermal_charging_toggle_write;

    return 0;
}
int bq27520_bat_upt_i2c_init(void)
{
    int ret = 0;
    struct i2c_adapter *adapter = NULL;
    struct i2c_client *client   = NULL;
    struct i2c_board_info *board_info= NULL;

    BAT_DBG("++++ %s ++++\n", __func__);

    //register i2c device
    board_info = &bq27520_bat_upt_i2c_board_info;
    adapter = i2c_get_adapter(((struct bq27520_bat_platform_data *)board_info->platform_data)->i2c_bus_id);
    if (adapter == NULL) {
        BAT_DBG_E("can not get i2c adapter, client address error\n");
        ret = -ENODEV;
        goto get_adapter_fail;
    }

    client = i2c_new_device(adapter, board_info);
    if (client == NULL) {
        BAT_DBG("allocate i2c client failed\n");
        ret = -ENOMEM;
        goto register_i2c_device_fail;
    }
    i2c_put_adapter(adapter);

    mutex_lock(&batt_dev_upt_mutex);    
    batt_upt_dev_info.i2c = client;
    mutex_unlock(&batt_dev_upt_mutex);

    //register i2c driver
    ret =  i2c_add_driver(&bq27520_bat_upt_i2c_driver);
    if (ret) {
        BAT_DBG("register bq27520 battery update i2c driver failed\n");
        goto i2c_register_driver_fail;
    }

    return ret;

i2c_register_driver_fail:
    i2c_unregister_device(client);
register_i2c_device_fail:
get_adapter_fail:
    return ret;
}
int bq27520_bat_upt_main_update_flow(void)
{
    int ret = UPDATE_NONE;

    BAT_DBG_E("[%s] enter \n", __func__);

    if (bq27520_is_rom_mode()) {
        ret = update_from_rom_mode();
    }
    else if (bq27520_is_normal_mode()) {
        ret = update_from_normal_mode();
    }
    else {
        return UPDATE_CHECK_MODE_FAIL;
    }

    return ret;
}
int update_from_normal_mode(void)
{
    int cell_type=0;
    int curr_cell_type=TYPE_LG, fw_cell_type=TYPE_LG;
    int ret = UPDATE_NONE;
    int curr_volt;
    int i,j;
    int fw_cfg_version;

    BAT_DBG("(%s) enter\n", __func__);

#if 0
    curr_cell_type = bq27520_batt_current_sel_type();
#endif
    fw_cell_type = bq27520_batt_fw_sel_type();
    curr_volt = bq27520_asus_battery_dev_read_volt();
    fw_cfg_version = bq27520_asus_battery_dev_read_fw_cfg_version();

    BAT_DBG("(%s) current_cell_type %d, fw_cell_type %d, current_volt %d, fw_cfg_version 0x%04X\n",
            __func__,
            curr_cell_type, fw_cell_type, curr_volt, fw_cfg_version
    );

    if (curr_cell_type == fw_cell_type) {
        if (fw_cfg_version == LATEST_FW_CFG_VERSION) {
            BAT_DBG(" No need to flash battery cell data due to that both firmware config version are equal");
            return ret;
        }
    }

    //Need update, check update voltage
    ret = UPDATE_VOLT_NOT_ENOUGH;
    if (curr_volt < 0 || curr_volt < 3700) {
        BAT_DBG_E("Voltage not enough \n");
        return ret;
    }

    ret = update_normal(curr_cell_type);

    return ret;
}
int bq27520_is_rom_mode(void)
{
    int retry = RETRY_COUNT;
    struct i2c_client *i2c = NULL;
    int val=0;
    int ret=0;

    BAT_DBG_E("[%s] enter \n", __func__);

    mutex_lock(&batt_dev_upt_mutex);    
    i2c = batt_upt_dev_info.i2c;
    mutex_unlock(&batt_dev_upt_mutex);

    while (retry--) {
        ret = bq27520_read_i2c(i2c, 0x00, &val, 1);
        if (ret < 0) continue;

        break;
    };
    if (ret < 0) {
        return 0; //not rom mode
    }
    return 1; //it's rom mode
}
int update_fw(struct update_op *p_start, struct update_op *p_end)
{
    int ret=UPDATE_OK;
    struct i2c_client *i2c_upt = NULL;
    struct i2c_client *i2c_dev = NULL;

    BAT_DBG("(%s) Start update firmware ... ", __func__); 

    mutex_lock(&bq27520_dev_info_mutex);    
    i2c_dev = bq27520_dev_info.i2c;
    mutex_unlock(&bq27520_dev_info_mutex);

    mutex_lock(&batt_dev_upt_mutex);    
    i2c_upt = batt_upt_dev_info.i2c;
    mutex_unlock(&batt_dev_upt_mutex);

    ret = UPDATE_PROCESS_FAIL;
    while (p_start <= p_end)
    {
        int op_execute_ret = 0;

#if 0
        /* print update command */
        BAT_DBG("OP: %d, off: %02X, val: %04X\n", 
                p_start->bq_op, p_start->off, p_start->arg
        );
#endif

        switch(p_start->bq_op) {
        case OP_ROM_END:
        case OP_ROM_WRITE:
            op_execute_ret = bq27520_rom_mode_write_i2c(p_start->off, p_start->arg, 1);
            if (op_execute_ret < 0) {
                BAT_DBG_E("   FAIL\n");
                return ret;
            }
            break;

        case OP_ROM_CMP:
            op_execute_ret = bq27520_rom_mode_cmp(p_start->off, p_start->arg);
            if (op_execute_ret == PROC_FALSE) {
                BAT_DBG_E("   FAIL\n");
                return ret;
            } else if (op_execute_ret != PROC_FALSE && op_execute_ret != PROC_TRUE) {
                if (op_execute_ret < 0) {
                    BAT_DBG_E("   FAIL\n");
                    return ret;
                }
            }
            break;

        case OP_I2C_START:
        case OP_I2C_WRITE:
            op_execute_ret = bq27520_write_i2c(i2c_dev, p_start->off, p_start->arg, 1);
            if (op_execute_ret < 0) {
                BAT_DBG_E("   FAIL\n");
                return ret;
            }
            break;

        case OP_I2C_CMP:
            op_execute_ret = bq27520_cmp_i2c(p_start->off, p_start->arg);
            if (op_execute_ret != PROC_FALSE && op_execute_ret != PROC_TRUE) {
                BAT_DBG_E("   FAIL %d\n", op_execute_ret);
                return ret;
            } else if (op_execute_ret == PROC_FALSE) {
                BAT_DBG_E("   FAIL\n");
                return ret;
            }
            break;

        case OP_WAIT:
            op_execute_ret = bq27520_rom_mode_wait(p_start->arg);
            if (op_execute_ret < 0) {
                BAT_DBG_E("   FAIL\n");
                return ret;
            }
            break;

        default:
            BAT_DBG("Not support OP \n");
            break;
        }; //end switch

        p_start++;
    }; //end while

    ret = UPDATE_OK;
    BAT_DBG("%s Done.\n", __func__);

    return ret;
}
int update_from_normal_mode(bool forceupdate) {

    int curr_cell_type=TYPE_LG, fw_cell_type=TYPE_LG;
    int ret = UPDATE_NONE;
    int curr_volt;
    int fw_cfg_version;

    BAT_DBG("(%s) enter\n", __func__);

#if 0
    curr_cell_type = bq27520_batt_current_sel_type();
#endif
    fw_cell_type = bq27520_batt_fw_sel_type();
    curr_volt = bq27520_asus_battery_dev_read_volt();
    fw_cfg_version = bq27520_asus_battery_dev_read_fw_cfg_version();

    BAT_DBG("(%s) current_cell_type %d, fw_cell_type %d, current_volt %d, fw_cfg_version 0x%04X\n",
            __func__,
            curr_cell_type, fw_cell_type, curr_volt, fw_cfg_version
    );

    if (!forceupdate) {
         if (fw_cfg_version == LATEST_FW_CFG_VERSION) {
                BAT_DBG("========= No need to flash battery cell data due to that both data flash version are equal =========");
                goto Done;
         }
    }

    //Need update, check update voltage
    ret = UPDATE_VOLT_NOT_ENOUGH;
    if (curr_volt < 0 || curr_volt < 3700) {
        BAT_DBG_E("Voltage not enough \n");
        goto Done;
    }

    if (batt_info.gauge_version == IC_VERSION_G3) {
        BAT_DBG("bq27520 gauge is G3, no need enter ROM mode.\n");

    } else if (batt_info.gauge_version == IC_VERSION_G4) {
        //unseal for enter rom mode
        ret = bq27520_default_unseal();
        if (ret < 0) {
           // default password unseal fail
           BAT_DBG_E("bq27520_default_unseal fail !!!!\n");
           bq27520_rom_mode_wait(5000);
           ret = bq27520_ME560CG_unseal();
           if (ret < 0) {
              // ME560CG password unseal fail
              BAT_DBG_E("bq27520_ME560CG_unseal fail !!!!\n");
              ret = UPDATE_CHECK_MODE_FAIL;
              goto Done;
          }
       }
    }

    smb347_charging_toggle(false);
    ret = update_normal(curr_cell_type);
    smb347_charging_toggle(true);

Done:
    flash_gauge_status = ret;
    return ret;
}
int bq27520_ME560CG_unseal() {
    struct i2c_client *i2c = NULL;
    int val=0;
    int ret=0;

    BAT_DBG_E("[%s] enter \n", __func__);

    mutex_lock(&bq27520_dev_info_mutex);    
    i2c = bq27520_dev_info.i2c;
    mutex_unlock(&bq27520_dev_info_mutex);

    ret = bq27520_write_i2c_retry(i2c, 0x00, 0x14);
    if (ret < 0) {
        BAT_DBG_E("Enter ROM mode FAIL \n");
        return ret;
    }
    ret = bq27520_write_i2c_retry(i2c, 0x01, 0x04);
    if (ret < 0) {
        BAT_DBG_E("Enter ROM mode FAIL \n");
        return ret;
    }
    ret = bq27520_write_i2c_retry(i2c, 0x00, 0x72);
    if (ret < 0) {
        BAT_DBG_E("Enter ROM mode FAIL \n");
        return ret;
    }
    ret = bq27520_write_i2c_retry(i2c, 0x01, 0x16);
    if (ret < 0) {
        BAT_DBG_E("Enter ROM mode FAIL \n");
        return ret;
    }
    bq27520_rom_mode_wait(20);
    ret = bq27520_write_i2c_retry(i2c, 0x00, 0xff);
    if (ret < 0) {
        BAT_DBG_E("Enter ROM mode FAIL \n");
        return ret;
    }
    ret = bq27520_write_i2c_retry(i2c, 0x01, 0xff);
    if (ret < 0) {
        BAT_DBG_E("Enter ROM mode FAIL \n");
        return ret;
    }
    ret = bq27520_write_i2c_retry(i2c, 0x00, 0xff);
    if (ret < 0) {
        BAT_DBG_E("Enter ROM mode FAIL \n");
        return ret;
    }
    ret = bq27520_write_i2c_retry(i2c, 0x01, 0xff);
    if (ret < 0) {
        BAT_DBG_E("Enter ROM mode FAIL \n");
        return ret;
    }
    bq27520_rom_mode_wait(20);
    ret = bq27520_write_i2c_retry(i2c, 0x00, 0x00);
    if (ret < 0) {
        BAT_DBG_E("Enter ROM mode FAIL \n");
        return ret;
    }
    ret = bq27520_write_i2c_retry(i2c, 0x01, 0x0f);
    if (ret < 0) {
        BAT_DBG_E("Enter ROM mode FAIL \n");
        return ret;
    }
    bq27520_rom_mode_wait(20);

    /* 
     * verify it's ROM mode.
     * Yes if read registers FAIL from now on.
     */
    ret = bq27520_read_i2c(i2c, 0x00, &val, 1);
    if (!ret)  {
        BAT_DBG_E("Exit ROM Mode verification FAIL.\n");
        return -EACCES;
    }

    return 0;
}
static void pmic_dump_registers(int dump_mask)
{
    int i, retval = 0, ret;
    uint8_t reg_val;
    uint16_t chk_reg_addr;
    uint16_t reg_addr_boot[] = {MSIC_BATT_RESETIRQ1_ADDR,
        MSIC_BATT_RESETIRQ2_ADDR, MSIC_BATT_CHR_LOWBATTDET_ADDR,
        MSIC_BATT_CHR_SPCHARGER_ADDR, MSIC_BATT_CHR_CHRTTIME_ADDR,
        MSIC_BATT_CHR_CHRCTRL1_ADDR, MSIC_BATT_CHR_CHRSTWDT_ADDR,
        MSIC_BATT_CHR_CHRSAFELMT_ADDR};
    char *reg_str_boot[] = {"rirq1", "rirq2", "lowdet",
                "spchr", "chrtime", "chrctrl1",
                "chrgwdt", "safelmt"};
    uint16_t reg_addr_int[] = {MSIC_BATT_CHR_PWRSRCINT_ADDR,
        MSIC_BATT_CHR_PWRSRCINT1_ADDR, MSIC_BATT_CHR_CHRINT_ADDR,
        MSIC_BATT_CHR_CHRINT1_ADDR, MSIC_BATT_CHR_PWRSRCLMT_ADDR};
    char *reg_str_int[] = {"pwrint", "pwrint1", "chrint",
                "chrint1", "pwrsrclmt"};
    uint16_t reg_addr_evt[] = {MSIC_BATT_CHR_CHRCTRL_ADDR,
        MSIC_BATT_CHR_CHRCVOLTAGE_ADDR, MSIC_BATT_CHR_CHRCCURRENT_ADDR,
        MSIC_BATT_CHR_SPWRSRCINT_ADDR, MSIC_BATT_CHR_SPWRSRCINT1_ADDR,
        CHR_STATUS_FAULT_REG};
    char *reg_str_evt[] = {"chrctrl", "chrcv", "chrcc",
                "spwrsrcint", "sprwsrcint1", "chrflt"};

    uint16_t reg_addr_others[] = {MSIC_BATT_CHR_MPWRSRCINT_ADDR,
        MSIC_BATT_CHR_MPWRSRCINT1_ADDR, MSIC_BATT_CHR_MCHRINT_ADDR,
        MSIC_BATT_CHR_MCHRINT1_ADDR, MSIC_BATT_CHR_VBUSDET_ADDR,
        MSIC_BATT_CHR_WDTWRITE_ADDR};
    char *reg_str_others[] = {"chrmpwrsrcint", "chrmpwrsrcint1", "chrmchrint",
                "chrmchrint1", "chrvbusdet", "chrwdtwrite"};

    if (dump_mask & MSIC_CHRG_REG_DUMP_BOOT) {
        for (i = 0; i < ARRAY_SIZE(reg_addr_boot); i++) {
            retval = intel_scu_ipc_ioread8(reg_addr_boot[i], &reg_val);
            if (retval) {
                chk_reg_addr = reg_addr_boot[i];
                goto ipcread_err;
            }
            BAT_DBG("PMIC(0x%03x)\tval: " BYTETOBINARYPATTERN "\t%s\n", reg_addr_boot[i],
                                BYTETOBINARY(reg_val), reg_str_boot[i]);
        }
    }
    if (dump_mask & MSIC_CHRG_REG_DUMP_INT) {
        for (i = 0; i < ARRAY_SIZE(reg_addr_int); i++) {
            retval = intel_scu_ipc_ioread8(reg_addr_int[i], &reg_val);
            if (retval) {
                chk_reg_addr = reg_addr_int[i];
                goto ipcread_err;
            }
            BAT_DBG("PMIC(0x%03x)\tval: " BYTETOBINARYPATTERN "\t%s\n", reg_addr_int[i],
                                BYTETOBINARY(reg_val), reg_str_int[i]);
        }
    }
    if (dump_mask & MSIC_CHRG_REG_DUMP_EVENT) {
        for (i = 0; i < ARRAY_SIZE(reg_addr_evt); i++) {
            retval = intel_scu_ipc_ioread8(reg_addr_evt[i], &reg_val);
            if (retval) {
                chk_reg_addr = reg_addr_evt[i];
                goto ipcread_err;
            }
            BAT_DBG("PMIC(0x%03x)\tval: " BYTETOBINARYPATTERN "\t%s\n", reg_addr_evt[i],
                                BYTETOBINARY(reg_val), reg_str_evt[i]);
        }
    }
    if (dump_mask & MSIC_CHRG_REG_DUMP_OTHERS) {
        for (i = 0; i < ARRAY_SIZE(reg_addr_others); i++) {
            retval = intel_scu_ipc_ioread8(reg_addr_others[i], &reg_val);
            if (retval) {
                chk_reg_addr = reg_addr_others[i];
                goto ipcread_err;
            }
            BAT_DBG("PMIC(0x%03x)\t val: " BYTETOBINARYPATTERN "\t%s\n", reg_addr_others[i],
                                BYTETOBINARY(reg_val), reg_str_others[i]);
        }
    }

	/*modify MSIC_BATT_CHR_LOWBATTDET_ADDR values [7:6]='11'*/
	intel_scu_ipc_ioread8(MSIC_BATT_CHR_LOWBATTDET_ADDR, &reg_val);
	reg_val |= (BIT(6)|BIT(7));
	ret = intel_scu_ipc_iowrite8(MSIC_BATT_CHR_LOWBATTDET_ADDR, reg_val);
	if (ret) {
		BAT_DBG_E("PMIC register MSIC_BATT_CHR_LOWBATTDET_ADDR Failed to write %d\n", ret);
	}else {
		intel_scu_ipc_ioread8(MSIC_BATT_CHR_LOWBATTDET_ADDR, &reg_val);
		BAT_DBG("PMIC register 0x%x Success to write 0x%x.\n", MSIC_BATT_CHR_LOWBATTDET_ADDR, reg_val);
	}

    return;

ipcread_err:
    BAT_DBG("ipcread_err: address: 0x%03x!!!", chk_reg_addr);
}