Merge tag 'for-v5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 8 Mar 2019 17:24:00 +0000 (09:24 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 8 Mar 2019 17:24:00 +0000 (09:24 -0800)
Pull power supply and reset updates from Sebastian Reichel:
 "Nothing too fancy in the power-supply subsystem this time. There are
  less patches than usual, since I did not have enough time to review
  them in time. The good news is, that all patches have been in
  linux-next for more than two weeks and there are no complicated
  cross-subsystem patchsets this time!

  Summary:

   - at91-reset: add sam9x60 support

   - sc27xx: improve capacity logic

   - goldfish_battery: enhance driver by adding many new properties

   - isp1704: drop platform data and migrate to gpiod

   - misc small fixes and improvements"

* tag 'for-v5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (25 commits)
  power: reset: at91-reset: add support for sam9x60 SoC
  dt-bindings: arm: atmel: add new sam9x60 reset controller binding
  dt-bindings: arm: atmel: add missing samx7 to reset controller
  max17042_battery: fix potential use-after-free on device remove
  power: supply: core: Add a field to support battery max voltage
  dt-bindings: power: supply: Add voltage-max-design-microvolt property
  bq27x00: use cached flags
  power: supply: ds2782: fix possible use-after-free on remove
  power: supply: bq25890: show max charge current/voltage as configured
  power: supply: sc27xx: Fix capacity saving function
  power: supply: sc27xx: Fix the incorrect formula when converting capacity to coulomb counter
  power: supply: sc27xx: Add one property to read charge voltage
  dt-bindings: power: sc27xx: Add one IIO channel to read charge voltage
  drivers: power: supply: goldfish_battery: Add support for reading more properties
  power: supply: charger-manager: Fix trivial language typos
  cpcap-charger: generate events for userspace
  power: supply: remove some duplicated includes
  power: twl4030: fix a missing check of return value
  drivers: power: supply: goldfish_battery: Use tabs for alignment
  drivers: power: supply: goldfish_battery: Fix alignment
  ...

18 files changed:
Documentation/devicetree/bindings/arm/atmel-sysregs.txt
Documentation/devicetree/bindings/power/supply/battery.txt
Documentation/devicetree/bindings/power/supply/sc27xx-fg.txt
drivers/power/reset/at91-reset.c
drivers/power/supply/axp288_fuel_gauge.c
drivers/power/supply/bq25890_charger.c
drivers/power/supply/bq27xxx_battery.c
drivers/power/supply/charger-manager.c
drivers/power/supply/cpcap-charger.c
drivers/power/supply/ds2782_battery.c
drivers/power/supply/goldfish_battery.c
drivers/power/supply/isp1704_charger.c
drivers/power/supply/max17042_battery.c
drivers/power/supply/power_supply_core.c
drivers/power/supply/sc27xx_fuel_gauge.c
drivers/power/supply/twl4030_charger.c
include/linux/power/isp1704_charger.h [deleted file]
include/linux/power_supply.h

index 3363d9ae4e7436999d4c9bf2e6d6cf0038a672c9..e61d00e25b9572487231438ec668392d7d46e3fc 100644 (file)
@@ -21,7 +21,8 @@ Its subnodes can be:
 
 RSTC Reset Controller required properties:
 - compatible: Should be "atmel,<chip>-rstc".
-  <chip> can be "at91sam9260" or "at91sam9g45" or "sama5d3"
+  <chip> can be "at91sam9260", "at91sam9g45", "sama5d3" or "samx7"
+  it also can be "microchip,sam9x60-rstc"
 - reg: Should contain registers location and length
 - clocks: phandle to input clock.
 
index 89871ab8c7040a3d02e309d9d9e0375438243b73..5c913d4cf36ca4840476729b69bda002af181806 100644 (file)
@@ -16,6 +16,7 @@ Required Properties:
 
 Optional Properties:
  - voltage-min-design-microvolt: drained battery voltage
+ - voltage-max-design-microvolt: fully charged battery voltage
  - energy-full-design-microwatt-hours: battery design energy
  - charge-full-design-microamp-hours: battery design capacity
  - precharge-current-microamp: current for pre-charge phase
