static int cw_init(struct cw_battery *cw_bat) { int ret; int i; u8 reg_val = MODE_SLEEP; #if 0 ret = cw_read(cw_bat->client, REG_MODE, ®_val); if (ret < 0) return ret; #endif if ((reg_val & MODE_SLEEP_MASK) == MODE_SLEEP) { reg_val = MODE_NORMAL; ret = cw_write(cw_bat->client, REG_MODE, ®_val); if (ret < 0) return ret; } ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); if (ret < 0) return ret; if ((reg_val & 0xf8) != ATHD) { dev_info(&cw_bat->client->dev, "the new ATHD have not set\n"); reg_val &= 0x07; /* clear ATHD */ reg_val |= ATHD; /* set ATHD */ ret = cw_write(cw_bat->client, REG_CONFIG, ®_val); if (ret < 0) return ret; } ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); if (ret < 0) return ret; if (!(reg_val & CONFIG_UPDATE_FLG)) { dev_info(&cw_bat->client->dev, "update flag for new battery info have not set\n"); ret = cw_update_config_info(cw_bat); if (ret < 0) return ret; } else { for(i = 0; i < SIZE_BATINFO; i++) { ret = cw_read(cw_bat->client, (REG_BATINFO + i), ®_val); if (ret < 0) return ret; if (cw_bat->plat_data->cw_bat_config_info[i] != reg_val) break; } if (i != SIZE_BATINFO) { dev_info(&cw_bat->client->dev, "update flag for new battery info have not set\n"); ret = cw_update_config_info(cw_bat); if (ret < 0) return ret; } } for (i = 0; i < 30; i++) { ret = cw_read(cw_bat->client, REG_SOC, ®_val); if (ret < 0) return ret; else if (ret != 0xff) break; msleep(100); if (i > 25) dev_err(&cw_bat->client->dev, "cw2015/cw2013 input unvalid power error\n"); } return 0; }
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; }