Commit 15953654 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.infradead.org/battery-2.6:
  ds2760_battery: Document ABI change
  ds2760_battery: Make charge_now and charge_full writeable
  power_supply: Add support for writeable properties
  power_supply: Use attribute groups
  power_supply: Add test_power driver
  tosa_battery: Fix build error due to direct driver_data usage
  wm97xx_battery: Quieten sparse warning (bat_set_pdata not declared)
  ds2782_battery: Get rid of magic numbers in driver_data
  ds2782_battery: Add support for ds2786 battery gas gauge
  pda_power: Add function callbacks for suspend and resume
  wm831x_power: Use genirq
  Driver for Zipit Z2 battery chip
  ds2782_battery: Fix clientdata on removal
parents c3ed9ea4 24af3202
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
What:		/sys/class/power/ds2760-battery.*/charge_now
Date:		May 2010
KernelVersion:	2.6.35
Contact:	Daniel Mack <daniel@caiaq.de>
Description:
		This file is writeable and can be used to set the current
		coloumb counter value inside the battery monitor chip. This
		is needed for unavoidable corrections of aging batteries.
		A userspace daemon can monitor the battery charging logic
		and once the counter drops out of considerable bounds, take
		appropriate action.

What:		/sys/class/power/ds2760-battery.*/charge_full
Date:		May 2010
KernelVersion:	2.6.35
Contact:	Daniel Mack <daniel@caiaq.de>
Description:
		This file is writeable and can be used to set the assumed
		battery 'full level'. As batteries age, this value has to be
		amended over time.
+13 −2
Original line number Diff line number Diff line
@@ -57,6 +57,11 @@ config WM8350_POWER
          Say Y here to enable support for the power management unit
	  provided by the Wolfson Microelectronics WM8350 PMIC.

config TEST_POWER
	tristate "Test power driver"
	help
	  This driver is used for testing. It's safe to say M here.

config BATTERY_DS2760
	tristate "DS2760 battery driver (HP iPAQ & others)"
	select W1
@@ -65,10 +70,10 @@ config BATTERY_DS2760
	  Say Y here to enable support for batteries with ds2760 chip.

config BATTERY_DS2782
	tristate "DS2782 standalone gas-gauge"
	tristate "DS2782/DS2786 standalone gas-gauge"
	depends on I2C
	help
	  Say Y here to enable support for the DS2782 standalone battery
	  Say Y here to enable support for the DS2782/DS2786 standalone battery
	  gas-gauge.

config BATTERY_PMU
@@ -125,6 +130,12 @@ config BATTERY_MAX17040
	  in handheld and portable equipment. The MAX17040 is configured
	  to operate with a single lithium cell

config BATTERY_Z2
	tristate "Z2 battery driver"
	depends on I2C && MACH_ZIPIT2
	help
	  Say Y to include support for the battery on the Zipit Z2.

config CHARGER_PCF50633
	tristate "NXP PCF50633 MBC"
	depends on MFD_PCF50633
+2 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ obj-$(CONFIG_MAX8925_POWER) += max8925_power.o
obj-$(CONFIG_WM831X_BACKUP)	+= wm831x_backup.o
obj-$(CONFIG_WM831X_POWER)	+= wm831x_power.o
obj-$(CONFIG_WM8350_POWER)	+= wm8350_power.o
obj-$(CONFIG_TEST_POWER)	+= test_power.o

obj-$(CONFIG_BATTERY_DS2760)	+= ds2760_battery.o
obj-$(CONFIG_BATTERY_DS2782)	+= ds2782_battery.o
@@ -31,4 +32,5 @@ obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
obj-$(CONFIG_BATTERY_BQ27x00)	+= bq27x00_battery.o
obj-$(CONFIG_BATTERY_DA9030)	+= da9030_battery.o
obj-$(CONFIG_BATTERY_MAX17040)	+= max17040_battery.o
obj-$(CONFIG_BATTERY_Z2)	+= z2_battery.o
obj-$(CONFIG_CHARGER_PCF50633)	+= pcf50633-charger.o
+64 −0
Original line number Diff line number Diff line
@@ -304,6 +304,28 @@ static void ds2760_battery_write_rated_capacity(struct ds2760_device_info *di,
	w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
}