@@ -48,6 +49,7 @@ Example:
        bat: battery {
                compatible = "simple-battery";
                voltage-min-design-microvolt = <3200000>;
+               voltage-max-design-microvolt = <4200000>;
                energy-full-design-microwatt-hours = <5290000>;
                charge-full-design-microamp-hours = <1430000>;
                precharge-current-microamp = <256000>;
index fc35ac577401d249ff365104baa17a4d879b1a4e..0a5705b8b59294de600d37b49ee60fea42e1cafe 100644 (file)
@@ -9,8 +9,8 @@ Required properties:
   "sprd,sc2731-fgu".
 - reg: The address offset of fuel gauge unit.
 - battery-detect-gpios: GPIO for battery detection.
-- io-channels: Specify the IIO ADC channel to get temperature.
-- io-channel-names: Should be "bat-temp".
+- io-channels: Specify the IIO ADC channels to get temperature and charge voltage.
+- io-channel-names: Should be "bat-temp" or "charge-vol".
 - nvmem-cells: A phandle to the calibration cells provided by eFuse device.
 - nvmem-cell-names: Should be "fgu_calib".
 - monitored-battery: Phandle of battery characteristics devicetree node.
@@ -47,8 +47,8 @@ Example:
                        compatible = "sprd,sc2731-fgu";
                        reg = <0xa00>;
                        battery-detect-gpios = <&pmic_eic 9 GPIO_ACTIVE_HIGH>;
-                       io-channels = <&pmic_adc 5>;
-                       io-channel-names = "bat-temp";
+                       io-channels = <&pmic_adc 5>, <&pmic_adc 14>;
+                       io-channel-names = "bat-temp", "charge-vol";
                        nvmem-cells = <&fgu_calib>;
                        nvmem-cell-names = "fgu_calib";
                        monitored-battery = <&bat>;
index f44a9ffcc2ab32bb82344a5252e4738b36721e25..44ca983a49a1b32b8361c5bdd5fb4c3c337f4243 100644 (file)
@@ -44,6 +44,9 @@ enum reset_type {
        RESET_TYPE_WATCHDOG     = 2,
        RESET_TYPE_SOFTWARE     = 3,
        RESET_TYPE_USER         = 4,
+       RESET_TYPE_CPU_FAIL     = 6,
+       RESET_TYPE_XTAL_FAIL    = 7,
+       RESET_TYPE_ULP2         = 8,
 };
 
 static void __iomem *at91_ramc_base[2], *at91_rstc_base;
@@ -164,6 +167,15 @@ static void __init at91_reset_status(struct platform_device *pdev)
        case RESET_TYPE_USER:
                reason = "user reset";
                break;
+       case RESET_TYPE_CPU_FAIL:
+               reason = "CPU clock failure detection";
+               break;
+       case RESET_TYPE_XTAL_FAIL:
+               reason = "32.768 kHz crystal failure detection";
+               break;
+       case RESET_TYPE_ULP2:
+               reason = "ULP2 reset";
+               break;
        default:
                reason = "unknown reset";
                break;
@@ -183,6 +195,7 @@ static const struct of_device_id at91_reset_of_match[] = {
        { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
        { .compatible = "atmel,sama5d3-rstc", .data = sama5d3_restart },
        { .compatible = "atmel,samx7-rstc", .data = samx7_restart },
+       { .compatible = "microchip,sam9x60-rstc", .data = samx7_restart },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, at91_reset_of_match);
index 084c8ba9749d7cc45500c4e419fb18855252e44d..9ff2461820d805c3abd7de964f04f4fc1cb217bc 100644 (file)
@@ -307,22 +307,12 @@ static int fuel_gauge_debug_show(struct seq_file *s, void *data)
        return 0;
 }
 
-static int debug_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, fuel_gauge_debug_show, inode->i_private);
-}
-
-static const struct file_operations fg_debug_fops = {
-       .open       = debug_open,
-       .read       = seq_read,
-       .llseek     = seq_lseek,
-       .release    = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(fuel_gauge_debug);
 
 static void fuel_gauge_create_debugfs(struct axp288_fg_info *info)
 {
        info->debug_file = debugfs_create_file("fuelgauge", 0666, NULL,
-               info, &fg_debug_fops);
+               info, &fuel_gauge_debug_fops);
 }
 
 static void fuel_gauge_remove_debugfs(struct axp288_fg_info *info)
index 3f6fb49c956cc5ded343bda7d75361c4f5140964..66991e6f75d99ab8e98afd04fb9c63426866107b 100644 (file)
@@ -436,7 +436,7 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
                break;
 
        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
-               val->intval = bq25890_tables[TBL_ICHG].rt.max;
+               val->intval = bq25890_find_val(bq->init_data.ichg, TBL_ICHG);
                break;
 
        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
