From b7e16ec6e3d2ea0b62cf93a0e849db55f403a871 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 6 Nov 2015 16:48:46 +0100 Subject: power: bq2415x_charger: Delete unnecessary checks before the function call "of_node_put" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The of_node_put() function tests whether its argument is NULL and then returns immediately. Thus the test around the calls is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Pali Rohár Signed-off-by: Sebastian Reichel diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c index 4afd768..27e8953 100644 --- a/drivers/power/bq2415x_charger.c +++ b/drivers/power/bq2415x_charger.c @@ -1704,7 +1704,7 @@ error_4: error_3: bq2415x_power_supply_exit(bq); error_2: - if (bq && bq->notify_node) + if (bq) of_node_put(bq->notify_node); kfree(name); error_1: @@ -1724,9 +1724,7 @@ static int bq2415x_remove(struct i2c_client *client) if (bq->nb.notifier_call) power_supply_unreg_notifier(&bq->nb); - if (bq->notify_node) - of_node_put(bq->notify_node); - + of_node_put(bq->notify_node); bq2415x_sysfs_exit(bq); bq2415x_power_supply_exit(bq); -- cgit v0.10.2 From 79fbdb66cf6ab4e26e7bcb8399ac02cd81fc5d6d Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 13 Nov 2015 19:41:34 +0100 Subject: power: ds2782_battery: constify ds278x_battery_ops structure The ds278x_battery_ops structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Sebastian Reichel diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index ed4d756..a1b7e05 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c @@ -59,7 +59,7 @@ struct ds278x_info { struct i2c_client *client; struct power_supply *battery; struct power_supply_desc battery_desc; - struct ds278x_battery_ops *ops; + const struct ds278x_battery_ops *ops; struct delayed_work bat_work; int id; int rsns; @@ -361,7 +361,7 @@ enum ds278x_num_id { DS2786, }; -static struct ds278x_battery_ops ds278x_ops[] = { +static const struct ds278x_battery_ops ds278x_ops[] = { [DS2782] = { .get_battery_current = ds2782_get_current, .get_battery_voltage = ds2782_get_voltage, -- cgit v0.10.2 From c4c0edfbf875a5ecb38a4aa65e2bdb87739e81d6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 18 Nov 2015 23:04:14 +0100 Subject: power/reset: at91-reset: add missing of_node_put for_each_matching_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ expression e,e1; local idexpression np; @@ for_each_matching_node(np, e1) { ... when != of_node_put(np) when != e = np ( return np; | + of_node_put(np); ? return ...; ) ... } // Signed-off-by: Julia Lawall Signed-off-by: Sebastian Reichel diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 3f6b5dd..1b5d450 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -198,6 +198,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) at91_ramc_base[idx] = of_iomap(np, 0); if (!at91_ramc_base[idx]) { dev_err(&pdev->dev, "Could not map ram controller address\n"); + of_node_put(np); return -ENODEV; } idx++; -- cgit v0.10.2 From d5fdfedc0ed946e96b2ac06d48b230e370105d7e Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Thu, 19 Nov 2015 12:42:59 +0530 Subject: power: max8903_charger: set IRQF_ONESHOT if no primary handler is specified If no primary handler is specified for threaded_irq then a default one is assigned which always returns IRQ_WAKE_THREAD. This handler requires the IRQF_ONESHOT, because the source of interrupt is not disabled. Signed-off-by: Saurabh Sengar Signed-off-by: Sebastian Reichel diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c index 6d39d52..17876ca 100644 --- a/drivers/power/max8903_charger.c +++ b/drivers/power/max8903_charger.c @@ -291,10 +291,10 @@ static int max8903_probe(struct platform_device *pdev) if (pdata->dc_valid) { ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->dok), - NULL, max8903_dcin, - IRQF_TRIGGER_FALLING | - IRQF_TRIGGER_RISING, - "MAX8903 DC IN", data); + NULL, max8903_dcin, + IRQF_TRIGGER_FALLING | + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "MAX8903 DC IN", data); if (ret) { dev_err(dev, "Cannot request irq %d for DC (%d)\n", gpio_to_irq(pdata->dok), ret); @@ -304,10 +304,10 @@ static int max8903_probe(struct platform_device *pdev) if (pdata->usb_valid) { ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->uok), - NULL, max8903_usbin, - IRQF_TRIGGER_FALLING | - IRQF_TRIGGER_RISING, - "MAX8903 USB IN", data); + NULL, max8903_usbin, + IRQF_TRIGGER_FALLING | + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "MAX8903 USB IN", data); if (ret) { dev_err(dev, "Cannot request irq %d for USB (%d)\n", gpio_to_irq(pdata->uok), ret); @@ -317,10 +317,10 @@ static int max8903_probe(struct platform_device *pdev) if (pdata->flt) { ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->flt), - NULL, max8903_fault, - IRQF_TRIGGER_FALLING | - IRQF_TRIGGER_RISING, - "MAX8903 Fault", data); + NULL, max8903_fault, + IRQF_TRIGGER_FALLING | + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "MAX8903 Fault", data); if (ret) { dev_err(dev, "Cannot request irq %d for Fault (%d)\n", gpio_to_irq(pdata->flt), ret); -- cgit v0.10.2 From 1f94b2563a02327aa8a1385c8a92b0c3f96d01b4 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 7 Oct 2015 20:42:38 +0200 Subject: power: bq27xxx: don't fill system log by missing battery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print message that battery is not calibrated only once to avoid spamming the log. Suggested-By: H. Nikolaus Schaller Suggested-By: Pali Rohár Signed-off-by: Sebastian Reichel diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c index 880233c..1cad7ac 100644 --- a/drivers/power/bq27xxx_battery.c +++ b/drivers/power/bq27xxx_battery.c @@ -722,7 +722,7 @@ static void bq27xxx_battery_update(struct bq27xxx_device_info *di) if (cache.flags >= 0) { cache.temperature = bq27xxx_battery_read_temperature(di); if (has_ci_flag && (cache.flags & BQ27000_FLAG_CI)) { - dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); + dev_info_once(di->dev, "battery is not calibrated! ignoring capacity values\n"); cache.capacity = -ENODATA; cache.energy = -ENODATA; cache.time_to_empty = -ENODATA; -- cgit v0.10.2 From 703df6c097956d17a818e63961c82e8e9eef9fef Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Mon, 23 Nov 2015 10:53:51 -0600 Subject: power: bq27xxx_battery: Reorganize I2C into a module Separate out I2C functionality into a module. This fixes several small issues and simplifies the driver initialization. Signed-off-by: Andrew F. Davis Signed-off-by: Sebastian Reichel diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 237d7aa..42a5b51 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -160,22 +160,16 @@ config BATTERY_SBS config BATTERY_BQ27XXX tristate "BQ27xxx battery driver" help - Say Y here to enable support for batteries with BQ27xxx (I2C/HDQ) chips. + Say Y here to enable support for batteries with BQ27xxx chips. config BATTERY_BQ27XXX_I2C - bool "BQ27xxx I2C support" + tristate "BQ27xxx I2C support" depends on BATTERY_BQ27XXX depends on I2C default y help - Say Y here to enable support for batteries with BQ27xxx (I2C) chips. - -config BATTERY_BQ27XXX_PLATFORM - bool "BQ27xxx HDQ support" - depends on BATTERY_BQ27XXX - default y - help - Say Y here to enable support for batteries with BQ27xxx (HDQ) chips. + Say Y here to enable support for batteries with BQ27xxx chips + connected over an I2C bus. config BATTERY_DA9030 tristate "DA9030 battery driver" diff --git a/drivers/power/Makefile b/drivers/power/Makefile index b656638..0e4eab5 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o +obj-$(CONFIG_BATTERY_BQ27XXX_I2C) += bq27xxx_battery_i2c.o obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c index 1cad7ac..8d4ef9f 100644 --- a/drivers/power/bq27xxx_battery.c +++ b/drivers/power/bq27xxx_battery.c @@ -45,11 +45,7 @@ #include #include #include -#include -#include #include -#include -#include #include @@ -78,11 +74,6 @@ #define BQ27XXX_POWER_CONSTANT (29200) /* 29.2 µV^2 * 1000 */ #define BQ27XXX_CURRENT_CONSTANT (3570) /* 3.57 µV * 1000 */ -struct bq27xxx_device_info; -struct bq27xxx_access_methods { - int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single); -}; - #define INVALID_REG_ADDR 0xff /* @@ -110,40 +101,6 @@ enum bq27xxx_reg_index { BQ27XXX_REG_AP, /* Average Power */ }; -struct bq27xxx_reg_cache { - int temperature; - int time_to_empty; - int time_to_empty_avg; - int time_to_full; - int charge_full; - int cycle_count; - int capacity; - int energy; - int flags; - int power_avg; - int health; -}; - -struct bq27xxx_device_info { - struct device *dev; - int id; - enum bq27xxx_chip chip; - - struct bq27xxx_reg_cache cache; - int charge_design_full; - - unsigned long last_update; - struct delayed_work work; - - struct power_supply *bat; - - struct bq27xxx_access_methods bus; - - struct mutex lock; - - u8 *regs; -}; - /* Register mappings */ static u8 bq27000_regs[] = { 0x00, /* CONTROL */ @@ -710,7 +667,7 @@ static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di) return POWER_SUPPLY_HEALTH_GOOD; } -static void bq27xxx_battery_update(struct bq27xxx_device_info *di) +void bq27xxx_battery_update(struct bq27xxx_device_info *di) { struct bq27xxx_reg_cache cache = {0, }; bool has_ci_flag = di->chip == BQ27000 || di->chip == BQ27010; @@ -761,6 +718,7 @@ static void bq27xxx_battery_update(struct bq27xxx_device_info *di) di->last_update = jiffies; } +EXPORT_SYMBOL_GPL(bq27xxx_battery_update); static void bq27xxx_battery_poll(struct work_struct *work) { @@ -991,32 +949,30 @@ static void bq27xxx_external_power_changed(struct power_supply *psy) schedule_delayed_work(&di->work, 0); } -static int bq27xxx_powersupply_init(struct bq27xxx_device_info *di, - const char *name) +int bq27xxx_battery_setup(struct bq27xxx_device_info *di) { - int ret; struct power_supply_desc *psy_desc; struct power_supply_config psy_cfg = { .drv_data = di, }; + INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll); + mutex_init(&di->lock); + di->regs = bq27xxx_regs[di->chip]; + psy_desc = devm_kzalloc(di->dev, sizeof(*psy_desc), GFP_KERNEL); if (!psy_desc) return -ENOMEM; - psy_desc->name = name; + psy_desc->name = di->name; psy_desc->type = POWER_SUPPLY_TYPE_BATTERY; psy_desc->properties = bq27xxx_battery_props[di->chip].props; psy_desc->num_properties = bq27xxx_battery_props[di->chip].size; psy_desc->get_property = bq27xxx_battery_get_property; psy_desc->external_power_changed = bq27xxx_external_power_changed; - INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll); - mutex_init(&di->lock); - di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg); if (IS_ERR(di->bat)) { - ret = PTR_ERR(di->bat); - dev_err(di->dev, "failed to register battery: %d\n", ret); - return ret; + dev_err(di->dev, "failed to register battery\n"); + return PTR_ERR(di->bat); } dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION); @@ -1025,8 +981,9 @@ static int bq27xxx_powersupply_init(struct bq27xxx_device_info *di, return 0; } +EXPORT_SYMBOL_GPL(bq27xxx_battery_setup); -static void bq27xxx_powersupply_unregister(struct bq27xxx_device_info *di) +void bq27xxx_battery_teardown(struct bq27xxx_device_info *di) { /* * power_supply_unregister call bq27xxx_battery_get_property which @@ -1042,192 +999,7 @@ static void bq27xxx_powersupply_unregister(struct bq27xxx_device_info *di) mutex_destroy(&di->lock); } - -/* i2c specific code */ -#ifdef CONFIG_BATTERY_BQ27XXX_I2C - -/* If the system has several batteries we need a different name for each - * of them... - */ -static DEFINE_IDR(battery_id); -static DEFINE_MUTEX(battery_mutex); - -static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data) -{ - struct bq27xxx_device_info *di = data; - - bq27xxx_battery_update(di); - - return IRQ_HANDLED; -} - -static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg, - bool single) -{ - struct i2c_client *client = to_i2c_client(di->dev); - struct i2c_msg msg[2]; - unsigned char data[2]; - int ret; - - if (!client->adapter) - return -ENODEV; - - msg[0].addr = client->addr; - msg[0].flags = 0; - msg[0].buf = ® - msg[0].len = sizeof(reg); - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].buf = data; - if (single) - msg[1].len = 1; - else - msg[1].len = 2; - - ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); - if (ret < 0) - return ret; - - if (!single) - ret = get_unaligned_le16(data); - else - ret = data[0]; - - return ret; -} - -static int bq27xxx_battery_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - char *name; - struct bq27xxx_device_info *di; - int num; - int retval = 0; - - /* Get new ID for the new battery device */ - mutex_lock(&battery_mutex); - num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL); - mutex_unlock(&battery_mutex); - if (num < 0) - return num; - - name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num); - if (!name) { - retval = -ENOMEM; - goto batt_failed; - } - - di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL); - if (!di) { - retval = -ENOMEM; - goto batt_failed; - } - - di->id = num; - di->dev = &client->dev; - di->chip = id->driver_data; - di->bus.read = &bq27xxx_battery_i2c_read; - di->regs = bq27xxx_regs[di->chip]; - - retval = bq27xxx_powersupply_init(di, name); - if (retval) - goto batt_failed; - - /* Schedule a polling after about 1 min */ - schedule_delayed_work(&di->work, 60 * HZ); - - i2c_set_clientdata(client, di); - - if (client->irq) { - retval = devm_request_threaded_irq(&client->dev, client->irq, - NULL, bq27xxx_battery_irq_handler_thread, - IRQF_ONESHOT, - name, di); - if (retval) { - dev_err(&client->dev, - "Unable to register IRQ %d error %d\n", - client->irq, retval); - return retval; - } - } - - return 0; - -batt_failed: - mutex_lock(&battery_mutex); - idr_remove(&battery_id, num); - mutex_unlock(&battery_mutex); - - return retval; -} - -static int bq27xxx_battery_i2c_remove(struct i2c_client *client) -{ - struct bq27xxx_device_info *di = i2c_get_clientdata(client); - - bq27xxx_powersupply_unregister(di); - - mutex_lock(&battery_mutex); - idr_remove(&battery_id, di->id); - mutex_unlock(&battery_mutex); - - return 0; -} - -static const struct i2c_device_id bq27xxx_id[] = { - { "bq27200", BQ27000 }, - { "bq27210", BQ27010 }, - { "bq27500", BQ27500 }, - { "bq27510", BQ27500 }, - { "bq27520", BQ27500 }, - { "bq27530", BQ27530 }, - { "bq27531", BQ27530 }, - { "bq27541", BQ27541 }, - { "bq27542", BQ27541 }, - { "bq27546", BQ27541 }, - { "bq27742", BQ27541 }, - { "bq27545", BQ27545 }, - { "bq27421", BQ27421 }, - { "bq27425", BQ27421 }, - { "bq27441", BQ27421 }, - { "bq27621", BQ27421 }, - {}, -}; -MODULE_DEVICE_TABLE(i2c, bq27xxx_id); - -static struct i2c_driver bq27xxx_battery_i2c_driver = { - .driver = { - .name = "bq27xxx-battery", - }, - .probe = bq27xxx_battery_i2c_probe, - .remove = bq27xxx_battery_i2c_remove, - .id_table = bq27xxx_id, -}; - -static inline int bq27xxx_battery_i2c_init(void) -{ - int ret = i2c_add_driver(&bq27xxx_battery_i2c_driver); - - if (ret) - pr_err("Unable to register BQ27xxx i2c driver\n"); - - return ret; -} - -static inline void bq27xxx_battery_i2c_exit(void) -{ - i2c_del_driver(&bq27xxx_battery_i2c_driver); -} - -#else - -static inline int bq27xxx_battery_i2c_init(void) { return 0; } -static inline void bq27xxx_battery_i2c_exit(void) {}; - -#endif - -/* platform specific code */ -#ifdef CONFIG_BATTERY_BQ27XXX_PLATFORM +EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown); static int bq27xxx_battery_platform_read(struct bq27xxx_device_info *di, u8 reg, bool single) @@ -1267,7 +1039,6 @@ static int bq27xxx_battery_platform_probe(struct platform_device *pdev) { struct bq27xxx_device_info *di; struct bq27xxx_platform_data *pdata = pdev->dev.platform_data; - const char *name; if (!pdata) { dev_err(&pdev->dev, "no platform_data supplied\n"); @@ -1292,83 +1063,36 @@ static int bq27xxx_battery_platform_probe(struct platform_device *pdev) di->dev = &pdev->dev; di->chip = pdata->chip; - di->regs = bq27xxx_regs[di->chip]; - - name = pdata->name ?: dev_name(&pdev->dev); - di->bus.read = &bq27xxx_battery_platform_read; + di->name = pdata->name ?: dev_name(&pdev->dev); + di->bus.read = bq27xxx_battery_platform_read; - return bq27xxx_powersupply_init(di, name); + return bq27xxx_battery_setup(di); } static int bq27xxx_battery_platform_remove(struct platform_device *pdev) { struct bq27xxx_device_info *di = platform_get_drvdata(pdev); - bq27xxx_powersupply_unregister(di); + bq27xxx_battery_teardown(di); return 0; } +static const struct platform_device_id bq27xxx_battery_platform_id_table[] = { + { "bq27000-battery", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, bq27xxx_battery_platform_id_table); + static struct platform_driver bq27xxx_battery_platform_driver = { .probe = bq27xxx_battery_platform_probe, .remove = bq27xxx_battery_platform_remove, .driver = { .name = "bq27000-battery", }, + .id_table = bq27xxx_battery_platform_id_table, }; - -static inline int bq27xxx_battery_platform_init(void) -{ - int ret = platform_driver_register(&bq27xxx_battery_platform_driver); - - if (ret) - pr_err("Unable to register BQ27xxx platform driver\n"); - - return ret; -} - -static inline void bq27xxx_battery_platform_exit(void) -{ - platform_driver_unregister(&bq27xxx_battery_platform_driver); -} - -#else - -static inline int bq27xxx_battery_platform_init(void) { return 0; } -static inline void bq27xxx_battery_platform_exit(void) {}; - -#endif - -/* - * Module stuff - */ - -static int __init bq27xxx_battery_init(void) -{ - int ret; - - ret = bq27xxx_battery_i2c_init(); - if (ret) - return ret; - - ret = bq27xxx_battery_platform_init(); - if (ret) - bq27xxx_battery_i2c_exit(); - - return ret; -} -module_init(bq27xxx_battery_init); - -static void __exit bq27xxx_battery_exit(void) -{ - bq27xxx_battery_platform_exit(); - bq27xxx_battery_i2c_exit(); -} -module_exit(bq27xxx_battery_exit); - -#ifdef CONFIG_BATTERY_BQ27XXX_PLATFORM -MODULE_ALIAS("platform:bq27000-battery"); -#endif +module_platform_driver(bq27xxx_battery_platform_driver); MODULE_AUTHOR("Rodolfo Giometti "); MODULE_DESCRIPTION("BQ27xxx battery monitor driver"); diff --git a/drivers/power/bq27xxx_battery_i2c.c b/drivers/power/bq27xxx_battery_i2c.c new file mode 100644 index 0000000..9429e66 --- /dev/null +++ b/drivers/power/bq27xxx_battery_i2c.c @@ -0,0 +1,150 @@ +/* + * SCI Reset driver for Keystone based devices + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#include + +static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data) +{ + struct bq27xxx_device_info *di = data; + + bq27xxx_battery_update(di); + + return IRQ_HANDLED; +} + +static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg, + bool single) +{ + struct i2c_client *client = to_i2c_client(di->dev); + struct i2c_msg msg[2]; + unsigned char data[2]; + int ret; + + if (!client->adapter) + return -ENODEV; + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].buf = ® + msg[0].len = sizeof(reg); + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = data; + if (single) + msg[1].len = 1; + else + msg[1].len = 2; + + ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + if (ret < 0) + return ret; + + if (!single) + ret = get_unaligned_le16(data); + else + ret = data[0]; + + return ret; +} + +static int bq27xxx_battery_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct bq27xxx_device_info *di; + int ret; + + di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL); + if (!di) + return -ENOMEM; + + di->dev = &client->dev; + di->chip = id->driver_data; + di->name = id->name; + di->bus.read = bq27xxx_battery_i2c_read; + + ret = bq27xxx_battery_setup(di); + if (ret) + return ret; + + /* Schedule a polling after about 1 min */ + schedule_delayed_work(&di->work, 60 * HZ); + + i2c_set_clientdata(client, di); + + if (client->irq) { + ret = devm_request_threaded_irq(&client->dev, client->irq, + NULL, bq27xxx_battery_irq_handler_thread, + IRQF_ONESHOT, + di->name, di); + if (ret) { + dev_err(&client->dev, + "Unable to register IRQ %d error %d\n", + client->irq, ret); + return ret; + } + } + + return 0; +} + +static int bq27xxx_battery_i2c_remove(struct i2c_client *client) +{ + struct bq27xxx_device_info *di = i2c_get_clientdata(client); + + bq27xxx_battery_teardown(di); + + return 0; +} + +static const struct i2c_device_id bq27xxx_i2c_id_table[] = { + { "bq27200", BQ27000 }, + { "bq27210", BQ27010 }, + { "bq27500", BQ27500 }, + { "bq27510", BQ27500 }, + { "bq27520", BQ27500 }, + { "bq27530", BQ27530 }, + { "bq27531", BQ27530 }, + { "bq27541", BQ27541 }, + { "bq27542", BQ27541 }, + { "bq27546", BQ27541 }, + { "bq27742", BQ27541 }, + { "bq27545", BQ27545 }, + { "bq27421", BQ27421 }, + { "bq27425", BQ27421 }, + { "bq27441", BQ27421 }, + { "bq27621", BQ27421 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table); + +static struct i2c_driver bq27xxx_battery_i2c_driver = { + .driver = { + .name = "bq27xxx-battery", + }, + .probe = bq27xxx_battery_i2c_probe, + .remove = bq27xxx_battery_i2c_remove, + .id_table = bq27xxx_i2c_id_table, +}; +module_i2c_driver(bq27xxx_battery_i2c_driver); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("BQ27xxx battery monitor i2c driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h index 45f6a7b..998d8f1 100644 --- a/include/linux/power/bq27xxx_battery.h +++ b/include/linux/power/bq27xxx_battery.h @@ -1,6 +1,16 @@ #ifndef __LINUX_BQ27X00_BATTERY_H__ #define __LINUX_BQ27X00_BATTERY_H__ +enum bq27xxx_chip { + BQ27000 = 1, /* bq27000, bq27200 */ + BQ27010, /* bq27010, bq27210 */ + BQ27500, /* bq27500, bq27510, bq27520 */ + BQ27530, /* bq27530, bq27531 */ + BQ27541, /* bq27541, bq27542, bq27546, bq27742 */ + BQ27545, /* bq27545 */ + BQ27421, /* bq27421, bq27425, bq27441, bq27621 */ +}; + /** * struct bq27xxx_plaform_data - Platform data for bq27xxx devices * @name: Name of the battery. @@ -12,20 +22,47 @@ * register to be read. The return value should either be the content of * the passed register or an error value. */ -enum bq27xxx_chip { - BQ27000 = 1, /* bq27000, bq27200 */ - BQ27010, /* bq27010, bq27210 */ - BQ27500, /* bq27500, bq27510, bq27520 */ - BQ27530, /* bq27530, bq27531 */ - BQ27541, /* bq27541, bq27542, bq27546, bq27742 */ - BQ27545, /* bq27545 */ - BQ27421, /* bq27421, bq27425, bq27441, bq27621 */ -}; - struct bq27xxx_platform_data { const char *name; enum bq27xxx_chip chip; int (*read)(struct device *dev, unsigned int); }; +struct bq27xxx_device_info; +struct bq27xxx_access_methods { + int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single); +}; + +struct bq27xxx_reg_cache { + int temperature; + int time_to_empty; + int time_to_empty_avg; + int time_to_full; + int charge_full; + int cycle_count; + int capacity; + int energy; + int flags; + int power_avg; + int health; +}; + +struct bq27xxx_device_info { + struct device *dev; + enum bq27xxx_chip chip; + const char *name; + struct bq27xxx_access_methods bus; + struct bq27xxx_reg_cache cache; + int charge_design_full; + unsigned long last_update; + struct delayed_work work; + struct power_supply *bat; + struct mutex lock; + u8 *regs; +}; + +void bq27xxx_battery_update(struct bq27xxx_device_info *di); +int bq27xxx_battery_setup(struct bq27xxx_device_info *di); +void bq27xxx_battery_teardown(struct bq27xxx_device_info *di); + #endif -- cgit v0.10.2 From f96576bd63e5b9a7a9c33a7fc4209fffc4d433cc Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 7 Dec 2015 12:45:12 +0900 Subject: power: Fix unmet dependency on POWER_SUPPLY by POWER_RESET by uncoupling them Currently the reset/power off handlers (POWER_RESET) and Adaptive Voltage Scaling class (POWER_AVS) are not built when POWER_SUPPLY is disabled. The POWER_RESET is also not visible in drivers main section of config. However they do not really depend on power supply so they can be built always. The objects for power supply drivers already depend on particular Kconfig symbols so there is no need for any changes in drivers/power/Makefile. This allows selecting POWER_RESET from main drivers config section and fixes following build warning (encountered on ARM exynos defconfig when POWER_SUPPLY is disabled manually): warning: (ARCH_HISI && ARCH_INTEGRATOR && ARCH_EXYNOS && ARCH_VEXPRESS && REALVIEW_DT) selects POWER_RESET which has unmet direct dependencies (POWER_SUPPLY) warning: (ARCH_EXYNOS) selects POWER_RESET_SYSCON which has unmet direct dependencies (POWER_SUPPLY && POWER_RESET && OF) warning: (ARCH_EXYNOS) selects POWER_RESET_SYSCON_POWEROFF which has unmet direct dependencies (POWER_SUPPLY && POWER_RESET && OF) Reported-by: Pavel Fedin Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sebastian Reichel diff --git a/drivers/Makefile b/drivers/Makefile index 795d0ca..8f5d076 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -106,7 +106,7 @@ obj-y += i2c/ media/ obj-$(CONFIG_PPS) += pps/ obj-$(CONFIG_PTP_1588_CLOCK) += ptp/ obj-$(CONFIG_W1) += w1/ -obj-$(CONFIG_POWER_SUPPLY) += power/ +obj-y += power/ obj-$(CONFIG_HWMON) += hwmon/ obj-$(CONFIG_THERMAL) += thermal/ obj-$(CONFIG_WATCHDOG) += watchdog/ diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 42a5b51..1ddd13c 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -502,8 +502,7 @@ config AXP20X_POWER This driver provides support for the power supply features of AXP20x PMIC. -source "drivers/power/reset/Kconfig" - endif # POWER_SUPPLY +source "drivers/power/reset/Kconfig" source "drivers/power/avs/Kconfig" -- cgit v0.10.2 From 549d7b317c761dbf4ed0c2945aec3acc9ca7ae14 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Thu, 17 Dec 2015 11:12:53 +0100 Subject: power: bq27xxx: fix reading for bq27000 and bq27010 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bug: the driver reports funny capacity values: root@letux:/sys/class/power_supply/bq27000-battery# cat uevent POWER_SUPPLY_NAME=bq27000-battery POWER_SUPPLY_STATUS=Charging POWER_SUPPLY_PRESENT=1 POWER_SUPPLY_VOLTAGE_NOW=3702000 POWER_SUPPLY_CURRENT_NOW=-464635 POWER_SUPPLY_CAPACITY=1536 <- over 100% is magic POWER_SUPPLY_CAPACITY_LEVEL=Normal POWER_SUPPLY_TEMP=311 POWER_SUPPLY_TIME_TO_FULL_NOW=10440 POWER_SUPPLY_TECHNOLOGY=Li-ion POWER_SUPPLY_CHARGE_FULL=805450 POWER_SUPPLY_CHARGE_NOW=1068 POWER_SUPPLY_CHARGE_FULL_DESIGN=8844998 <- battery has just 1200 mAh POWER_SUPPLY_CYCLE_COUNT=21 POWER_SUPPLY_ENERGY_NOW=0 POWER_SUPPLY_POWER_AVG=0 POWER_SUPPLY_HEALTH=Good POWER_SUPPLY_MANUFACTURER=Texas Instruments reason: the state of charge and the design capacity register are single byte only. The design capacity returns the higer order byte. tested: GTA04 with Openmoko/FIC HF08x battery (using hdq) Fixes: d74534c27775 ("power: bq27xxx_battery: Add support for additional bq27xxx family devices") Signed-off-by: H. Nikolaus Schaller Acked-by: Andrew F. Davis Reviewed-by: Pali Rohár Signed-off-by: Sebastian Reichel diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c index 8d4ef9f..0b95542 100644 --- a/drivers/power/bq27xxx_battery.c +++ b/drivers/power/bq27xxx_battery.c @@ -428,7 +428,10 @@ static int bq27xxx_battery_read_soc(struct bq27xxx_device_info *di) { int soc; - soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false); + if (di->chip == BQ27000 || di->chip == BQ27010) + soc = bq27xxx_read(di, BQ27XXX_REG_SOC, true); + else + soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false); if (soc < 0) dev_dbg(di->dev, "error reading State-of-Charge\n"); @@ -493,7 +496,10 @@ static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di) { int dcap; - dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false); + if (di->chip == BQ27000 || di->chip == BQ27010) + dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, true); + else + dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false); if (dcap < 0) { dev_dbg(di->dev, "error reading initial last measured discharge\n"); @@ -501,7 +507,7 @@ static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di) } if (di->chip == BQ27000 || di->chip == BQ27010) - dcap *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; + dcap = (dcap << 8) * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; else dcap *= 1000; -- cgit v0.10.2 From 099867a16a0fa9fd5aafc32e3b1a6f8a90f17834 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Thu, 17 Dec 2015 11:12:54 +0100 Subject: power: bq27xxx: fix register numbers of bq27500 bug: according to data sheet some register numbers are wrong. tested: no Fixes: d74534c27775 ("power: bq27xxx_battery: Add support for additional bq27xxx family devices") Signed-off-by: H. Nikolaus Schaller Acked-by: Andrew F. Davis Signed-off-by: Sebastian Reichel diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c index 0b95542..73b647b 100644 --- a/drivers/power/bq27xxx_battery.c +++ b/drivers/power/bq27xxx_battery.c @@ -155,10 +155,10 @@ static u8 bq27500_regs[] = { INVALID_REG_ADDR, /* TTECP - NA */ 0x0c, /* NAC */ 0x12, /* LMD(FCC) */ - 0x1e, /* CYCT */ + 0x2a, /* CYCT */ INVALID_REG_ADDR, /* AE - NA */ - 0x20, /* SOC(RSOC) */ - 0x2e, /* DCAP(ILMD) */ + 0x2c, /* SOC(RSOC) */ + 0x3c, /* DCAP(ILMD) */ INVALID_REG_ADDR, /* AP - NA */ }; -- cgit v0.10.2 From 88025632515adfb7fcfac15d087f155b719e78cd Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Fri, 1 Jan 2016 13:03:29 +0200 Subject: power: isp1704_charger: Fix isp1704_write() definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All calls to isp1704_write() are using parameter sequence of isp1704_write(isp, reg, val) but the function is defined as isp1704_write(isp, val, reg). Fix isp1704_write function definition so that the driver to be functional. Signed-off-by: Ivaylo Dimitrov Reviewed-by: Pali Rohár Signed-off-by: Sebastian Reichel diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c index f2a7d97..46a292a 100644 --- a/drivers/power/isp1704_charger.c +++ b/drivers/power/isp1704_charger.c @@ -76,7 +76,7 @@ static inline int isp1704_read(struct isp1704_charger *isp, u32 reg) return usb_phy_io_read(isp->phy, reg); } -static inline int isp1704_write(struct isp1704_charger *isp, u32 val, u32 reg) +static inline int isp1704_write(struct isp1704_charger *isp, u32 reg, u32 val) { return usb_phy_io_write(isp->phy, val, reg); } -- cgit v0.10.2 From 127d2868484b9769e08a8353e9e43023dcb8b9b3 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 1 Jan 2016 22:59:11 +0800 Subject: power: generic-adc-battery: use to_delayed_work Use to_delayed_work() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Sebastian Reichel diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c index fedc581..edb36bf 100644 --- a/drivers/power/generic-adc-battery.c +++ b/drivers/power/generic-adc-battery.c @@ -206,7 +206,7 @@ static void gab_work(struct work_struct *work) bool is_plugged; int status; - delayed_work = container_of(work, struct delayed_work, work); + delayed_work = to_delayed_work(work); adc_bat = container_of(delayed_work, struct gab, bat_work); pdata = adc_bat->pdata; status = adc_bat->status; -- cgit v0.10.2 From 6b9140f39c2aaf76791197fbab0839c0e4af56e8 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Tue, 22 Dec 2015 12:43:36 -0500 Subject: power: test_power: correctly handle empty writes Writing 0 length data into test_power makes it access an invalid array location and kill the system. Fixes: f17ef9b2d ("power: Make test_power driver more dynamic.") Signed-off-by: Sasha Levin Signed-off-by: Sebastian Reichel diff --git a/drivers/power/test_power.c b/drivers/power/test_power.c index 83c42ea..57246cd 100644 --- a/drivers/power/test_power.c +++ b/drivers/power/test_power.c @@ -301,6 +301,8 @@ static int map_get_value(struct battery_property_map *map, const char *key, buf[MAX_KEYLENGTH-1] = '\0'; cr = strnlen(buf, MAX_KEYLENGTH) - 1; + if (cr < 0) + return def_val; if (buf[cr] == '\n') buf[cr] = '\0'; -- cgit v0.10.2 From 265b60497a57da56a4be7d5c72983ae89dc0765e Mon Sep 17 00:00:00 2001 From: Liu Xiang Date: Sat, 9 Jan 2016 22:10:39 +0800 Subject: power: bq27xxx_battery: Fix bq27541 AveragePower register address Currently in bq27541 driver, the average power register address is incorrectly set to 0x76, which would result in an error: bq27xxx-battery 2-0055: error reading average power register 10: -11 According to the bq27541 datasheet, fix this problem by setting the average power register address to 0x24. Fixes: d74534c27775 ("power: bq27xxx_battery: Add support for additional bq27xxx family devices") Signed-off-by: Liu Xiang Acked-by: Andrew F. Davis Signed-off-by: Sebastian Reichel diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c index 73b647b..6b027a4 100644 --- a/drivers/power/bq27xxx_battery.c +++ b/drivers/power/bq27xxx_battery.c @@ -199,7 +199,7 @@ static u8 bq27541_regs[] = { INVALID_REG_ADDR, /* AE - NA */ 0x2c, /* SOC(RSOC) */ 0x3c, /* DCAP */ - 0x76, /* AP */ + 0x24, /* AP */ }; static u8 bq27545_regs[] = { -- cgit v0.10.2