Beispiel #1
0
/*
 * Return the battery average current in µA
 * Note that current can be negative signed as well
 * Or 0 if something fails.
 */
static int bq27x00_battery_current(struct bq27x00_device_info *di,
				   union power_supply_propval *val)
{
	int curr;
	int flags;

	curr = bq27x00_read(di, BQ27x00_REG_AI, false);
	if (curr < 0) {
		dev_err(di->dev, "error reading current\n");
		return curr;
	}

	if (bq27xxx_is_chip_version_higher(di)) {
		/* bq27500 returns signed value */
		val->intval = (int)((s16)curr) * 1000;
	} else {
		flags = bq27x00_read(di, BQ27x00_REG_FLAGS, false);
		if (flags & BQ27000_FLAG_CHGS) {
			dev_dbg(di->dev, "negative current!\n");
			curr = -curr;
		}

		val->intval = curr * 3570 / BQ27000_RS;
	}

	return 0;
}
Beispiel #2
0
/*
 * Return the battery Initial last measured discharge in µAh
 * Or < 0 if something fails.
 */
static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
{
	int ilmd;

	if (bq27xxx_is_chip_version_higher(di)) {
		if (di->chip == BQ27425)
			ilmd = bq27x00_read(di, BQ27425_REG_DCAP, false);
		else if (di->chip == BQ27510)
			ilmd = bq27x00_read(di, BQ27510_REG_DCAP, false);
		else
			ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false);
	} else {
		ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
	}

	if (ilmd < 0) {
		dev_dbg(di->dev, "error reading initial last measured discharge\n");
		return ilmd;
	}

	if (bq27xxx_is_chip_version_higher(di))
		ilmd *= 1000;
	else
		ilmd = ilmd * 256 * 3570 / BQ27000_RS;

	return ilmd;
}
Beispiel #3
0
int bq27x00_battery_status(struct bq27541_info *di,int* value)
{
    int flags = 0;
    int curr = 0;
    int ret;

    ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
    if (ret < 0) {
        dev_err(di->dev, "error reading flags\n");
        return ret;
    }
    if (flags & BQ27500_FLAG_FC)
        *value = POWER_SUPPLY_STATUS_FULL;
    else if (flags & BQ27500_FLAG_DSC)
        *value = POWER_SUPPLY_STATUS_DISCHARGING;
    else{
        
        ret = bq27x00_read(BQ27x00_REG_AI, &curr, 0, di);
        if (ret < 0) {
            dev_err(di->dev, "error reading flags\n");
            return ret;
        }
        if(curr==0){
            *value = POWER_SUPPLY_STATUS_NOT_CHARGING;
        }else if(curr>0){
            *value = POWER_SUPPLY_STATUS_CHARGING;
        }
    }

    return ret;
}
Beispiel #4
0
/*
 * Return the battery Cycle count total
 * Or < 0 if something fails.
 */
static int bq27x00_battery_read_cyct(struct bq27x00_device_info *di)
{
	int cyct;

	if (di->chip == BQ27510)
		cyct = bq27x00_read(di, BQ27510_REG_CYCT, false);
	else
		cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false);
	if (cyct < 0)
		dev_err(di->dev, "error reading cycle count total\n");

	return cyct;
}
Beispiel #5
0
/*
 * Return the battery Relative State-of-Charge
 * Or < 0 if something fails.
 */
static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
{
	int rsoc;

	if (di->chip == BQ27500)
		rsoc = bq27x00_read(di, BQ27500_REG_SOC, false);
	else
		rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true);

	if (rsoc < 0)
		dev_dbg(di->dev, "error reading relative State-of-Charge\n");

	return rsoc;
}
Beispiel #6
0
/*
 * Read flag register.
 * Return < 0 if something fails.
 */