@@ -454,7 +454,7 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
                break;
 
        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
-               val->intval = bq25890_tables[TBL_VREG].rt.max;
+               val->intval = bq25890_find_val(bq->init_data.vreg, TBL_VREG);
                break;
 
        case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
index 6dbbe95844a396b2cb7c55d3104598f5a216478e..29b3a40568650695990c0dcb9e5a0f1ca1192cc0 100644 (file)
@@ -1555,27 +1555,14 @@ static bool bq27xxx_battery_dead(struct bq27xxx_device_info *di, u16 flags)
                return flags & (BQ27XXX_FLAG_SOC1 | BQ27XXX_FLAG_SOCF);
 }
 
-/*
- * Read flag register.
- * Return < 0 if something fails.
- */
 static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
 {
-       int flags;
-       bool has_singe_flag = di->opts & BQ27XXX_O_ZERO;
-
-       flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
-       if (flags < 0) {
-               dev_err(di->dev, "error reading flag register:%d\n", flags);
-               return flags;
-       }
-
        /* Unlikely but important to return first */
-       if (unlikely(bq27xxx_battery_overtemp(di, flags)))
+       if (unlikely(bq27xxx_battery_overtemp(di, di->cache.flags)))
                return POWER_SUPPLY_HEALTH_OVERHEAT;
-       if (unlikely(bq27xxx_battery_undertemp(di, flags)))
+       if (unlikely(bq27xxx_battery_undertemp(di, di->cache.flags)))
                return POWER_SUPPLY_HEALTH_COLD;
-       if (unlikely(bq27xxx_battery_dead(di, flags)))
+       if (unlikely(bq27xxx_battery_dead(di, di->cache.flags)))
                return POWER_SUPPLY_HEALTH_DEAD;
 
        return POWER_SUPPLY_HEALTH_GOOD;
@@ -1612,6 +1599,7 @@ void bq27xxx_battery_update(struct bq27xxx_device_info *di)
                        cache.capacity = bq27xxx_battery_read_soc(di);
                        if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
                                cache.energy = bq27xxx_battery_read_energy(di);
+                       di->cache.flags = cache.flags;
                        cache.health = bq27xxx_battery_read_health(di);
                }
                if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
index 38be91f21cc433b6f4179aefa6cf5ce60f5b7b01..2e8db5e6de0bcb6af1bec0cc46ec106312ca796b 100644 (file)
@@ -4,7 +4,7 @@
  *
  * This driver enables to monitor battery health and control charger
  * during suspend-to-mem.
- * Charger manager depends on other devices. register this later than
+ * Charger manager depends on other devices. Register this later than
  * the depending devices.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -29,7 +29,7 @@
 #include <linux/thermal.h>
 
 /*
- * Default termperature threshold for charging.
+ * Default temperature threshold for charging.
  * Every temperature units are in tenth of centigrade.
  */
 #define CM_DEFAULT_RECHARGE_TEMP_DIFF  50
@@ -356,7 +356,7 @@ static bool is_polling_required(struct charger_manager *cm)
  * Note that Charger Manager keeps the charger enabled regardless whether
  * the charger is charging or not (because battery is full or no external
  * power source exists) except when CM needs to disable chargers forcibly
