Commit c8192ba4 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply

Pull power supply and reset changes from Sebastian Reichel:
 - new reset driver for ZTE SoCs
 - add support for sama5d3 reset handling
 - overhaul of twl4030 charger driver
 - misc fixes and cleanups

* tag 'for-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (35 commits)
  bq2415x_charger: Allow to load and use driver even if notify device is not registered yet
  twl4030_charger: fix compile error when TWL4030_MADC not available.
  power: bq24190_charger: Fix charge type sysfs property
  power: Allow compile test of GPIO consumers if !GPIOLIB
  power: Export I2C module alias information in missing drivers
  twl4030_charger: Increase current carefully while watching voltage.
  twl4030_charger: add ac/mode to match usb/mode
  twl4030_charger: add software controlled linear charging mode.
  twl4030_charger: enable manual enable/disable of usb charging.
  twl4030_charger: allow max_current to be managed via sysfs.
  twl4030_charger: distinguish between USB current and 'AC' current
  twl4030_charger: allow fine control of charger current.
  twl4030_charger: split uA calculation into a function.
  twl4030_charger: trust phy to determine when USB power is available.
  twl4030_charger: correctly handle -EPROBE_DEFER from devm_usb_get_phy_by_node
  twl4030_charger: convert to module_platform_driver instead of ..._probe.
  twl4030_charger: use runtime_pm to keep usb phy active while charging.
  rx51-battery: Set name to rx51-battery
  MAINTAINERS: AVS is not maintained via power supply tree
  power: olpc_battery: clean up eeprom read function
  ...