static int bq27x00_battery_read_health(struct bq27x00_device_info *di)
{
	int tval;

	tval = bq27x00_read(di, BQ27x00_REG_FLAGS, false);
	if (tval < 0) {
		dev_err(di->dev, "error reading flag register:%d\n", tval);
		return tval;
	}

	if (di->chip == BQ27500) {
		if (tval & BQ27500_FLAG_SOCF)
			tval = POWER_SUPPLY_HEALTH_DEAD;
		else if (tval & BQ27500_FLAG_OTC)
			tval = POWER_SUPPLY_HEALTH_OVERHEAT;
		else
			tval = POWER_SUPPLY_HEALTH_GOOD;
		return tval;
	} else if (di->chip == BQ27510) {
		if (tval & BQ27500_FLAG_OTC)
			return POWER_SUPPLY_HEALTH_OVERHEAT;
		return POWER_SUPPLY_HEALTH_GOOD;
	} else {
		if (tval & BQ27000_FLAG_EDV1)
			tval = POWER_SUPPLY_HEALTH_DEAD;
		else
			tval = POWER_SUPPLY_HEALTH_GOOD;
		return tval;
	}

	return -1;
}
Beispiel #7
0
/*
 * Return the battery State-of-Charge for bq34z100
 * Or < 0 if something fails.
 */
static int bq27x00_battery_read_soc(struct bq27x00_device_info *di)
{
    int soc;

    if (di->chip == BQ27500)
        soc = bq27x00_read(di, BQ27500_REG_SOC, false);
    else if (di->chip == BQ27425)
        soc = bq27x00_read(di, BQ27425_REG_SOC, false);
    else
        soc = bq27x00_read(di, BQ27x00_REG_SOC, false);

    if (soc < 0)
        dev_dbg(di->dev, "error reading State-of-Charge\n");

    return soc;
}
Beispiel #8
0
static int __devinit bq27541_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    struct bq27541_info *di;
    int ret;
    int error;

    printk(KERN_INFO "%s\n",__func__);
    di = kzalloc(sizeof(*di), GFP_KERNEL);
    if (!di) {
        return -ENOMEM;
    }
    di->bat_client                     = client;
    di->dev                        = &client->dev;
    di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
    di->bat.name = "battery";
    di->bat.properties = bq27x00_battery_props;
    di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);
    di->bat.get_property = bq27x00_get_property;
    di->bat.external_power_changed = NULL;
    di->temp = 0;
    di->ntc_temp = 0;
    di->voltage = 0;
    di->current_avg = 0;
    di->capacity = 0;
    di->status = 0;
    di->sec = 0;
/*Manufacturer id check function */
    di->manufacturer = UNKNOW;
    di->battery_polling = 1;fake_temp=-990;fake_full_available_capacity=0;
    di->disable_led=0;
    di->health = POWER_SUPPLY_HEALTH_GOOD;
    i2c_set_clientdata(client, di);
    ret = power_supply_register(di->dev, &di->bat);
    if (ret) {
    	dev_dbg(di->dev,"failed to register battery\n");
    	//goto bk_batt_failed;
    }
/*Manufacturer id check function */
    di->manufacturer=check_manufacturer(di);
    bq27x00_read(REG_FULL_AVAILABLE_CHARGE, &g_full_available_capacity, 0, di);
    create_bq_procfs(di);
#ifdef BAT_LOG
    INIT_DELAYED_WORK_DEFERRABLE(&di->bat_log_work,bat_log_work_func);