- * bacause of emergency causes; when the battery is overheated or too cold.
+ * because of emergency causes; when the battery is overheated or too cold.
  */
 static int try_charger_enable(struct charger_manager *cm, bool enable)
 {
@@ -643,7 +643,7 @@ static int cm_check_thermal_status(struct charger_manager *cm)
        if (ret) {
                /* FIXME:
                 * No information of battery temperature might
-                * occur hazadous result. We have to handle it
+                * occur hazardous result. We have to handle it
                 * depending on battery type.
                 */
                dev_err(cm->dev, "Failed to get battery temperature\n");
@@ -693,7 +693,7 @@ static bool _cm_monitor(struct charger_manager *cm)
                        uevent_notify(cm, default_event_names[temp_alrt]);
 
        /*
-        * Check whole charging duration and discharing duration
+        * Check whole charging duration and discharging duration
         * after full-batt.
         */
        } else if (!cm->emergency_stop && check_charging_duration(cm)) {
@@ -866,7 +866,7 @@ static void battout_handler(struct charger_manager *cm)
 }
 
 /**
- * misc_event_handler - Handler for other evnets
+ * misc_event_handler - Handler for other events
  * @cm: the Charger Manager representing the battery.
  * @type: the Charger Manager representing the battery.
  */
@@ -1218,7 +1218,7 @@ static int charger_extcon_init(struct charger_manager *cm,
 }
 
 /**
- * charger_manager_register_extcon - Register extcon device to recevie state
+ * charger_manager_register_extcon - Register extcon device to receive state
  *                                  of charger cable.
  * @cm: the Charger Manager representing the battery.
  *
@@ -1538,7 +1538,7 @@ static struct charger_desc *of_cm_parse_desc(struct device *dev)
        of_property_read_u32(np, "cm-discharging-max",
                                &desc->discharging_max_duration_ms);
 
-       /* battery charger regualtors */
+       /* battery charger regulators */
        desc->num_charger_regulators = of_get_child_count(np);
        if (desc->num_charger_regulators) {
                struct charger_regulator *chg_regs;
@@ -1801,7 +1801,7 @@ static int charger_manager_probe(struct platform_device *pdev)
 
        /*
         * Charger-manager have to check the charging state right after
-        * tialization of charger-manager and then update current charging
+        * initialization of charger-manager and then update current charging
         * state.
         */
        cm_monitor();
index c843eaff8ad055ae3a3de0067ca1edbf9d09716e..c3ed7b476676dd069ce22efa0df02c3200aaa5b3 100644 (file)
@@ -458,6 +458,7 @@ static void cpcap_usb_detect(struct work_struct *work)
                        goto out_err;
        }
 
+       power_supply_changed(ddata->usb);
        return;
 
 out_err:
index 019c58493e3d5a833b48b3b4256c6ebbd8440455..04b0fe7d7d625c2fa9dc4cb86f71df7af3e83b86 100644 (file)
@@ -319,17 +319,17 @@ static void ds278x_power_supply_init(struct power_supply_desc *battery)
 static int ds278x_battery_remove(struct i2c_client *client)
 {
        struct ds278x_info *info = i2c_get_clientdata(client);
+       int id = info->id;
 
        power_supply_unregister(info->battery);
+       cancel_delayed_work_sync(&info->bat_work);
        kfree(info->battery_desc.name);
+       kfree(info);
 
        mutex_lock(&battery_lock);
-       idr_remove(&battery_id, info->id);
+       idr_remove(&battery_id, id);
        mutex_unlock(&battery_lock);
 
-       cancel_delayed_work(&info->bat_work);
-
-       kfree(info);
        return 0;
 }
 
index f5c525e4482a18b533ad80c09b1e8a7da8be06a8..ad969d9fc9815a173385588e034a1c650ba6c868 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL
 /*
  * Power supply driver for the goldfish emulator
  *
@@ -5,15 +6,6 @@
  * Copyright (C) 2012 Intel, Inc.
  * Copyright (C) 2013 Intel, Inc.
  * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
@@ -40,27 +32,30 @@ struct goldfish_battery_data {
 #define GOLDFISH_BATTERY_WRITE(data, addr, x) \
        (writel(x, data->reg_base + addr))
 
-/*
- * Temporary variable used between goldfish_battery_probe() and
- * goldfish_battery_open().
- */
-static struct goldfish_battery_data *battery_data;
-
 enum {
        /* status register */
-       BATTERY_INT_STATUS          = 0x00,
+       BATTERY_INT_STATUS      = 0x00,
        /* set this to enable IRQ */
-       BATTERY_INT_ENABLE          = 0x04,
-
-       BATTERY_AC_ONLINE       = 0x08,
-       BATTERY_STATUS          = 0x0C,
-       BATTERY_HEALTH          = 0x10,
-       BATTERY_PRESENT         = 0x14,
-       BATTERY_CAPACITY        = 0x18,
+       BATTERY_INT_ENABLE      = 0x04,
+
+       BATTERY_AC_ONLINE       = 0x08,
+       BATTERY_STATUS          = 0x0C,
+       BATTERY_HEALTH          = 0x10,
+       BATTERY_PRESENT         = 0x14,
+       BATTERY_CAPACITY        = 0x18,
+       BATTERY_VOLTAGE         = 0x1C,
+       BATTERY_TEMP            = 0x20,
+       BATTERY_CHARGE_COUNTER  = 0x24,
+       BATTERY_VOLTAGE_MAX     = 0x28,
+       BATTERY_CURRENT_MAX     = 0x2C,
+       BATTERY_CURRENT_NOW     = 0x30,
+       BATTERY_CURRENT_AVG     = 0x34,
+       BATTERY_CHARGE_FULL_UAH = 0x38,
+       BATTERY_CYCLE_COUNT     = 0x40,
 
        BATTERY_STATUS_CHANGED  = 1U << 0,
        AC_STATUS_CHANGED       = 1U << 1,
-       BATTERY_INT_MASK        = BATTERY_STATUS_CHANGED | AC_STATUS_CHANGED,
+       BATTERY_INT_MASK        = BATTERY_STATUS_CHANGED | AC_STATUS_CHANGED,
 };
 
 
@@ -75,6 +70,12 @@ static int goldfish_ac_get_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_ONLINE:
                val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_AC_ONLINE);
                break;
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+               val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_VOLTAGE_MAX);
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_MAX:
+               val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_CURRENT_MAX);
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -105,6 +106,29 @@ static int goldfish_battery_get_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_CAPACITY:
                val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_CAPACITY);
                break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_VOLTAGE);
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+               val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_TEMP);
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+               val->intval = GOLDFISH_BATTERY_READ(data,
+                                                   BATTERY_CHARGE_COUNTER);
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_CURRENT_NOW);
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_AVG:
+               val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_CURRENT_AVG);
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_FULL:
+               val->intval = GOLDFISH_BATTERY_READ(data,
+                                                   BATTERY_CHARGE_FULL_UAH);
+               break;
+       case POWER_SUPPLY_PROP_CYCLE_COUNT:
+               val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_CYCLE_COUNT);
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -119,10 +143,19 @@ static enum power_supply_property goldfish_battery_props[] = {
        POWER_SUPPLY_PROP_PRESENT,
        POWER_SUPPLY_PROP_TECHNOLOGY,
        POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_TEMP,
+       POWER_SUPPLY_PROP_CHARGE_COUNTER,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_CURRENT_AVG,
+       POWER_SUPPLY_PROP_CHARGE_FULL,
+       POWER_SUPPLY_PROP_CYCLE_COUNT,
 };
 
 static enum power_supply_property goldfish_ac_props[] = {
        POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_VOLTAGE_MAX,
+       POWER_SUPPLY_PROP_CURRENT_MAX,
 };
 
 static irqreturn_t goldfish_battery_interrupt(int irq, void *dev_id)
