static int ec_get_battery_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { struct ec_battery_info *chip = container_of(psy, struct ec_battery_info, bat); int ret = 0, cur_sign = -1; int comp_cap = 0; u8 val8, cap; u16 val16; mutex_lock(&chip->lock); switch (psp) { case POWER_SUPPLY_PROP_STATUS: ret = byt_ec_read_byte(EC_BAT0_CUR_CAP_REG, &cap); if (ret < 0) goto ec_read_err; ret = byt_ec_read_byte(EC_BAT0_STAT_REG, &val8); if (ret < 0) goto ec_read_err; ret = byt_ec_read_word(EC_BAT0_BATTSBS_STATUS, &val16); if (ret < 0) goto ec_read_err; if (val8 & BAT0_STAT_DISCHARGING) val->intval = POWER_SUPPLY_STATUS_DISCHARGING; else if (val8 & BAT0_STAT_CHARGING) val->intval = POWER_SUPPLY_STATUS_CHARGING; else if (val8 & BAT0_STAT_LOW_BATT) val->intval = POWER_SUPPLY_STATUS_DISCHARGING; else if ((cap == 100) || (val16 & BAT0_BATTSBS_STATUS_FC)) val->intval = POWER_SUPPLY_STATUS_FULL; else if (cap != 0) val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; else val->intval = POWER_SUPPLY_STATUS_UNKNOWN; break; case POWER_SUPPLY_PROP_HEALTH: ret = byt_ec_read_byte(EC_BAT0_STAT_REG, &val8); if (ret < 0) goto ec_read_err; /* If battery is not connected * return POWER_SUPPLY_HEALTH_UNKNOWN */ if (!(val8 & BAT0_STAT_BATT_PRESENT)) { val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; break; } /* Battery operational temperature range is * 0C to 40C while charging and -20 C to 60C * while Discharging/Full/Not Charging. */ ret = byt_ec_read_word(EC_BAT0_TEMP_REG, &val16); if (ret < 0) goto ec_read_err; /* Android framwork don't differentiate b/w hot and cold. *Both are treated as overheat cases. *So report overheat in both high and low temp cases. */ if ((val16 >= EC_BAT_CHRG_OVER_TEMP) | (val16 <= EC_BAT_CHRG_UNDER_TEMP)) { val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; break; } ret = byt_ec_read_word(EC_BAT0_VBATT_REG, &val16); if (ret < 0) goto ec_read_err; /* The battery is treated as DEAD if the battery voltage is *bellow <= 6.55V in BYT-M */ if (val16 <= EC_BAT_DEAD_VOLTAGE) { val->intval = POWER_SUPPLY_HEALTH_DEAD; break; } val->intval = POWER_SUPPLY_HEALTH_GOOD; break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: ret = byt_ec_read_word(EC_BAT0_VBATT_REG, &val16); if (ret < 0) goto ec_read_err; val->intval = val16 * 1000; break; case POWER_SUPPLY_PROP_CURRENT_NOW: ret = byt_ec_read_byte(EC_BAT0_STAT_REG, &val8); if (ret < 0) goto ec_read_err; if (val8 & BAT0_STAT_CHARGING) { ret = byt_ec_read_word(EC_BAT0_CIBATT_CUR_REG, &val16); cur_sign = 1; } else { ret = byt_ec_read_word(EC_BAT0_DIBATT_CUR_REG, &val16); cur_sign = -1; } if (ret < 0) goto ec_read_err; val->intval = cur_sign * ((int)val16 * 1000); break; case POWER_SUPPLY_PROP_CURRENT_AVG: ret = byt_ec_read_word(EC_BAT0_AVG_CUR_REG, &val16); if (ret < 0) goto ec_read_err; val->intval = (int)adjust_sign_value(val16) * 1000; break; case POWER_SUPPLY_PROP_PRESENT: ret = byt_ec_read_byte(EC_BAT0_CUR_CAP_REG, &cap); if (ret < 0) goto ec_read_err; ret = byt_ec_read_byte(EC_BAT0_STAT_REG, &val8); if (ret < 0) goto ec_read_err; if ((val8 & 0x7) || (cap != 0)) val->intval = 1; else val->intval = 0; break; case POWER_SUPPLY_PROP_CAPACITY: ret = byt_ec_read_byte(EC_BAT0_CUR_CAP_REG, &val8); if (ret < 0) goto ec_read_err; /* 6% of battery capacity is minimun treshold for BYT-M *So, the 6% is mapped to 0% in android. * 6% to 100% is compensated with 0% to 100% to OS. * Compensated capacity = cap - ((100 - cap)*6)/100 + 0.5 */ comp_cap = val8; comp_cap = comp_cap*100 - ((100 - comp_cap) *EC_BAT_SAFE_MIN_CAPACITY) + 50; comp_cap /= 100; if (comp_cap < 0) comp_cap = 0; val->intval = comp_cap; break; case POWER_SUPPLY_PROP_TEMP: ret = byt_ec_read_word(EC_BAT0_TEMP_REG, &val16); if (ret < 0) goto ec_read_err; /* * convert temperature from degree kelvin * to degree celsius: T(C) = T(K) - 273.15 * also 1 LSB of Temp register = 0.1 Kelvin. */ val->intval = (((int)val16 * 10) - EC_BAT_TEMP_CONV_FACTOR) / 10; break; case POWER_SUPPLY_PROP_TECHNOLOGY: ret = byt_ec_read_byte(EC_BAT0_STAT_REG, &val8); if (ret < 0) goto ec_read_err; /*If battery is not connected *return POWER_SUPPLY_TECHNOLOGY_UNKNOWN */ if (val8 & BAT0_STAT_BATT_PRESENT) val->intval = POWER_SUPPLY_TECHNOLOGY_LION; else val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; break; case POWER_SUPPLY_PROP_CHARGE_NOW: ret = byt_ec_read_word(EC_BAT0_REM_CAP_REG, &val16); if (ret < 0) goto ec_read_err; val->intval = ((int)val16) * 1000; break; case POWER_SUPPLY_PROP_CHARGE_FULL: ret = byt_ec_read_word(EC_BAT0_FULL_CHRG_CAP_REG, &val16); if (ret < 0) goto ec_read_err; val->intval = ((int)val16) * 1000; break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: ret = byt_ec_read_word(EC_BAT0_DESIGN_CAP_REG, &val16); if (ret < 0) goto ec_read_err; val->intval = ((int)val16) * 1000; break; default: mutex_unlock(&chip->lock); return -EINVAL; } mutex_unlock(&chip->lock); return 0; ec_read_err: mutex_unlock(&chip->lock); return ret; }
static int ulpmc_get_battery_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { int ret = 0; struct ulpmc_chip_info *chip = container_of(psy, struct ulpmc_chip_info, bat); mutex_lock(&chip->lock); switch (psp) { case POWER_SUPPLY_PROP_STATUS: ret = ulpmc_read_reg16(chip->client, ULPMC_FG_REG_FLAGS); if (ret < 0) goto i2c_read_err; val->intval = ulpmc_battery_status(chip, ret); break; case POWER_SUPPLY_PROP_HEALTH: /* * RVP doesn't support health detection yet. * This feature will be supported on PR1. */ val->intval = POWER_SUPPLY_HEALTH_GOOD; break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: ret = ulpmc_read_reg16(chip->client, ULPMC_FG_REG_VOLT); if (ret < 0) goto i2c_read_err; val->intval = ret * 1000; break; case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: val->intval = chip->pdata->volt_sh_min * 1000; break; case POWER_SUPPLY_PROP_CURRENT_AVG: ret = ulpmc_read_reg16(chip->client, ULPMC_FG_REG_AI); if (ret < 0) goto i2c_read_err; val->intval = ((int)adjust_sign_value(ret)) * 1000; break; case POWER_SUPPLY_PROP_PRESENT: ret = ulpmc_read_reg16(chip->client, ULPMC_FG_REG_FLAGS); if (ret < 0) goto i2c_read_err; val->intval = (ret & FG_FLAG_BDET) ? 1 : 0; break; case POWER_SUPPLY_PROP_CAPACITY: if (chip->pdata->version == BYTULPMCFGV3) ret = ulpmc_read_reg16(chip->client, ULPMC_FG_REG_SOC); else ret = ulpmc_read_reg16(chip->client, ULPMC_FG_REG_SOC_V4); if (ret < 0) goto i2c_read_err; val->intval = ret; break; case POWER_SUPPLY_PROP_TEMP: ret = ulpmc_read_reg16(chip->client, ULPMC_FG_REG_TEMP); if (ret < 0) goto i2c_read_err; dev_dbg(&chip->client->dev, "BQ FG Temp:%d\n", ret - 2731); /* * RVP doesn't support temperature readings. * This feature will be supported on PR1. */ val->intval = 350; break; case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = POWER_SUPPLY_TECHNOLOGY_LION; break; case POWER_SUPPLY_PROP_CHARGE_NOW: ret = ulpmc_read_reg16(chip->client, ULPMC_FG_REG_RMC); if (ret < 0) goto i2c_read_err; val->intval = ret * 1000; break; case POWER_SUPPLY_PROP_CHARGE_FULL: ret = ulpmc_read_reg16(chip->client, ULPMC_FG_REG_FCC); if (ret < 0) goto i2c_read_err; val->intval = ret * 1000; break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: ret = ulpmc_read_reg16(chip->client, ULPMC_FG_REG_FAC); if (ret < 0) goto i2c_read_err; val->intval = ret * 1000; break; case POWER_SUPPLY_PROP_CYCLE_COUNT: if (chip->pdata->version == BYTULPMCFGV3) ret = ulpmc_read_reg16(chip->client, ULPMC_FG_REG_CYCT); else ret = ulpmc_read_reg16(chip->client, ULPMC_FG_REG_CYCT_V4); if (ret < 0) goto i2c_read_err; val->intval = ret; break; case POWER_SUPPLY_PROP_MODEL_NAME: val->strval = chip->pdata->battid; break; default: mutex_unlock(&chip->lock); return -EINVAL; } mutex_unlock(&chip->lock); return 0; i2c_read_err: mutex_unlock(&chip->lock); return ret; }