#endif
    INIT_DELAYED_WORK_DEFERRABLE(&di->bat_monitor_work,bat_monitor_work_func);
    queue_delayed_work(bat_work_queue,&di->bat_monitor_work,
            msecs_to_jiffies(1000 * 1));
    BLOCKING_INIT_NOTIFIER_HEAD(&notifier_list);

    /* Create a sysfs node */
    error = sysfs_create_group(&di->dev->kobj, &bq_attr_grp);
    if (error) {
    	dev_dbg(di->dev,"could not create sysfs_create_group\n");
    	return -1;
    }
    return 0;
}
static void bq27x00_update(struct bq27x00_device_info *di)
{
	struct bq27x00_reg_cache cache = {0, };
	bool is_bq27500 = di->chip == BQ27500;
	bool is_bq27425 = di->chip == BQ27425;

	cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);
	if ((cache.flags & 0xff) == 0xff)
		/* read error */
		cache.flags = -1;
	if (cache.flags >= 0) {
		if (!is_bq27500 && !is_bq27425
				&& (cache.flags & BQ27000_FLAG_CI)) {
			dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
			cache.capacity = -ENODATA;
			cache.energy = -ENODATA;
			cache.time_to_empty = -ENODATA;
			cache.time_to_empty_avg = -ENODATA;
			cache.time_to_full = -ENODATA;
			cache.charge_full = -ENODATA;
			cache.health = -ENODATA;
		} else {
			cache.capacity = bq27x00_battery_read_rsoc(di);
			if (!is_bq27425) {
				cache.energy = bq27x00_battery_read_energy(di);
				cache.time_to_empty =
					bq27x00_battery_read_time(di,
							BQ27x00_REG_TTE);
				cache.time_to_empty_avg =
					bq27x00_battery_read_time(di,
							BQ27x00_REG_TTECP);
				cache.time_to_full =
					bq27x00_battery_read_time(di,
							BQ27x00_REG_TTF);
			}
			cache.charge_full = bq27x00_battery_read_lmd(di);
			cache.health = bq27x00_battery_read_health(di);
		}
		cache.temperature = bq27x00_battery_read_temperature(di);
		if (!is_bq27425)
			cache.cycle_count = bq27x00_battery_read_cyct(di);
		cache.power_avg =
			bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG);

		/* We only have to read charge design full once */
		if (di->charge_design_full <= 0)
			di->charge_design_full = bq27x00_battery_read_ilmd(di);
	}

	if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) {
		di->cache = cache;
		power_supply_changed(&di->bat);
	}

	di->last_update = jiffies;
}
Beispiel #10
0
static ssize_t time_to_empty_at_constant_power_show(struct device *dev, struct device_attribute *attr,char *buf)
{
    struct bq27541_info *di = i2c_get_clientdata(to_i2c_client(dev));
    int ret=0;
    int minute=0;
    ret = bq27x00_read(REG_TIME_TO_EMPTYT_AT_CONSTANT_POWER, &minute, 0, di);
    if (ret) {
        return 0;
    }
    return sprintf(buf, "%d minute\n", minute);
}
Beispiel #11
0
static ssize_t max_load_time_to_empty_show(struct device *dev, struct device_attribute *attr,char *buf)
{
    struct bq27541_info *di = i2c_get_clientdata(to_i2c_client(dev));
    int ret=0;
    int minute=0;
    ret = bq27x00_read(REG_MAX_LOAD_TIME_TO_EMPTY, &minute, 0, di);
    if (ret) {
        return 0;
    }
    return sprintf(buf, "%d minute\n", minute);
}
Beispiel #12
0
static ssize_t nominal_available_capacity_show(struct device *dev, struct device_attribute *attr,char *buf)
{
    struct bq27541_info *di = i2c_get_clientdata(to_i2c_client(dev));
    int ret=0;
    int capacity=0;
    ret = bq27x00_read(REG_NOMINAL_AVAILABLE_CAPACITY, &capacity, 0, di);
    if (ret) {
        return 0;
    }
    return sprintf(buf, "%d mAh\n", capacity);
}
Beispiel #13
0
static ssize_t at_rate_time_to_empty_show(struct device *dev, struct device_attribute *attr,char *buf)
{
    struct bq27541_info *di = i2c_get_clientdata(to_i2c_client(dev));
    int ret=0;
    int time=0;
    ret = bq27x00_read(REG_AT_RATE_TIME_TO_EMPTY, &time, 0, di);
    if (ret < 0) {
        return 0;
    }
    return sprintf(buf, "%d minute\n", time);
}
Beispiel #14
0
/*
 * Return the battery Voltage in milivolts
 * Or < 0 if something fails.
 */