parents 9c6a019c b68c3161
What: /sys/class/power_supply/twl4030_ac/max_current
/sys/class/power_supply/twl4030_usb/max_current
Description:
Read/Write limit on current which may
be drawn from the ac (Accessory Charger) or
USB port.
Value is in micro-Amps.
Value is set automatically to an appropriate
value when a cable is plugged or unplugged.
Value can the set by writing to the attribute.
The change will only persist until the next
plug event. These event are reported via udev.
What: /sys/class/power_supply/twl4030_usb/mode
Description:
Changing mode for USB port.
Writing to this can disable charging.
Possible values are:
"auto" - draw power as appropriate for detected
power source and battery status.
"off" - do not draw any power.
"continuous"
- activate mode described as "linear" in
TWL data sheets. This uses whatever
current is available and doesn't switch off
when voltage drops.
This is useful for unstable power sources
such as bicycle dynamo, but care should
be taken that battery is not over-charged.
What: /sys/class/power_supply/twl4030_ac/mode
Description:
Changing mode for 'ac' port.
Writing to this can disable charging.
Possible values are:
"auto" - draw power as appropriate for detected
power source and battery status.
"off" - do not draw any power.
...@@ -87,7 +87,7 @@ One interrupt per TC channel in a TC block: ...@@ -87,7 +87,7 @@ One interrupt per TC channel in a TC block:
RSTC Reset Controller required properties: RSTC Reset Controller required properties:
- compatible: Should be "atmel,<chip>-rstc". - compatible: Should be "atmel,<chip>-rstc".
<chip> can be "at91sam9260" or "at91sam9g45" <chip> can be "at91sam9260" or "at91sam9g45" or "sama5d3"
- reg: Should contain registers location and length - reg: Should contain registers location and length
Example: Example:
......
...@@ -8093,6 +8093,7 @@ T: git git://git.infradead.org/battery-2.6.git ...@@ -8093,6 +8093,7 @@ T: git git://git.infradead.org/battery-2.6.git
S: Maintained S: Maintained
F: include/linux/power_supply.h F: include/linux/power_supply.h
F: drivers/power/ F: drivers/power/
X: drivers/power/avs/
PNP SUPPORT PNP SUPPORT
M: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> M: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
......
...@@ -788,9 +788,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, ...@@ -788,9 +788,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
static struct regulator_consumer_supply usb1v8 = { static struct regulator_consumer_supply usb1v8 = {
.supply = "usb1v8", .supply = "usb1v8",
}; };
static struct regulator_consumer_supply usb3v1[] = { static struct regulator_consumer_supply usb3v1 = {
{ .supply = "usb3v1" }, .supply = "usb3v1",
{ .supply = "bci3v1" },
}; };
/* First add the regulators so that they can be used by transceiver */ /* First add the regulators so that they can be used by transceiver */
...@@ -818,7 +817,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, ...@@ -818,7 +817,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
return PTR_ERR(child); return PTR_ERR(child);
child = add_regulator_linked(TWL4030_REG_VUSB3V1, child = add_regulator_linked(TWL4030_REG_VUSB3V1,
&usb_fixed, usb3v1, 2, &usb_fixed, &usb3v1, 1,
features); features);
if (IS_ERR(child)) if (IS_ERR(child))
return PTR_ERR(child); return PTR_ERR(child);
...@@ -838,7 +837,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, ...@@ -838,7 +837,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) { if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) {
usb1v5.dev_name = dev_name(child); usb1v5.dev_name = dev_name(child);
usb1v8.dev_name = dev_name(child); usb1v8.dev_name = dev_name(child);
usb3v1[0].dev_name = dev_name(child); usb3v1.dev_name = dev_name(child);
} }
} }
......
...@@ -333,7 +333,7 @@ config CHARGER_LP8788 ...@@ -333,7 +333,7 @@ config CHARGER_LP8788
config CHARGER_GPIO config CHARGER_GPIO
tristate "GPIO charger" tristate "GPIO charger"
depends on GPIOLIB depends on GPIOLIB || COMPILE_TEST
help help
Say Y to include support for chargers which report their online status Say Y to include support for chargers which report their online status
through a GPIO pin. through a GPIO pin.
...@@ -391,26 +391,30 @@ config CHARGER_BQ2415X ...@@ -391,26 +391,30 @@ config CHARGER_BQ2415X
config CHARGER_BQ24190 config CHARGER_BQ24190
tristate "TI BQ24190 battery charger driver" tristate "TI BQ24190 battery charger driver"
depends on I2C && GPIOLIB depends on I2C
depends on GPIOLIB || COMPILE_TEST
help help
Say Y to enable support for the TI BQ24190 battery charger. Say Y to enable support for the TI BQ24190 battery charger.
config CHARGER_BQ24257 config CHARGER_BQ24257
tristate "TI BQ24257 battery charger driver" tristate "TI BQ24257 battery charger driver"
depends on I2C && GPIOLIB depends on I2C
depends on GPIOLIB || COMPILE_TEST
depends on REGMAP_I2C depends on REGMAP_I2C
help help
Say Y to enable support for the TI BQ24257 battery charger. Say Y to enable support for the TI BQ24257 battery charger.
config CHARGER_BQ24735 config CHARGER_BQ24735
tristate "TI BQ24735 battery charger support" tristate "TI BQ24735 battery charger support"
depends on I2C && GPIOLIB depends on I2C
depends on GPIOLIB || COMPILE_TEST
help help
Say Y to enable support for the TI BQ24735 battery charger. Say Y to enable support for the TI BQ24735 battery charger.
config CHARGER_BQ25890 config CHARGER_BQ25890
tristate "TI BQ25890 battery charger driver" tristate "TI BQ25890 battery charger driver"
depends on I2C && GPIOLIB depends on I2C
depends on GPIOLIB || COMPILE_TEST
select REGMAP_I2C select REGMAP_I2C
help help
Say Y to enable support for the TI BQ25890 battery charger. Say Y to enable support for the TI BQ25890 battery charger.
...@@ -462,7 +466,8 @@ config BATTERY_RT5033 ...@@ -462,7 +466,8 @@ config BATTERY_RT5033
config CHARGER_RT9455 config CHARGER_RT9455
tristate "Richtek RT9455 battery charger driver" tristate "Richtek RT9455 battery charger driver"
depends on I2C && GPIOLIB depends on I2C
depends on GPIOLIB || COMPILE_TEST
select REGMAP_I2C select REGMAP_I2C
help help
Say Y to enable support for Richtek RT9455 battery charger. Say Y to enable support for Richtek RT9455 battery charger.
......
...@@ -170,7 +170,7 @@ struct bq2415x_device { ...@@ -170,7 +170,7 @@ struct bq2415x_device {
struct power_supply *charger; struct power_supply *charger;
struct power_supply_desc charger_desc; struct power_supply_desc charger_desc;
struct delayed_work work; struct delayed_work work;
struct power_supply *notify_psy; struct device_node *notify_node;
struct notifier_block nb; struct notifier_block nb;
enum bq2415x_mode reported_mode;/* mode reported by hook function */ enum bq2415x_mode reported_mode;/* mode reported by hook function */
enum bq2415x_mode mode; /* currently configured mode */ enum bq2415x_mode mode; /* currently configured mode */
...@@ -792,22 +792,47 @@ static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode) ...@@ -792,22 +792,47 @@ static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode)
} }
static bool bq2415x_update_reported_mode(struct bq2415x_device *bq, int mA)
{
enum bq2415x_mode mode;
if (mA == 0)
mode = BQ2415X_MODE_OFF;
else if (mA < 500)
mode = BQ2415X_MODE_NONE;
else if (mA < 1800)
mode = BQ2415X_MODE_HOST_CHARGER;
else
mode = BQ2415X_MODE_DEDICATED_CHARGER;
if (bq->reported_mode == mode)
return false;
bq->reported_mode = mode;
return true;
}
static int bq2415x_notifier_call(struct notifier_block *nb, static int bq2415x_notifier_call(struct notifier_block *nb,
unsigned long val, void *v) unsigned long val, void *v)
{ {
struct bq2415x_device *bq = struct bq2415x_device *bq =
container_of(nb, struct bq2415x_device, nb); container_of(nb, struct bq2415x_device, nb);
struct power_supply *psy = v; struct power_supply *psy = v;
enum bq2415x_mode mode;
union power_supply_propval prop; union power_supply_propval prop;
int ret; int ret;
int mA;
if (val != PSY_EVENT_PROP_CHANGED) if (val != PSY_EVENT_PROP_CHANGED)
return NOTIFY_OK; return NOTIFY_OK;
if (psy != bq->notify_psy) /* Ignore event if it was not send by notify_node/notify_device */
if (bq->notify_node) {
if (!psy->dev.parent ||
psy->dev.parent->of_node != bq->notify_node)
return NOTIFY_OK; return NOTIFY_OK;
} else if (bq->init_data.notify_device) {
if (strcmp(psy->desc->name, bq->init_data.notify_device) != 0)
return NOTIFY_OK;
}
dev_dbg(bq->dev, "notifier call was called\n"); dev_dbg(bq->dev, "notifier call was called\n");
...@@ -816,22 +841,9 @@ static int bq2415x_notifier_call(struct notifier_block *nb, ...@@ -816,22 +841,9 @@ static int bq2415x_notifier_call(struct notifier_block *nb,
if (ret != 0) if (ret != 0)
return NOTIFY_OK; return NOTIFY_OK;
mA = prop.intval; if (!bq2415x_update_reported_mode(bq, prop.intval))
if (mA == 0)
mode = BQ2415X_MODE_OFF;
else if (mA < 500)
mode = BQ2415X_MODE_NONE;
else if (mA < 1800)
mode = BQ2415X_MODE_HOST_CHARGER;
else
mode = BQ2415X_MODE_DEDICATED_CHARGER;
if (bq->reported_mode == mode)
return NOTIFY_OK; return NOTIFY_OK;
bq->reported_mode = mode;
/* if automode is not enabled do not tell about reported_mode */ /* if automode is not enabled do not tell about reported_mode */
if (bq->automode < 1) if (bq->automode < 1)
return NOTIFY_OK; return NOTIFY_OK;
...@@ -1536,6 +1548,8 @@ static int bq2415x_probe(struct i2c_client *client, ...@@ -1536,6 +1548,8 @@ static int bq2415x_probe(struct i2c_client *client,
struct device_node *np = client->dev.of_node; struct device_node *np = client->dev.of_node;
struct bq2415x_platform_data *pdata = client->dev.platform_data; struct bq2415x_platform_data *pdata = client->dev.platform_data;
const struct acpi_device_id *acpi_id = NULL; const struct acpi_device_id *acpi_id = NULL;
struct power_supply *notify_psy = NULL;
union power_supply_propval prop;
if (!np && !pdata && !ACPI_HANDLE(&client->dev)) { if (!np && !pdata && !ACPI_HANDLE(&client->dev)) {
dev_err(&client->dev, "Neither devicetree, nor platform data, nor ACPI support\n"); dev_err(&client->dev, "Neither devicetree, nor platform data, nor ACPI support\n");
...@@ -1569,25 +1583,6 @@ static int bq2415x_probe(struct i2c_client *client, ...@@ -1569,25 +1583,6 @@ static int bq2415x_probe(struct i2c_client *client,
goto error_2; goto error_2;
} }
if (np) {
bq->notify_psy = power_supply_get_by_phandle(np,
"ti,usb-charger-detection");
if (IS_ERR(bq->notify_psy)) {
dev_info(&client->dev,
"no 'ti,usb-charger-detection' property (err=%ld)\n",
PTR_ERR(bq->notify_psy));
bq->notify_psy = NULL;
} else if (!bq->notify_psy) {
ret = -EPROBE_DEFER;
goto error_2;
}
} else if (pdata && pdata->notify_device) {
bq->notify_psy = power_supply_get_by_name(pdata->notify_device);
} else {
bq->notify_psy = NULL;
}
i2c_set_clientdata(client, bq); i2c_set_clientdata(client, bq);
bq->id = num; bq->id = num;
...@@ -1607,32 +1602,35 @@ static int bq2415x_probe(struct i2c_client *client, ...@@ -1607,32 +1602,35 @@ static int bq2415x_probe(struct i2c_client *client,
"ti,current-limit", "ti,current-limit",
&bq->init_data.current_limit); &bq->init_data.current_limit);
if (ret) if (ret)
goto error_3; goto error_2;
ret = device_property_read_u32(bq->dev, ret = device_property_read_u32(bq->dev,
"ti,weak-battery-voltage", "ti,weak-battery-voltage",
&bq->init_data.weak_battery_voltage); &bq->init_data.weak_battery_voltage);
if (ret) if (ret)
goto error_3; goto error_2;
ret = device_property_read_u32(bq->dev, ret = device_property_read_u32(bq->dev,
"ti,battery-regulation-voltage", "ti,battery-regulation-voltage",
&bq->init_data.battery_regulation_voltage); &bq->init_data.battery_regulation_voltage);
if (ret) if (ret)
goto error_3; goto error_2;
ret = device_property_read_u32(bq->dev, ret = device_property_read_u32(bq->dev,
"ti,charge-current", "ti,charge-current",
&bq->init_data.charge_current); &bq->init_data.charge_current);
if (ret) if (ret)
goto error_3; goto error_2;
ret = device_property_read_u32(bq->dev, ret = device_property_read_u32(bq->dev,
"ti,termination-current", "ti,termination-current",
&bq->init_data.termination_current); &bq->init_data.termination_current);
if (ret) if (ret)
goto error_3; goto error_2;
ret = device_property_read_u32(bq->dev, ret = device_property_read_u32(bq->dev,
"ti,resistor-sense", "ti,resistor-sense",
&bq->init_data.resistor_sense); &bq->init_data.resistor_sense);
if (ret) if (ret)
goto error_3; goto error_2;
if (np)
bq->notify_node = of_parse_phandle(np,
"ti,usb-charger-detection", 0);
} else { } else {
memcpy(&bq->init_data, pdata, sizeof(bq->init_data)); memcpy(&bq->init_data, pdata, sizeof(bq->init_data));
} }
...@@ -1642,56 +1640,72 @@ static int bq2415x_probe(struct i2c_client *client, ...@@ -1642,56 +1640,72 @@ static int bq2415x_probe(struct i2c_client *client,
ret = bq2415x_power_supply_init(bq); ret = bq2415x_power_supply_init(bq);
if (ret) { if (ret) {
dev_err(bq->dev, "failed to register power supply: %d\n", ret); dev_err(bq->dev, "failed to register power supply: %d\n", ret);
goto error_3; goto error_2;
} }
ret = bq2415x_sysfs_init(bq); ret = bq2415x_sysfs_init(bq);
if (ret) { if (ret) {
dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret); dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret);
goto error_4; goto error_3;
} }
ret = bq2415x_set_defaults(bq); ret = bq2415x_set_defaults(bq);
if (ret) { if (ret) {
dev_err(bq->dev, "failed to set default values: %d\n", ret); dev_err(bq->dev, "failed to set default values: %d\n", ret);
goto error_5; goto error_4;
} }
if (bq->notify_psy) { if (bq->notify_node || bq->init_data.notify_device) {
bq->nb.notifier_call = bq2415x_notifier_call; bq->nb.notifier_call = bq2415x_notifier_call;
ret = power_supply_reg_notifier(&bq->nb); ret = power_supply_reg_notifier(&bq->nb);
if (ret) { if (ret) {
dev_err(bq->dev, "failed to reg notifier: %d\n", ret); dev_err(bq->dev, "failed to reg notifier: %d\n", ret);
goto error_6; goto error_4;
} }
/* Query for initial reported_mode and set it */
bq2415x_notifier_call(&bq->nb, PSY_EVENT_PROP_CHANGED,
bq->notify_psy);
bq2415x_set_mode(bq, bq->reported_mode);
bq->automode = 1; bq->automode = 1;
dev_info(bq->dev, "automode enabled\n"); dev_info(bq->dev, "automode supported, waiting for events\n");
} else { } else {
bq->automode = -1; bq->automode = -1;
dev_info(bq->dev, "automode not supported\n"); dev_info(bq->dev, "automode not supported\n");
} }
/* Query for initial reported_mode and set it */
if (bq->nb.notifier_call) {
if (np) {
notify_psy = power_supply_get_by_phandle(np,
"ti,usb-charger-detection");
if (IS_ERR(notify_psy))
notify_psy = NULL;
} else if (bq->init_data.notify_device) {
notify_psy = power_supply_get_by_name(
bq->init_data.notify_device);
}
}
if (notify_psy) {
ret = power_supply_get_property(notify_psy,
POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
power_supply_put(notify_psy);
if (ret == 0) {
bq2415x_update_reported_mode(bq, prop.intval);
bq2415x_set_mode(bq, bq->reported_mode);
}
}
INIT_DELAYED_WORK(&bq->work, bq2415x_timer_work); INIT_DELAYED_WORK(&bq->work, bq2415x_timer_work);
bq2415x_set_autotimer(bq, 1); bq2415x_set_autotimer(bq, 1);
dev_info(bq->dev, "driver registered\n"); dev_info(bq->dev, "driver registered\n");
return 0; return 0;
error_6:
error_5:
bq2415x_sysfs_exit(bq);
error_4: error_4:
bq2415x_power_supply_exit(bq); bq2415x_sysfs_exit(bq);
error_3: error_3:
if (bq->notify_psy) bq2415x_power_supply_exit(bq);
power_supply_put(bq->notify_psy);
error_2: error_2:
if (bq->notify_node)
of_node_put(bq->notify_node);
kfree(name); kfree(name);
error_1: error_1:
mutex_lock(&bq2415x_id_mutex); mutex_lock(&bq2415x_id_mutex);
...@@ -1707,10 +1721,11 @@ static int bq2415x_remove(struct i2c_client *client) ...@@ -1707,10 +1721,11 @@ static int bq2415x_remove(struct i2c_client *client)
{ {
struct bq2415x_device *bq = i2c_get_clientdata(client); struct bq2415x_device *bq = i2c_get_clientdata(client);
if (bq->notify_psy) { if (bq->nb.notifier_call)
power_supply_unreg_notifier(&bq->nb); power_supply_unreg_notifier(&bq->nb);
power_supply_put(bq->notify_psy);
} if (bq->notify_node)
of_node_put(bq->notify_node);
bq2415x_sysfs_exit(bq); bq2415x_sysfs_exit(bq);
bq2415x_power_supply_exit(bq); bq2415x_power_supply_exit(bq);
......
...@@ -902,7 +902,7 @@ static int bq24190_charger_property_is_writeable(struct power_supply *psy, ...@@ -902,7 +902,7 @@ static int bq24190_charger_property_is_writeable(struct power_supply *psy,
} }
static enum power_supply_property bq24190_charger_properties[] = { static enum power_supply_property bq24190_charger_properties[] = {
POWER_SUPPLY_PROP_TYPE, POWER_SUPPLY_PROP_CHARGE_TYPE,
POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
...@@ -1515,6 +1515,7 @@ static const struct i2c_device_id bq24190_i2c_ids[] = { ...@@ -1515,6 +1515,7 @@ static const struct i2c_device_id bq24190_i2c_ids[] = {
{ "bq24190", BQ24190_REG_VPRS_PN_24190 }, { "bq24190", BQ24190_REG_VPRS_PN_24190 },
{ }, { },
}; };
MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id bq24190_of_match[] = { static const struct of_device_id bq24190_of_match[] = {
...@@ -1534,7 +1535,6 @@ static struct i2c_driver bq24190_driver = { ...@@ -1534,7 +1535,6 @@ static struct i2c_driver bq24190_driver = {
.id_table = bq24190_i2c_ids, .id_table = bq24190_i2c_ids,
.driver = { .driver = {
.name = "bq24190-charger", .name = "bq24190-charger",
.owner = THIS_MODULE,
.pm = &bq24190_pm_ops, .pm = &bq24190_pm_ops,
.of_match_table = of_match_ptr(bq24190_of_match), .of_match_table = of_match_ptr(bq24190_of_match),
}, },
......
...@@ -267,7 +267,8 @@ static int bq24735_charger_probe(struct i2c_client *client, ...@@ -267,7 +267,8 @@ static int bq24735_charger_probe(struct i2c_client *client,
name = (char *)charger->pdata->name; name = (char *)charger->pdata->name;
if (!name) { if (!name) {
name = kasprintf(GFP_KERNEL, "bq24735@%s", name = devm_kasprintf(&client->dev, GFP_KERNEL,
"bq24735@%s",
dev_name(&client->dev)); dev_name(&client->dev));
if (!name) { if (!name) {
dev_err(&client->dev, "Failed to alloc device name\n"); dev_err(&client->dev, "Failed to alloc device name\n");
...@@ -296,23 +297,21 @@ static int bq24735_charger_probe(struct i2c_client *client, ...@@ -296,23 +297,21 @@ static int bq24735_charger_probe(struct i2c_client *client,
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "Failed to read manufacturer id : %d\n", dev_err(&client->dev, "Failed to read manufacturer id : %d\n",
ret); ret);
goto err_free_name; return ret;
} else if (ret != 0x0040) { } else if (ret != 0x0040) {
dev_err(&client->dev, dev_err(&client->dev,
"manufacturer id mismatch. 0x0040 != 0x%04x\n", ret); "manufacturer id mismatch. 0x0040 != 0x%04x\n", ret);
ret = -ENODEV; return -ENODEV;
goto err_free_name;
} }
ret = bq24735_read_word(client, BQ24735_DEVICE_ID); ret = bq24735_read_word(client, BQ24735_DEVICE_ID);
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "Failed to read device id : %d\n", ret); dev_err(&client->dev, "Failed to read device id : %d\n", ret);
goto err_free_name; return ret;
} else if (ret != 0x000B) { } else if (ret != 0x000B) {
dev_err(&client->dev, dev_err(&client->dev,
"device id mismatch. 0x000b != 0x%04x\n", ret); "device id mismatch. 0x000b != 0x%04x\n", ret);
ret = -ENODEV; return -ENODEV;
goto err_free_name;
} }
if (gpio_is_valid(charger->pdata->status_gpio)) { if (gpio_is_valid(charger->pdata->status_gpio)) {
...@@ -331,7 +330,7 @@ static int bq24735_charger_probe(struct i2c_client *client, ...@@ -331,7 +330,7 @@ static int bq24735_charger_probe(struct i2c_client *client,
ret = bq24735_config_charger(charger); ret = bq24735_config_charger(charger);
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "failed in configuring charger"); dev_err(&client->dev, "failed in configuring charger");
goto err_free_name; return ret;
} }
/* check for AC adapter presence */ /* check for AC adapter presence */
...@@ -339,17 +338,17 @@ static int bq24735_charger_probe(struct i2c_client *client, ...@@ -339,17 +338,17 @@ static int bq24735_charger_probe(struct i2c_client *client,
ret = bq24735_enable_charging(charger); ret = bq24735_enable_charging(charger);
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "Failed to enable charging\n"); dev_err(&client->dev, "Failed to enable charging\n");
goto err_free_name; return ret;
} }
} }
charger->charger = power_supply_register(&client->dev, supply_desc, charger->charger = devm_power_supply_register(&client->dev, supply_desc,
&psy_cfg); &psy_cfg);
if (IS_ERR(charger->charger)) { if (IS_ERR(charger->charger)) {
ret = PTR_ERR(charger->charger); ret = PTR_ERR(charger->charger);
dev_err(&client->dev, "Failed to register power supply: %d\n", dev_err(&client->dev, "Failed to register power supply: %d\n",
ret); ret);
goto err_free_name; return ret;
} }
if (client->irq) { if (client->irq) {
...@@ -364,33 +363,10 @@ static int bq24735_charger_probe(struct i2c_client *client, ...@@ -364,33 +363,10 @@ static int bq24735_charger_probe(struct i2c_client *client,
dev_err(&client->dev, dev_err(&client->dev,
"Unable to register IRQ %d err %d\n", "Unable to register IRQ %d err %d\n",
client->irq, ret); client->irq, ret);
goto err_unregister_supply; return ret;
} }
} }
return 0;
err_unregister_supply:
power_supply_unregister(charger->charger);
err_free_name:
if (name != charger->pdata->name)
kfree(name);
return ret;
}
static int bq24735_charger_remove(struct i2c_client *client)
{
struct bq24735 *charger = i2c_get_clientdata(client);
if (charger->client->irq)
devm_free_irq(&charger->client->dev, charger->client->irq,
&charger->charger);
power_supply_unregister(charger->charger);
if (charger->charger_desc.name != charger->pdata->name)
kfree(charger->charger_desc.name);
return 0; return 0;
} }
...@@ -409,11 +385,9 @@ MODULE_DEVICE_TABLE(of, bq24735_match_ids); ...@@ -409,11 +385,9 @@ MODULE_DEVICE_TABLE(of, bq24735_match_ids);
static struct i2c_driver bq24735_charger_driver = { static struct i2c_driver bq24735_charger_driver = {
.driver = { .driver = {
.name = "bq24735-charger", .name = "bq24735-charger",
.owner = THIS_MODULE,
.of_match_table = bq24735_match_ids, .of_match_table = bq24735_match_ids,
}, },
.probe = bq24735_charger_probe, .probe = bq24735_charger_probe,
.remove = bq24735_charger_remove,
.id_table = bq24735_charger_id, .id_table = bq24735_charger_id,
}; };
......
...@@ -41,6 +41,8 @@ ...@@ -41,6 +41,8 @@
#define DRIVER_VERSION "1.2.0" #define DRIVER_VERSION "1.2.0"
#define BQ27XXX_MANUFACTURER "Texas Instruments"
#define BQ27x00_REG_TEMP 0x06 #define BQ27x00_REG_TEMP 0x06
#define BQ27x00_REG_VOLT 0x08 #define BQ27x00_REG_VOLT 0x08
#define BQ27x00_REG_AI 0x14 #define BQ27x00_REG_AI 0x14
...@@ -142,6 +144,7 @@ static enum power_supply_property bq27x00_battery_props[] = { ...@@ -142,6 +144,7 @@ static enum power_supply_property bq27x00_battery_props[] = {
POWER_SUPPLY_PROP_ENERGY_NOW, POWER_SUPPLY_PROP_ENERGY_NOW,
POWER_SUPPLY_PROP_POWER_AVG, POWER_SUPPLY_PROP_POWER_AVG,
POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_MANUFACTURER,
}; };
static enum power_supply_property bq27425_battery_props[] = { static enum power_supply_property bq27425_battery_props[] = {
...@@ -156,6 +159,7 @@ static enum power_supply_property bq27425_battery_props[] = { ...@@ -156,6 +159,7 @@ static enum power_supply_property bq27425_battery_props[] = {
POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_NOW,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_MANUFACTURER,
}; };
static enum power_supply_property bq27742_battery_props[] = { static enum power_supply_property bq27742_battery_props[] = {
...@@ -174,6 +178,7 @@ static enum power_supply_property bq27742_battery_props[] = { ...@@ -174,6 +178,7 @@ static enum power_supply_property bq27742_battery_props[] = {
POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_CYCLE_COUNT,
POWER_SUPPLY_PROP_POWER_AVG, POWER_SUPPLY_PROP_POWER_AVG,
POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_MANUFACTURER,
}; };
static enum power_supply_property bq27510_battery_props[] = { static enum power_supply_property bq27510_battery_props[] = {
...@@ -192,12 +197,13 @@ static enum power_supply_property bq27510_battery_props[] = { ...@@ -192,12 +197,13 @@ static enum power_supply_property bq27510_battery_props[] = {
POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_CYCLE_COUNT,
POWER_SUPPLY_PROP_POWER_AVG, POWER_SUPPLY_PROP_POWER_AVG,
POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_MANUFACTURER,
}; };
static unsigned int poll_interval = 360; static unsigned int poll_interval = 360;
module_param(poll_interval, uint, 0644); module_param(poll_interval, uint, 0644);
MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \ MODULE_PARM_DESC(poll_interval,
"0 disables polling"); "battery poll interval in seconds - 0 disables polling");
/* /*
* Common code for BQ27x00 devices * Common code for BQ27x00 devices
...@@ -313,8 +319,9 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di) ...@@ -313,8 +319,9 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
ilmd = bq27x00_read(di, BQ27510_REG_DCAP, false); ilmd = bq27x00_read(di, BQ27510_REG_DCAP, false);
else else
ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false); ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false);
} else } else {
ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true); ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
}
if (ilmd < 0) { if (ilmd < 0) {
dev_dbg(di->dev, "error reading initial last measured discharge\n"); dev_dbg(di->dev, "error reading initial last measured discharge\n");
...@@ -445,7 +452,7 @@ static int bq27x00_battery_read_health(struct bq27x00_device_info *di) ...@@ -445,7 +452,7 @@ static int bq27x00_battery_read_health(struct bq27x00_device_info *di)
return tval; return tval;
} }
if ((di->chip == BQ27500)) { if (di->chip == BQ27500) {
if (tval & BQ27500_FLAG_SOCF) if (tval & BQ27500_FLAG_SOCF)
tval = POWER_SUPPLY_HEALTH_DEAD; tval = POWER_SUPPLY_HEALTH_DEAD;
else if (tval & BQ27500_FLAG_OTC) else if (tval & BQ27500_FLAG_OTC)
...@@ -749,6 +756,9 @@ static int bq27x00_battery_get_property(struct power_supply *psy, ...@@ -749,6 +756,9 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_HEALTH: case POWER_SUPPLY_PROP_HEALTH:
ret = bq27x00_simple_value(di->cache.health, val); ret = bq27x00_simple_value(di->cache.health, val);
break; break;
case POWER_SUPPLY_PROP_MANUFACTURER:
val->strval = BQ27XXX_MANUFACTURER;
break;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -827,7 +837,6 @@ static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di) ...@@ -827,7 +837,6 @@ static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
mutex_destroy(&di->lock); mutex_destroy(&di->lock);
} }
/* i2c specific code */ /* i2c specific code */
#ifdef CONFIG_BATTERY_BQ27X00_I2C #ifdef CONFIG_BATTERY_BQ27X00_I2C
...@@ -888,14 +897,12 @@ static int bq27x00_battery_probe(struct i2c_client *client, ...@@ -888,14 +897,12 @@ static int bq27x00_battery_probe(struct i2c_client *client,
name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num); name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num);
if (!name) { if (!name) {
dev_err(&client->dev, "failed to allocate device name\n");
retval = -ENOMEM; retval = -ENOMEM;
goto batt_failed; goto batt_failed;
} }
di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL); di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
if (!di) { if (!di) {
dev_err(&client->dev, "failed to allocate device info data\n");
retval = -ENOMEM; retval = -ENOMEM;
goto batt_failed; goto batt_failed;
} }
...@@ -956,8 +963,9 @@ static struct i2c_driver bq27x00_battery_driver = { ...@@ -956,8 +963,9 @@ static struct i2c_driver bq27x00_battery_driver = {
static inline int bq27x00_battery_i2c_init(void) static inline int bq27x00_battery_i2c_init(void)
{ {
int ret = i2c_add_driver(&bq27x00_battery_driver); int ret = i2c_add_driver(&bq27x00_battery_driver);
if (ret) if (ret)
printk(KERN_ERR "Unable to register BQ27x00 i2c driver\n"); pr_err("Unable to register BQ27x00 i2c driver\n");
return ret; return ret;
} }
...@@ -1028,10 +1036,8 @@ static int bq27000_battery_probe(struct platform_device *pdev) ...@@ -1028,10 +1036,8 @@ static int bq27000_battery_probe(struct platform_device *pdev)
} }
di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
if (!di) { if (!di)
dev_err(&pdev->dev, "failed to allocate device info data\n");
return -ENOMEM; return -ENOMEM;
}
platform_set_drvdata(pdev, di); platform_set_drvdata(pdev, di);
...@@ -1064,8 +1070,9 @@ static struct platform_driver bq27000_battery_driver = { ...@@ -1064,8 +1070,9 @@ static struct platform_driver bq27000_battery_driver = {
static inline int bq27x00_battery_platform_init(void) static inline int bq27x00_battery_platform_init(void)
{ {
int ret = platform_driver_register(&bq27000_battery_driver); int ret = platform_driver_register(&bq27000_battery_driver);
if (ret) if (ret)
printk(KERN_ERR "Unable to register BQ27000 platform driver\n"); pr_err("Unable to register BQ27000 platform driver\n");
return ret; return ret;
} }
......
...@@ -637,10 +637,6 @@ static ssize_t ds2780_read_param_eeprom_bin(struct file *filp, ...@@ -637,10 +637,6 @@ static ssize_t ds2780_read_param_eeprom_bin(struct file *filp,
struct power_supply *psy = to_power_supply(dev); struct power_supply *psy = to_power_supply(dev);
struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
count = min_t(loff_t, count,
DS2780_EEPROM_BLOCK1_END -
DS2780_EEPROM_BLOCK1_START + 1 - off);
return ds2780_read_block(dev_info, buf, return ds2780_read_block(dev_info, buf,
DS2780_EEPROM_BLOCK1_START + off, count); DS2780_EEPROM_BLOCK1_START + off, count);
} }
...@@ -655,10 +651,6 @@ static ssize_t ds2780_write_param_eeprom_bin(struct file *filp, ...@@ -655,10 +651,6 @@ static ssize_t ds2780_write_param_eeprom_bin(struct file *filp,
struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
int ret; int ret;
count = min_t(loff_t, count,
DS2780_EEPROM_BLOCK1_END -
DS2780_EEPROM_BLOCK1_START + 1 - off);
ret = ds2780_write(dev_info, buf, ret = ds2780_write(dev_info, buf,
DS2780_EEPROM_BLOCK1_START + off, count); DS2780_EEPROM_BLOCK1_START + off, count);
if (ret < 0) if (ret < 0)
...@@ -676,7 +668,7 @@ static struct bin_attribute ds2780_param_eeprom_bin_attr = { ...@@ -676,7 +668,7 @@ static struct bin_attribute ds2780_param_eeprom_bin_attr = {
.name = "param_eeprom", .name = "param_eeprom",
.mode = S_IRUGO | S_IWUSR, .mode = S_IRUGO | S_IWUSR,
}, },
.size = DS2780_EEPROM_BLOCK1_END - DS2780_EEPROM_BLOCK1_START + 1, .size = DS2780_PARAM_EEPROM_SIZE,
.read = ds2780_read_param_eeprom_bin, .read = ds2780_read_param_eeprom_bin,
.write = ds2780_write_param_eeprom_bin, .write = ds2780_write_param_eeprom_bin,
}; };
...@@ -690,10 +682,6 @@ static ssize_t ds2780_read_user_eeprom_bin(struct file *filp, ...@@ -690,10 +682,6 @@ static ssize_t ds2780_read_user_eeprom_bin(struct file *filp,
struct power_supply *psy = to_power_supply(dev); struct power_supply *psy = to_power_supply(dev);
struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
count = min_t(loff_t, count,
DS2780_EEPROM_BLOCK0_END -
DS2780_EEPROM_BLOCK0_START + 1 - off);
return ds2780_read_block(dev_info, buf, return ds2780_read_block(dev_info, buf,
DS2780_EEPROM_BLOCK0_START + off, count); DS2780_EEPROM_BLOCK0_START + off, count);
} }
...@@ -708,10 +696,6 @@ static ssize_t ds2780_write_user_eeprom_bin(struct file *filp, ...@@ -708,10 +696,6 @@ static ssize_t ds2780_write_user_eeprom_bin(struct file *filp,
struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
int ret; int ret;
count = min_t(loff_t, count,
DS2780_EEPROM_BLOCK0_END -
DS2780_EEPROM_BLOCK0_START + 1 - off);
ret = ds2780_write(dev_info, buf, ret = ds2780_write(dev_info, buf,
DS2780_EEPROM_BLOCK0_START + off, count); DS2780_EEPROM_BLOCK0_START + off, count);
if (ret < 0) if (ret < 0)
...@@ -729,7 +713,7 @@ static struct bin_attribute ds2780_user_eeprom_bin_attr = { ...@@ -729,7 +713,7 @@ static struct bin_attribute ds2780_user_eeprom_bin_attr = {
.name = "user_eeprom", .name = "user_eeprom",
.mode = S_IRUGO | S_IWUSR, .mode = S_IRUGO | S_IWUSR,
}, },
.size = DS2780_EEPROM_BLOCK0_END - DS2780_EEPROM_BLOCK0_START + 1, .size = DS2780_USER_EEPROM_SIZE,
.read = ds2780_read_user_eeprom_bin, .read = ds2780_read_user_eeprom_bin,
.write = ds2780_write_user_eeprom_bin, .write = ds2780_write_user_eeprom_bin,
}; };
......
...@@ -639,8 +639,6 @@ static ssize_t ds2781_read_param_eeprom_bin(struct file *filp, ...@@ -639,8 +639,6 @@ static ssize_t ds2781_read_param_eeprom_bin(struct file *filp,
struct power_supply *psy = to_power_supply(dev); struct power_supply *psy = to_power_supply(dev);
struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); struct ds2781_device_info *dev_info = to_ds2781_device_info(psy);
count = min_t(loff_t, count, DS2781_PARAM_EEPROM_SIZE - off);
return ds2781_read_block(dev_info, buf, return ds2781_read_block(dev_info, buf,
DS2781_EEPROM_BLOCK1_START + off, count); DS2781_EEPROM_BLOCK1_START + off, count);
} }
...@@ -655,8 +653,6 @@ static ssize_t ds2781_write_param_eeprom_bin(struct file *filp, ...@@ -655,8 +653,6 @@ static ssize_t ds2781_write_param_eeprom_bin(struct file *filp,
struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); struct ds2781_device_info *dev_info = to_ds2781_device_info(psy);
int ret; int ret;
count = min_t(loff_t, count, DS2781_PARAM_EEPROM_SIZE - off);
ret = ds2781_write(dev_info, buf, ret = ds2781_write(dev_info, buf,
DS2781_EEPROM_BLOCK1_START + off, count); DS2781_EEPROM_BLOCK1_START + off, count);
if (ret < 0) if (ret < 0)
...@@ -688,8 +684,6 @@ static ssize_t ds2781_read_user_eeprom_bin(struct file *filp, ...@@ -688,8 +684,6 @@ static ssize_t ds2781_read_user_eeprom_bin(struct file *filp,
struct power_supply *psy = to_power_supply(dev); struct power_supply *psy = to_power_supply(dev);
struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); struct ds2781_device_info *dev_info = to_ds2781_device_info(psy);
count = min_t(loff_t, count, DS2781_USER_EEPROM_SIZE - off);
return ds2781_read_block(dev_info, buf, return ds2781_read_block(dev_info, buf,
DS2781_EEPROM_BLOCK0_START + off, count); DS2781_EEPROM_BLOCK0_START + off, count);
...@@ -705,8 +699,6 @@ static ssize_t ds2781_write_user_eeprom_bin(struct file *filp, ...@@ -705,8 +699,6 @@ static ssize_t ds2781_write_user_eeprom_bin(struct file *filp,
struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); struct ds2781_device_info *dev_info = to_ds2781_device_info(psy);
int ret; int ret;
count = min_t(loff_t, count, DS2781_USER_EEPROM_SIZE - off);
ret = ds2781_write(dev_info, buf, ret = ds2781_write(dev_info, buf,
DS2781_EEPROM_BLOCK0_START + off, count); DS2781_EEPROM_BLOCK0_START + off, count);
if (ret < 0) if (ret < 0)
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/swab.h> #include <linux/swab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/idr.h>
#include <linux/power_supply.h> #include <linux/power_supply.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -63,15 +62,11 @@ struct ltc294x_info { ...@@ -63,15 +62,11 @@ struct ltc294x_info {
struct power_supply_desc supply_desc; /* Supply description */ struct power_supply_desc supply_desc; /* Supply description */
struct delayed_work work; /* Work scheduler */ struct delayed_work work; /* Work scheduler */
int num_regs; /* Number of registers (chip type) */ int num_regs; /* Number of registers (chip type) */
int id; /* Identifier of ltc294x chip */
int charge; /* Last charge register content */ int charge; /* Last charge register content */
int r_sense; /* mOhm */ int r_sense; /* mOhm */
int Qlsb; /* nAh */ int Qlsb; /* nAh */
}; };
static DEFINE_IDR(ltc294x_id);
static DEFINE_MUTEX(ltc294x_lock);
static inline int convert_bin_to_uAh( static inline int convert_bin_to_uAh(
const struct ltc294x_info *info, int Q) const struct ltc294x_info *info, int Q)
{ {
...@@ -371,10 +366,6 @@ static int ltc294x_i2c_remove(struct i2c_client *client) ...@@ -371,10 +366,6 @@ static int ltc294x_i2c_remove(struct i2c_client *client)
cancel_delayed_work(&info->work); cancel_delayed_work(&info->work);
power_supply_unregister(info->supply); power_supply_unregister(info->supply);
kfree(info->supply_desc.name);
mutex_lock(&ltc294x_lock);
idr_remove(&ltc294x_id, info->id);
mutex_unlock(&ltc294x_lock);
return 0; return 0;
} }
...@@ -384,44 +375,28 @@ static int ltc294x_i2c_probe(struct i2c_client *client, ...@@ -384,44 +375,28 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
struct power_supply_config psy_cfg = {}; struct power_supply_config psy_cfg = {};
struct ltc294x_info *info; struct ltc294x_info *info;
int ret; int ret;
int num;
u32 prescaler_exp; u32 prescaler_exp;
s32 r_sense; s32 r_sense;
struct device_node *np; struct device_node *np;
mutex_lock(&ltc294x_lock);
ret = idr_alloc(&ltc294x_id, client, 0, 0, GFP_KERNEL);
mutex_unlock(&ltc294x_lock);
if (ret < 0)
goto fail_id;
num = ret;
info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
if (info == NULL) { if (info == NULL)
ret = -ENOMEM; return -ENOMEM;
goto fail_info;
}
i2c_set_clientdata(client, info); i2c_set_clientdata(client, info);
info->num_regs = id->driver_data;
info->supply_desc.name = kasprintf(GFP_KERNEL, "%s-%d", client->name,
num);
if (!info->supply_desc.name) {
ret = -ENOMEM;
goto fail_name;
}
np = of_node_get(client->dev.of_node); np = of_node_get(client->dev.of_node);
info->num_regs = id->driver_data;
info->supply_desc.name = np->name;
/* r_sense can be negative, when sense+ is connected to the battery /* r_sense can be negative, when sense+ is connected to the battery
* instead of the sense-. This results in reversed measurements. */ * instead of the sense-. This results in reversed measurements. */
ret = of_property_read_u32(np, "lltc,resistor-sense", &r_sense); ret = of_property_read_u32(np, "lltc,resistor-sense", &r_sense);
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, dev_err(&client->dev,
"Could not find lltc,resistor-sense in devicetree\n"); "Could not find lltc,resistor-sense in devicetree\n");
goto fail_name; return ret;
} }
info->r_sense = r_sense; info->r_sense = r_sense;
...@@ -446,7 +421,6 @@ static int ltc294x_i2c_probe(struct i2c_client *client, ...@@ -446,7 +421,6 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
} }
info->client = client; info->client = client;
info->id = num;
info->supply_desc.type = POWER_SUPPLY_TYPE_BATTERY; info->supply_desc.type = POWER_SUPPLY_TYPE_BATTERY;
info->supply_desc.properties = ltc294x_properties; info->supply_desc.properties = ltc294x_properties;
if (info->num_regs >= LTC294X_REG_TEMPERATURE_LSB) if (info->num_regs >= LTC294X_REG_TEMPERATURE_LSB)
...@@ -473,31 +447,19 @@ static int ltc294x_i2c_probe(struct i2c_client *client, ...@@ -473,31 +447,19 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
ret = ltc294x_reset(info, prescaler_exp); ret = ltc294x_reset(info, prescaler_exp);
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "Communication with chip failed\n"); dev_err(&client->dev, "Communication with chip failed\n");
goto fail_comm; return ret;
} }
info->supply = power_supply_register(&client->dev, &info->supply_desc, info->supply = power_supply_register(&client->dev, &info->supply_desc,
&psy_cfg); &psy_cfg);
if (IS_ERR(info->supply)) { if (IS_ERR(info->supply)) {
dev_err(&client->dev, "failed to register ltc2941\n"); dev_err(&client->dev, "failed to register ltc2941\n");
ret = PTR_ERR(info->supply); return PTR_ERR(info->supply);
goto fail_register;
} else { } else {
schedule_delayed_work(&info->work, LTC294X_WORK_DELAY * HZ); schedule_delayed_work(&info->work, LTC294X_WORK_DELAY * HZ);
} }
return 0; return 0;
fail_register:
kfree(info->supply_desc.name);
fail_comm:
fail_name:
fail_info:
mutex_lock(&ltc294x_lock);
idr_remove(&ltc294x_id, num);
mutex_unlock(&ltc294x_lock);
fail_id:
return ret;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
......
...@@ -521,11 +521,6 @@ static ssize_t olpc_bat_eeprom_read(struct file *filp, struct kobject *kobj, ...@@ -521,11 +521,6 @@ static ssize_t olpc_bat_eeprom_read(struct file *filp, struct kobject *kobj,
int ret; int ret;
int i; int i;
if (off >= EEPROM_SIZE)
return 0;
if (off + count > EEPROM_SIZE)
count = EEPROM_SIZE - off;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
ec_byte = EEPROM_START + off + i; ec_byte = EEPROM_START + off + i;
ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &buf[i], 1); ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &buf[i], 1);
...@@ -545,7 +540,7 @@ static struct bin_attribute olpc_bat_eeprom = { ...@@ -545,7 +540,7 @@ static struct bin_attribute olpc_bat_eeprom = {
.name = "eeprom", .name = "eeprom",
.mode = S_IRUGO, .mode = S_IRUGO,
}, },
.size = 0, .size = EEPROM_SIZE,
.read = olpc_bat_eeprom_read, .read = olpc_bat_eeprom_read,
}; };
......
...@@ -1244,7 +1244,6 @@ static struct i2c_driver pm2xxx_charger_driver = { ...@@ -1244,7 +1244,6 @@ static struct i2c_driver pm2xxx_charger_driver = {
.remove = pm2xxx_wall_charger_remove, .remove = pm2xxx_wall_charger_remove,
.driver = { .driver = {
.name = "pm2xxx-wall_charger", .name = "pm2xxx-wall_charger",
.owner = THIS_MODULE,
.pm = PM2XXX_PM_OPS, .pm = PM2XXX_PM_OPS,
}, },
.id_table = pm2xxx_id, .id_table = pm2xxx_id,
......
...@@ -166,5 +166,12 @@ config POWER_RESET_RMOBILE ...@@ -166,5 +166,12 @@ config POWER_RESET_RMOBILE
help help
Reboot support for Renesas R-Mobile and SH-Mobile SoCs. Reboot support for Renesas R-Mobile and SH-Mobile SoCs.
config POWER_RESET_ZX
tristate "ZTE SoCs reset driver"
depends on ARCH_ZX || COMPILE_TEST
depends on HAS_IOMEM
help
Reboot support for ZTE SoCs.
endif endif
...@@ -19,3 +19,4 @@ obj-$(CONFIG_POWER_RESET_KEYSTONE) += keystone-reset.o ...@@ -19,3 +19,4 @@ obj-$(CONFIG_POWER_RESET_KEYSTONE) += keystone-reset.o
obj-$(CONFIG_POWER_RESET_SYSCON) += syscon-reboot.o obj-$(CONFIG_POWER_RESET_SYSCON) += syscon-reboot.o
obj-$(CONFIG_POWER_RESET_SYSCON_POWEROFF) += syscon-poweroff.o obj-$(CONFIG_POWER_RESET_SYSCON_POWEROFF) += syscon-poweroff.o
obj-$(CONFIG_POWER_RESET_RMOBILE) += rmobile-reset.o obj-$(CONFIG_POWER_RESET_RMOBILE) += rmobile-reset.o
obj-$(CONFIG_POWER_RESET_ZX) += zx-reboot.o
...@@ -123,6 +123,15 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, ...@@ -123,6 +123,15 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static int sama5d3_restart(struct notifier_block *this, unsigned long mode,
void *cmd)
{
writel(cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST),
at91_rstc_base);
return NOTIFY_DONE;
}
static void __init at91_reset_status(struct platform_device *pdev) static void __init at91_reset_status(struct platform_device *pdev)
{ {
u32 reg = readl(at91_rstc_base + AT91_RSTC_SR); u32 reg = readl(at91_rstc_base + AT91_RSTC_SR);
...@@ -155,13 +164,13 @@ static void __init at91_reset_status(struct platform_device *pdev) ...@@ -155,13 +164,13 @@ static void __init at91_reset_status(struct platform_device *pdev)
static const struct of_device_id at91_ramc_of_match[] = { static const struct of_device_id at91_ramc_of_match[] = {
{ .compatible = "atmel,at91sam9260-sdramc", }, { .compatible = "atmel,at91sam9260-sdramc", },
{ .compatible = "atmel,at91sam9g45-ddramc", }, { .compatible = "atmel,at91sam9g45-ddramc", },
{ .compatible = "atmel,sama5d3-ddramc", },
{ /* sentinel */ } { /* sentinel */ }
}; };
static const struct of_device_id at91_reset_of_match[] = { static const struct of_device_id at91_reset_of_match[] = {
{ .compatible = "atmel,at91sam9260-rstc", .data = at91sam9260_restart }, { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9260_restart },
{ .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart }, { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
{ .compatible = "atmel,sama5d3-rstc", .data = sama5d3_restart },
{ /* sentinel */ } { /* sentinel */ }
}; };
...@@ -181,6 +190,8 @@ static int at91_reset_of_probe(struct platform_device *pdev) ...@@ -181,6 +190,8 @@ static int at91_reset_of_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
if (!of_device_is_compatible(pdev->dev.of_node, "atmel,sama5d3-rstc")) {
/* we need to shutdown the ddr controller, so get ramc base */
for_each_matching_node(np, at91_ramc_of_match) { for_each_matching_node(np, at91_ramc_of_match) {
at91_ramc_base[idx] = of_iomap(np, 0); at91_ramc_base[idx] = of_iomap(np, 0);
if (!at91_ramc_base[idx]) { if (!at91_ramc_base[idx]) {
...@@ -189,6 +200,7 @@ static int at91_reset_of_probe(struct platform_device *pdev) ...@@ -189,6 +200,7 @@ static int at91_reset_of_probe(struct platform_device *pdev)
} }
idx++; idx++;
} }
}
match = of_match_node(at91_reset_of_match, pdev->dev.of_node); match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
at91_restart_nb.notifier_call = match->data; at91_restart_nb.notifier_call = match->data;
......
/*
* ZTE zx296702 SoC reset code
*
* Copyright (c) 2015 Linaro Ltd.
*
* Author: Jun Nie <jun.nie@linaro.org>
*
* 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.
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
static void __iomem *base;
static void __iomem *pcu_base;
static int zx_restart_handler(struct notifier_block *this,
unsigned long mode, void *cmd)
{
writel_relaxed(1, base + 0xb0);
writel_relaxed(1, pcu_base + 0x34);
mdelay(50);
pr_emerg("Unable to restart system\n");
return NOTIFY_DONE;
}
static struct notifier_block zx_restart_nb = {
.notifier_call = zx_restart_handler,
.priority = 128,
};
static int zx_reboot_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int err;
base = of_iomap(np, 0);
if (!base) {
WARN(1, "failed to map base address");
return -ENODEV;
}
np = of_find_compatible_node(NULL, NULL, "zte,zx296702-pcu");
pcu_base = of_iomap(np, 0);
if (!pcu_base) {
iounmap(base);
WARN(1, "failed to map pcu_base address");
return -ENODEV;
}
err = register_restart_handler(&zx_restart_nb);
if (err)
dev_err(&pdev->dev, "Register restart handler failed(err=%d)\n",
err);
return err;
}
static const struct of_device_id zx_reboot_of_match[] = {
{ .compatible = "zte,sysctrl" },
{}
};
static struct platform_driver zx_reboot_driver = {
.probe = zx_reboot_probe,
.driver = {
.name = "zx-reboot",
.of_match_table = zx_reboot_of_match,
},
};
module_platform_driver(zx_reboot_driver);
...@@ -165,7 +165,7 @@ static const struct i2c_device_id rt5033_battery_id[] = { ...@@ -165,7 +165,7 @@ static const struct i2c_device_id rt5033_battery_id[] = {
{ "rt5033-battery", }, { "rt5033-battery", },
{ } { }
}; };
MODULE_DEVICE_TABLE(platform, rt5033_battery_id); MODULE_DEVICE_TABLE(i2c, rt5033_battery_id);
static struct i2c_driver rt5033_battery_driver = { static struct i2c_driver rt5033_battery_driver = {
.driver = { .driver = {
......
...@@ -973,7 +973,6 @@ static int rt9455_irq_handler_check_irq2_register(struct rt9455_info *info, ...@@ -973,7 +973,6 @@ static int rt9455_irq_handler_check_irq2_register(struct rt9455_info *info,
if (irq2 & GET_MASK(F_CHRVPI)) { if (irq2 & GET_MASK(F_CHRVPI)) {
dev_dbg(dev, "Charger fault occurred\n"); dev_dbg(dev, "Charger fault occurred\n");
alert_userspace = true;
/* /*
* CHRVPI bit is set in 2 cases: * CHRVPI bit is set in 2 cases:
* 1. when the power source is connected to the charger. * 1. when the power source is connected to the charger.
...@@ -981,6 +980,9 @@ static int rt9455_irq_handler_check_irq2_register(struct rt9455_info *info, ...@@ -981,6 +980,9 @@ static int rt9455_irq_handler_check_irq2_register(struct rt9455_info *info,
* To identify the case, PWR_RDY bit is checked. Because * To identify the case, PWR_RDY bit is checked. Because
* PWR_RDY bit is set / cleared after CHRVPI interrupt is * PWR_RDY bit is set / cleared after CHRVPI interrupt is
* triggered, it is used delayed_work to later read PWR_RDY bit. * triggered, it is used delayed_work to later read PWR_RDY bit.
* Also, do not set to true alert_userspace, because there is no
* need to notify userspace when CHRVPI interrupt has occurred.
* Userspace will be notified after PWR_RDY bit is read.
*/ */
queue_delayed_work(system_power_efficient_wq, queue_delayed_work(system_power_efficient_wq,
&info->pwr_rdy_work, &info->pwr_rdy_work,
...@@ -1178,7 +1180,7 @@ static irqreturn_t rt9455_irq_handler_thread(int irq, void *data) ...@@ -1178,7 +1180,7 @@ static irqreturn_t rt9455_irq_handler_thread(int irq, void *data)
/* /*
* Sometimes, an interrupt occurs while rt9455_probe() function * Sometimes, an interrupt occurs while rt9455_probe() function
* is executing and power_supply_register() is not yet called. * is executing and power_supply_register() is not yet called.
* Do not call power_supply_charged() in this case. * Do not call power_supply_changed() in this case.
*/ */
if (info->charger) if (info->charger)
power_supply_changed(info->charger); power_supply_changed(info->charger);
...@@ -1478,6 +1480,11 @@ static void rt9455_pwr_rdy_work_callback(struct work_struct *work) ...@@ -1478,6 +1480,11 @@ static void rt9455_pwr_rdy_work_callback(struct work_struct *work)
RT9455_MAX_CHARGING_TIME * HZ); RT9455_MAX_CHARGING_TIME * HZ);
break; break;
} }
/*
* Notify userspace that the charger has been either connected to or
* disconnected from the power source.
*/
power_supply_changed(info->charger);
} }
static void rt9455_max_charging_time_work_callback(struct work_struct *work) static void rt9455_max_charging_time_work_callback(struct work_struct *work)
...@@ -1533,6 +1540,11 @@ static void rt9455_batt_presence_work_callback(struct work_struct *work) ...@@ -1533,6 +1540,11 @@ static void rt9455_batt_presence_work_callback(struct work_struct *work)
if (ret) if (ret)
dev_err(dev, "Failed to unmask BATAB interrupt\n"); dev_err(dev, "Failed to unmask BATAB interrupt\n");
} }
/*
* Notify userspace that the battery is now connected to the
* charger.
*/
power_supply_changed(info->charger);
} }
} }
......
...@@ -215,7 +215,7 @@ static int rx51_battery_probe(struct platform_device *pdev) ...@@ -215,7 +215,7 @@ static int rx51_battery_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, di); platform_set_drvdata(pdev, di);
di->dev = &pdev->dev; di->dev = &pdev->dev;
di->bat_desc.name = dev_name(&pdev->dev); di->bat_desc.name = "rx51-battery";
di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY; di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
di->bat_desc.properties = rx51_battery_props; di->bat_desc.properties = rx51_battery_props;
di->bat_desc.num_properties = ARRAY_SIZE(rx51_battery_props); di->bat_desc.num_properties = ARRAY_SIZE(rx51_battery_props);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment