예제 #1
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("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("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;
}
예제 #2
0
int update_from_rom_mode(void) 
{
    int cell_type=TYPE_LG;
    int i,j,k;
    int ret;
    struct update_op *p_op_start = NULL, *p_op_end = NULL, *p_op_buf = NULL;

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

#if 0
    cell_type = bq27520_batt_current_sel_type();
#endif

    BAT_DBG(" fw flashing... please wait for about 30s at least.\n");

    ret = UPDATE_ERR_MATCH_OP_BUF;
    for (i=0; i<num_of_op_buf; i++) {
        if (cell_type != bq27xx_fw[i].cell_type) 
            continue;

        //Skip normal i2c mode op until OP_I2C_START + 1 
        p_op_buf = bq27xx_fw[i].op;
        p_op_end = &p_op_buf[bq27xx_fw[i].num_op-1];
        for (j=0; j<bq27xx_fw[i].num_op; j++) {
#if 0
            BAT_DBG("OP: %d, 0x%02X, 0x%02X\n", 
                    p_op_buf[j].bq_op, 
                    p_op_buf[j].off,
                    p_op_buf[j].arg
            );
#endif
            if (p_op_buf[j].bq_op >= OP_I2C_START) {
                k=j;
                while(p_op_buf[k].bq_op >= OP_I2C_START) k++;
                p_op_start = &p_op_buf[k];
                break;
            }
        }

        for (j=0; j<RETRY_COUNT; j++) {
            ret = update_fw(p_op_start, p_op_end);
            if (ret == UPDATE_OK) {
                ret = UPDATE_FROM_ROM_MODE;
                break;
            }
        }
        break;

    }

    return ret;
}
예제 #3
0
int asus_charging_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] == '1') {
        /* turn on charging limit in eng mode */
        eng_charging_limit = true;
    }
    else if (buffer[0] == '0') {
        /* turn off charging limit in eng mode */
        eng_charging_limit = false;
    }

    tmp_batt_info.eng_charging_limit = eng_charging_limit;

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

    asus_queue_update_all();

    return count;
}
예제 #4
0
int thermal_charging_toggle_write(struct file *file, const char *buffer, unsigned long count, void *data)
{
    struct battery_info_reply tmp_batt_info;
    bool thermal_charging_limit = true;

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

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


    if (buffer[0] == '0') {
        // Disable thermal protection
        thermal_charging_limit = false;

    }
    else // Enable thermal protection
        thermal_charging_limit = true;

    tmp_batt_info.thermal_charging_limit = thermal_charging_limit;

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

    asus_queue_update_all();

    return count;
}
예제 #5
0
int asus_charging_for_gague_toggle_read(char *page, char **start, off_t off, int count, int *eof, void *date)
{
    int len = 0;

    BAT_DBG("%s:\n", __func__);
    return len;
}
예제 #6
0
int update_normal(int curr_cell_type)
{
    int ret;
    struct update_op *p_op_start = NULL, *p_op_end = NULL, *p_op_buf = NULL;
    int i,j;

    BAT_DBG(" fw flashing... please wait for about 10s at least.\n");

    ret = UPDATE_ERR_MATCH_OP_BUF;
    for (i=0; i<num_of_op_buf; i++) {
        if (curr_cell_type != bq27xx_fw[i].cell_type) 
            continue;

        //Skip normal i2c mode op until OP_I2C_START + 1 
        p_op_buf = bq27xx_fw[i].op;
        p_op_start = p_op_buf;
        p_op_end = &p_op_buf[bq27xx_fw[i].num_op-1];

        for (j=0; j<RETRY_COUNT; j++) {
            ret = update_fw(p_op_start, p_op_end);
            if (ret == UPDATE_OK) break;
        }
        break;

    }

    return ret;
}
예제 #7
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;
}
void touch_work_func(struct work_struct *work)
{
    int perc;

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

    mutex_lock(&batt_info_mutex);
    perc = batt_info.percentage;
    mutex_unlock(&batt_info_mutex);
    notify_touch(perc);
}
예제 #9
0
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;
}
예제 #10
0
static int asus_battery_update_status_no_mutex(int percentage)
{
        int status;
        int temperature;
        //int flags; //for bq series
        struct battery_info_reply tmp_batt_info;
        u32 cable_status;

        tmp_batt_info = batt_info;
        cable_status = tmp_batt_info.cable_status;
        BAT_DBG("%s , cable status = %d, percentage = %d\n", __func__, cable_status, percentage);

        if (cable_status == USB_ADAPTER || cable_status == USB_PC) {
                status = POWER_SUPPLY_STATUS_CHARGING;
#ifdef CONFIG_ASUS_FACTORY_MODE
                /* ME371MG, ME302C eng mode : stop charging when battery percentage is over 60% */
                if (percentage >= 60 && tmp_batt_info.eng_charging_limit) {
                        BAT_DBG("in fac mode and capasity > 60%\n");
                        smb347_charging_toggle(false);
                        status = POWER_SUPPLY_STATUS_DISCHARGING;
                        goto final;
                }
예제 #11
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)
{
    struct battery_info_reply tmp_batt_info;
    int len = 0;

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

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

    len = sprintf(page, "%d\n", tmp_batt_info.thermal_charging_limit);
    return len;
}
int update_normal(int curr_cell_type)
{
    int ret;
    struct update_op *p_op_start = NULL, *p_op_end = NULL, *p_op_buf = NULL;
    int i,j;

    BAT_DBG(" fw flashing... please wait for about 10s at least.\n");

    ret = UPDATE_ERR_MATCH_OP_BUF;
    if (batt_info.gauge_version == IC_VERSION_G3) {
        BAT_DBG("bq27520 gauge is G3, no dffs file ignore it.\n");
        ret = UPDATE_NONE;

    } else if (batt_info.gauge_version == IC_VERSION_G4) {
        BAT_DBG("bq27520 gauge is G4\n");
        for (i=0; i<g4_num_of_op_buf; i++) {
            if (curr_cell_type != g4_bq27xx_fw[i].cell_type)
                continue;

            //Skip normal i2c mode op until OP_I2C_START + 1
            p_op_buf = g4_bq27xx_fw[i].op;
            p_op_start = p_op_buf;
            p_op_end = &p_op_buf[g4_bq27xx_fw[i].num_op-1];

            for (j=0; j<RETRY_COUNT; j++) {
                ret = update_fw(p_op_start, p_op_end);
                if (ret == UPDATE_OK) break;
            }
            break;

        }

    }

    return ret;
}
예제 #13
0
void bq27520_bat_upt_i2c_exit(void)
{
    struct i2c_client *client = NULL;
        
    asus_battery_exit();

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

    i2c_unregister_device(batt_upt_dev_info.i2c);
    i2c_del_driver(&bq27520_bat_upt_i2c_driver);

    BAT_DBG("%s exit\n", __func__);
}
static int asus_battery_update_available_energy_no_mutex(void)
{
    int mWhr = -EINVAL;
    struct battery_info_reply tmp_batt_info;

    tmp_batt_info = batt_info;
    if (tmp_batt_info.gauge_version != IC_VERSION_G3) {
        BAT_DBG("Read available energy error due to not G3.\n");
        return mWhr;
    }

    if (tmp_batt_info.tbl && tmp_batt_info.tbl->read_av_energy)
        mWhr = tmp_batt_info.tbl->read_av_energy();

    return mWhr;
}
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;
}
예제 #16
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);
}
예제 #17
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;
}