Commit a21c1ea6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-v4.1' of git://git.infradead.org/battery-2.6

Pull power supply and reset changes from Sebastian Reichel:

 - new API for safe access of power supply function attrs

 - devres support for power supply (un)registration

 - new drivers / chips:
     - generic syscon based poweroff driver
     - iio & charger driver for da9150
     - fuel gauge driver for axp288
     - bq27x00: add support for bq27510
     - bq2415x: add support for bq24157s

 - twl4030-madc-battery: convert to iio consumer

 - misc fixes

* tag 'for-v4.1' of git://git.infradead.org/battery-2.6: (66 commits)
  power: twl4030_madc_battery: Add missing MODULE_ALIAS
  power: twl4030-madc-battery: Convert to iio consumer.
  dt: power: Add docs for generic SYSCON poweroff driver.
  power: reset: Add generic SYSCON register mapped poweroff.
  power: max17042_battery: add missed blank
  power: max17042_battery: Use reg type instead of chip type
  power/reset: at91: big endian fixes for atsama5d3x
  power_supply: charger-manager: Fix dereferencing of ERR_PTR
  HID: input: Fix NULL pointer dereference when power_supply_register fails
  power: constify of_device_id array
  power/reset/rmobile-reset.c: Fix !HAS_IOMEM build
  power_supply: 88pm860x_charger: Fix possible NULL pointer dereference and use of initialized variable
  arm: mach-pxa: Decrement the power supply's device reference counter
  mfd: ab8500: Decrement the power supply's device reference counter
  power_supply: bq2415x_charger: Decrement the power supply's device reference counter
  power_supply: 88pm860x_charger: Decrement the power supply's device reference counter
  x86/olpc/xo15/sci: Use newly added power_supply_put API
  x86/olpc/xo1/sci: Use newly added power_supply_put API
  power_supply: charger-manager: Decrement the power supply's device reference counter
  power_supply: Increment power supply use counter when obtaining references
  ...
