static int cw_get_capacity(struct cw_battery *cw_bat) { int cw_capacity; int ret; u8 reg_val[2]; struct timespec ts; long new_run_time; long new_sleep_time; long capacity_or_aconline_time; int allow_change; int allow_capacity; static int if_quickstart = 0; static int jump_flag =0; int charge_time; // ret = cw_read(cw_bat->client, REG_SOC, ®_val); ret = cw_read_word(cw_bat->client, REG_SOC, reg_val); if (ret < 0) return ret; cw_capacity = reg_val[0]; if ((cw_capacity < 0) || (cw_capacity > 100)) { dev_err(&cw_bat->client->dev, "get cw_capacity error; cw_capacity = %d\n", cw_capacity); return cw_capacity; } if (cw_capacity == 0) dev_dbg(&cw_bat->client->dev, "the cw201x capacity is 0 !!!!!!!, funciton: %s, line: %d\n", __func__, __LINE__); else dev_dbg(&cw_bat->client->dev, "the cw201x capacity is %d, funciton: %s\n", cw_capacity, __func__); // ret = cw_read(cw_bat->client, REG_SOC + 1, ®_val); ktime_get_ts(&ts); new_run_time = ts.tv_sec; get_monotonic_boottime(&ts); new_sleep_time = ts.tv_sec - new_run_time; if ((cw_bat->charger_mode > 0) && (cw_capacity >= 95) && (cw_capacity <= cw_bat->capacity)) { // avoid no charge full capacity_or_aconline_time = (cw_bat->sleep_time_capacity_change > cw_bat->sleep_time_charge_start) ? cw_bat->sleep_time_capacity_change : cw_bat->sleep_time_charge_start; capacity_or_aconline_time += (cw_bat->run_time_capacity_change > cw_bat->run_time_charge_start) ? cw_bat->run_time_capacity_change : cw_bat->run_time_charge_start; allow_change = (new_sleep_time + new_run_time - capacity_or_aconline_time) / BATTERY_UP_MAX_CHANGE; if (allow_change > 0) { allow_capacity = cw_bat->capacity + allow_change; cw_capacity = (allow_capacity <= 100) ? allow_capacity : 100; jump_flag =1; } else if (cw_capacity <= cw_bat->capacity) { cw_capacity = cw_bat->capacity; } } else if (((cw_bat->charger_mode > 0) && (cw_capacity == (cw_bat->capacity - 1))) || ((cw_bat->charger_mode == 0) && (cw_capacity == (cw_bat->capacity + 1)))) { // modify battery level swing if (!(cw_capacity == 0 && cw_bat->capacity == 1)) { cw_capacity = cw_bat->capacity; } } else if ((cw_capacity == 0) && (cw_bat->capacity > 1)) { // avoid battery level jump to 0% at a moment from more than 2% allow_change = ((new_run_time - cw_bat->run_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_RUN); allow_change += ((new_sleep_time - cw_bat->sleep_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_SLEEP); allow_capacity = cw_bat->capacity - allow_change; cw_capacity = (allow_capacity >= cw_capacity) ? allow_capacity: cw_capacity; reg_val[0] = MODE_NORMAL; ret = cw_write(cw_bat->client, REG_MODE, reg_val); if (ret < 0) return ret; } else if ((cw_bat->charger_mode == 0) && (cw_capacity <= cw_bat->capacity ) && (cw_capacity >= 90) && (jump_flag == 1)) { // avoid battery level jump to CW_BAT capacity_or_aconline_time = (cw_bat->sleep_time_capacity_change > cw_bat->sleep_time_charge_start) ? cw_bat->sleep_time_capacity_change : cw_bat->sleep_time_charge_start; capacity_or_aconline_time += (cw_bat->run_time_capacity_change > cw_bat->run_time_charge_start) ? cw_bat->run_time_capacity_change : cw_bat->run_time_charge_start; allow_change = (new_sleep_time + new_run_time - capacity_or_aconline_time) / BATTERY_DOWN_CHANGE; if (allow_change > 0) { allow_capacity = cw_bat->capacity - allow_change; if (cw_capacity >= allow_capacity){ jump_flag =0; } else{ cw_capacity = (allow_capacity <= 100) ? allow_capacity : 100; } } else if (cw_capacity <= cw_bat->capacity) { cw_capacity = cw_bat->capacity; } } #if 1 if((cw_bat->charger_mode > 0) &&(cw_capacity == 0)) { charge_time = new_sleep_time + new_run_time - cw_bat->sleep_time_charge_start - cw_bat->run_time_charge_start; if ((charge_time > BATTERY_DOWN_MAX_CHANGE_RUN_AC_ONLINE) && (if_quickstart == 0)) { cw_quickstart(cw_bat); // if the cw_capacity = 0 the cw2015 will qstrt if_quickstart = 1; } } else if ((if_quickstart == 1)&&(cw_bat->charger_mode == 0)) { if_quickstart = 0; } #endif #if 0 if (cw_bat->plat_data->chg_ok_pin != INVALID_GPIO) { if(gpio_get_value(cw_bat->plat_data->chg_ok_pin) != cw_bat->plat_data->chg_ok_level) { if (cw_capacity == 100) { cw_capacity = 99; } } else { if (cw_bat->charger_mode > 0) { cw_capacity = 100; } } } #endif #ifdef SYSTEM_SHUTDOWN_VOLTAGE if ((cw_bat->charger_mode == 0) && (cw_capacity <= 10) && (cw_bat->voltage <= SYSTEM_SHUTDOWN_VOLTAGE)){ if (if_quickstart == 10){ cw_quickstart(cw_bat); if_quickstart = 12; cw_capacity = 0; } else if (if_quickstart <= 10) if_quickstart =if_quickstart+2; dev_info(&cw_bat->client->dev, "the cw201x voltage is less than SYSTEM_SHUTDOWN_VOLTAGE !!!!!!!, funciton: %s, line: %d\n", __func__, __LINE__); } else if ((cw_bat->charger_mode > 0)&& (if_quickstart <= 12)) { if_quickstart = 0; } #endif return cw_capacity; }
static int cw_get_capacity(struct cw_battery *cw_bat) { int ret; u8 reg_val[2]; struct timespec ts; long new_run_time; long new_sleep_time; long capacity_or_aconline_time; int allow_change; int allow_capacity; static int if_quickstart; static int jump_flag; static int jump_flag2; static int reset_loop; int charge_time; u8 reset_val; ret = cw_i2c_read(cw_bat->client, REG_SOC, reg_val, 2); if (ret < 0) return ret; cw_capacity = reg_val[0]; if ((cw_capacity < 0) || (cw_capacity > 100)) { dev_err(&cw_bat->client->dev, "get cw_capacity error; cw_capacity = %d\n", cw_capacity); reset_loop++; if (reset_loop > 5) { reset_val = MODE_SLEEP; ret = cw_i2c_write(cw_bat->client, REG_MODE, &reset_val, 1); if (ret < 0) return ret; reset_val = MODE_NORMAL; msleep(10); ret = cw_i2c_write(cw_bat->client, REG_MODE, &reset_val, 1); if (ret < 0) return ret; dev_dbg(&cw_bat->client->dev, "report battery capacity error"); ret = cw_update_config_info(cw_bat); if (ret) return ret; reset_loop = 0; } return cw_capacity; } else { reset_loop = 0; } if (cw_capacity == 0) dev_dbg(&cw_bat->client->dev, "the cw201x capacity is 0 !!!!!!!, funciton: %s, line: %d\n", __func__, __LINE__); else dev_dbg(&cw_bat->client->dev, "the cw201x capacity is %d, funciton: %s\n", cw_capacity, __func__); ktime_get_ts(&ts); new_run_time = ts.tv_sec; get_monotonic_boottime(&ts); new_sleep_time = ts.tv_sec - new_run_time; if (((cw_bat->charger_mode > 0) && (cw_capacity <= (cw_bat->capacity - 1)) && (cw_capacity > (cw_bat->capacity - 30/*9*/))) || ((cw_bat->charger_mode == 0) && (cw_capacity == (cw_bat->capacity + 1)))) { if (!(cw_capacity == 0 && cw_bat->capacity <= 2)) { cw_capacity = cw_bat->capacity; } } if ((cw_bat->charger_mode > 0) && (cw_capacity >= 95) && (cw_capacity <= cw_bat->capacity)) { capacity_or_aconline_time = (cw_bat->sleep_time_capacity_change > cw_bat->sleep_time_charge_start) ? cw_bat->sleep_time_capacity_change : cw_bat->sleep_time_charge_start; capacity_or_aconline_time += (cw_bat->run_time_capacity_change > cw_bat->run_time_charge_start) ? cw_bat->run_time_capacity_change : cw_bat->run_time_charge_start; allow_change = (new_sleep_time + new_run_time - capacity_or_aconline_time) / BATTERY_UP_MAX_CHANGE; if (allow_change > 0) { allow_capacity = cw_bat->capacity + allow_change; cw_capacity = (allow_capacity <= 100) ? allow_capacity : 100; jump_flag = 1; } else if (cw_capacity <= cw_bat->capacity) { cw_capacity = cw_bat->capacity; } } else if ((cw_bat->charger_mode == 0) && cw_bat->capacity == 100 && cw_capacity < cw_bat->capacity && jump_flag2 == 0) { cw_capacity = cw_bat->capacity; jump_flag2 = 1; } else if ((cw_bat->charger_mode == 0) && (cw_capacity <= cw_bat->capacity) && (cw_capacity >= 90) && ((jump_flag == 1) || (jump_flag2 == 1))) { capacity_or_aconline_time = (cw_bat->sleep_time_capacity_change > cw_bat->sleep_time_charge_start) ? cw_bat->sleep_time_capacity_change : cw_bat->sleep_time_charge_start; capacity_or_aconline_time += (cw_bat->run_time_capacity_change > cw_bat->run_time_charge_start) ? cw_bat->run_time_capacity_change : cw_bat->run_time_charge_start; allow_change = (new_sleep_time + new_run_time - capacity_or_aconline_time) / BATTERY_DOWN_CHANGE; if (allow_change > 0) { allow_capacity = cw_bat->capacity - allow_change; if (cw_capacity >= allow_capacity) { jump_flag = 0; jump_flag2 = 0; } else { cw_capacity = (allow_capacity <= 100) ? allow_capacity : 100; } } else if (cw_capacity <= cw_bat->capacity) { cw_capacity = cw_bat->capacity; } } if ((cw_capacity == 0) && (cw_bat->capacity > 1)) { allow_change = ((new_run_time - cw_bat->run_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_RUN); allow_change += ((new_sleep_time - cw_bat->sleep_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_SLEEP); allow_capacity = cw_bat->capacity - allow_change; cw_capacity = (allow_capacity >= cw_capacity) ? allow_capacity : cw_capacity; dev_dbg(&cw_bat->client->dev, "report GGIC POR happened"); reg_val[0] = MODE_NORMAL; ret = cw_i2c_write(cw_bat->client, REG_MODE, reg_val, 1); if (ret < 0) return ret; dev_dbg(&cw_bat->client->dev, "report battery capacity jump 0 "); } #if 1 if ((cw_bat->charger_mode > 0) && (cw_capacity == 0)) { charge_time = new_sleep_time + new_run_time - cw_bat->sleep_time_charge_start - cw_bat->run_time_charge_start; if ((charge_time > BATTERY_DOWN_MAX_CHANGE_RUN_AC_ONLINE) && (if_quickstart == 0)) { cw_quickstart(cw_bat); reset_val = MODE_SLEEP; ret = cw_i2c_write(cw_bat->client, REG_MODE, &reset_val, 1); if (ret < 0) return ret; reset_val = MODE_NORMAL; msleep(10); ret = cw_i2c_write(cw_bat->client, REG_MODE, &reset_val, 1); if (ret < 0) return ret; dev_dbg(&cw_bat->client->dev, "report battery capacity error"); ret = cw_update_config_info(cw_bat); if (ret) return ret; dev_dbg(&cw_bat->client->dev, "report battery capacity still 0 if in changing"); if_quickstart = 1; } } else if ((if_quickstart == 1) && (cw_bat->charger_mode == 0)) { if_quickstart = 0; } #endif #ifdef SYSTEM_SHUTDOWN_VOLTAGE if ((cw_bat->charger_mode == 0) && (cw_capacity <= 20) && (cw_bat->voltage <= SYSTEM_SHUTDOWN_VOLTAGE)) { if (if_quickstart == 10) { allow_change = ((new_run_time - cw_bat->run_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_RUN); allow_change += ((new_sleep_time - cw_bat->sleep_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_SLEEP); allow_capacity = cw_bat->capacity - allow_change; cw_capacity = (allow_capacity >= 0) ? allow_capacity : 0; if (cw_capacity < 1) { cw_quickstart(cw_bat); if_quickstart = 12; cw_capacity = 0; } } else if (if_quickstart <= 10) if_quickstart = if_quickstart+2; dev_dbg(&cw_bat->client->dev, "the cw201x voltage is less than SYSTEM_SHUTDOWN_VOLTAGE !!!!!!!, funciton: %s, line: %d\n", __func__, __LINE__); } else if ((cw_bat->charger_mode > 0) && (if_quickstart <= 12)) { if_quickstart = 0; } #endif return cw_capacity; }