@@ -193,8 +226,9 @@ static int goldfish_battery_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       ret = devm_request_irq(&pdev->dev, data->irq, goldfish_battery_interrupt,
-                                               IRQF_SHARED, pdev->name, data);
+       ret = devm_request_irq(&pdev->dev, data->irq,
+                              goldfish_battery_interrupt,
+                              IRQF_SHARED, pdev->name, data);
        if (ret)
                return ret;
 
@@ -212,7 +246,6 @@ static int goldfish_battery_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, data);
-       battery_data = data;
 
        GOLDFISH_BATTERY_WRITE(data, BATTERY_INT_ENABLE, BATTERY_INT_MASK);
        return 0;
@@ -224,7 +257,6 @@ static int goldfish_battery_remove(struct platform_device *pdev)
 
        power_supply_unregister(data->battery);
        power_supply_unregister(data->ac);
-       battery_data = NULL;
        return 0;
 }
 
index 95af5f305838a6508bf1b95988a28854d829a6dc..a63cb5dcfa08e6b885c92ff56ec10c9aa5a5b816 100644 (file)
 #include <linux/power_supply.h>
 #include <linux/delay.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
 
+#include <linux/gpio/consumer.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-#include <linux/power/isp1704_charger.h>
 
 /* Vendor specific Power Control register */
 #define ISP1704_PWR_CTRL               0x3d
@@ -60,6 +59,7 @@ struct isp1704_charger {
        struct device                   *dev;
        struct power_supply             *psy;
        struct power_supply_desc        psy_desc;
+       struct gpio_desc                *enable_gpio;
        struct usb_phy                  *phy;
        struct notifier_block           nb;
        struct work_struct              work;
@@ -81,18 +81,9 @@ static inline int isp1704_write(struct isp1704_charger *isp, u32 reg, u32 val)
        return usb_phy_io_write(isp->phy, val, reg);
 }
 