parents d700b056 5939d9df
Dialog Semiconductor DA9150 IIO GPADC bindings
Required properties:
- compatible: "dlg,da9150-gpadc" for DA9150 IIO GPADC
- #io-channel-cells: Should be set to <1>
(See Documentation/devicetree/bindings/iio/iio-bindings.txt for further info)
For further information on GPADC channels, see device datasheet.
Example:
gpadc: da9150-gpadc {
compatible = "dlg,da9150-gpadc";
#io-channel-cells = <1>;
};
Dialog Semiconductor DA9150 Charger Power Supply bindings
Required properties:
- compatible: "dlg,da9150-charger" for DA9150 Charger Power Supply
Optional properties:
- io-channels: List of phandle and IIO specifier pairs
- io-channel-names: List of channel names used by charger
["CHAN_IBUS", "CHAN_VBUS", "CHAN_TJUNC", "CHAN_VBAT"]
(See Documentation/devicetree/bindings/iio/iio-bindings.txt for further info)
Example:
da9150-charger {
compatible = "dlg,da9150-charger";
io-channels = <&gpadc 0>,
<&gpadc 2>,
<&gpadc 8>,
<&gpadc 5>;
io-channel-names = "CHAN_IBUS",
"CHAN_VBUS",
"CHAN_TJUNC",
"CHAN_VBAT";
};
Generic SYSCON mapped register poweroff driver
This is a generic poweroff driver using syscon to map the poweroff register.
The poweroff is generally performed with a write to the poweroff register
defined by the register map pointed by syscon reference plus the offset
with the mask defined in the poweroff node.
Required properties:
- compatible: should contain "syscon-poweroff"
- regmap: this is phandle to the register map node
- offset: offset in the register map for the poweroff register (in bytes)
- mask: the poweroff value written to the poweroff register (32 bit access)
Default will be little endian mode, 32 bit access only.
Examples:
poweroff {
compatible = "syscon-poweroff";
regmap = <&regmapnode>;
offset = <0x0>;
mask = <0x7a>;
};
......@@ -3137,12 +3137,15 @@ S: Supported
F: Documentation/hwmon/da90??
F: drivers/gpio/gpio-da90??.c
F: drivers/hwmon/da90??-hwmon.c
F: drivers/iio/adc/da91??-*.c
F: drivers/input/misc/da90??_onkey.c
F: drivers/input/touchscreen/da9052_tsi.c
F: drivers/leds/leds-da90??.c
F: drivers/mfd/da903x.c
F: drivers/mfd/da90??-*.c
F: drivers/mfd/da91??-*.c
F: drivers/power/da9052-battery.c
F: drivers/power/da91??-*.c
F: drivers/regulator/da903x.c
F: drivers/regulator/da9???-regulator.[ch]
F: drivers/rtc/rtc-da90??.c
......@@ -3152,6 +3155,7 @@ F: include/linux/mfd/da903x.h
F: include/linux/mfd/da9052/
F: include/linux/mfd/da9055/
F: include/linux/mfd/da9063/
F: include/linux/mfd/da9150/
F: include/sound/da[79]*.h
F: sound/soc/codecs/da[79]*.[ch]
......
......@@ -758,8 +758,10 @@ static void raumfeld_power_signal_charged(void)
struct power_supply *psy =
power_supply_get_by_name(raumfeld_power_supplicants[0]);
if (psy)
if (psy) {
power_supply_set_battery_charged(psy);
power_supply_put(psy);
}
}
static int raumfeld_power_resume(void)
......
......@@ -61,7 +61,7 @@ static void battery_status_changed(void)
if (psy) {
power_supply_changed(psy);
put_device(psy->dev);
power_supply_put(psy);
}
}
......@@ -71,7 +71,7 @@ static void ac_status_changed(void)
if (psy) {
power_supply_changed(psy);
put_device(psy->dev);
power_supply_put(psy);
}
}
......
......@@ -83,7 +83,7 @@ static void battery_status_changed(void)
if (psy) {
power_supply_changed(psy);
put_device(psy->dev);
power_supply_put(psy);
}
}
......@@ -93,7 +93,7 @@ static void ac_status_changed(void)
if (psy) {
power_supply_changed(psy);
put_device(psy->dev);
power_supply_put(psy);
}
}
......
......@@ -95,13 +95,14 @@ static struct acpi_driver acpi_ac_driver = {
};
struct acpi_ac {
struct power_supply charger;
struct power_supply *charger;
struct power_supply_desc charger_desc;
struct acpi_device * device;
unsigned long long state;
struct notifier_block battery_nb;
};
#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger)
#define to_acpi_ac(x) power_supply_get_drvdata(x)
#ifdef CONFIG_ACPI_PROCFS_POWER
static const struct file_operations acpi_ac_fops = {
......@@ -275,7 +276,7 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event)
dev_name(&device->dev), event,
(u32) ac->state);
acpi_notifier_call_chain(device, event, (u32) ac->state);
kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE);
}
return;
......@@ -321,6 +322,7 @@ static struct dmi_system_id ac_dmi_table[] = {
static int acpi_ac_add(struct acpi_device *device)
{
struct power_supply_config psy_cfg = {};
int result = 0;
struct acpi_ac *ac = NULL;
......@@ -341,19 +343,24 @@ static int acpi_ac_add(struct acpi_device *device)
if (result)
goto end;
ac->charger.name = acpi_device_bid(device);
psy_cfg.drv_data = ac;
ac->charger_desc.name = acpi_device_bid(device);
#ifdef CONFIG_ACPI_PROCFS_POWER
result = acpi_ac_add_fs(ac);
if (result)
goto end;
#endif
ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
ac->charger.properties = ac_props;
ac->charger.num_properties = ARRAY_SIZE(ac_props);
ac->charger.get_property = get_ac_property;
result = power_supply_register(&ac->device->dev, &ac->charger);
if (result)
ac->charger_desc.type = POWER_SUPPLY_TYPE_MAINS;
ac->charger_desc.properties = ac_props;
ac->charger_desc.num_properties = ARRAY_SIZE(ac_props);
ac->charger_desc.get_property = get_ac_property;
ac->charger = power_supply_register(&ac->device->dev,
&ac->charger_desc, &psy_cfg);
if (IS_ERR(ac->charger)) {
result = PTR_ERR(ac->charger);
goto end;
}
printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
acpi_device_name(device), acpi_device_bid(device),
......@@ -390,7 +397,7 @@ static int acpi_ac_resume(struct device *dev)
if (acpi_ac_get_state(ac))
return 0;
if (old_state != ac->state)
kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE);
return 0;
}
#else
......@@ -407,8 +414,7 @@ static int acpi_ac_remove(struct acpi_device *device)
ac = acpi_driver_data(device);
if (ac->charger.dev)
power_supply_unregister(&ac->charger);
power_supply_unregister(ac->charger);
unregister_acpi_notifier(&ac->battery_nb);
#ifdef CONFIG_ACPI_PROCFS_POWER
......
......@@ -117,7 +117,8 @@ enum {
struct acpi_battery {
struct mutex lock;
struct mutex sysfs_lock;
struct power_supply bat;
struct power_supply *bat;
struct power_supply_desc bat_desc;
struct acpi_device *device;
struct notifier_block pm_nb;
unsigned long update_time;
......@@ -149,7 +150,7 @@ struct acpi_battery {
unsigned long flags;
};
#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
#define to_acpi_battery(x) power_supply_get_drvdata(x)
static inline int acpi_battery_present(struct acpi_battery *battery)
{
......@@ -608,40 +609,45 @@ static struct device_attribute alarm_attr = {
static int sysfs_add_battery(struct acpi_battery *battery)
{
int result;
struct power_supply_config psy_cfg = { .drv_data = battery, };
if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
battery->bat.properties = charge_battery_props;
battery->bat.num_properties =
battery->bat_desc.properties = charge_battery_props;
battery->bat_desc.num_properties =
ARRAY_SIZE(charge_battery_props);
} else {
battery->bat.properties = energy_battery_props;
battery->bat.num_properties =
battery->bat_desc.properties = energy_battery_props;
battery->bat_desc.num_properties =
ARRAY_SIZE(energy_battery_props);
}
battery->bat.name = acpi_device_bid(battery->device);
battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
battery->bat.get_property = acpi_battery_get_property;
battery->bat_desc.name = acpi_device_bid(battery->device);
battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
battery->bat_desc.get_property = acpi_battery_get_property;
result = power_supply_register_no_ws(&battery->device->dev, &battery->bat);
battery->bat = power_supply_register_no_ws(&battery->device->dev,
&battery->bat_desc, &psy_cfg);
if (result)
if (IS_ERR(battery->bat)) {
int result = PTR_ERR(battery->bat);
battery->bat = NULL;
return result;
return device_create_file(battery->bat.dev, &alarm_attr);
}
return device_create_file(&battery->bat->dev, &alarm_attr);
}
static void sysfs_remove_battery(struct acpi_battery *battery)
{
mutex_lock(&battery->sysfs_lock);
if (!battery->bat.dev) {
if (!battery->bat) {
mutex_unlock(&battery->sysfs_lock);
return;
}
device_remove_file(battery->bat.dev, &alarm_attr);
power_supply_unregister(&battery->bat);
battery->bat.dev = NULL;
device_remove_file(&battery->bat->dev, &alarm_attr);
power_supply_unregister(battery->bat);
battery->bat = NULL;
mutex_unlock(&battery->sysfs_lock);
}
......@@ -738,7 +744,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
return result;
acpi_battery_init_alarm(battery);
}
if (!battery->bat.dev) {
if (!battery->bat) {
result = sysfs_add_battery(battery);
if (result)
return result;
......@@ -764,7 +770,7 @@ static void acpi_battery_refresh(struct acpi_battery *battery)
{
int power_unit;
if (!battery->bat.dev)
if (!battery->bat)
return;
power_unit = battery->power_unit;
......@@ -1062,11 +1068,11 @@ static void acpi_battery_remove_fs(struct acpi_device *device)
static void acpi_battery_notify(struct acpi_device *device, u32 event)
{
struct acpi_battery *battery = acpi_driver_data(device);
struct device *old;
struct power_supply *old;
if (!battery)
return;
old = battery->bat.dev;
old = battery->bat;
/*
* On Acer Aspire V5-573G notifications are sometimes triggered too
* early. For example, when AC is unplugged and notification is
......@@ -1083,8 +1089,8 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event)
acpi_battery_present(battery));
acpi_notifier_call_chain(device, event, acpi_battery_present(battery));
/* acpi_battery_update could remove power_supply object */
if (old && battery->bat.dev)
power_supply_changed(&battery->bat);
if (old && battery->bat)
power_supply_changed(battery->bat);
}
static int battery_notify(struct notifier_block *nb,
......@@ -1100,7 +1106,7 @@ static int battery_notify(struct notifier_block *nb,
if (!acpi_battery_present(battery))
return 0;
if (!battery->bat.dev) {
if (battery->bat) {
result = acpi_battery_get_info(battery);
if (result)
return result;
......
......@@ -74,7 +74,8 @@ static const struct acpi_device_id sbs_device_ids[] = {
MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
struct acpi_battery {
struct power_supply bat;
struct power_supply *bat;
struct power_supply_desc bat_desc;
struct acpi_sbs *sbs;
unsigned long update_time;
char name[8];
......@@ -101,10 +102,10 @@ struct acpi_battery {
u8 have_sysfs_alarm:1;
};
#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
#define to_acpi_battery(x) power_supply_get_drvdata(x)
struct acpi_sbs {
struct power_supply charger;
struct power_supply *charger;
struct acpi_device *device;
struct acpi_smb_hc *hc;
struct mutex lock;
......@@ -115,7 +116,7 @@ struct acpi_sbs {
u8 charger_exists:1;
};
#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
#define to_acpi_sbs(x) power_supply_get_drvdata(x)
static int acpi_sbs_remove(struct acpi_device *device);
static int acpi_battery_get_state(struct acpi_battery *battery);
......@@ -303,6 +304,13 @@ static enum power_supply_property sbs_energy_battery_props[] = {
POWER_SUPPLY_PROP_MANUFACTURER,
};
static const struct power_supply_desc acpi_sbs_charger_desc = {
.name = "sbs-charger",
.type = POWER_SUPPLY_TYPE_MAINS,
.properties = sbs_ac_props,
.num_properties = ARRAY_SIZE(sbs_ac_props),
.get_property = sbs_get_ac_property,
};
/* --------------------------------------------------------------------------
Smart Battery System Management
......@@ -519,6 +527,7 @@ static int acpi_battery_read(struct acpi_battery *battery)
static int acpi_battery_add(struct acpi_sbs *sbs, int id)
{
struct acpi_battery *battery = &sbs->battery[id];
struct power_supply_config psy_cfg = { .drv_data = battery, };
int result;
battery->id = id;
......@@ -528,23 +537,27 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
return result;
sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
battery->bat.name = battery->name;
battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
battery->bat_desc.name = battery->name;
battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
if (!acpi_battery_mode(battery)) {
battery->bat.properties = sbs_charge_battery_props;
battery->bat.num_properties =
battery->bat_desc.properties = sbs_charge_battery_props;
battery->bat_desc.num_properties =
ARRAY_SIZE(sbs_charge_battery_props);
} else {
battery->bat.properties = sbs_energy_battery_props;
battery->bat.num_properties =
battery->bat_desc.properties = sbs_energy_battery_props;
battery->bat_desc.num_properties =
ARRAY_SIZE(sbs_energy_battery_props);
}
battery->bat.get_property = acpi_sbs_battery_get_property;
result = power_supply_register(&sbs->device->dev, &battery->bat);
if (result)
battery->bat_desc.get_property = acpi_sbs_battery_get_property;
battery->bat = power_supply_register(&sbs->device->dev,
&battery->bat_desc, &psy_cfg);
if (IS_ERR(battery->bat)) {
result = PTR_ERR(battery->bat);
battery->bat = NULL;
goto end;
}
result = device_create_file(battery->bat.dev, &alarm_attr);
result = device_create_file(&battery->bat->dev, &alarm_attr);
if (result)
goto end;
battery->have_sysfs_alarm = 1;
......@@ -559,28 +572,29 @@ static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
{
struct acpi_battery *battery = &sbs->battery[id];
if (battery->bat.dev) {
if (battery->bat) {
if (battery->have_sysfs_alarm)
device_remove_file(battery->bat.dev, &alarm_attr);
power_supply_unregister(&battery->bat);
device_remove_file(&battery->bat->dev, &alarm_attr);
power_supply_unregister(battery->bat);
}
}
static int acpi_charger_add(struct acpi_sbs *sbs)
{
int result;
struct power_supply_config psy_cfg = { .drv_data = sbs, };
result = acpi_ac_get_present(sbs);
if (result)
goto end;
sbs->charger_exists = 1;
sbs->charger.name = "sbs-charger";
sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
sbs->charger.properties = sbs_ac_props;
sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props);
sbs->charger.get_property = sbs_get_ac_property;
power_supply_register(&sbs->device->dev, &sbs->charger);
sbs->charger = power_supply_register(&sbs->device->dev,
&acpi_sbs_charger_desc, &psy_cfg);
if (IS_ERR(sbs->charger)) {
result = PTR_ERR(sbs->charger);
sbs->charger = NULL;
}
printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
......@@ -590,8 +604,8 @@ static int acpi_charger_add(struct acpi_sbs *sbs)
static void acpi_charger_remove(struct acpi_sbs *sbs)
{
if (sbs->charger.dev)
power_supply_unregister(&sbs->charger);
if (sbs->charger)
power_supply_unregister(sbs->charger);
}
static void acpi_sbs_callback(void *context)
......@@ -605,7 +619,7 @@ static void acpi_sbs_callback(void *context)
if (sbs->charger_exists) {
acpi_ac_get_present(sbs);
if (sbs->charger_present != saved_charger_state)
kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
kobject_uevent(&sbs->charger->dev.kobj, KOBJ_CHANGE);
}
if (sbs->manager_present) {
......@@ -617,7 +631,7 @@ static void acpi_sbs_callback(void *context)
acpi_battery_read(bat);
if (saved_battery_state == bat->present)
continue;
kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);
kobject_uevent(&bat->bat->dev.kobj, KOBJ_CHANGE);
}
}
}
......
......@@ -339,7 +339,7 @@ static int hidinput_get_battery_property(struct power_supply *psy,
enum power_supply_property prop,
union power_supply_propval *val)
{
struct hid_device *dev = container_of(psy, struct hid_device, battery);
struct hid_device *dev = power_supply_get_drvdata(psy);
int ret = 0;
__u8 *buf;
......@@ -397,26 +397,32 @@ static int hidinput_get_battery_property(struct power_supply *psy,
static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field)
{
struct power_supply *battery = &dev->battery;
int ret;
struct power_supply_desc *psy_desc = NULL;
struct power_supply_config psy_cfg = { .drv_data = dev, };
unsigned quirks;
s32 min, max;
if (field->usage->hid != HID_DC_BATTERYSTRENGTH)
return false; /* no match */
if (battery->name != NULL)
if (dev->battery != NULL)
goto out; /* already initialized? */
battery->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq);
if (battery->name == NULL)
psy_desc = kzalloc(sizeof(*psy_desc), GFP_KERNEL);
if (psy_desc == NULL)
goto out;
battery->type = POWER_SUPPLY_TYPE_BATTERY;
battery->properties = hidinput_battery_props;
battery->num_properties = ARRAY_SIZE(hidinput_battery_props);
battery->use_for_apm = 0;
battery->get_property = hidinput_get_battery_property;
psy_desc->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq);
if (psy_desc->name == NULL) {
kfree(psy_desc);
goto out;
}
psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
psy_desc->properties = hidinput_battery_props;
psy_desc->num_properties = ARRAY_SIZE(hidinput_battery_props);
psy_desc->use_for_apm = 0;
psy_desc->get_property = hidinput_get_battery_property;
quirks = find_battery_quirk(dev);
......@@ -439,27 +445,30 @@ static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
dev->battery_report_type = report_type;
dev->battery_report_id = field->report->id;
ret = power_supply_register(&dev->dev, battery);
if (ret != 0) {
hid_warn(dev, "can't register power supply: %d\n", ret);
kfree(battery->name);
battery->name = NULL;
dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg);
if (IS_ERR(dev->battery)) {
hid_warn(dev, "can't register power supply: %ld\n",
PTR_ERR(dev->battery));
kfree(psy_desc->name);
kfree(psy_desc);
dev->battery = NULL;
} else {
power_supply_powers(dev->battery, &dev->dev);
}
power_supply_powers(battery, &dev->dev);
out:
return true;
}