From 3b5dd3a49496220b35af83c96e3d2ff5716550ae Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Thu, 1 Sep 2016 15:50:52 +0800 Subject: power: supply: sbs-battery: Use gpio_desc and sleeping calls for battery detect Switch to using new gpio_desc interface and devm gpio get calls to automatically manage gpio resource. Use gpiod_get_value which handles active high / low calls. If gpio_detect is set then force loading of the driver as it is reasonable to assume that the battery may not be present. Update the is_present flag immediately in the IRQ. Remove legacy gpio specification from platform data. Signed-off-by: Phil Reid Signed-off-by: Sebastian Reichel --- include/linux/power/sbs-battery.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/power/sbs-battery.h b/include/linux/power/sbs-battery.h index 2b0a9d9ff57e..811f1a0c00cb 100644 --- a/include/linux/power/sbs-battery.h +++ b/include/linux/power/sbs-battery.h @@ -26,15 +26,11 @@ /** * struct sbs_platform_data - platform data for sbs devices - * @battery_detect: GPIO which is used to detect battery presence - * @battery_detect_present: gpio state when battery is present (0 / 1) * @i2c_retry_count: # of times to retry on i2c IO failure * @poll_retry_count: # of times to retry looking for new status after * external change notification */ struct sbs_platform_data { - int battery_detect; - int battery_detect_present; int i2c_retry_count; int poll_retry_count; }; -- cgit v1.2.3 From c65a8b51123a14f6960e4238bfa4673d54ee183a Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Sat, 3 Sep 2016 00:09:53 +0200 Subject: power: supply: bq24735-charger: Request status GPIO with initial input setup This requests the status GPIO with initial input setup. It is required to read the GPIO status at probe time and thus correctly avoid sending I2C messages when AC is not plugged. When requesting the GPIO without initial input setup, it always reads 0 which causes probe to fail as it assumes the charger is connected, sends I2C messages and fails. While at it, this switches the driver over to gpiod API. Signed-off-by: Paul Kocialkowski Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq24735-charger.c | 39 +++++++++++----------------------- include/linux/power/bq24735-charger.h | 4 ---- 2 files changed, 12 insertions(+), 31 deletions(-) (limited to 'include/linux') diff --git a/drivers/power/supply/bq24735-charger.c b/drivers/power/supply/bq24735-charger.c index dc460bb03d84..eb7783b42e0a 100644 --- a/drivers/power/supply/bq24735-charger.c +++ b/drivers/power/supply/bq24735-charger.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include @@ -49,6 +49,7 @@ struct bq24735 { struct i2c_client *client; struct bq24735_platform *pdata; struct mutex lock; + struct gpio_desc *status_gpio; bool charging; }; @@ -177,12 +178,8 @@ static int bq24735_config_charger(struct bq24735 *charger) static bool bq24735_charger_is_present(struct bq24735 *charger) { - struct bq24735_platform *pdata = charger->pdata; - int ret; - - if (pdata->status_gpio_valid) { - ret = gpio_get_value_cansleep(pdata->status_gpio); - return ret ^= pdata->status_gpio_active_low == 0; + if (charger->status_gpio) { + return !gpiod_get_value_cansleep(charger->status_gpio); } else { int ac = 0; @@ -308,7 +305,6 @@ static struct bq24735_platform *bq24735_parse_dt_data(struct i2c_client *client) struct device_node *np = client->dev.of_node; u32 val; int ret; - enum of_gpio_flags flags; pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { @@ -317,12 +313,6 @@ static struct bq24735_platform *bq24735_parse_dt_data(struct i2c_client *client) return NULL; } - pdata->status_gpio = of_get_named_gpio_flags(np, "ti,ac-detect-gpios", - 0, &flags); - - if (flags & OF_GPIO_ACTIVE_LOW) - pdata->status_gpio_active_low = 1; - ret = of_property_read_u32(np, "ti,charge-current", &val); if (!ret) pdata->charge_current = val; @@ -396,21 +386,16 @@ static int bq24735_charger_probe(struct i2c_client *client, i2c_set_clientdata(client, charger); - if (gpio_is_valid(charger->pdata->status_gpio)) { - ret = devm_gpio_request(&client->dev, - charger->pdata->status_gpio, - name); - if (ret) { - dev_err(&client->dev, - "Failed GPIO request for GPIO %d: %d\n", - charger->pdata->status_gpio, ret); - } - - charger->pdata->status_gpio_valid = !ret; + charger->status_gpio = devm_gpiod_get_optional(&client->dev, + "ti,ac-detect", + GPIOD_IN); + if (IS_ERR(charger->status_gpio)) { + ret = PTR_ERR(charger->status_gpio); + dev_err(&client->dev, "Getting gpio failed: %d\n", ret); + return ret; } - if (!charger->pdata->status_gpio_valid - || bq24735_charger_is_present(charger)) { + if (!charger->status_gpio || bq24735_charger_is_present(charger)) { ret = bq24735_read_word(client, BQ24735_MANUFACTURER_ID); if (ret < 0) { dev_err(&client->dev, "Failed to read manufacturer id : %d\n", diff --git a/include/linux/power/bq24735-charger.h b/include/linux/power/bq24735-charger.h index 6b750c1a45fa..b04be59f914c 100644 --- a/include/linux/power/bq24735-charger.h +++ b/include/linux/power/bq24735-charger.h @@ -28,10 +28,6 @@ struct bq24735_platform { const char *name; - int status_gpio; - int status_gpio_active_low; - bool status_gpio_valid; - bool ext_control; char **supplied_to; -- cgit v1.2.3 From 389958bb6be8b08c9f6d350dcaa9fc127123eada Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Tue, 20 Sep 2016 09:01:12 +0800 Subject: power: supply: sbs-battery: Cleanup removal of chip->pdata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There where still a few lingering references to pdata after commit power: supply: sbs-battery: simplify DT parsing. Remove pdata from struct·sbs_info and conditional checks to ser if this was set from the i2c read / write functions. Instead of call max in each function for incrementing poll_retry_count do it once in the probe function. Fixup null pointer dereference in to pdata in sbs_external_power_changed. Change retry counts to u32 to avoid need for max. Signed-off-by: Phil Reid Signed-off-by: Sebastian Reichel --- drivers/power/supply/sbs-battery.c | 22 +++++++++------------- include/linux/power/sbs-battery.h | 4 ++-- 2 files changed, 11 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c index bc7acdf84d60..8bb2eb38eb1c 100644 --- a/drivers/power/supply/sbs-battery.c +++ b/drivers/power/supply/sbs-battery.c @@ -163,14 +163,13 @@ static enum power_supply_property sbs_properties[] = { struct sbs_info { struct i2c_client *client; struct power_supply *power_supply; - struct sbs_platform_data *pdata; bool is_present; struct gpio_desc *gpio_detect; bool enable_detection; int last_state; int poll_time; - int i2c_retry_count; - int poll_retry_count; + u32 i2c_retry_count; + u32 poll_retry_count; struct delayed_work work; int ignore_changes; }; @@ -185,8 +184,7 @@ static int sbs_read_word_data(struct i2c_client *client, u8 address) s32 ret = 0; int retries = 1; - if (chip->pdata) - retries = max(chip->i2c_retry_count + 1, 1); + retries = chip->i2c_retry_count; while (retries > 0) { ret = i2c_smbus_read_word_data(client, address); @@ -213,10 +211,8 @@ static int sbs_read_string_data(struct i2c_client *client, u8 address, int retries_length = 1, retries_block = 1; u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; - if (chip->pdata) { - retries_length = max(chip->i2c_retry_count + 1, 1); - retries_block = max(chip->i2c_retry_count + 1, 1); - } + retries_length = chip->i2c_retry_count; + retries_block = chip->i2c_retry_count; /* Adapter needs to support these two functions */ if (!i2c_check_functionality(client->adapter, @@ -280,8 +276,7 @@ static int sbs_write_word_data(struct i2c_client *client, u8 address, s32 ret = 0; int retries = 1; - if (chip->pdata) - retries = max(chip->i2c_retry_count + 1, 1); + retries = chip->i2c_retry_count; while (retries > 0) { ret = i2c_smbus_write_word_data(client, address, @@ -708,7 +703,7 @@ static void sbs_external_power_changed(struct power_supply *psy) cancel_delayed_work_sync(&chip->work); schedule_delayed_work(&chip->work, HZ); - chip->poll_time = chip->pdata->poll_retry_count; + chip->poll_time = chip->poll_retry_count; } static void sbs_delayed_work(struct work_struct *work) @@ -792,7 +787,7 @@ static int sbs_probe(struct i2c_client *client, rc = of_property_read_u32(client->dev.of_node, "sbs,i2c-retry-count", &chip->i2c_retry_count); if (rc) - chip->i2c_retry_count = 1; + chip->i2c_retry_count = 0; rc = of_property_read_u32(client->dev.of_node, "sbs,poll-retry-count", &chip->poll_retry_count); @@ -803,6 +798,7 @@ static int sbs_probe(struct i2c_client *client, chip->poll_retry_count = pdata->poll_retry_count; chip->i2c_retry_count = pdata->i2c_retry_count; } + chip->i2c_retry_count = chip->i2c_retry_count + 1; chip->gpio_detect = devm_gpiod_get_optional(&client->dev, "sbs,battery-detect", GPIOD_IN); diff --git a/include/linux/power/sbs-battery.h b/include/linux/power/sbs-battery.h index 811f1a0c00cb..519b8b43239a 100644 --- a/include/linux/power/sbs-battery.h +++ b/include/linux/power/sbs-battery.h @@ -31,8 +31,8 @@ * external change notification */ struct sbs_platform_data { - int i2c_retry_count; - int poll_retry_count; + u32 i2c_retry_count; + u32 poll_retry_count; }; #endif -- cgit v1.2.3 From 1d72706f0485b58e151b5a7584c4c65d66670587 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Mon, 19 Sep 2016 20:43:02 -0700 Subject: power: supply: bq27xxx_battery: allow kernel poll_interval parameter runtime update Fix issue with poll_interval being not updated till the previous interval expired. Cc: Tony Lindgren Cc: Liam Breck Signed-off-by: Matt Ranostay Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq27xxx_battery.c | 38 +++++++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 1 + 2 files changed, 38 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c index 3f57dd54803a..3b0dbc689d72 100644 --- a/drivers/power/supply/bq27xxx_battery.c +++ b/drivers/power/supply/bq27xxx_battery.c @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -390,8 +391,35 @@ static struct { BQ27XXX_PROP(BQ27421, bq27421_battery_props), }; +static DEFINE_MUTEX(bq27xxx_list_lock); +static LIST_HEAD(bq27xxx_battery_devices); + +static int poll_interval_param_set(const char *val, const struct kernel_param *kp) +{ + struct bq27xxx_device_info *di; + int ret; + + ret = param_set_uint(val, kp); + if (ret < 0) + return ret; + + mutex_lock(&bq27xxx_list_lock); + list_for_each_entry(di, &bq27xxx_battery_devices, list) { + cancel_delayed_work_sync(&di->work); + schedule_delayed_work(&di->work, 0); + } + mutex_unlock(&bq27xxx_list_lock); + + return ret; +} + +static const struct kernel_param_ops param_ops_poll_interval = { + .get = param_get_uint, + .set = poll_interval_param_set, +}; + static unsigned int poll_interval = 360; -module_param(poll_interval, uint, 0644); +module_param_cb(poll_interval, ¶m_ops_poll_interval, &poll_interval, 0644); MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - 0 disables polling"); @@ -972,6 +1000,10 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) bq27xxx_battery_update(di); + mutex_lock(&bq27xxx_list_lock); + list_add(&di->list, &bq27xxx_battery_devices); + mutex_unlock(&bq27xxx_list_lock); + return 0; } EXPORT_SYMBOL_GPL(bq27xxx_battery_setup); @@ -990,6 +1022,10 @@ void bq27xxx_battery_teardown(struct bq27xxx_device_info *di) power_supply_unregister(di->bat); + mutex_lock(&bq27xxx_list_lock); + list_del(&di->list); + mutex_unlock(&bq27xxx_list_lock); + mutex_destroy(&di->lock); } EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown); diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h index b50c0492629d..e30deb046156 100644 --- a/include/linux/power/bq27xxx_battery.h +++ b/include/linux/power/bq27xxx_battery.h @@ -58,6 +58,7 @@ struct bq27xxx_device_info { unsigned long last_update; struct delayed_work work; struct power_supply *bat; + struct list_head list; struct mutex lock; u8 *regs; }; -- cgit v1.2.3