From 3bf4e03d199f7f2871919e33e7bfc6e3d4c3368f Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Wed, 17 Jan 2018 20:48:54 +0100 Subject: power: supply: ltc2941-battery-gauge: Add charge empty and full properties Add properties for charge empty and charge full thresholds. Signed-off-by: Ladislav Michl Signed-off-by: Sebastian Reichel --- drivers/power/supply/ltc2941-battery-gauge.c | 59 +++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 9 deletions(-) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/ltc2941-battery-gauge.c b/drivers/power/supply/ltc2941-battery-gauge.c index 4cfa3f0cd689..9360faca7026 100644 --- a/drivers/power/supply/ltc2941-battery-gauge.c +++ b/drivers/power/supply/ltc2941-battery-gauge.c @@ -34,6 +34,10 @@ enum ltc294x_reg { LTC294X_REG_CONTROL = 0x01, LTC294X_REG_ACC_CHARGE_MSB = 0x02, LTC294X_REG_ACC_CHARGE_LSB = 0x03, + LTC294X_REG_CHARGE_THR_HIGH_MSB = 0x04, + LTC294X_REG_CHARGE_THR_HIGH_LSB = 0x05, + LTC294X_REG_CHARGE_THR_LOW_MSB = 0x06, + LTC294X_REG_CHARGE_THR_LOW_LSB = 0x07, LTC294X_REG_VOLTAGE_MSB = 0x08, LTC294X_REG_VOLTAGE_LSB = 0x09, LTC2942_REG_TEMPERATURE_MSB = 0x0C, @@ -179,21 +183,22 @@ error_exit: return ret; } -static int ltc294x_read_charge_register(const struct ltc294x_info *info) -{ +static int ltc294x_read_charge_register(const struct ltc294x_info *info, + enum ltc294x_reg reg) + { int ret; u8 datar[2]; - ret = ltc294x_read_regs(info->client, - LTC294X_REG_ACC_CHARGE_MSB, &datar[0], 2); + ret = ltc294x_read_regs(info->client, reg, &datar[0], 2); if (ret < 0) return ret; return (datar[0] << 8) + datar[1]; } -static int ltc294x_get_charge_now(const struct ltc294x_info *info, int *val) +static int ltc294x_get_charge(const struct ltc294x_info *info, + enum ltc294x_reg reg, int *val) { - int value = ltc294x_read_charge_register(info); + int value = ltc294x_read_charge_register(info, reg); if (value < 0) return value; @@ -245,10 +250,29 @@ error_exit: return ret < 0 ? ret : 0; } +static int ltc294x_set_charge_thr(const struct ltc294x_info *info, + enum ltc294x_reg reg, int val) +{ + u8 dataw[2]; + s32 value; + + value = convert_uAh_to_bin(info, val); + /* Direction depends on how sense+/- were connected */ + if (info->Qlsb < 0) + value += 0xFFFF; + if ((value < 0) || (value > 0xFFFF)) /* input validation */ + return -EINVAL; + + /* Set new charge value */ + dataw[0] = I16_MSB(value); + dataw[1] = I16_LSB(value); + return ltc294x_write_regs(info->client, reg, &dataw[0], 2); +} + static int ltc294x_get_charge_counter( const struct ltc294x_info *info, int *val) { - int value = ltc294x_read_charge_register(info); + int value = ltc294x_read_charge_register(info, LTC294X_REG_ACC_CHARGE_MSB); if (value < 0) return value; @@ -336,8 +360,15 @@ static int ltc294x_get_property(struct power_supply *psy, struct ltc294x_info *info = power_supply_get_drvdata(psy); switch (prop) { + case POWER_SUPPLY_PROP_CHARGE_FULL: + return ltc294x_get_charge(info, LTC294X_REG_CHARGE_THR_HIGH_MSB, + &val->intval); + case POWER_SUPPLY_PROP_CHARGE_EMPTY: + return ltc294x_get_charge(info, LTC294X_REG_CHARGE_THR_LOW_MSB, + &val->intval); case POWER_SUPPLY_PROP_CHARGE_NOW: - return ltc294x_get_charge_now(info, &val->intval); + return ltc294x_get_charge(info, LTC294X_REG_ACC_CHARGE_MSB, + &val->intval); case POWER_SUPPLY_PROP_CHARGE_COUNTER: return ltc294x_get_charge_counter(info, &val->intval); case POWER_SUPPLY_PROP_VOLTAGE_NOW: @@ -358,6 +389,12 @@ static int ltc294x_set_property(struct power_supply *psy, struct ltc294x_info *info = power_supply_get_drvdata(psy); switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_FULL: + return ltc294x_set_charge_thr(info, + LTC294X_REG_CHARGE_THR_HIGH_MSB, val->intval); + case POWER_SUPPLY_PROP_CHARGE_EMPTY: + return ltc294x_set_charge_thr(info, + LTC294X_REG_CHARGE_THR_LOW_MSB, val->intval); case POWER_SUPPLY_PROP_CHARGE_NOW: return ltc294x_set_charge_now(info, val->intval); default: @@ -369,6 +406,8 @@ static int ltc294x_property_is_writeable( struct power_supply *psy, enum power_supply_property psp) { switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_FULL: + case POWER_SUPPLY_PROP_CHARGE_EMPTY: case POWER_SUPPLY_PROP_CHARGE_NOW: return 1; default: @@ -378,7 +417,7 @@ static int ltc294x_property_is_writeable( static void ltc294x_update(struct ltc294x_info *info) { - int charge = ltc294x_read_charge_register(info); + int charge = ltc294x_read_charge_register(info, LTC294X_REG_ACC_CHARGE_MSB); if (charge != info->charge) { info->charge = charge; @@ -397,6 +436,8 @@ static void ltc294x_work(struct work_struct *work) static enum power_supply_property ltc294x_properties[] = { POWER_SUPPLY_PROP_CHARGE_COUNTER, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_EMPTY, POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_TEMP, -- cgit v1.2.3-55-g7522 From 419cac572b79eda70f796c452895fefeee86a79a Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Wed, 17 Jan 2018 21:31:14 +0100 Subject: power: supply: gpio-charger: Drop driver remove function Simplify error unwinding using devm_* allocators. This also makes driver remove function empty, so remove it. Signed-off-by: Ladislav Michl Signed-off-by: Sebastian Reichel --- drivers/power/supply/gpio-charger.c | 43 ++++++------------------------------- 1 file changed, 7 insertions(+), 36 deletions(-) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/gpio-charger.c b/drivers/power/supply/gpio-charger.c index 001731e88718..666abc23e2ee 100644 --- a/drivers/power/supply/gpio-charger.c +++ b/drivers/power/supply/gpio-charger.c @@ -35,7 +35,6 @@ struct gpio_charger { struct power_supply *charger; struct power_supply_desc charger_desc; struct gpio_desc *gpiod; - bool legacy_gpio_requested; }; static irqreturn_t gpio_charger_irq(int irq, void *devid) @@ -159,19 +158,13 @@ static int gpio_charger_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Invalid gpio pin in pdata\n"); return -EINVAL; } - ret = gpio_request(pdata->gpio, dev_name(&pdev->dev)); + ret = devm_gpio_request_one(&pdev->dev, pdata->gpio, GPIOF_IN, + dev_name(&pdev->dev)); if (ret) { dev_err(&pdev->dev, "Failed to request gpio pin: %d\n", ret); return ret; } - gpio_charger->legacy_gpio_requested = true; - ret = gpio_direction_input(pdata->gpio); - if (ret) { - dev_err(&pdev->dev, "Failed to set gpio to input: %d\n", - ret); - goto err_gpio_free; - } /* Then convert this to gpiod for now */ gpio_charger->gpiod = gpio_to_desc(pdata->gpio); } else if (IS_ERR(gpio_charger->gpiod)) { @@ -195,20 +188,19 @@ static int gpio_charger_probe(struct platform_device *pdev) psy_cfg.of_node = pdev->dev.of_node; psy_cfg.drv_data = gpio_charger; - gpio_charger->pdata = pdata; - - gpio_charger->charger = power_supply_register(&pdev->dev, - charger_desc, &psy_cfg); + gpio_charger->charger = devm_power_supply_register(&pdev->dev, + charger_desc, &psy_cfg); if (IS_ERR(gpio_charger->charger)) { ret = PTR_ERR(gpio_charger->charger); dev_err(&pdev->dev, "Failed to register power supply: %d\n", ret); - goto err_gpio_free; + return ret; } irq = gpiod_to_irq(gpio_charger->gpiod); if (irq > 0) { - ret = request_any_context_irq(irq, gpio_charger_irq, + ret = devm_request_any_context_irq(&pdev->dev, irq, + gpio_charger_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), gpio_charger->charger); if (ret < 0) @@ -222,26 +214,6 @@ static int gpio_charger_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); return 0; - -err_gpio_free: - if (gpio_charger->legacy_gpio_requested) - gpio_free(pdata->gpio); - return ret; -} - -static int gpio_charger_remove(struct platform_device *pdev) -{ - struct gpio_charger *gpio_charger = platform_get_drvdata(pdev); - - if (gpio_charger->irq) - free_irq(gpio_charger->irq, gpio_charger->charger); - - power_supply_unregister(gpio_charger->charger); - - if (gpio_charger->legacy_gpio_requested) - gpio_free(gpio_charger->pdata->gpio); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -280,7 +252,6 @@ MODULE_DEVICE_TABLE(of, gpio_charger_match); static struct platform_driver gpio_charger_driver = { .probe = gpio_charger_probe, - .remove = gpio_charger_remove, .driver = { .name = "gpio-charger", .pm = &gpio_charger_pm_ops, -- cgit v1.2.3-55-g7522 From 416a1ae673db0918fbe6707c7d6f4459598e2c65 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Wed, 17 Jan 2018 21:31:49 +0100 Subject: power: supply: gpio-charger: use helper variable to access device info Using explicit struct device variable makes code a bit more readable. Signed-off-by: Ladislav Michl Signed-off-by: Sebastian Reichel --- drivers/power/supply/gpio-charger.c | 42 ++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/gpio-charger.c b/drivers/power/supply/gpio-charger.c index 666abc23e2ee..f0d8cc19ad1e 100644 --- a/drivers/power/supply/gpio-charger.c +++ b/drivers/power/supply/gpio-charger.c @@ -118,7 +118,8 @@ struct gpio_charger_platform_data *gpio_charger_parse_dt(struct device *dev) static int gpio_charger_probe(struct platform_device *pdev) { - const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + const struct gpio_charger_platform_data *pdata = dev->platform_data; struct power_supply_config psy_cfg = {}; struct gpio_charger *gpio_charger; struct power_supply_desc *charger_desc; @@ -126,19 +127,18 @@ static int gpio_charger_probe(struct platform_device *pdev) int irq; if (!pdata) { - pdata = gpio_charger_parse_dt(&pdev->dev); + pdata = gpio_charger_parse_dt(dev); if (IS_ERR(pdata)) { ret = PTR_ERR(pdata); if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "No platform data\n"); + dev_err(dev, "No platform data\n"); return ret; } } - gpio_charger = devm_kzalloc(&pdev->dev, sizeof(*gpio_charger), - GFP_KERNEL); + gpio_charger = devm_kzalloc(dev, sizeof(*gpio_charger), GFP_KERNEL); if (!gpio_charger) { - dev_err(&pdev->dev, "Failed to alloc driver structure\n"); + dev_err(dev, "Failed to alloc driver structure\n"); return -ENOMEM; } @@ -146,20 +146,20 @@ static int gpio_charger_probe(struct platform_device *pdev) * This will fetch a GPIO descriptor from device tree, ACPI or * boardfile descriptor tables. It's good to try this first. */ - gpio_charger->gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_IN); + gpio_charger->gpiod = devm_gpiod_get(dev, NULL, GPIOD_IN); /* * If this fails and we're not using device tree, try the * legacy platform data method. */ - if (IS_ERR(gpio_charger->gpiod) && !pdev->dev.of_node) { + if (IS_ERR(gpio_charger->gpiod) && !dev->of_node) { /* Non-DT: use legacy GPIO numbers */ if (!gpio_is_valid(pdata->gpio)) { - dev_err(&pdev->dev, "Invalid gpio pin in pdata\n"); + dev_err(dev, "Invalid gpio pin in pdata\n"); return -EINVAL; } - ret = devm_gpio_request_one(&pdev->dev, pdata->gpio, GPIOF_IN, - dev_name(&pdev->dev)); + ret = devm_gpio_request_one(dev, pdata->gpio, GPIOF_IN, + dev_name(dev)); if (ret) { dev_err(&pdev->dev, "Failed to request gpio pin: %d\n", ret); @@ -171,7 +171,7 @@ static int gpio_charger_probe(struct platform_device *pdev) /* Just try again if this happens */ if (PTR_ERR(gpio_charger->gpiod) == -EPROBE_DEFER) return -EPROBE_DEFER; - dev_err(&pdev->dev, "error getting GPIO descriptor\n"); + dev_err(dev, "error getting GPIO descriptor\n"); return PTR_ERR(gpio_charger->gpiod); } @@ -185,33 +185,31 @@ static int gpio_charger_probe(struct platform_device *pdev) psy_cfg.supplied_to = pdata->supplied_to; psy_cfg.num_supplicants = pdata->num_supplicants; - psy_cfg.of_node = pdev->dev.of_node; + psy_cfg.of_node = dev->of_node; psy_cfg.drv_data = gpio_charger; - gpio_charger->charger = devm_power_supply_register(&pdev->dev, - charger_desc, &psy_cfg); + gpio_charger->charger = devm_power_supply_register(dev, charger_desc, + &psy_cfg); if (IS_ERR(gpio_charger->charger)) { ret = PTR_ERR(gpio_charger->charger); - dev_err(&pdev->dev, "Failed to register power supply: %d\n", - ret); + dev_err(dev, "Failed to register power supply: %d\n", ret); return ret; } irq = gpiod_to_irq(gpio_charger->gpiod); if (irq > 0) { - ret = devm_request_any_context_irq(&pdev->dev, irq, - gpio_charger_irq, + ret = devm_request_any_context_irq(dev, irq, gpio_charger_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - dev_name(&pdev->dev), gpio_charger->charger); + dev_name(dev), gpio_charger->charger); if (ret < 0) - dev_warn(&pdev->dev, "Failed to request irq: %d\n", ret); + dev_warn(dev, "Failed to request irq: %d\n", ret); else gpio_charger->irq = irq; } platform_set_drvdata(pdev, gpio_charger); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(dev, 1); return 0; } -- cgit v1.2.3-55-g7522 From dde5953f05a89eb63a0d666ffe51d447b2ac3e05 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 22 Feb 2018 18:21:36 +0100 Subject: power: supply: ltc2941-battery-gauge: Fix temperature units Temperature is measured in tenths of degree Celsius. Fixes: 085bc24d1553 ("Add LTC2941/LTC2943 Battery Gauge Driver") Signed-off-by: Ladislav Michl Signed-off-by: Sebastian Reichel --- drivers/power/supply/ltc2941-battery-gauge.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/ltc2941-battery-gauge.c b/drivers/power/supply/ltc2941-battery-gauge.c index 4cfa3f0cd689..cc7c516bb417 100644 --- a/drivers/power/supply/ltc2941-battery-gauge.c +++ b/drivers/power/supply/ltc2941-battery-gauge.c @@ -317,15 +317,15 @@ static int ltc294x_get_temperature(const struct ltc294x_info *info, int *val) if (info->id == LTC2942_ID) { reg = LTC2942_REG_TEMPERATURE_MSB; - value = 60000; /* Full-scale is 600 Kelvin */ + value = 6000; /* Full-scale is 600 Kelvin */ } else { reg = LTC2943_REG_TEMPERATURE_MSB; - value = 51000; /* Full-scale is 510 Kelvin */ + value = 5100; /* Full-scale is 510 Kelvin */ } ret = ltc294x_read_regs(info->client, reg, &datar[0], 2); value *= (datar[0] << 8) | datar[1]; - /* Convert to centidegrees */ - *val = value / 0xFFFF - 27215; + /* Convert to tenths of degree Celsius */ + *val = value / 0xFFFF - 2722; return ret; } -- cgit v1.2.3-55-g7522 From d433d04bb70085ceea2815cdb879d4e6fae470d9 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Mon, 5 Mar 2018 19:04:14 +0100 Subject: power: supply: gpio-charger: Remove redundant dev_err call in probe function There is an error message within devm_kzalloc already. Signed-off-by: Ladislav Michl Signed-off-by: Sebastian Reichel --- drivers/power/supply/gpio-charger.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/gpio-charger.c b/drivers/power/supply/gpio-charger.c index f0d8cc19ad1e..78b55566e215 100644 --- a/drivers/power/supply/gpio-charger.c +++ b/drivers/power/supply/gpio-charger.c @@ -137,10 +137,8 @@ static int gpio_charger_probe(struct platform_device *pdev) } gpio_charger = devm_kzalloc(dev, sizeof(*gpio_charger), GFP_KERNEL); - if (!gpio_charger) { - dev_err(dev, "Failed to alloc driver structure\n"); + if (!gpio_charger) return -ENOMEM; - } /* * This will fetch a GPIO descriptor from device tree, ACPI or -- cgit v1.2.3-55-g7522 From f5fec4cc2949421af74bdd005abd99fcbaf9d0d7 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Mon, 5 Mar 2018 19:05:18 +0100 Subject: power: supply: gpio-charger: Use GPIOF_ACTIVE_LOW for legacy setup Setting GPIOF_ACTIVE_LOW flag based on platform data gpio_active_low makes return value of gpiod_get_value_cansleep directly usable. Signed-off-by: Ladislav Michl Signed-off-by: Sebastian Reichel --- drivers/power/supply/gpio-charger.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/gpio-charger.c b/drivers/power/supply/gpio-charger.c index 78b55566e215..768bbcad97cb 100644 --- a/drivers/power/supply/gpio-charger.c +++ b/drivers/power/supply/gpio-charger.c @@ -55,13 +55,10 @@ static int gpio_charger_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { struct gpio_charger *gpio_charger = psy_to_gpio_charger(psy); - const struct gpio_charger_platform_data *pdata = gpio_charger->pdata; switch (psp) { case POWER_SUPPLY_PROP_ONLINE: val->intval = gpiod_get_value_cansleep(gpio_charger->gpiod); - /* This xor is only ever used with legacy pdata GPIO */ - val->intval ^= pdata->gpio_active_low; break; default: return -EINVAL; @@ -123,8 +120,8 @@ static int gpio_charger_probe(struct platform_device *pdev) struct power_supply_config psy_cfg = {}; struct gpio_charger *gpio_charger; struct power_supply_desc *charger_desc; - int ret; - int irq; + unsigned long flags; + int irq, ret; if (!pdata) { pdata = gpio_charger_parse_dt(dev); @@ -156,11 +153,13 @@ static int gpio_charger_probe(struct platform_device *pdev) dev_err(dev, "Invalid gpio pin in pdata\n"); return -EINVAL; } - ret = devm_gpio_request_one(dev, pdata->gpio, GPIOF_IN, - dev_name(dev)); + flags = GPIOF_IN; + if (pdata->gpio_active_low) + flags |= GPIOF_ACTIVE_LOW; + ret = devm_gpio_request_one(dev, pdata->gpio, flags, + dev_name(dev)); if (ret) { - dev_err(&pdev->dev, "Failed to request gpio pin: %d\n", - ret); + dev_err(dev, "Failed to request gpio pin: %d\n", ret); return ret; } /* Then convert this to gpiod for now */ -- cgit v1.2.3-55-g7522 From d47c1e4b2f51e81683b087480401b9b42b2a58fd Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Mon, 5 Mar 2018 19:05:55 +0100 Subject: power: supply: gpio-charger: Remove pdata from gpio_charger Platform data are now used only during probe time, so remove them from gpio_charger structure and consolidate probing function accordingly. Signed-off-by: Ladislav Michl [Replace of_property_read_string with dev_property_read_string] Signed-off-by: Sebastian Reichel --- drivers/power/supply/gpio-charger.c | 95 ++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 54 deletions(-) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/gpio-charger.c b/drivers/power/supply/gpio-charger.c index 768bbcad97cb..bd2468ca6b63 100644 --- a/drivers/power/supply/gpio-charger.c +++ b/drivers/power/supply/gpio-charger.c @@ -28,7 +28,6 @@ #include struct gpio_charger { - const struct gpio_charger_platform_data *pdata; unsigned int irq; bool wakeup_enabled; @@ -67,52 +66,37 @@ static int gpio_charger_get_property(struct power_supply *psy, return 0; } -static enum power_supply_property gpio_charger_properties[] = { - POWER_SUPPLY_PROP_ONLINE, -}; - -static -struct gpio_charger_platform_data *gpio_charger_parse_dt(struct device *dev) +static enum power_supply_type gpio_charger_get_type(struct device *dev) { - struct device_node *np = dev->of_node; - struct gpio_charger_platform_data *pdata; const char *chargetype; - int ret; - - if (!np) - return ERR_PTR(-ENOENT); - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return ERR_PTR(-ENOMEM); - - pdata->name = np->name; - pdata->type = POWER_SUPPLY_TYPE_UNKNOWN; - ret = of_property_read_string(np, "charger-type", &chargetype); - if (ret >= 0) { - if (!strncmp("unknown", chargetype, 7)) - pdata->type = POWER_SUPPLY_TYPE_UNKNOWN; - else if (!strncmp("battery", chargetype, 7)) - pdata->type = POWER_SUPPLY_TYPE_BATTERY; - else if (!strncmp("ups", chargetype, 3)) - pdata->type = POWER_SUPPLY_TYPE_UPS; - else if (!strncmp("mains", chargetype, 5)) - pdata->type = POWER_SUPPLY_TYPE_MAINS; - else if (!strncmp("usb-sdp", chargetype, 7)) - pdata->type = POWER_SUPPLY_TYPE_USB; - else if (!strncmp("usb-dcp", chargetype, 7)) - pdata->type = POWER_SUPPLY_TYPE_USB_DCP; - else if (!strncmp("usb-cdp", chargetype, 7)) - pdata->type = POWER_SUPPLY_TYPE_USB_CDP; - else if (!strncmp("usb-aca", chargetype, 7)) - pdata->type = POWER_SUPPLY_TYPE_USB_ACA; - else - dev_warn(dev, "unknown charger type %s\n", chargetype); + + if (!device_property_read_string(dev, "charger-type", &chargetype)) { + if (!strcmp("unknown", chargetype)) + return POWER_SUPPLY_TYPE_UNKNOWN; + if (!strcmp("battery", chargetype)) + return POWER_SUPPLY_TYPE_BATTERY; + if (!strcmp("ups", chargetype)) + return POWER_SUPPLY_TYPE_UPS; + if (!strcmp("mains", chargetype)) + return POWER_SUPPLY_TYPE_MAINS; + if (!strcmp("usb-sdp", chargetype)) + return POWER_SUPPLY_TYPE_USB; + if (!strcmp("usb-dcp", chargetype)) + return POWER_SUPPLY_TYPE_USB_DCP; + if (!strcmp("usb-cdp", chargetype)) + return POWER_SUPPLY_TYPE_USB_CDP; + if (!strcmp("usb-aca", chargetype)) + return POWER_SUPPLY_TYPE_USB_ACA; } + dev_warn(dev, "unknown charger type %s\n", chargetype); - return pdata; + return POWER_SUPPLY_TYPE_UNKNOWN; } +static enum power_supply_property gpio_charger_properties[] = { + POWER_SUPPLY_PROP_ONLINE, +}; + static int gpio_charger_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -123,14 +107,9 @@ static int gpio_charger_probe(struct platform_device *pdev) unsigned long flags; int irq, ret; - if (!pdata) { - pdata = gpio_charger_parse_dt(dev); - if (IS_ERR(pdata)) { - ret = PTR_ERR(pdata); - if (ret != -EPROBE_DEFER) - dev_err(dev, "No platform data\n"); - return ret; - } + if (!pdata && !dev->of_node) { + dev_err(dev, "No platform data\n"); + return -ENOENT; } gpio_charger = devm_kzalloc(dev, sizeof(*gpio_charger), GFP_KERNEL); @@ -173,18 +152,26 @@ static int gpio_charger_probe(struct platform_device *pdev) } charger_desc = &gpio_charger->charger_desc; - - charger_desc->name = pdata->name ? pdata->name : "gpio-charger"; - charger_desc->type = pdata->type; charger_desc->properties = gpio_charger_properties; charger_desc->num_properties = ARRAY_SIZE(gpio_charger_properties); charger_desc->get_property = gpio_charger_get_property; - psy_cfg.supplied_to = pdata->supplied_to; - psy_cfg.num_supplicants = pdata->num_supplicants; psy_cfg.of_node = dev->of_node; psy_cfg.drv_data = gpio_charger; + if (pdata) { + charger_desc->name = pdata->name; + charger_desc->type = pdata->type; + psy_cfg.supplied_to = pdata->supplied_to; + psy_cfg.num_supplicants = pdata->num_supplicants; + } else { + charger_desc->name = dev->of_node->name; + charger_desc->type = gpio_charger_get_type(dev); + } + + if (!charger_desc->name) + charger_desc->name = pdev->name; + gpio_charger->charger = devm_power_supply_register(dev, charger_desc, &psy_cfg); if (IS_ERR(gpio_charger->charger)) { -- cgit v1.2.3-55-g7522 From 648badd797c762a713b48afc3b67d56abdd0073b Mon Sep 17 00:00:00 2001 From: Quentin Schulz Date: Wed, 28 Feb 2018 11:35:58 +0100 Subject: power: supply: axp20x_battery: use data struct for variant specific code We used to use IDs to select a function or a feature depending on the variant. It's easier to maintain the code by adding data structure storing the few differences between variants so that we don't add a pile of if conditions. Let's use this data structure and update the code to use it. Signed-off-by: Quentin Schulz Reviewed-by: Chen-Yu Tsai [updated POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN write property to use the introduced set_max_voltage() callback] Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp20x_battery.c | 102 ++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 35 deletions(-) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c index 7494f0f0eadb..738470077f1f 100644 --- a/drivers/power/supply/axp20x_battery.c +++ b/drivers/power/supply/axp20x_battery.c @@ -53,6 +53,16 @@ #define AXP20X_V_OFF_MASK GENMASK(2, 0) +struct axp20x_batt_ps; + +struct axp_data { + int ccc_scale; + int ccc_offset; + bool has_fg_valid; + int (*get_max_voltage)(struct axp20x_batt_ps *batt, int *val); + int (*set_max_voltage)(struct axp20x_batt_ps *batt, int val); +}; + struct axp20x_batt_ps { struct regmap *regmap; struct power_supply *batt; @@ -62,7 +72,7 @@ struct axp20x_batt_ps { struct iio_channel *batt_v; /* Maximum constant charge current */ unsigned int max_ccc; - u8 axp_id; + const struct axp_data *data; }; static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt, @@ -123,22 +133,6 @@ static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt, return 0; } -static void raw_to_constant_charge_current(struct axp20x_batt_ps *axp, int *val) -{ - if (axp->axp_id == AXP209_ID) - *val = *val * 100000 + 300000; - else - *val = *val * 150000 + 300000; -} - -static void constant_charge_current_to_raw(struct axp20x_batt_ps *axp, int *val) -{ - if (axp->axp_id == AXP209_ID) - *val = (*val - 300000) / 100000; - else - *val = (*val - 300000) / 150000; -} - static int axp20x_get_constant_charge_current(struct axp20x_batt_ps *axp, int *val) { @@ -150,7 +144,7 @@ static int axp20x_get_constant_charge_current(struct axp20x_batt_ps *axp, *val &= AXP20X_CHRG_CTRL1_TGT_CURR; - raw_to_constant_charge_current(axp, val); + *val = *val * axp->data->ccc_scale + axp->data->ccc_offset; return 0; } @@ -269,8 +263,7 @@ static int axp20x_battery_get_prop(struct power_supply *psy, if (ret) return ret; - if (axp20x_batt->axp_id == AXP221_ID && - !(reg & AXP22X_FG_VALID)) + if (axp20x_batt->data->has_fg_valid && !(reg & AXP22X_FG_VALID)) return -EINVAL; /* @@ -281,11 +274,8 @@ static int axp20x_battery_get_prop(struct power_supply *psy, break; case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - if (axp20x_batt->axp_id == AXP209_ID) - return axp20x_battery_get_max_voltage(axp20x_batt, - &val->intval); - return axp22x_battery_get_max_voltage(axp20x_batt, - &val->intval); + return axp20x_batt->data->get_max_voltage(axp20x_batt, + &val->intval); case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, ®); @@ -312,6 +302,32 @@ static int axp20x_battery_get_prop(struct power_supply *psy, return 0; } +static int axp22x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt, + int val) +{ + switch (val) { + case 4100000: + val = AXP20X_CHRG_CTRL1_TGT_4_1V; + break; + + case 4200000: + val = AXP20X_CHRG_CTRL1_TGT_4_2V; + break; + + default: + /* + * AXP20x max voltage can be set to 4.36V and AXP22X max voltage + * can be set to 4.22V and 4.24V, but these voltages are too + * high for Lithium based batteries (AXP PMICs are supposed to + * be used with these kinds of battery). + */ + return -EINVAL; + } + + return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, + AXP20X_CHRG_CTRL1_TGT_VOLT, val); +} + static int axp20x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt, int val) { @@ -321,9 +337,6 @@ static int axp20x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt, break; case 4150000: - if (axp20x_batt->axp_id == AXP221_ID) - return -EINVAL; - val = AXP20X_CHRG_CTRL1_TGT_4_15V; break; @@ -351,7 +364,8 @@ static int axp20x_set_constant_charge_current(struct axp20x_batt_ps *axp_batt, if (charge_current > axp_batt->max_ccc) return -EINVAL; - constant_charge_current_to_raw(axp_batt, &charge_current); + charge_current = (charge_current - axp_batt->data->ccc_offset) / + axp_batt->data->ccc_scale; if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0) return -EINVAL; @@ -365,12 +379,14 @@ static int axp20x_set_max_constant_charge_current(struct axp20x_batt_ps *axp, { bool lower_max = false; - constant_charge_current_to_raw(axp, &charge_current); + charge_current = (charge_current - axp->data->ccc_offset) / + axp->data->ccc_scale; if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0) return -EINVAL; - raw_to_constant_charge_current(axp, &charge_current); + charge_current = charge_current * axp->data->ccc_scale + + axp->data->ccc_offset; if (charge_current > axp->max_ccc) dev_warn(axp->dev, @@ -413,7 +429,7 @@ static int axp20x_battery_set_prop(struct power_supply *psy, return axp20x_set_voltage_min_design(axp20x_batt, val->intval); case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - return axp20x_battery_set_max_voltage(axp20x_batt, val->intval); + return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval); case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: return axp20x_set_constant_charge_current(axp20x_batt, @@ -460,13 +476,28 @@ static const struct power_supply_desc axp20x_batt_ps_desc = { .set_property = axp20x_battery_set_prop, }; +static const struct axp_data axp209_data = { + .ccc_scale = 100000, + .ccc_offset = 300000, + .get_max_voltage = axp20x_battery_get_max_voltage, + .set_max_voltage = axp20x_battery_set_max_voltage, +}; + +static const struct axp_data axp221_data = { + .ccc_scale = 150000, + .ccc_offset = 300000, + .has_fg_valid = true, + .get_max_voltage = axp22x_battery_get_max_voltage, + .set_max_voltage = axp22x_battery_set_max_voltage, +}; + static const struct of_device_id axp20x_battery_ps_id[] = { { .compatible = "x-powers,axp209-battery-power-supply", - .data = (void *)AXP209_ID, + .data = (void *)&axp209_data, }, { .compatible = "x-powers,axp221-battery-power-supply", - .data = (void *)AXP221_ID, + .data = (void *)&axp221_data, }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, axp20x_battery_ps_id); @@ -476,6 +507,7 @@ static int axp20x_power_probe(struct platform_device *pdev) struct axp20x_batt_ps *axp20x_batt; struct power_supply_config psy_cfg = {}; struct power_supply_battery_info info; + struct device *dev = &pdev->dev; if (!of_device_is_available(pdev->dev.of_node)) return -ENODEV; @@ -516,7 +548,7 @@ static int axp20x_power_probe(struct platform_device *pdev) psy_cfg.drv_data = axp20x_batt; psy_cfg.of_node = pdev->dev.of_node; - axp20x_batt->axp_id = (uintptr_t)of_device_get_match_data(&pdev->dev); + axp20x_batt->data = (struct axp_data *)of_device_get_match_data(dev); axp20x_batt->batt = devm_power_supply_register(&pdev->dev, &axp20x_batt_ps_desc, -- cgit v1.2.3-55-g7522 From 6ff653e3e8b9cd53cf490e8bea888e8af3e39ea7 Mon Sep 17 00:00:00 2001 From: Quentin Schulz Date: Wed, 28 Feb 2018 11:36:00 +0100 Subject: power: supply: axp20x_battery: add support for AXP813 The X-Powers AXP813 PMIC has got some slight differences from AXP20X/AXP22X PMICs: - the maximum voltage supplied by the PMIC is 4.35 instead of 4.36/4.24 for AXP20X/AXP22X, - the constant charge current formula is different, It also has a bit to tell whether the battery percentage returned by the PMIC is valid. Signed-off-by: Quentin Schulz Reviewed-by: Chen-Yu Tsai Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp20x_battery.c | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c index 738470077f1f..e84b6e4da14a 100644 --- a/drivers/power/supply/axp20x_battery.c +++ b/drivers/power/supply/axp20x_battery.c @@ -49,6 +49,8 @@ #define AXP22X_CHRG_CTRL1_TGT_4_22V (1 << 5) #define AXP22X_CHRG_CTRL1_TGT_4_24V (3 << 5) +#define AXP813_CHRG_CTRL1_TGT_4_35V (3 << 5) + #define AXP20X_CHRG_CTRL1_TGT_CURR GENMASK(3, 0) #define AXP20X_V_OFF_MASK GENMASK(2, 0) @@ -133,6 +135,35 @@ static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt, return 0; } +static int axp813_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt, + int *val) +{ + int ret, reg; + + ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, ®); + if (ret) + return ret; + + switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) { + case AXP20X_CHRG_CTRL1_TGT_4_1V: + *val = 4100000; + break; + case AXP20X_CHRG_CTRL1_TGT_4_15V: + *val = 4150000; + break; + case AXP20X_CHRG_CTRL1_TGT_4_2V: + *val = 4200000; + break; + case AXP813_CHRG_CTRL1_TGT_4_35V: + *val = 4350000; + break; + default: + return -EINVAL; + } + + return 0; +} + static int axp20x_get_constant_charge_current(struct axp20x_batt_ps *axp, int *val) { @@ -491,6 +522,14 @@ static const struct axp_data axp221_data = { .set_max_voltage = axp22x_battery_set_max_voltage, }; +static const struct axp_data axp813_data = { + .ccc_scale = 200000, + .ccc_offset = 200000, + .has_fg_valid = true, + .get_max_voltage = axp813_battery_get_max_voltage, + .set_max_voltage = axp20x_battery_set_max_voltage, +}; + static const struct of_device_id axp20x_battery_ps_id[] = { { .compatible = "x-powers,axp209-battery-power-supply", @@ -498,6 +537,9 @@ static const struct of_device_id axp20x_battery_ps_id[] = { }, { .compatible = "x-powers,axp221-battery-power-supply", .data = (void *)&axp221_data, + }, { + .compatible = "x-powers,axp813-battery-power-supply", + .data = (void *)&axp813_data, }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, axp20x_battery_ps_id); -- cgit v1.2.3-55-g7522 From 7638eb5666eb3c216dfdef63b573933ed9740676 Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Fri, 16 Feb 2018 08:26:16 +0000 Subject: power: supply: axp288_fuel_gauge: Do not register FG on ECS EF20EA The ECS EF20EA laptop ships an AXP288 but it is actually using a different, separate FG chip for AC and battery monitoring. On this laptop we need to keep using the regular ACPI driver and disable the AXP288 FG to avoid reporting two batteries to userspace. Signed-off-by: Carlo Caione Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_fuel_gauge.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c index 4cc6e038dfdd..903891a9bcf0 100644 --- a/drivers/power/supply/axp288_fuel_gauge.c +++ b/drivers/power/supply/axp288_fuel_gauge.c @@ -708,6 +708,12 @@ static const struct dmi_system_id axp288_fuel_gauge_blacklist[] = { DMI_MATCH(DMI_BOARD_VERSION, "V1.1"), }, }, + { + /* ECS EF20EA */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), + }, + }, {} }; -- cgit v1.2.3-55-g7522 From f451655c722b6f8a15d152d7912ab8526a3fe8bd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 15 Feb 2018 15:00:36 +0100 Subject: power: supply: axp288_fuel_gauge: Fix full status reporting Commit 2b5a4b4bf222 ("power: supply: axp288_fuel_gauge: Rework get_status()"), switched from 0A current detection to using the capacity register for full detection. It turns out this fixes full reporting on some devices which keep trickle charging long after the capacity register reach 100%, but breaks it on some other devices where the charger stops charging before the capacity register reaches 100%. This commit fixes this by also checking for 0A current when the reported capacity is above 90%. Fixes: 2b5a4b4bf222 ("psy: axp288_fuel_gauge: Rework get_status()") Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_fuel_gauge.c | 47 ++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 12 deletions(-) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c index 903891a9bcf0..fd8f0b2210bc 100644 --- a/drivers/power/supply/axp288_fuel_gauge.c +++ b/drivers/power/supply/axp288_fuel_gauge.c @@ -343,7 +343,7 @@ static inline void fuel_gauge_remove_debugfs(struct axp288_fg_info *info) static void fuel_gauge_get_status(struct axp288_fg_info *info) { - int pwr_stat, fg_res; + int pwr_stat, fg_res, curr, ret; pwr_stat = fuel_gauge_reg_readb(info, AXP20X_PWR_INPUT_STATUS); if (pwr_stat < 0) { @@ -353,19 +353,42 @@ static void fuel_gauge_get_status(struct axp288_fg_info *info) } /* Report full if Vbus is valid and the reported capacity is 100% */ - if (pwr_stat & PS_STAT_VBUS_VALID) { - fg_res = fuel_gauge_reg_readb(info, AXP20X_FG_RES); - if (fg_res < 0) { - dev_err(&info->pdev->dev, - "FG RES read failed: %d\n", fg_res); - return; - } - if (fg_res == (FG_REP_CAP_VALID | 100)) { - info->status = POWER_SUPPLY_STATUS_FULL; - return; - } + if (!(pwr_stat & PS_STAT_VBUS_VALID)) + goto not_full; + + fg_res = fuel_gauge_reg_readb(info, AXP20X_FG_RES); + if (fg_res < 0) { + dev_err(&info->pdev->dev, "FG RES read failed: %d\n", fg_res); + return; + } + if (!(fg_res & FG_REP_CAP_VALID)) + goto not_full; + + fg_res &= ~FG_REP_CAP_VALID; + if (fg_res == 100) { + info->status = POWER_SUPPLY_STATUS_FULL; + return; + } + + /* + * Sometimes the charger turns itself off before fg-res reaches 100%. + * When this happens the AXP288 reports a not-charging status and + * 0 mA discharge current. + */ + if (fg_res < 90 || (pwr_stat & PS_STAT_BAT_CHRG_DIR)) + goto not_full; + + ret = iio_read_channel_raw(info->iio_channel[BAT_D_CURR], &curr); + if (ret < 0) { + dev_err(&info->pdev->dev, "FG get current failed: %d\n", ret); + return; + } + if (curr == 0) { + info->status = POWER_SUPPLY_STATUS_FULL; + return; } +not_full: if (pwr_stat & PS_STAT_BAT_CHRG_DIR) info->status = POWER_SUPPLY_STATUS_CHARGING; else -- cgit v1.2.3-55-g7522 From 66ec32fc7cd116dab5c02603ea8ec28ff92da3b5 Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Tue, 20 Feb 2018 16:03:18 +0100 Subject: max17042: propagate of_node to power supply device max17042_get_status uses the core power_supply_am_i_supplied. That function relies on DT properties to figure out the power supply topology, and will error out without DT. Fixes max17042 battery status being reported as "unknown". Signed-off-by: Pierre Bourdon Signed-off-by: Andre Heider Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 35dde81b1c9b..1a568df383db 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -1053,6 +1053,7 @@ static int max17042_probe(struct i2c_client *client, i2c_set_clientdata(client, chip); psy_cfg.drv_data = chip; + psy_cfg.of_node = dev->of_node; /* When current is not measured, * CURRENT_NOW and CURRENT_AVG properties should be invisible. */ -- cgit v1.2.3-55-g7522 From f72c14ad8c6631a0a42115e74164f9b5faf4c724 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Thu, 15 Feb 2018 21:28:40 +0100 Subject: power: supply: bq27xxx: support missing supplier device power_supply_am_i_supplied() can return negative error codes. In this case we should assume, that no charger is connected and the battery should be marked as DISCHARGING instead of NOT_CHARGING. Reported-by: Merlijn Wajer Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq27xxx_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c index d99981542a46..7ce60519b1bc 100644 --- a/drivers/power/supply/bq27xxx_battery.c +++ b/drivers/power/supply/bq27xxx_battery.c @@ -1670,7 +1670,7 @@ static int bq27xxx_battery_status(struct bq27xxx_device_info *di, status = POWER_SUPPLY_STATUS_FULL; else if (di->cache.flags & BQ27000_FLAG_CHGS) status = POWER_SUPPLY_STATUS_CHARGING; - else if (power_supply_am_i_supplied(di->bat)) + else if (power_supply_am_i_supplied(di->bat) > 0) status = POWER_SUPPLY_STATUS_NOT_CHARGING; else status = POWER_SUPPLY_STATUS_DISCHARGING; -- cgit v1.2.3-55-g7522 From 90ad4cc203c025788ccaf70dc1e57fbf43702c4d Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Wed, 21 Feb 2018 12:42:20 +0100 Subject: power: supply: bq2415x: add DT referencing support Add support for using bq2415x together with power_supply_am_i_supplied(). Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq2415x_charger.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/bq2415x_charger.c b/drivers/power/supply/bq2415x_charger.c index c4770a94cc8e..cbec70f3e73e 100644 --- a/drivers/power/supply/bq2415x_charger.c +++ b/drivers/power/supply/bq2415x_charger.c @@ -1037,7 +1037,10 @@ static int bq2415x_power_supply_init(struct bq2415x_device *bq) int ret; int chip; char revstr[8]; - struct power_supply_config psy_cfg = { .drv_data = bq, }; + struct power_supply_config psy_cfg = { + .drv_data = bq, + .of_node = bq->dev->of_node, + }; bq->charger_desc.name = bq->name; bq->charger_desc.type = POWER_SUPPLY_TYPE_USB; -- cgit v1.2.3-55-g7522 From fc5a7f0339d0641c0df14a9ed8af49c9992f9bef Mon Sep 17 00:00:00 2001 From: Gustavo A. R. Silva Date: Fri, 9 Mar 2018 12:27:08 -0600 Subject: power: supply: da9150-fg: remove VLA usage In preparation to enabling -Wvla, remove VLA usage and replace it with fixed-length arrays. DA9150_QIF_LONG_SIZE (4 bytes) is the biggest size of an attribute which can be accessed [1]. Fixed as part of the directive to remove all VLAs from the kernel: https://lkml.org/lkml/2018/3/7/621 [1] https://marc.info/?l=kernel-hardening&m=152059600524753&w=2 Signed-off-by: Gustavo A. R. Silva Acked-by: Adam Thomson Signed-off-by: Sebastian Reichel --- drivers/power/supply/da9150-fg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/power/supply') diff --git a/drivers/power/supply/da9150-fg.c b/drivers/power/supply/da9150-fg.c index 8b8ce978656a..1e2e5b0520c9 100644 --- a/drivers/power/supply/da9150-fg.c +++ b/drivers/power/supply/da9150-fg.c @@ -92,7 +92,7 @@ struct da9150_fg { static u32 da9150_fg_read_attr(struct da9150_fg *fg, u8 code, u8 size) { - u8 buf[size]; + u8 buf[DA9150_QIF_LONG_SIZE]; u8 read_addr; u32 res = 0; int i; @@ -111,7 +111,7 @@ static void da9150_fg_write_attr(struct da9150_fg *fg, u8 code, u8 size, u32 val) { - u8 buf[size]; + u8 buf[DA9150_QIF_LONG_SIZE]; u8 write_addr; int i; -- cgit v1.2.3-55-g7522