int bq27x00_battery_voltage(struct bq27541_info *di,int* value)
{
    int ret=0;
    int volt = 0;
    ret = bq27x00_read(BQ27x00_REG_VOLT, &volt, 0, di);
    if (ret) {
        dev_err(di->dev, "error reading voltage\n");
        return ret;
    }
    *value =volt * 1000;
    return ret;
}
Beispiel #15
0
/*
 * Return the battery Nominal available capaciy in µAh
 * Or < 0 if something fails.
 */
static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di)
{
	int flags;
	bool is_bq27500 = di->chip == BQ27500;
	bool is_higher = bq27xxx_is_chip_version_higher(di);

	flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);
	if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI))
		return -ENODATA;

	return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC);
}
Beispiel #16
0
static ssize_t max_load_current_show(struct device *dev, struct device_attribute *attr,char *buf)
{
    struct bq27541_info *di = i2c_get_clientdata(to_i2c_client(dev));
    int ret=0;
    int curr=0;
    ret = bq27x00_read(REG_MAX_LOAD_CURRENT, &curr, 0, di);
    if (ret) {
        return 0;
    }
    /* bq27500 returns signed value */
    curr = (int)(s16)curr;
    return sprintf(buf, "%d mA\n", curr);
}
Beispiel #17
0
static ssize_t at_rate_show(struct device *dev, struct device_attribute *attr,char *buf)
{
    struct bq27541_info *di = i2c_get_clientdata(to_i2c_client(dev));
    int ret=0;
    int at_rate=0;
    ret = bq27x00_read(REG_AT_RATE, &at_rate, 0, di);
    if (ret) {
        return 0;
    }
    /* bq27500 returns signed value */
    at_rate = (int)(s16)at_rate;
    return sprintf(buf, "%d mA\n", at_rate);
}
Beispiel #18
0
/*
 * Return the battery Relative State-of-Charge
 * Or < 0 if something fails.
 */
int bq27x00_battery_rsoc(struct bq27541_info *di,int* value)
{
    int ret=0;
    int rsoc=0;
    ret = bq27x00_read(BQ27500_REG_SOC, &rsoc, 0, di);
    if (ret < 0) {
        dev_err(di->dev, "error reading rsoc\n");
        return ret;
    }
    *value=rsoc;
   
    return ret;
}
Beispiel #19
0
/*
 * Return the battery temperature in tenths of degree Celsius
 * Or < 0 if something fails.
 */
int bq27x00_battery_temperature(struct bq27541_info *di,int* value)
{
    int ret=0;
    int temp = 0;

    ret = bq27x00_read(BQ27x00_REG_TEMP, &temp, 0, di);//0.1K
    if (ret) {
        dev_err(di->dev, "error reading temperature\n");
        return ret;
    }    
    //Kelvin to Celsius °C = K − 273.15
    *value=temp - 2731;
    return ret;
}
Beispiel #20
0
/*
 * Return the battery Voltage in millivolts
 * Or < 0 if something fails.
 */
static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
				   union power_supply_propval *val)
{
	int volt;

	volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
	if (volt < 0) {
		dev_err(di->dev, "error reading voltage\n");
		return volt;
	}

	val->intval = volt * 1000;

	return 0;
}
Beispiel #21
0
/*
 * Return the battery temperature in tenths of degree Kelvin
 * Or < 0 if something fails.
 */
static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di)
{
	int temp;

	temp = bq27x00_read(di, BQ27x00_REG_TEMP, false);
	if (temp < 0) {
		dev_err(di->dev, "error reading temperature\n");
		return temp;
	}

	if (!bq27xxx_is_chip_version_higher(di))
		temp = 5 * temp / 2;

	return temp;
}
Beispiel #22
0
/*
 * Read a power avg register.
 * Return < 0 if something fails.
 */
static int bq27x00_battery_read_pwr_avg(struct bq27x00_device_info *di, u8 reg)
{
	int tval;

	tval = bq27x00_read(di, reg, false);
	if (tval < 0) {
		dev_err(di->dev, "error reading power avg rgister  %02x: %d\n",
			reg, tval);
		return tval;
	}

	if (di->chip == BQ27500)
		return tval;
	else
		return (tval * BQ27x00_POWER_CONSTANT) / BQ27000_RS;
}
Beispiel #23
0
/*
 * Read a time register.
 * Return < 0 if something fails.
 */