-/*
- * Disable/enable the power from the isp1704 if a function for it
- * has been provided with platform data.
- */
 static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on)
 {
-       struct isp1704_charger_data     *board = isp->dev->platform_data;
-
-       if (board && board->set_power)
-               board->set_power(on);
-       else if (board)
-               gpio_set_value(board->enable_gpio, on);
+       gpiod_set_value(isp->enable_gpio, on);
 }
 
 /*
@@ -405,46 +396,19 @@ static int isp1704_charger_probe(struct platform_device *pdev)
        int                     ret = -ENODEV;
        struct power_supply_config psy_cfg = {};
 
-       struct isp1704_charger_data *pdata = dev_get_platdata(&pdev->dev);
-       struct device_node *np = pdev->dev.of_node;
-
-       if (np) {
-               int gpio = of_get_named_gpio(np, "nxp,enable-gpio", 0);
-
-               if (gpio < 0) {
-                       dev_err(&pdev->dev, "missing DT GPIO nxp,enable-gpio\n");
-                       return gpio;
-               }
-
-               pdata = devm_kzalloc(&pdev->dev,
-                       sizeof(struct isp1704_charger_data), GFP_KERNEL);
-               if (!pdata) {
-                       ret = -ENOMEM;
-                       goto fail0;
-               }
-               pdata->enable_gpio = gpio;
-
-               dev_info(&pdev->dev, "init gpio %d\n", pdata->enable_gpio);
-
-               ret = devm_gpio_request_one(&pdev->dev, pdata->enable_gpio,
-                                       GPIOF_OUT_INIT_HIGH, "isp1704_reset");
-               if (ret) {
-                       dev_err(&pdev->dev, "gpio request failed\n");
-                       goto fail0;
-               }
-       }
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "missing platform data!\n");
-               return -ENODEV;
-       }
-
-
        isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL);
        if (!isp)
                return -ENOMEM;
 
-       if (np)
+       isp->enable_gpio = devm_gpiod_get(&pdev->dev, "nxp,enable",
+                                         GPIOD_OUT_HIGH);
+       if (IS_ERR(isp->enable_gpio)) {
+               ret = PTR_ERR(isp->enable_gpio);
+               dev_err(&pdev->dev, "Could not get reset gpio: %d\n", ret);
+               return ret;
+       }
+
+       if (pdev->dev.of_node)
                isp->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
        else
                isp->phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
index 2a8d75e5e9304593d5599c5c26e77adf57653fe4..581c6bd23388e0cb486dd229050e987967c6543d 100644 (file)
@@ -995,6 +995,13 @@ static const struct power_supply_desc max17042_no_current_sense_psy_desc = {
        .num_properties = ARRAY_SIZE(max17042_battery_props) - 2,
 };
 
+static void max17042_stop_work(void *data)
+{
+       struct max17042_chip *chip = data;
+
+       cancel_work_sync(&chip->work);
+}
+
 static int max17042_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
@@ -1101,6 +1108,9 @@ static int max17042_probe(struct i2c_client *client,
        regmap_read(chip->regmap, MAX17042_STATUS, &val);
        if (val & STATUS_POR_BIT) {
                INIT_WORK(&chip->work, max17042_init_worker);
+               ret = devm_add_action(&client->dev, max17042_stop_work, chip);
+               if (ret)
+                       return ret;
                schedule_work(&chip->work);
        } else {
                chip->init_complete = 1;
index 569790ea6917e0895e95e6c32ec7230b58ed5099..c917a8b43b2bc29ef29a538c80eb433bb1e6266f 100644 (file)
@@ -156,8 +156,6 @@ static void power_supply_deferred_register_work(struct work_struct *work)
 }
 
 #ifdef CONFIG_OF
-#include <linux/of.h>
-
 static int __power_supply_populate_supplied_from(struct device *dev,
                                                 void *data)
 {
@@ -575,6 +573,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
        info->energy_full_design_uwh         = -EINVAL;
        info->charge_full_design_uah         = -EINVAL;
        info->voltage_min_design_uv          = -EINVAL;
+       info->voltage_max_design_uv          = -EINVAL;
        info->precharge_current_ua           = -EINVAL;
        info->charge_term_current_ua         = -EINVAL;
        info->constant_charge_current_max_ua = -EINVAL;
@@ -615,6 +614,8 @@ int power_supply_get_battery_info(struct power_supply *psy,
                             &info->charge_full_design_uah);
        of_property_read_u32(battery_np, "voltage-min-design-microvolt",
                             &info->voltage_min_design_uv);
+       of_property_read_u32(battery_np, "voltage-max-design-microvolt",
+                            &info->voltage_max_design_uv);
        of_property_read_u32(battery_np, "precharge-current-microamp",
                             &info->precharge_current_ua);
        of_property_read_u32(battery_np, "charge-term-current-microamp",
index 76da1895b782e6ee1f0ba62becd11619c838d5c9..24895cc3b41e0c55210aef317c3d4fb65ab13592 100644 (file)
@@ -72,6 +72,7 @@
  * @lock: protect the structure
  * @gpiod: GPIO for battery detection
  * @channel: IIO channel to get battery temperature
+ * @charge_chan: IIO channel to get charge voltage
  * @internal_resist: the battery internal resistance in mOhm
  * @total_cap: the total capacity of the battery in mAh
  * @init_cap: the initial capacity of the battery in mAh
@@ -92,6 +93,7 @@ struct sc27xx_fgu_data {
        struct mutex lock;
        struct gpio_desc *gpiod;
        struct iio_channel *channel;
+       struct iio_channel *charge_chan;
        bool bat_present;
        int internal_resist;
        int total_cap;
@@ -169,10 +171,37 @@ static int sc27xx_fgu_save_boot_mode(struct sc27xx_fgu_data *data,
        if (ret)
                return ret;
 
+       /*
+        * Since the user area registers are put on power always-on region,
+        * then these registers changing time will be a little long. Thus
+        * here we should delay 200us to wait until values are updated
+        * successfully according to the datasheet.
+        */
+       udelay(200);
+
+       ret = regmap_update_bits(data->regmap,
+                                data->base + SC27XX_FGU_USER_AREA_SET,
+                                SC27XX_FGU_MODE_AREA_MASK,
+                                boot_mode << SC27XX_FGU_MODE_AREA_SHIFT);
+       if (ret)
+               return ret;
+
+       /*
+        * Since the user area registers are put on power always-on region,
+        * then these registers changing time will be a little long. Thus
+        * here we should delay 200us to wait until values are updated
+        * successfully according to the datasheet.
+        */
+       udelay(200);
+
+       /*
+        * According to the datasheet, we should set the USER_AREA_CLEAR to 0 to
+        * make the user area data available, otherwise we can not save the user
+        * area data.
+        */
        return regmap_update_bits(data->regmap,
-                                 data->base + SC27XX_FGU_USER_AREA_SET,
-                                 SC27XX_FGU_MODE_AREA_MASK,
-                                 boot_mode << SC27XX_FGU_MODE_AREA_SHIFT);
+                                 data->base + SC27XX_FGU_USER_AREA_CLEAR,
+                                 SC27XX_FGU_MODE_AREA_MASK, 0);
 }
 
 static int sc27xx_fgu_save_last_cap(struct sc27xx_fgu_data *data, int cap)
