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;
}
int bq27520_write_i2c_retry (struct i2c_client *i2c, int addr, int value) {
   int retry = RETRY_COUNT;
   int ret = 0;
   while (retry--) {
      ret = bq27520_write_i2c(i2c, addr, value, 1);
      if (ret < 0) continue;

      break;
   };

   return ret;
}
int bq27520_rom_mode_write_i2c(u8 reg, int value, int b_single)
{
    struct i2c_client *i2c = NULL;

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

    if (!i2c|| !i2c->adapter)
        return -ENODEV;

    return bq27520_write_i2c(i2c, reg, value, b_single);
}
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;
}
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;
}