Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 740b755a authored by Lars-Peter Clausen's avatar Lars-Peter Clausen
Browse files

bq27x00: Poll battery state



This patch adds support for polling the battery state and generating a
power_supply_changed() event if it has changed.

Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Tested-by: default avatarGrazvydas Ignotas <notasas@gmail.com>
parent 297a533b
Loading
Loading
Loading
Loading
+53 −5
Original line number Original line Diff line number Diff line
@@ -74,10 +74,13 @@ struct bq27x00_device_info {


	struct bq27x00_reg_cache cache;
	struct bq27x00_reg_cache cache;
	unsigned long last_update;
	unsigned long last_update;
	struct delayed_work work;


	struct power_supply	bat;
	struct power_supply	bat;


	struct bq27x00_access_methods bus;
	struct bq27x00_access_methods bus;

	struct mutex lock;
};
};


static enum power_supply_property bq27x00_battery_props[] = {
static enum power_supply_property bq27x00_battery_props[] = {
@@ -93,6 +96,11 @@ static enum power_supply_property bq27x00_battery_props[] = {
	POWER_SUPPLY_PROP_TECHNOLOGY,
	POWER_SUPPLY_PROP_TECHNOLOGY,
};
};


static unsigned int poll_interval = 360;
module_param(poll_interval, uint, 0644);
MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \
				"0 disables polling");

/*
/*
 * Common code for BQ27x00 devices
 * Common code for BQ27x00 devices
 */
 */
@@ -169,6 +177,21 @@ static void bq27x00_update(struct bq27x00_device_info *di)
	di->last_update = jiffies;
	di->last_update = jiffies;
}
}


static void bq27x00_battery_poll(struct work_struct *work)
{
	struct bq27x00_device_info *di =
		container_of(work, struct bq27x00_device_info, work.work);

	bq27x00_update(di);

	if (poll_interval > 0) {
		/* The timer does not have to be accurate. */
		set_timer_slack(&di->work.timer, poll_interval * HZ / 4);
		schedule_delayed_work(&di->work, poll_interval * HZ);
	}
}


/*
/*
 * Return the battery temperature in tenths of degree Celsius
 * Return the battery temperature in tenths of degree Celsius
 * Or < 0 if something fails.
 * Or < 0 if something fails.
@@ -283,8 +306,12 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
	int ret = 0;
	int ret = 0;
	struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
	struct bq27x00_device_info *di = to_bq27x00_device_info(psy);


	if (time_is_before_jiffies(di->last_update + 5 * HZ))
	mutex_lock(&di->lock);
		bq27x00_update(di);
	if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
		cancel_delayed_work_sync(&di->work);
		bq27x00_battery_poll(&di->work.work);
	}
	mutex_unlock(&di->lock);


	if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
	if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
		return -ENODEV;
		return -ENODEV;
@@ -327,6 +354,14 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
	return ret;
	return ret;
}
}


static void bq27x00_external_power_changed(struct power_supply *psy)
{
	struct bq27x00_device_info *di = to_bq27x00_device_info(psy);

	cancel_delayed_work_sync(&di->work);
	schedule_delayed_work(&di->work, 0);
}

static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
{
{
	int ret;
	int ret;
@@ -335,7 +370,10 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
	di->bat.properties = bq27x00_battery_props;
	di->bat.properties = bq27x00_battery_props;
	di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);
	di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);
	di->bat.get_property = bq27x00_battery_get_property;
	di->bat.get_property = bq27x00_battery_get_property;
	di->bat.external_power_changed = NULL;
	di->bat.external_power_changed = bq27x00_external_power_changed;

	INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);
	mutex_init(&di->lock);


	ret = power_supply_register(di->dev, &di->bat);
	ret = power_supply_register(di->dev, &di->bat);
	if (ret) {
	if (ret) {
@@ -350,6 +388,15 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
	return 0;
	return 0;
}
}


static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
{
	cancel_delayed_work_sync(&di->work);

	power_supply_unregister(&di->bat);

	mutex_destroy(&di->lock);
}



/* i2c specific code */
/* i2c specific code */
#ifdef CONFIG_BATTERY_BQ27X00_I2C
#ifdef CONFIG_BATTERY_BQ27X00_I2C
@@ -457,7 +504,7 @@ static int bq27x00_battery_remove(struct i2c_client *client)
{
{
	struct bq27x00_device_info *di = i2c_get_clientdata(client);
	struct bq27x00_device_info *di = i2c_get_clientdata(client);


	power_supply_unregister(&di->bat);
	bq27x00_powersupply_unregister(di);


	kfree(di->bat.name);
	kfree(di->bat.name);


@@ -590,7 +637,8 @@ static int __devexit bq27000_battery_remove(struct platform_device *pdev)
{
{
	struct bq27x00_device_info *di = platform_get_drvdata(pdev);
	struct bq27x00_device_info *di = platform_get_drvdata(pdev);


	power_supply_unregister(&di->bat);
	bq27x00_powersupply_unregister(di);

	platform_set_drvdata(pdev, NULL);
	platform_set_drvdata(pdev, NULL);
	kfree(di);
	kfree(di);