@@ -186,9 +215,36 @@ static int sc27xx_fgu_save_last_cap(struct sc27xx_fgu_data *data, int cap)
        if (ret)
                return ret;
 
+       /*
+        * Since the user area registers are put on power always-on region,
+        * then these registers changing time will be a little long. Thus
+        * here we should delay 200us to wait until values are updated
+        * successfully according to the datasheet.
+        */
+       udelay(200);
+
+       ret = regmap_update_bits(data->regmap,
+                                data->base + SC27XX_FGU_USER_AREA_SET,
+                                SC27XX_FGU_CAP_AREA_MASK, cap);
+       if (ret)
+               return ret;
+
+       /*
+        * Since the user area registers are put on power always-on region,
+        * then these registers changing time will be a little long. Thus
+        * here we should delay 200us to wait until values are updated
+        * successfully according to the datasheet.
+        */
+       udelay(200);
+
+       /*
+        * According to the datasheet, we should set the USER_AREA_CLEAR to 0 to
+        * make the user area data available, otherwise we can not save the user
+        * area data.
+        */
        return regmap_update_bits(data->regmap,
-                                 data->base + SC27XX_FGU_USER_AREA_SET,
-                                 SC27XX_FGU_CAP_AREA_MASK, cap);
+                                 data->base + SC27XX_FGU_USER_AREA_CLEAR,
+                                 SC27XX_FGU_CAP_AREA_MASK, 0);
 }
 
 static int sc27xx_fgu_read_last_cap(struct sc27xx_fgu_data *data, int *cap)
@@ -391,6 +447,18 @@ static int sc27xx_fgu_get_vbat_ocv(struct sc27xx_fgu_data *data, int *val)
        return 0;
 }
 