static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg)
{
	int tval;

	tval = bq27x00_read(di, reg, false);
	if (tval < 0) {
		dev_dbg(di->dev, "error reading time register %02x: %d\n",
			reg, tval);
		return tval;
	}

	if (tval == 65535)
		return -ENODATA;

	return tval * 60;
}
Beispiel #24
0
/*
 * Return the battery average current(milliamp)
 * Note that current can be negative signed as well
 * Or 0 if something fails.
 */
int bq27x00_battery_current(struct bq27541_info *di,int* value)
{
    int ret=0;
    int curr = 0;

    ret = bq27x00_read(BQ27x00_REG_AI, &curr, 0, di);
    if (ret) {
        dev_err(di->dev, "error reading current\n");
        return ret;
    }
    /* bq27500 returns signed value */
    curr = (int)(s16)curr;
    *value=curr * 1000;

    return ret;
}
Beispiel #25
0
/*
 * Return the battery temperature in tenths of degree Celsius
 * Or < 0 if something fails.
 */
static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di)
{
	int temp;

	temp = bq27x00_read(di, BQ27x00_REG_TEMP, false);
	if (temp < 0) {
		dev_err(di->dev, "error reading temperature\n");
		return temp;
	}

	if (di->chip == BQ27500)
		temp -= 2731;
	else
		temp = ((temp * 5) - 5463) / 2;

	return temp;
}
Beispiel #26
0
/*
 * Return the battery Available energy in µWh
 * Or < 0 if something fails.
 */
static int bq27x00_battery_read_energy(struct bq27x00_device_info *di)
{
	int ae;

	ae = bq27x00_read(di, BQ27x00_REG_AE, false);
	if (ae < 0) {
		dev_dbg(di->dev, "error reading available energy\n");
		return ae;
	}

	if (di->chip == BQ27500)
		ae *= 1000;
	else
		ae = ae * 29200 / BQ27000_RS;

	return ae;
}
Beispiel #27
0
static int bq27x00_battery_cycle_count(struct bq27541_info *di, unsigned int *value)
{
	int ret = -1, count = 0;

	*value = 0;

	ret = bq27x00_read(REG_CYCLE_COUNT, &count, 0, di);

	if (ret) {
		dev_err(di->dev, "error reading cycle count\n");
		return ret;
	}

	*value = (unsigned int)count;

	return 0;
}
Beispiel #28
0
/*
 * Return a battery charge value in µAh
 * Or < 0 if something fails.
 */
static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
{
	int charge;

	charge = bq27x00_read(di, reg, false);
	if (charge < 0) {
		dev_dbg(di->dev, "error reading charge register %02x: %d\n",
			reg, charge);
		return charge;
	}

	if (bq27xxx_is_chip_version_higher(di))
		charge *= 1000;
	else
		charge = charge * 3570 / BQ27000_RS;

	return charge;
}
Beispiel #29
0
static int bq27x00_battery_full_charge_uncompensated(struct bq27541_info *di, unsigned int *value)
{
	int ret = -1, charge = 0;

	*value = 0;

	ret = bq27x00_read(REG_FULL_AVAILABLE_CHARGE, &charge, 0, di);

	if (ret) {
		dev_err(di->dev, "error reading full charge (uncompensated)\n");
		return ret;
	}

	/* Convert mAh to uAh */
	*value = (unsigned int)(charge * 1000);

	return 0;
}
Beispiel #30
0
static int bq27x00_battery_remaining_charge(struct bq27541_info *di, unsigned int *value)
{
	int ret = -1, charge = 0;

	*value = 0;

	ret = bq27x00_read(REG_REMAINING_CHARGE, &charge, 0, di);

	if (ret) {
		dev_err(di->dev, "error reading remaining capacity\n");
		return ret;
	}

	/* Convert mAh to uAh */
	*value = (unsigned int)(charge * 1000);

	return 0;
}