static void ds2760_battery_write_active_full(struct ds2760_device_info *di,
					     int active_full)
{
	unsigned char tmp[2] = {
		active_full >> 8,
		active_full & 0xff
	};

	if (tmp[0] == di->raw[DS2760_ACTIVE_FULL] &&
	    tmp[1] == di->raw[DS2760_ACTIVE_FULL + 1])
		return;

	w1_ds2760_write(di->w1_dev, tmp, DS2760_ACTIVE_FULL, sizeof(tmp));
	w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK0);
	w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK0);

	/* Write to the di->raw[] buffer directly - the DS2760_ACTIVE_FULL
	 * values won't be read back by ds2760_battery_read_status() */
	di->raw[DS2760_ACTIVE_FULL] = tmp[0];
	di->raw[DS2760_ACTIVE_FULL + 1] = tmp[1];
}

static void ds2760_battery_work(struct work_struct *work)
{
	struct ds2760_device_info *di = container_of(work,
@@ -426,6 +448,45 @@ static int ds2760_battery_get_property(struct power_supply *psy,
	return 0;
}

static int ds2760_battery_set_property(struct power_supply *psy,
				       enum power_supply_property psp,
				       const union power_supply_propval *val)
{
	struct ds2760_device_info *di = to_ds2760_device_info(psy);

	switch (psp) {
	case POWER_SUPPLY_PROP_CHARGE_FULL:
		/* the interface counts in uAh, convert the value */
		ds2760_battery_write_active_full(di, val->intval / 1000L);
		break;

	case POWER_SUPPLY_PROP_CHARGE_NOW:
		/* ds2760_battery_set_current_accum() does the conversion */
		ds2760_battery_set_current_accum(di, val->intval);
		break;

	default:
		return -EPERM;
	}

	return 0;
}

static int ds2760_battery_property_is_writeable(struct power_supply *psy,
						enum power_supply_property psp)
{
	switch (psp) {
	case POWER_SUPPLY_PROP_CHARGE_FULL:
	case POWER_SUPPLY_PROP_CHARGE_NOW:
		return 1;

	default:
		break;
	}

	return 0;
}

static enum power_supply_property ds2760_battery_props[] = {
	POWER_SUPPLY_PROP_STATUS,
	POWER_SUPPLY_PROP_VOLTAGE_NOW,
@@ -460,6 +521,9 @@ static int ds2760_battery_probe(struct platform_device *pdev)
	di->bat.properties	= ds2760_battery_props;
	di->bat.num_properties	= ARRAY_SIZE(ds2760_battery_props);
	di->bat.get_property	= ds2760_battery_get_property;
	di->bat.set_property	= ds2760_battery_set_property;
	di->bat.property_is_writeable =
				  ds2760_battery_property_is_writeable;
	di->bat.set_charged	= ds2760_battery_set_charged;
	di->bat.external_power_changed =
				  ds2760_battery_external_power_changed;
+142 −52
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@
 *
 * Author: Ryan Mallon <ryan@bluewatersys.com>
 *
 * DS2786 added by Yulia Vilensky <vilensky@compulab.co.il>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
@@ -20,12 +22,13 @@
#include <linux/idr.h>
#include <linux/power_supply.h>
#include <linux/slab.h>
#include <linux/ds2782_battery.h>

#define DS2782_REG_RARC		0x06	/* Remaining active relative capacity */

#define DS2782_REG_VOLT_MSB	0x0c
#define DS2782_REG_TEMP_MSB	0x0a
#define DS2782_REG_CURRENT_MSB	0x0e
#define DS278x_REG_VOLT_MSB	0x0c
#define DS278x_REG_TEMP_MSB	0x0a
#define DS278x_REG_CURRENT_MSB	0x0e

/* EEPROM Block */
#define DS2782_REG_RSNSP	0x69	/* Sense resistor value */
@@ -33,18 +36,33 @@
/* Current unit measurement in uA for a 1 milli-ohm sense resistor */
#define DS2782_CURRENT_UNITS	1563

#define to_ds2782_info(x) container_of(x, struct ds2782_info, battery)
#define DS2786_REG_RARC		0x02	/* Remaining active relative capacity */

#define DS2786_CURRENT_UNITS	25

struct ds278x_info;

struct ds278x_battery_ops {
	int	(*get_current)(struct ds278x_info *info, int *current_uA);
	int	(*get_voltage)(struct ds278x_info *info, int *voltage_uA);
	int	(*get_capacity)(struct ds278x_info *info, int *capacity_uA);

};

#define to_ds278x_info(x) container_of(x, struct ds278x_info, battery)

struct ds2782_info {
struct ds278x_info {
	struct i2c_client	*client;
	struct power_supply	battery;
	struct ds278x_battery_ops  *ops;
	int			id;
	int                     rsns;
};

static DEFINE_IDR(battery_id);
static DEFINE_MUTEX(battery_lock);

static inline int ds2782_read_reg(struct ds2782_info *info, int reg, u8 *val)
static inline int ds278x_read_reg(struct ds278x_info *info, int reg, u8 *val)
{
	int ret;

@@ -58,7 +76,7 @@ static inline int ds2782_read_reg(struct ds2782_info *info, int reg, u8 *val)
	return 0;
}

static inline int ds2782_read_reg16(struct ds2782_info *info, int reg_msb,
static inline int ds278x_read_reg16(struct ds278x_info *info, int reg_msb,
				    s16 *val)
{
	int ret;
@@ -73,7 +91,7 @@ static inline int ds2782_read_reg16(struct ds2782_info *info, int reg_msb,
	return 0;
}

static int ds2782_get_temp(struct ds2782_info *info, int *temp)
static int ds278x_get_temp(struct ds278x_info *info, int *temp)
{
	s16 raw;
	int err;
@@ -84,14 +102,14 @@ static int ds2782_get_temp(struct ds2782_info *info, int *temp)
	 * celsius. The temperature value is stored as a 10 bit number, plus
	 * sign in the upper bits of a 16 bit register.
	 */
	err = ds2782_read_reg16(info, DS2782_REG_TEMP_MSB, &raw);
	err = ds278x_read_reg16(info, DS278x_REG_TEMP_MSB, &raw);
	if (err)
		return err;
	*temp = ((raw / 32) * 125) / 100;
	return 0;
}

static int ds2782_get_current(struct ds2782_info *info, int *current_uA)
static int ds2782_get_current(struct ds278x_info *info, int *current_uA)
{
	int sense_res;
	int err;
@@ -102,7 +120,7 @@ static int ds2782_get_current(struct ds2782_info *info, int *current_uA)
	 * The units of measurement for current are dependent on the value of
	 * the sense resistor.
	 */
	err = ds2782_read_reg(info, DS2782_REG_RSNSP, &sense_res_raw);
	err = ds278x_read_reg(info, DS2782_REG_RSNSP, &sense_res_raw);
	if (err)
		return err;
	if (sense_res_raw == 0) {
@@ -113,14 +131,14 @@ static int ds2782_get_current(struct ds2782_info *info, int *current_uA)

	dev_dbg(&info->client->dev, "sense resistor = %d milli-ohms\n",
		sense_res);
	err = ds2782_read_reg16(info, DS2782_REG_CURRENT_MSB, &raw);
	err = ds278x_read_reg16(info, DS278x_REG_CURRENT_MSB, &raw);
	if (err)
		return err;
	*current_uA = raw * (DS2782_CURRENT_UNITS / sense_res);
	return 0;
}

static int ds2782_get_voltage(struct ds2782_info *info, int *voltage_uA)
static int ds2782_get_voltage(struct ds278x_info *info, int *voltage_uA)
{
	s16 raw;
	int err;
@@ -129,36 +147,77 @@ static int ds2782_get_voltage(struct ds2782_info *info, int *voltage_uA)
	 * Voltage is measured in units of 4.88mV. The voltage is stored as
	 * a 10-bit number plus sign, in the upper bits of a 16-bit register
	 */
	err = ds2782_read_reg16(info, DS2782_REG_VOLT_MSB, &raw);
	err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw);
	if (err)
		return err;
	*voltage_uA = (raw / 32) * 4800;
	return 0;
}

static int ds2782_get_capacity(struct ds2782_info *info, int *capacity)
static int ds2782_get_capacity(struct ds278x_info *info, int *capacity)
{
	int err;
	u8 raw;

	err = ds2782_read_reg(info, DS2782_REG_RARC, &raw);
	err = ds278x_read_reg(info, DS2782_REG_RARC, &raw);
	if (err)
		return err;
	*capacity = raw;
	return raw;
}

static int ds2782_get_status(struct ds2782_info *info, int *status)
static int ds2786_get_current(struct ds278x_info *info, int *current_uA)
{
	int err;
	s16 raw;

	err = ds278x_read_reg16(info, DS278x_REG_CURRENT_MSB, &raw);
	if (err)
		return err;
	*current_uA = (raw / 16) * (DS2786_CURRENT_UNITS / info->rsns);
	return 0;
}

static int ds2786_get_voltage(struct ds278x_info *info, int *voltage_uA)
{
	s16 raw;
	int err;

	/*
	 * Voltage is measured in units of 1.22mV. The voltage is stored as
	 * a 10-bit number plus sign, in the upper bits of a 16-bit register
	 */
	err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw);
	if (err)
		return err;
	*voltage_uA = (raw / 8) * 1220;
	return 0;
}

static int ds2786_get_capacity(struct ds278x_info *info, int *capacity)
{
	int err;
	u8 raw;

	err = ds278x_read_reg(info, DS2786_REG_RARC, &raw);
	if (err)
		return err;
	/* Relative capacity is displayed with resolution 0.5 % */
	*capacity = raw/2 ;
	return 0;
}

static int ds278x_get_status(struct ds278x_info *info, int *status)
{
	int err;
	int current_uA;
	int capacity;

	err = ds2782_get_current(info, &current_uA);
	err = info->ops->get_current(info, &current_uA);
	if (err)
		return err;

	err = ds2782_get_capacity(info, &capacity);
	err = info->ops->get_capacity(info, &capacity);
	if (err)
		return err;

@@ -174,32 +233,32 @@ static int ds2782_get_status(struct ds2782_info *info, int *status)
	return 0;
}

static int ds2782_battery_get_property(struct power_supply *psy,
static int ds278x_battery_get_property(struct power_supply *psy,
				       enum power_supply_property prop,
				       union power_supply_propval *val)
{
	struct ds2782_info *info = to_ds2782_info(psy);
	struct ds278x_info *info = to_ds278x_info(psy);
	int ret;

	switch (prop) {
	case POWER_SUPPLY_PROP_STATUS:
		ret = ds2782_get_status(info, &val->intval);
		ret = ds278x_get_status(info, &val->intval);
		break;

	case POWER_SUPPLY_PROP_CAPACITY:
		ret = ds2782_get_capacity(info, &val->intval);
		ret = info->ops->get_capacity(info, &val->intval);
		break;

	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
		ret = ds2782_get_voltage(info, &val->intval);
		ret = info->ops->get_voltage(info, &val->intval);
		break;

	case POWER_SUPPLY_PROP_CURRENT_NOW:
		ret = ds2782_get_current(info, &val->intval);
		ret = info->ops->get_current(info, &val->intval);
		break;

	case POWER_SUPPLY_PROP_TEMP:
		ret = ds2782_get_temp(info, &val->intval);
		ret = ds278x_get_temp(info, &val->intval);
		break;

	default:
@@ -209,7 +268,7 @@ static int ds2782_battery_get_property(struct power_supply *psy,
	return ret;
}

static enum power_supply_property ds2782_battery_props[] = {
static enum power_supply_property ds278x_battery_props[] = {
	POWER_SUPPLY_PROP_STATUS,
	POWER_SUPPLY_PROP_CAPACITY,
	POWER_SUPPLY_PROP_VOLTAGE_NOW,
@@ -217,18 +276,18 @@ static enum power_supply_property ds2782_battery_props[] = {
	POWER_SUPPLY_PROP_TEMP,
};

static void ds2782_power_supply_init(struct power_supply *battery)
static void ds278x_power_supply_init(struct power_supply *battery)
{
	battery->type			= POWER_SUPPLY_TYPE_BATTERY;
	battery->properties		= ds2782_battery_props;
	battery->num_properties		= ARRAY_SIZE(ds2782_battery_props);
	battery->get_property		= ds2782_battery_get_property;
	battery->properties		= ds278x_battery_props;
	battery->num_properties		= ARRAY_SIZE(ds278x_battery_props);
	battery->get_property		= ds278x_battery_get_property;
	battery->external_power_changed	= NULL;
}

static int ds2782_battery_remove(struct i2c_client *client)
static int ds278x_battery_remove(struct i2c_client *client)
{
	struct ds2782_info *info = i2c_get_clientdata(client);
	struct ds278x_info *info = i2c_get_clientdata(client);

	power_supply_unregister(&info->battery);
	kfree(info->battery.name);
@@ -237,19 +296,45 @@ static int ds2782_battery_remove(struct i2c_client *client)
	idr_remove(&battery_id, info->id);
	mutex_unlock(&battery_lock);

	i2c_set_clientdata(client, info);

	kfree(info);
	return 0;
}

static int ds2782_battery_probe(struct i2c_client *client,
enum ds278x_num_id {
	DS2782 = 0,
	DS2786,
};

static struct ds278x_battery_ops ds278x_ops[] = {
	[DS2782] = {
		.get_current  = ds2782_get_current,
		.get_voltage  = ds2782_get_voltage,
		.get_capacity = ds2782_get_capacity,
	},
	[DS2786] = {
		.get_current  = ds2786_get_current,
		.get_voltage  = ds2786_get_voltage,
		.get_capacity = ds2786_get_capacity,
	}
};

static int ds278x_battery_probe(struct i2c_client *client,
				const struct i2c_device_id *id)
{
	struct ds2782_info *info;
	struct ds278x_platform_data *pdata = client->dev.platform_data;
	struct ds278x_info *info;
	int ret;
	int num;

	/*
	 * ds2786 should have the sense resistor value set
	 * in the platform data
	 */
	if (id->driver_data == DS2786 && !pdata) {
		dev_err(&client->dev, "missing platform data for ds2786\n");
		return -EINVAL;
	}

	/* Get an ID for this battery */
	ret = idr_pre_get(&battery_id, GFP_KERNEL);
	if (ret == 0) {
@@ -269,15 +354,20 @@ static int ds2782_battery_probe(struct i2c_client *client,
		goto fail_info;
	}

	info->battery.name = kasprintf(GFP_KERNEL, "ds2782-%d", num);
	info->battery.name = kasprintf(GFP_KERNEL, "%s-%d", client->name, num);
	if (!info->battery.name) {
		ret = -ENOMEM;
		goto fail_name;
	}

	if (id->driver_data == DS2786)
		info->rsns = pdata->rsns;

	i2c_set_clientdata(client, info);
	info->client = client;
	ds2782_power_supply_init(&info->battery);
	info->id = num;
	info->ops  = &ds278x_ops[id->driver_data];
	ds278x_power_supply_init(&info->battery);

	ret = power_supply_register(&client->dev, &info->battery);
	if (ret) {
@@ -290,7 +380,6 @@ static int ds2782_battery_probe(struct i2c_client *client,
fail_register:
	kfree(info->battery.name);
fail_name:
	i2c_set_clientdata(client, info);
	kfree(info);
fail_info:
	mutex_lock(&battery_lock);
@@ -300,31 +389,32 @@ fail_id:
	return ret;
}

static const struct i2c_device_id ds2782_id[] = {
	{"ds2782", 0},
static const struct i2c_device_id ds278x_id[] = {
	{"ds2782", DS2782},
	{"ds2786", DS2786},
	{},
};

static struct i2c_driver ds2782_battery_driver = {
static struct i2c_driver ds278x_battery_driver = {
	.driver 	= {
		.name	= "ds2782-battery",
	},
	.probe		= ds2782_battery_probe,
	.remove		= ds2782_battery_remove,
	.id_table	= ds2782_id,
	.probe		= ds278x_battery_probe,
	.remove		= ds278x_battery_remove,
	.id_table	= ds278x_id,
};

static int __init ds2782_init(void)
static int __init ds278x_init(void)
{
	return i2c_add_driver(&ds2782_battery_driver);
	return i2c_add_driver(&ds278x_battery_driver);
}
module_init(ds2782_init);
module_init(ds278x_init);

static void __exit ds2782_exit(void)
static void __exit ds278x_exit(void)
{
	i2c_del_driver(&ds2782_battery_driver);
	i2c_del_driver(&ds278x_battery_driver);
}
module_exit(ds2782_exit);
module_exit(ds278x_exit);

MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>");
MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver");
Loading