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; }
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; }
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; }
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; }
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; }
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; }
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); }
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; }
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; }
//++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; }
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; }
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], ®_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], ®_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], ®_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], ®_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, ®_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, ®_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); }
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; }