+static int sc27xx_fgu_get_charge_vol(struct sc27xx_fgu_data *data, int *val)
+{
+       int ret, vol;
+
+       ret = iio_read_channel_processed(data->charge_chan, &vol);
+       if (ret < 0)
+               return ret;
+
+       *val = vol * 1000;
+       return 0;
+}
+
 static int sc27xx_fgu_get_temp(struct sc27xx_fgu_data *data, int *temp)
 {
        return iio_read_channel_processed(data->channel, temp);
@@ -502,6 +570,14 @@ static int sc27xx_fgu_get_property(struct power_supply *psy,
                val->intval = value;
                break;
 
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+               ret = sc27xx_fgu_get_charge_vol(data, &value);
+               if (ret)
+                       goto error;
+
+               val->intval = value;
+               break;
+
        case POWER_SUPPLY_PROP_CURRENT_NOW:
        case POWER_SUPPLY_PROP_CURRENT_AVG:
                ret = sc27xx_fgu_get_current(data, &value);
@@ -567,6 +643,7 @@ static enum power_supply_property sc27xx_fgu_props[] = {
        POWER_SUPPLY_PROP_VOLTAGE_OCV,
        POWER_SUPPLY_PROP_CURRENT_NOW,
        POWER_SUPPLY_PROP_CURRENT_AVG,
+       POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
 };
 
 static const struct power_supply_desc sc27xx_fgu_desc = {
@@ -708,7 +785,7 @@ static int sc27xx_fgu_cap_to_clbcnt(struct sc27xx_fgu_data *data, int capacity)
         * Convert current capacity (mAh) to coulomb counter according to the
         * formula: 1 mAh =3.6 coulomb.
         */
-       return DIV_ROUND_CLOSEST(cur_cap * 36, 10);
+       return DIV_ROUND_CLOSEST(cur_cap * 36 * data->cur_1000ma_adc, 10);
 }
 
 static int sc27xx_fgu_calibration(struct sc27xx_fgu_data *data)
@@ -907,6 +984,12 @@ static int sc27xx_fgu_probe(struct platform_device *pdev)
                return PTR_ERR(data->channel);
        }
 
+       data->charge_chan = devm_iio_channel_get(&pdev->dev, "charge-vol");
+       if (IS_ERR(data->charge_chan)) {
+               dev_err(&pdev->dev, "failed to get charge IIO channel\n");
+               return PTR_ERR(data->charge_chan);
+       }
+
        data->gpiod = devm_gpiod_get(&pdev->dev, "bat-detect", GPIOD_IN);
        if (IS_ERR(data->gpiod)) {
                dev_err(&pdev->dev, "failed to get battery detection GPIO\n");
index 0e202d4273fb627f671af379f591bdabbcae297b..4299873a11188249c6aebeb516a2ead6677ae06a 100644 (file)
@@ -809,7 +809,9 @@ static int twl4030_bci_get_property(struct power_supply *psy,
                is_charging = state & TWL4030_MSTATEC_AC;
        if (!is_charging) {
                u8 s;
-               twl4030_bci_read(TWL4030_BCIMDEN, &s);
+               ret = twl4030_bci_read(TWL4030_BCIMDEN, &s);
+               if (ret < 0)
+                       return ret;
                if (psy->desc->type == POWER_SUPPLY_TYPE_USB)
                        is_charging = s & 1;
                else
diff --git a/include/linux/power/isp1704_charger.h b/include/linux/power/isp1704_charger.h
deleted file mode 100644 (file)
index 0105d9e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * ISP1704 USB Charger Detection driver
- *
- * Copyright (C) 2011 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#ifndef __ISP1704_CHARGER_H
-#define __ISP1704_CHARGER_H
-
-struct isp1704_charger_data {
-       void            (*set_power)(bool on);
-       int             enable_gpio;
-};
-
-#endif
index 57b2ab82b95102c72267487ceb5da3102e41c71d..2f9c201a54d1b6865640ed297fd61168ae9b7e10 100644 (file)
@@ -332,6 +332,7 @@ struct power_supply_battery_info {
        int energy_full_design_uwh;         /* microWatt-hours */
        int charge_full_design_uah;         /* microAmp-hours */
        int voltage_min_design_uv;          /* microVolts */
+       int voltage_max_design_uv;          /* microVolts */
        int precharge_current_ua;           /* microAmps */
        int charge_term_current_ua;         /* microAmps */
        int constant_charge_current_max_ua; /* microAmps */