summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-06-19 18:13:09 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-06-19 18:13:09 -0700
commit390d73adf896bf4883c7d3bcd13c1b53d64351e3 (patch)
tree74dc30d42adf8edf169efd51e3f5b6e2d8d3d118
parent1a3746ccbb0a97bed3c06ccde6b880013b1dddc1 (diff)
parenta888754e51e915731c8974c4d6d62709facb35d3 (diff)
Merge tag 'for-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply
Pull power supply and reset updates from Sebastian Reichel: "Power-supply drivers: - New EC driver providing battery info for Microsoft Surface RT - New driver for battery charger in Samsung S2M PMICs - Rework max17042 driver - sysfs control for bd71828 auto input current limitation All over: - Use named fields for struct platform_device_id and of_device_id entries - Misc small cleanups and fixes" * tag 'for-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (33 commits) Documentation: ABI: sysfs-class-reboot-mode-reboot_modes: fix doc warnings power: supply: charger-manager: fix refcount leak in is_full_charged() power: supply: core: fix supplied_from allocations power: supply: max17042_battery: Use modern PM ops to clear up warning power: supply: add support for Samsung S2M series PMIC charger device power: supply: Add support for Surface RT battery and charger dt-bindings: embedded-controller: Document Surface RT EC power: supply: bd71828: sysfs for auto input current limitation power: supply: cpcap-charger: include missing <linux/property.h> power: supply: cros_charge-control: Move MODULE_DEVICE_TABLE next to the table itself power: supply: ab8500_fg: Fix typos in comments power: supply: Use named initializers for arrays of i2c_device_data power: supply: Remove unused jz4740-battery.h power: reset: st-poweroff: Use of_device_get_match_data() power: supply: bq257xx: Add fields for 'charging' and 'overvoltage' states power: supply: bq257xx: Consistently use indirect get/set helpers power: supply: bq257xx: Make the default current limit a per-chip attribute power: supply: bq257xx: Fix VSYSMIN clamping logic power: supply: cpcap-battery: Fix missing nvmem_device_put() causing reference leak power: supply: max17042: fix OF node reference imbalance ...
-rw-r--r--Documentation/ABI/testing/sysfs-class-power-bd7182812
-rw-r--r--Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes13
-rw-r--r--Documentation/devicetree/bindings/embedded-controller/microsoft,surface-rt-ec.yaml63
-rw-r--r--drivers/power/reset/linkstation-poweroff.c2
-rw-r--r--drivers/power/reset/qemu-virt-ctrl.c2
-rw-r--r--drivers/power/reset/sc27xx-poweroff.c8
-rw-r--r--drivers/power/reset/spacemit-p1-reboot.c4
-rw-r--r--drivers/power/reset/st-poweroff.c8
-rw-r--r--drivers/power/reset/tps65086-restart.c2
-rw-r--r--drivers/power/supply/Kconfig21
-rw-r--r--drivers/power/supply/Makefile2
-rw-r--r--drivers/power/supply/ab8500_fg.c2
-rw-r--r--drivers/power/supply/adp5061.c2
-rw-r--r--drivers/power/supply/axp288_charger.c2
-rw-r--r--drivers/power/supply/axp288_fuel_gauge.c2
-rw-r--r--drivers/power/supply/bd71828-power.c77
-rw-r--r--drivers/power/supply/bq2415x_charger.c28
-rw-r--r--drivers/power/supply/bq24190_charger.c16
-rw-r--r--drivers/power/supply/bq24257_charger.c8
-rw-r--r--drivers/power/supply/bq24735-charger.c4
-rw-r--r--drivers/power/supply/bq2515x_charger.c6
-rw-r--r--drivers/power/supply/bq256xx_charger.c16
-rw-r--r--drivers/power/supply/bq257xx_charger.c52
-rw-r--r--drivers/power/supply/bq25890_charger.c10
-rw-r--r--drivers/power/supply/bq25980_charger.c8
-rw-r--r--drivers/power/supply/bq27xxx_battery_i2c.c64
-rw-r--r--drivers/power/supply/charger-manager.c10
-rw-r--r--drivers/power/supply/cpcap-battery.c11
-rw-r--r--drivers/power/supply/cpcap-charger.c1
-rw-r--r--drivers/power/supply/cros_charge-control.c6
-rw-r--r--drivers/power/supply/cros_peripheral_charger.c4
-rw-r--r--drivers/power/supply/cros_usbpd-charger.c4
-rw-r--r--drivers/power/supply/cw2015_battery.c2
-rw-r--r--drivers/power/supply/ds2782_battery.c6
-rw-r--r--drivers/power/supply/lp8727_charger.c2
-rw-r--r--drivers/power/supply/ltc2941-battery-gauge.c10
-rw-r--r--drivers/power/supply/ltc4162-l-charger.c8
-rw-r--r--drivers/power/supply/macsmc-power.c2
-rw-r--r--drivers/power/supply/max14577_charger.c12
-rw-r--r--drivers/power/supply/max14656_charger_detector.c4
-rw-r--r--drivers/power/supply/max17040_battery.c18
-rw-r--r--drivers/power/supply/max17042_battery.c394
-rw-r--r--drivers/power/supply/max77693_charger.c2
-rw-r--r--drivers/power/supply/max77759_charger.c2
-rw-r--r--drivers/power/supply/max77976_charger.c2
-rw-r--r--drivers/power/supply/max8971_charger.c2
-rw-r--r--drivers/power/supply/max8997_charger.c2
-rw-r--r--drivers/power/supply/max8998_charger.c2
-rw-r--r--drivers/power/supply/mm8013.c4
-rw-r--r--drivers/power/supply/mt6360_charger.c6
-rw-r--r--drivers/power/supply/pf1550-charger.c2
-rw-r--r--drivers/power/supply/power_supply_core.c11
-rw-r--r--drivers/power/supply/rt5033_battery.c2
-rw-r--r--drivers/power/supply/rt5033_charger.c2
-rw-r--r--drivers/power/supply/rt9455_charger.c2
-rw-r--r--drivers/power/supply/s2m-charger.c313
-rw-r--r--drivers/power/supply/sbs-battery.c8
-rw-r--r--drivers/power/supply/sbs-charger.c2
-rw-r--r--drivers/power/supply/sbs-manager.c4
-rw-r--r--drivers/power/supply/smb347-charger.c10
-rw-r--r--drivers/power/supply/stc3117_fuel_gauge.c2
-rw-r--r--drivers/power/supply/surface-rt-ec.c389
-rw-r--r--drivers/power/supply/ug3105_battery.c2
-rw-r--r--include/linux/power/max17042_battery.h32
64 files changed, 1319 insertions, 412 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-power-bd71828 b/Documentation/ABI/testing/sysfs-class-power-bd71828
new file mode 100644
index 000000000000..2d451e1c8336
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-power-bd71828
@@ -0,0 +1,12 @@
+What: /sys/class/power_supply/bd71828_ac/auto_dcin_limit
+Description:
+ Enable/Disable automatic management of input current limit
+ (ILIM_DCIN_EN bit).
+
+ Possible values are:
+
+ ============ ===========================================
+ 1 automatic adjustment of input current limit
+ 0 no adjustment of input current limit. This
+ helps for more unusual power sources like
+ solar modules.
diff --git a/Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes b/Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes
index a16c54ab841b..4306966b7fcc 100644
--- a/Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes
+++ b/Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes
@@ -2,33 +2,36 @@ What: /sys/class/reboot-mode/<driver>/reboot_modes
Date: March 2026(TBD)
KernelVersion: TBD
Contact: linux-pm@vger.kernel.org
- Description:
+Description:
This interface exposes the reboot-mode arguments
registered with the reboot-mode framework. It is
a read-only interface and provides a space
separated list of reboot-mode arguments supported
on the current platform.
Example:
+
recovery fastboot bootloader
The exact sysfs path may vary depending on the
name of the driver that registers the arguments.
- Example:
+ Example::
+
/sys/class/reboot-mode/nvmem-reboot-mode/reboot_modes
/sys/class/reboot-mode/syscon-reboot-mode/reboot_modes
/sys/class/reboot-mode/qcom-pon/reboot_modes
The supported arguments can be used by userspace to
invoke device reset using the standard reboot() system
- call interface, with the "argument" as string to "*arg"
- parameter along with LINUX_REBOOT_CMD_RESTART2.
+ call interface, with the "argument" as string to ``*arg``
+ parameter along with ``LINUX_REBOOT_CMD_RESTART2``.
A driver can expose the supported arguments by
registering them with the reboot-mode framework
using the property names that follow the
mode-<argument> format.
Example:
- mode-bootloader, mode-recovery.
+
+ mode-bootloader, mode-recovery
This attribute is useful for scripts or initramfs
logic that need to programmatically determine
diff --git a/Documentation/devicetree/bindings/embedded-controller/microsoft,surface-rt-ec.yaml b/Documentation/devicetree/bindings/embedded-controller/microsoft,surface-rt-ec.yaml
new file mode 100644
index 000000000000..0fee574a3015
--- /dev/null
+++ b/Documentation/devicetree/bindings/embedded-controller/microsoft,surface-rt-ec.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/embedded-controller/microsoft,surface-rt-ec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microsoft Surface RT fuel gauge and charger EC
+
+maintainers:
+ - Jonas Schwöbel <jonasschwoebel@yahoo.de>
+ - Svyatoslav Ryhel <clamor95@gmail.com>
+
+description:
+ An Embedded Controller used in Microsoft Surface RT for monitoring
+ battery properties and charger status.
+
+allOf:
+ - $ref: /schemas/power/supply/power-supply.yaml#
+
+properties:
+ compatible:
+ const: microsoft,surface-rt-ec
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ enable-gpios:
+ maxItems: 1
+
+ monitored-battery: true
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - enable-gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ embedded-controller@a {
+ compatible = "microsoft,surface-rt-ec";
+ reg = <0x0a>;
+
+ interrupt-parent = <&gpio>;
+ interrupts = <74 IRQ_TYPE_EDGE_RISING>;
+
+ enable-gpios = <&gpio 88 GPIO_ACTIVE_HIGH>;
+ monitored-battery = <&battery>;
+ };
+ };
+...
diff --git a/drivers/power/reset/linkstation-poweroff.c b/drivers/power/reset/linkstation-poweroff.c
index 02f5fdb8ffc4..e56d75bfcc43 100644
--- a/drivers/power/reset/linkstation-poweroff.c
+++ b/drivers/power/reset/linkstation-poweroff.c
@@ -163,10 +163,10 @@ static int __init linkstation_poweroff_init(void)
dn = of_find_matching_node(NULL, ls_poweroff_of_match);
if (!dn)
return -ENODEV;
- of_node_put(dn);
match = of_match_node(ls_poweroff_of_match, dn);
cfg = match->data;
+ of_node_put(dn);
dn = of_find_node_by_name(NULL, cfg->mdio_node_name);
if (!dn)
diff --git a/drivers/power/reset/qemu-virt-ctrl.c b/drivers/power/reset/qemu-virt-ctrl.c
index 01409dfe2265..aa8355270b2c 100644
--- a/drivers/power/reset/qemu-virt-ctrl.c
+++ b/drivers/power/reset/qemu-virt-ctrl.c
@@ -103,7 +103,7 @@ static int qemu_virt_ctrl_probe(struct platform_device *pdev)
}
static const struct platform_device_id qemu_virt_ctrl_id[] = {
- { "qemu-virt-ctrl", 0 },
+ { .name = "qemu-virt-ctrl" },
{ }
};
MODULE_DEVICE_TABLE(platform, qemu_virt_ctrl_id);
diff --git a/drivers/power/reset/sc27xx-poweroff.c b/drivers/power/reset/sc27xx-poweroff.c
index 393bd1c33b73..6376706bf561 100644
--- a/drivers/power/reset/sc27xx-poweroff.c
+++ b/drivers/power/reset/sc27xx-poweroff.c
@@ -6,6 +6,7 @@
#include <linux/cpu.h>
#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
@@ -70,11 +71,18 @@ static int sc27xx_poweroff_probe(struct platform_device *pdev)
return 0;
}
+static const struct platform_device_id sc27xx_poweroff_id_table[] = {
+ { "sc2731-poweroff" },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, sc27xx_poweroff_id_table);
+
static struct platform_driver sc27xx_poweroff_driver = {
.probe = sc27xx_poweroff_probe,
.driver = {
.name = "sc27xx-poweroff",
},
+ .id_table = sc27xx_poweroff_id_table,
};
module_platform_driver(sc27xx_poweroff_driver);
diff --git a/drivers/power/reset/spacemit-p1-reboot.c b/drivers/power/reset/spacemit-p1-reboot.c
index 9ec3d1fff8f3..84026b042ea2 100644
--- a/drivers/power/reset/spacemit-p1-reboot.c
+++ b/drivers/power/reset/spacemit-p1-reboot.c
@@ -70,8 +70,8 @@ static int spacemit_p1_reboot_probe(struct platform_device *pdev)
}
static const struct platform_device_id spacemit_p1_reboot_id_table[] = {
- { "spacemit-p1-reboot", },
- { /* sentinel */ },
+ { .name = "spacemit-p1-reboot" },
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, spacemit_p1_reboot_id_table);
diff --git a/drivers/power/reset/st-poweroff.c b/drivers/power/reset/st-poweroff.c
index 85175066beea..2c0cedd18406 100644
--- a/drivers/power/reset/st-poweroff.c
+++ b/drivers/power/reset/st-poweroff.c
@@ -9,7 +9,6 @@
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/mfd/syscon.h>
#include <linux/reboot.h>
@@ -73,15 +72,12 @@ static const struct of_device_id st_reset_of_match[] = {
static int st_reset_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- const struct of_device_id *match;
struct device *dev = &pdev->dev;
- match = of_match_device(st_reset_of_match, dev);
- if (!match)
+ st_restart_syscfg = (struct reset_syscfg *)of_device_get_match_data(dev);
+ if (!st_restart_syscfg)
return -ENODEV;
- st_restart_syscfg = (struct reset_syscfg *)match->data;
-
st_restart_syscfg->regmap =
syscon_regmap_lookup_by_phandle(np, "st,syscfg");
if (IS_ERR(st_restart_syscfg->regmap)) {
diff --git a/drivers/power/reset/tps65086-restart.c b/drivers/power/reset/tps65086-restart.c
index 6976dbcac74f..37d248a9df17 100644
--- a/drivers/power/reset/tps65086-restart.c
+++ b/drivers/power/reset/tps65086-restart.c
@@ -41,7 +41,7 @@ static int tps65086_restart_probe(struct platform_device *pdev)
}
static const struct platform_device_id tps65086_restart_id_table[] = {
- { "tps65086-reset", },
+ { .name = "tps65086-reset" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, tps65086_restart_id_table);
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 83392ed6a8da..f0ede1cecb6a 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -856,6 +856,16 @@ config CHARGER_RK817
help
Say Y to include support for Rockchip RK817 Battery Charger.
+config CHARGER_S2M
+ tristate "Samsung S2M series PMIC battery charger support"
+ depends on EXTCON_S2M
+ depends on MFD_SEC_CORE
+ help
+ This option enables support for charger devices found in
+ certain Samsung S2M series PMICs, such as the S2MU005. These
+ devices provide USB power supply information and also required
+ for USB OTG role switching.
+
config CHARGER_SMB347
tristate "Summit Microelectronics SMB3XX Battery Charger"
depends on I2C
@@ -1135,6 +1145,17 @@ config BATTERY_UG3105
device is off or suspended, the functionality of this driver is
limited to reporting capacity only.
+config BATTERY_CHARGER_SURFACE_RT
+ tristate "Battery & Charger driver for Microsoft Surface RT"
+ depends on I2C && GPIOLIB
+ help
+ UEFI/APX driver for the 1st-generation Microsoft Surface RT
+ battery. Driver supports reading battery properties and
+ charger status.
+
+ This driver can also be built as a module. If so, the module
+ will be called surface-rt-ec.
+
config CHARGER_QCOM_SMB2
tristate "Qualcomm PMI8998 PMIC charger driver"
depends on MFD_SPMI_PMIC
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 7ee839dca7f3..31fe4a145929 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -107,6 +107,7 @@ obj-$(CONFIG_CHARGER_BQ25890) += bq25890_charger.o
obj-$(CONFIG_CHARGER_BQ25980) += bq25980_charger.o
obj-$(CONFIG_CHARGER_BQ256XX) += bq256xx_charger.o
obj-$(CONFIG_CHARGER_RK817) += rk817_charger.o
+obj-$(CONFIG_CHARGER_S2M) += s2m-charger.o
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o
@@ -126,6 +127,7 @@ obj-$(CONFIG_RN5T618_POWER) += rn5t618_power.o
obj-$(CONFIG_BATTERY_ACER_A500) += acer_a500_battery.o
obj-$(CONFIG_BATTERY_SURFACE) += surface_battery.o
obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o
+obj-$(CONFIG_BATTERY_CHARGER_SURFACE_RT) += surface-rt-ec.o
obj-$(CONFIG_BATTERY_UG3105) += ug3105_battery.o
obj-$(CONFIG_CHARGER_QCOM_SMB2) += qcom_smbx.o
obj-$(CONFIG_FUEL_GAUGE_MM8013) += mm8013.o
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index 9dd99722667a..eb5c1ae68e44 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -2037,7 +2037,7 @@ static irqreturn_t ab8500_fg_cc_convend_handler(int irq, void *_di)
}
/**
- * ab8500_fg_batt_ovv_handler() - Battery OVV occured
+ * ab8500_fg_batt_ovv_handler() - Battery OVV occurred
* @irq: interrupt number
* @_di: pointer to the ab8500_fg structure
*
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
index 458fd3024373..7d5754c24553 100644
--- a/drivers/power/supply/adp5061.c
+++ b/drivers/power/supply/adp5061.c
@@ -727,7 +727,7 @@ static int adp5061_probe(struct i2c_client *client)
}
static const struct i2c_device_id adp5061_id[] = {
- { "adp5061" },
+ { .name = "adp5061" },
{ }
};
MODULE_DEVICE_TABLE(i2c, adp5061_id);
diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c
index ea0f5caee8f0..24a8b1ee2fec 100644
--- a/drivers/power/supply/axp288_charger.c
+++ b/drivers/power/supply/axp288_charger.c
@@ -955,7 +955,7 @@ static int axp288_charger_probe(struct platform_device *pdev)
static const struct platform_device_id axp288_charger_id_table[] = {
{ .name = "axp288_charger" },
- {},
+ { }
};
MODULE_DEVICE_TABLE(platform, axp288_charger_id_table);
diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index a3d71fc72064..5af334c0a980 100644
--- a/drivers/power/supply/axp288_fuel_gauge.c
+++ b/drivers/power/supply/axp288_fuel_gauge.c
@@ -799,7 +799,7 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
static const struct platform_device_id axp288_fg_id_table[] = {
{ .name = DEV_NAME },
- {},
+ { }
};
MODULE_DEVICE_TABLE(platform, axp288_fg_id_table);
diff --git a/drivers/power/supply/bd71828-power.c b/drivers/power/supply/bd71828-power.c
index 5e78faa0a4aa..b671563ead79 100644
--- a/drivers/power/supply/bd71828-power.c
+++ b/drivers/power/supply/bd71828-power.c
@@ -12,6 +12,7 @@
#include <linux/property.h>
#include <linux/power_supply.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
/* common defines */
#define BD7182x_MASK_VBAT_U 0x1f
@@ -25,6 +26,7 @@
#define BD71815_MASK_CONF_XSTB BIT(1)
#define BD7182x_MASK_BAT_STAT 0x3f
#define BD7182x_MASK_ILIM 0x3f
+#define BD71828_MASK_ILIM_DCIN_EN BIT(6)
#define BD7182x_MASK_DCIN_STAT 0x07
#define BD7182x_MASK_WDT_AUTO 0x40
@@ -1099,10 +1101,75 @@ static int bd7182x_get_rsens(struct bd71828_power *pwr)
return 0;
}
+static ssize_t auto_dcin_limit_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bd71828_power *pwr = dev_get_drvdata(dev->parent);
+ int ret;
+ unsigned int v;
+
+ ret = regmap_read(pwr->regmap, pwr->regs->dcin_set, &v);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%d\n", !!(v & BD71828_MASK_ILIM_DCIN_EN));
+}
+
+static ssize_t auto_dcin_limit_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct bd71828_power *pwr = dev_get_drvdata(dev->parent);
+ int ret;
+ bool v;
+
+ ret = kstrtobool(buf, &v);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_update_bits(pwr->regmap, BD71828_REG_DCIN_SET,
+ BD71828_MASK_ILIM_DCIN_EN,
+ v ? BD71828_MASK_ILIM_DCIN_EN : 0);
+ if (ret < 0)
+ return ret;
+
+ return len;
+}
+
+static DEVICE_ATTR_RW(auto_dcin_limit);
+
+static struct attribute *bd71828_ac_sysfs_attrs[] = {
+ &dev_attr_auto_dcin_limit.attr,
+ NULL,
+};
+
+static bool bd71828_ac_sysfs_group_visible(struct kobject *kobj)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct bd71828_power *pwr = dev_get_drvdata(dev->parent);
+
+ return !!pwr->regs->dcin_set;
+}
+
+DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(bd71828_ac_sysfs);
+
+static const struct attribute_group bd71828_ac_sysfs_group = {
+ .attrs = bd71828_ac_sysfs_attrs,
+ .is_visible = SYSFS_GROUP_VISIBLE(bd71828_ac_sysfs)
+};
+
+static const struct attribute_group *bd71828_ac_sysfs_groups[] = {
+ &bd71828_ac_sysfs_group,
+ NULL
+};
+
static int bd71828_power_probe(struct platform_device *pdev)
{
struct bd71828_power *pwr;
- struct power_supply_config ac_cfg = {};
+ struct power_supply_config ac_cfg = {
+ .attr_grp = bd71828_ac_sysfs_groups,
+ };
struct power_supply_config bat_cfg = {};
int ret;
@@ -1184,10 +1251,10 @@ static int bd71828_power_probe(struct platform_device *pdev)
}
static const struct platform_device_id bd71828_charger_id[] = {
- { "bd71815-power", ROHM_CHIP_TYPE_BD71815 },
- { "bd71828-power", ROHM_CHIP_TYPE_BD71828 },
- { "bd72720-power", ROHM_CHIP_TYPE_BD72720 },
- { },
+ { .name = "bd71815-power", .driver_data = ROHM_CHIP_TYPE_BD71815 },
+ { .name = "bd71828-power", .driver_data = ROHM_CHIP_TYPE_BD71828 },
+ { .name = "bd72720-power", .driver_data = ROHM_CHIP_TYPE_BD72720 },
+ { }
};
MODULE_DEVICE_TABLE(platform, bd71828_charger_id);
diff --git a/drivers/power/supply/bq2415x_charger.c b/drivers/power/supply/bq2415x_charger.c
index b50a28b9dd38..9f801717bfb0 100644
--- a/drivers/power/supply/bq2415x_charger.c
+++ b/drivers/power/supply/bq2415x_charger.c
@@ -1738,20 +1738,20 @@ static void bq2415x_remove(struct i2c_client *client)
}
static const struct i2c_device_id bq2415x_i2c_id_table[] = {
- { "bq2415x", BQUNKNOWN },
- { "bq24150", BQ24150 },
- { "bq24150a", BQ24150A },
- { "bq24151", BQ24151 },
- { "bq24151a", BQ24151A },
- { "bq24152", BQ24152 },
- { "bq24153", BQ24153 },
- { "bq24153a", BQ24153A },
- { "bq24155", BQ24155 },
- { "bq24156", BQ24156 },
- { "bq24156a", BQ24156A },
- { "bq24157s", BQ24157S },
- { "bq24158", BQ24158 },
- {},
+ { .name = "bq2415x", .driver_data = BQUNKNOWN },
+ { .name = "bq24150", .driver_data = BQ24150 },
+ { .name = "bq24150a", .driver_data = BQ24150A },
+ { .name = "bq24151", .driver_data = BQ24151 },
+ { .name = "bq24151a", .driver_data = BQ24151A },
+ { .name = "bq24152", .driver_data = BQ24152 },
+ { .name = "bq24153", .driver_data = BQ24153 },
+ { .name = "bq24153a", .driver_data = BQ24153A },
+ { .name = "bq24155", .driver_data = BQ24155 },
+ { .name = "bq24156", .driver_data = BQ24156 },
+ { .name = "bq24156a", .driver_data = BQ24156A },
+ { .name = "bq24157s", .driver_data = BQ24157S },
+ { .name = "bq24158", .driver_data = BQ24158 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, bq2415x_i2c_id_table);
diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
index 55da91bacc3e..6700d578a98f 100644
--- a/drivers/power/supply/bq24190_charger.c
+++ b/drivers/power/supply/bq24190_charger.c
@@ -2308,14 +2308,14 @@ static const struct dev_pm_ops bq24190_pm_ops = {
};
static const struct i2c_device_id bq24190_i2c_ids[] = {
- { "bq24190", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24190] },
- { "bq24192", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192] },
- { "bq24192i", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192i] },
- { "bq24193", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24193] },
- { "bq24196", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24196] },
- { "bq24296", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24296] },
- { "bq24297", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24297] },
- { },
+ { .name = "bq24190", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24190] },
+ { .name = "bq24192", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192] },
+ { .name = "bq24192i", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192i] },
+ { .name = "bq24193", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24193] },
+ { .name = "bq24196", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24196] },
+ { .name = "bq24296", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24296] },
+ { .name = "bq24297", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24297] },
+ { }
};
MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids);
diff --git a/drivers/power/supply/bq24257_charger.c b/drivers/power/supply/bq24257_charger.c
index 766eecb35694..72f1bfea8d54 100644
--- a/drivers/power/supply/bq24257_charger.c
+++ b/drivers/power/supply/bq24257_charger.c
@@ -1133,10 +1133,10 @@ static const struct bq2425x_chip_info bq24257_info = {
};
static const struct i2c_device_id bq24257_i2c_ids[] = {
- { "bq24250", (kernel_ulong_t)&bq24250_info },
- { "bq24251", (kernel_ulong_t)&bq24251_info },
- { "bq24257", (kernel_ulong_t)&bq24257_info },
- {}
+ { .name = "bq24250", .driver_data = (kernel_ulong_t)&bq24250_info },
+ { .name = "bq24251", .driver_data = (kernel_ulong_t)&bq24251_info },
+ { .name = "bq24257", .driver_data = (kernel_ulong_t)&bq24257_info },
+ { }
};
MODULE_DEVICE_TABLE(i2c, bq24257_i2c_ids);
diff --git a/drivers/power/supply/bq24735-charger.c b/drivers/power/supply/bq24735-charger.c
index 637e0da65f87..99abbaf0470f 100644
--- a/drivers/power/supply/bq24735-charger.c
+++ b/drivers/power/supply/bq24735-charger.c
@@ -489,8 +489,8 @@ static int bq24735_charger_probe(struct i2c_client *client)
}
static const struct i2c_device_id bq24735_charger_id[] = {
- { "bq24735-charger" },
- {}
+ { .name = "bq24735-charger" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, bq24735_charger_id);
diff --git a/drivers/power/supply/bq2515x_charger.c b/drivers/power/supply/bq2515x_charger.c
index 437bff5bc420..0208358ebbe4 100644
--- a/drivers/power/supply/bq2515x_charger.c
+++ b/drivers/power/supply/bq2515x_charger.c
@@ -1137,9 +1137,9 @@ static const struct bq2515x_info bq25155 = {
};
static const struct i2c_device_id bq2515x_i2c_ids[] = {
- { "bq25150", (kernel_ulong_t)&bq25150 },
- { "bq25155", (kernel_ulong_t)&bq25155 },
- {}
+ { .name = "bq25150", .driver_data = (kernel_ulong_t)&bq25150 },
+ { .name = "bq25155", .driver_data = (kernel_ulong_t)&bq25155 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, bq2515x_i2c_ids);
diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c
index 563f512709b3..5a6634fde837 100644
--- a/drivers/power/supply/bq256xx_charger.c
+++ b/drivers/power/supply/bq256xx_charger.c
@@ -1768,14 +1768,14 @@ static int bq256xx_probe(struct i2c_client *client)
}
static const struct i2c_device_id bq256xx_i2c_ids[] = {
- { "bq25600", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600] },
- { "bq25600d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600D] },
- { "bq25601", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601] },
- { "bq25601d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601D] },
- { "bq25611d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25611D] },
- { "bq25618", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25618] },
- { "bq25619", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25619] },
- {}
+ { .name = "bq25600", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600] },
+ { .name = "bq25600d", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600D] },
+ { .name = "bq25601", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601] },
+ { .name = "bq25601d", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601D] },
+ { .name = "bq25611d", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25611D] },
+ { .name = "bq25618", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25618] },
+ { .name = "bq25619", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25619] },
+ { }
};
MODULE_DEVICE_TABLE(i2c, bq256xx_i2c_ids);
diff --git a/drivers/power/supply/bq257xx_charger.c b/drivers/power/supply/bq257xx_charger.c
index 02c7d8b61e82..9c082865e745 100644
--- a/drivers/power/supply/bq257xx_charger.c
+++ b/drivers/power/supply/bq257xx_charger.c
@@ -18,20 +18,34 @@ struct bq257xx_chg;
/**
* struct bq257xx_chip_info - chip specific routines
+ * @default_iindpm_uA: default input current limit in microamps
* @bq257xx_hw_init: init function for hw
* @bq257xx_hw_shutdown: shutdown function for hw
* @bq257xx_get_state: get and update state of hardware
+ * @bq257xx_get_ichg: get maximum charge current (in uA)
* @bq257xx_set_ichg: set maximum charge current (in uA)
+ * @bq257xx_get_vbatreg: get maximum charge voltage (in uV)
* @bq257xx_set_vbatreg: set maximum charge voltage (in uV)
+ * @bq257xx_get_iindpm: get maximum input current (in uA)
* @bq257xx_set_iindpm: set maximum input current (in uA)
+ * @bq257xx_get_cur: get battery current from ADC (in uA)
+ * @bq257xx_get_vbat: get battery voltage from ADC (in uV)
+ * @bq257xx_get_min_vsys: get minimum system voltage (in uV)
*/
struct bq257xx_chip_info {
+ int default_iindpm_uA;
int (*bq257xx_hw_init)(struct bq257xx_chg *pdata);
void (*bq257xx_hw_shutdown)(struct bq257xx_chg *pdata);
int (*bq257xx_get_state)(struct bq257xx_chg *pdata);
+ int (*bq257xx_get_ichg)(struct bq257xx_chg *pdata, int *intval);
int (*bq257xx_set_ichg)(struct bq257xx_chg *pdata, int ichg);
+ int (*bq257xx_get_vbatreg)(struct bq257xx_chg *pdata, int *intval);
int (*bq257xx_set_vbatreg)(struct bq257xx_chg *pdata, int vbatreg);
+ int (*bq257xx_get_iindpm)(struct bq257xx_chg *pdata, int *intval);
int (*bq257xx_set_iindpm)(struct bq257xx_chg *pdata, int iindpm);
+ int (*bq257xx_get_cur)(struct bq257xx_chg *pdata, int *intval);
+ int (*bq257xx_get_vbat)(struct bq257xx_chg *pdata, int *intval);
+ int (*bq257xx_get_min_vsys)(struct bq257xx_chg *pdata, int *intval);
};
/**
@@ -40,8 +54,10 @@ struct bq257xx_chip_info {
* @bq: parent MFD device
* @charger: power supply device
* @online: charger input is present
+ * @charging: charger is actively charging the battery
* @fast_charge: charger is in fast charge mode
* @pre_charge: charger is in pre-charge mode
+ * @overvoltage: overvoltage fault detected
* @ov_fault: charger reports over voltage fault
* @batoc_fault: charger reports battery over current fault
* @oc_fault: charger reports over current fault
@@ -57,8 +73,10 @@ struct bq257xx_chg {
struct bq257xx_device *bq;
struct power_supply *charger;
bool online;
+ bool charging;
bool fast_charge;
bool pre_charge;
+ bool overvoltage;
bool ov_fault;
bool batoc_fault;
bool oc_fault;
@@ -92,8 +110,10 @@ static int bq25703_get_state(struct bq257xx_chg *pdata)
pdata->online = reg & BQ25703_STS_AC_STAT;
pdata->fast_charge = reg & BQ25703_STS_IN_FCHRG;
pdata->pre_charge = reg & BQ25703_STS_IN_PCHRG;
+ pdata->charging = pdata->fast_charge || pdata->pre_charge;
pdata->ov_fault = reg & BQ25703_STS_FAULT_ACOV;
pdata->batoc_fault = reg & BQ25703_STS_FAULT_BATOC;
+ pdata->overvoltage = pdata->ov_fault || pdata->batoc_fault;
pdata->oc_fault = reg & BQ25703_STS_FAULT_ACOC;
return 0;
@@ -128,9 +148,8 @@ static int bq25703_get_min_vsys(struct bq257xx_chg *pdata, int *intval)
* @vsys: voltage value to set in uV.
*
* This function takes a requested minimum system voltage value, clamps
- * it between the minimum supported value by the charger and a user
- * defined minimum system value, and then writes the value to the
- * appropriate register.
+ * it between the user defined minimum system value and the maximum supported
+ * value by the charger, and then writes the value to the appropriate register.
*
* Return: Returns 0 on success or error if an error occurs.
*/
@@ -139,7 +158,7 @@ static int bq25703_set_min_vsys(struct bq257xx_chg *pdata, int vsys)
unsigned int reg;
int vsys_min = pdata->vsys_min;
- vsys = clamp(vsys, BQ25703_MINVSYS_MIN_UV, vsys_min);
+ vsys = clamp(vsys, vsys_min, BQ25703_MINVSYS_MAX_UV);
reg = ((vsys - BQ25703_MINVSYS_MIN_UV) / BQ25703_MINVSYS_STEP_UV);
reg = FIELD_PREP(BQ25703_MINVSYS_MASK, reg);
@@ -465,14 +484,14 @@ static int bq257xx_get_charger_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_STATUS:
if (!pdata->online)
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
- else if (pdata->fast_charge || pdata->pre_charge)
+ else if (pdata->charging)
val->intval = POWER_SUPPLY_STATUS_CHARGING;
else
val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
break;
case POWER_SUPPLY_PROP_HEALTH:
- if (pdata->ov_fault || pdata->batoc_fault)
+ if (pdata->overvoltage)
val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
else if (pdata->oc_fault)
val->intval = POWER_SUPPLY_HEALTH_OVERCURRENT;
@@ -489,22 +508,22 @@ static int bq257xx_get_charger_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
- return bq25703_get_iindpm(pdata, &val->intval);
+ return pdata->chip->bq257xx_get_iindpm(pdata, &val->intval);
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
- return bq25703_get_chrg_volt(pdata, &val->intval);
+ return pdata->chip->bq257xx_get_vbatreg(pdata, &val->intval);
case POWER_SUPPLY_PROP_CURRENT_NOW:
- return bq25703_get_cur(pdata, &val->intval);
+ return pdata->chip->bq257xx_get_cur(pdata, &val->intval);
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- return bq25703_get_vbat(pdata, &val->intval);
+ return pdata->chip->bq257xx_get_vbat(pdata, &val->intval);
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
- return bq25703_get_ichg_cur(pdata, &val->intval);
+ return pdata->chip->bq257xx_get_ichg(pdata, &val->intval);
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
- return bq25703_get_min_vsys(pdata, &val->intval);
+ return pdata->chip->bq257xx_get_min_vsys(pdata, &val->intval);
case POWER_SUPPLY_PROP_USB_TYPE:
val->intval = pdata->usb_type;
@@ -628,12 +647,19 @@ static const struct power_supply_desc bq257xx_power_supply_desc = {
};
static const struct bq257xx_chip_info bq25703_chip_info = {
+ .default_iindpm_uA = BQ25703_IINDPM_DEFAULT_UA,
.bq257xx_hw_init = &bq25703_hw_init,
.bq257xx_hw_shutdown = &bq25703_hw_shutdown,
.bq257xx_get_state = &bq25703_get_state,
+ .bq257xx_get_ichg = &bq25703_get_ichg_cur,
.bq257xx_set_ichg = &bq25703_set_ichg_cur,
+ .bq257xx_get_vbatreg = &bq25703_get_chrg_volt,
.bq257xx_set_vbatreg = &bq25703_set_chrg_volt,
+ .bq257xx_get_iindpm = &bq25703_get_iindpm,
.bq257xx_set_iindpm = &bq25703_set_iindpm,
+ .bq257xx_get_cur = &bq25703_get_cur,
+ .bq257xx_get_vbat = &bq25703_get_vbat,
+ .bq257xx_get_min_vsys = &bq25703_get_min_vsys,
};
/**
@@ -676,7 +702,7 @@ static int bq257xx_parse_dt(struct bq257xx_chg *pdata,
"input-current-limit-microamp",
&pdata->iindpm_max);
if (ret)
- pdata->iindpm_max = BQ25703_IINDPM_DEFAULT_UA;
+ pdata->iindpm_max = pdata->chip->default_iindpm_uA;
return 0;
}
diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c
index 868e86e1749b..c1c12a447178 100644
--- a/drivers/power/supply/bq25890_charger.c
+++ b/drivers/power/supply/bq25890_charger.c
@@ -1617,11 +1617,11 @@ static const struct dev_pm_ops bq25890_pm = {
};
static const struct i2c_device_id bq25890_i2c_ids[] = {
- { "bq25890" },
- { "bq25892" },
- { "bq25895" },
- { "bq25896" },
- {}
+ { .name = "bq25890" },
+ { .name = "bq25892" },
+ { .name = "bq25895" },
+ { .name = "bq25896" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, bq25890_i2c_ids);
diff --git a/drivers/power/supply/bq25980_charger.c b/drivers/power/supply/bq25980_charger.c
index 44af3a0c92e5..eced3aecc7d2 100644
--- a/drivers/power/supply/bq25980_charger.c
+++ b/drivers/power/supply/bq25980_charger.c
@@ -1266,10 +1266,10 @@ static int bq25980_probe(struct i2c_client *client)
}
static const struct i2c_device_id bq25980_i2c_ids[] = {
- { "bq25980", BQ25980 },
- { "bq25975", BQ25975 },
- { "bq25960", BQ25960 },
- {},
+ { .name = "bq25980", .driver_data = BQ25980 },
+ { .name = "bq25975", .driver_data = BQ25975 },
+ { .name = "bq25960", .driver_data = BQ25960 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, bq25980_i2c_ids);
diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
index 868e95f0887e..c4e7a9521d08 100644
--- a/drivers/power/supply/bq27xxx_battery_i2c.c
+++ b/drivers/power/supply/bq27xxx_battery_i2c.c
@@ -225,38 +225,38 @@ static void bq27xxx_battery_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
- { "bq27200", BQ27000 },
- { "bq27210", BQ27010 },
- { "bq27500", BQ2750X },
- { "bq27510", BQ2751X },
- { "bq27520", BQ2752X },
- { "bq27500-1", BQ27500 },
- { "bq27510g1", BQ27510G1 },
- { "bq27510g2", BQ27510G2 },
- { "bq27510g3", BQ27510G3 },
- { "bq27520g1", BQ27520G1 },
- { "bq27520g2", BQ27520G2 },
- { "bq27520g3", BQ27520G3 },
- { "bq27520g4", BQ27520G4 },
- { "bq27521", BQ27521 },
- { "bq27530", BQ27530 },
- { "bq27531", BQ27531 },
- { "bq27541", BQ27541 },
- { "bq27542", BQ27542 },
- { "bq27546", BQ27546 },
- { "bq27742", BQ27742 },
- { "bq27545", BQ27545 },
- { "bq27411", BQ27411 },
- { "bq27421", BQ27421 },
- { "bq27425", BQ27425 },
- { "bq27426", BQ27426 },
- { "bq27441", BQ27441 },
- { "bq27621", BQ27621 },
- { "bq27z561", BQ27Z561 },
- { "bq28z610", BQ28Z610 },
- { "bq34z100", BQ34Z100 },
- { "bq78z100", BQ78Z100 },
- {},
+ { .name = "bq27200", .driver_data = BQ27000 },
+ { .name = "bq27210", .driver_data = BQ27010 },
+ { .name = "bq27500", .driver_data = BQ2750X },
+ { .name = "bq27510", .driver_data = BQ2751X },
+ { .name = "bq27520", .driver_data = BQ2752X },
+ { .name = "bq27500-1", .driver_data = BQ27500 },
+ { .name = "bq27510g1", .driver_data = BQ27510G1 },
+ { .name = "bq27510g2", .driver_data = BQ27510G2 },
+ { .name = "bq27510g3", .driver_data = BQ27510G3 },
+ { .name = "bq27520g1", .driver_data = BQ27520G1 },
+ { .name = "bq27520g2", .driver_data = BQ27520G2 },
+ { .name = "bq27520g3", .driver_data = BQ27520G3 },
+ { .name = "bq27520g4", .driver_data = BQ27520G4 },
+ { .name = "bq27521", .driver_data = BQ27521 },
+ { .name = "bq27530", .driver_data = BQ27530 },
+ { .name = "bq27531", .driver_data = BQ27531 },
+ { .name = "bq27541", .driver_data = BQ27541 },
+ { .name = "bq27542", .driver_data = BQ27542 },
+ { .name = "bq27546", .driver_data = BQ27546 },
+ { .name = "bq27742", .driver_data = BQ27742 },
+ { .name = "bq27545", .driver_data = BQ27545 },
+ { .name = "bq27411", .driver_data = BQ27411 },
+ { .name = "bq27421", .driver_data = BQ27421 },
+ { .name = "bq27425", .driver_data = BQ27425 },
+ { .name = "bq27426", .driver_data = BQ27426 },
+ { .name = "bq27441", .driver_data = BQ27441 },
+ { .name = "bq27621", .driver_data = BQ27621 },
+ { .name = "bq27z561", .driver_data = BQ27Z561 },
+ { .name = "bq28z610", .driver_data = BQ28Z610 },
+ { .name = "bq34z100", .driver_data = BQ34Z100 },
+ { .name = "bq78z100", .driver_data = BQ78Z100 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c
index 1b0239c59114..71b6e49a835f 100644
--- a/drivers/power/supply/charger-manager.c
+++ b/drivers/power/supply/charger-manager.c
@@ -303,8 +303,10 @@ static bool is_full_charged(struct charger_manager *cm)
if (cm->battery_status == POWER_SUPPLY_STATUS_FULL
&& desc->fullbatt_vchkdrop_uV)
uV += desc->fullbatt_vchkdrop_uV;
- if (uV >= desc->fullbatt_uV)
- return true;
+ if (uV >= desc->fullbatt_uV) {
+ is_full = true;
+ goto out;
+ }
}
}
@@ -1649,8 +1651,8 @@ static void charger_manager_remove(struct platform_device *pdev)
}
static const struct platform_device_id charger_manager_id[] = {
- { "charger-manager", 0 },
- { },
+ { .name = "charger-manager" },
+ { }
};
MODULE_DEVICE_TABLE(platform, charger_manager_id);
diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c
index 7b7bdce3162f..59c741993ef8 100644
--- a/drivers/power/supply/cpcap-battery.c
+++ b/drivers/power/supply/cpcap-battery.c
@@ -439,10 +439,13 @@ static void cpcap_battery_detect_battery_type(struct cpcap_battery_ddata *ddata)
if (IS_ERR_OR_NULL(nvmem)) {
ddata->check_nvmem = true;
dev_info_once(ddata->dev, "Can not find battery nvmem device. Assuming generic lipo battery\n");
- } else if (nvmem_device_read(nvmem, 2, 1, &battery_id) < 0) {
- battery_id = 0;
- ddata->check_nvmem = true;
- dev_warn(ddata->dev, "Can not read battery nvmem device. Assuming generic lipo battery\n");
+ } else {
+ if (nvmem_device_read(nvmem, 2, 1, &battery_id) < 0) {
+ battery_id = 0;
+ ddata->check_nvmem = true;
+ dev_warn(ddata->dev, "Can not read battery nvmem device. Assuming generic lipo battery\n");
+ }
+ nvmem_device_put(nvmem);
}
switch (battery_id) {
diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c
index d0c3008db534..24221244b45b 100644
--- a/drivers/power/supply/cpcap-charger.c
+++ b/drivers/power/supply/cpcap-charger.c
@@ -21,6 +21,7 @@
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/gpio/consumer.h>
diff --git a/drivers/power/supply/cros_charge-control.c b/drivers/power/supply/cros_charge-control.c
index 53e6a77e03fc..e1b8f3b1b7de 100644
--- a/drivers/power/supply/cros_charge-control.c
+++ b/drivers/power/supply/cros_charge-control.c
@@ -320,9 +320,10 @@ static int cros_chctl_probe(struct platform_device *pdev)
}
static const struct platform_device_id cros_chctl_id[] = {
- { "cros-charge-control", 0 },
- {}
+ { .name = "cros-charge-control" },
+ { }
};
+MODULE_DEVICE_TABLE(platform, cros_chctl_id);
static struct platform_driver cros_chctl_driver = {
.driver.name = "cros-charge-control",
@@ -331,7 +332,6 @@ static struct platform_driver cros_chctl_driver = {
};
module_platform_driver(cros_chctl_driver);
-MODULE_DEVICE_TABLE(platform, cros_chctl_id);
MODULE_DESCRIPTION("ChromeOS EC charge control");
MODULE_AUTHOR("Thomas Weißschuh <linux@weissschuh.net>");
MODULE_LICENSE("GPL");
diff --git a/drivers/power/supply/cros_peripheral_charger.c b/drivers/power/supply/cros_peripheral_charger.c
index f132fad288cb..9f67a6dbd94e 100644
--- a/drivers/power/supply/cros_peripheral_charger.c
+++ b/drivers/power/supply/cros_peripheral_charger.c
@@ -369,8 +369,8 @@ static int __maybe_unused cros_pchg_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(cros_pchg_pm_ops, NULL, cros_pchg_resume);
static const struct platform_device_id cros_pchg_id[] = {
- { DRV_NAME, 0 },
- {}
+ { .name = DRV_NAME },
+ { }
};
MODULE_DEVICE_TABLE(platform, cros_pchg_id);
diff --git a/drivers/power/supply/cros_usbpd-charger.c b/drivers/power/supply/cros_usbpd-charger.c
index 7d3e676a951c..308e1d4e6dd8 100644
--- a/drivers/power/supply/cros_usbpd-charger.c
+++ b/drivers/power/supply/cros_usbpd-charger.c
@@ -707,8 +707,8 @@ static SIMPLE_DEV_PM_OPS(cros_usbpd_charger_pm_ops, NULL,
cros_usbpd_charger_resume);
static const struct platform_device_id cros_usbpd_charger_id[] = {
- { DRV_NAME, 0 },
- {}
+ { .name = DRV_NAME },
+ { }
};
MODULE_DEVICE_TABLE(platform, cros_usbpd_charger_id);
diff --git a/drivers/power/supply/cw2015_battery.c b/drivers/power/supply/cw2015_battery.c
index 286524d2318c..7496295d2948 100644
--- a/drivers/power/supply/cw2015_battery.c
+++ b/drivers/power/supply/cw2015_battery.c
@@ -733,7 +733,7 @@ static int __maybe_unused cw_bat_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(cw_bat_pm_ops, cw_bat_suspend, cw_bat_resume);
static const struct i2c_device_id cw_bat_id_table[] = {
- { "cw2015" },
+ { .name = "cw2015" },
{ }
};
diff --git a/drivers/power/supply/ds2782_battery.c b/drivers/power/supply/ds2782_battery.c
index cae95d35d398..ed44837473e7 100644
--- a/drivers/power/supply/ds2782_battery.c
+++ b/drivers/power/supply/ds2782_battery.c
@@ -423,9 +423,9 @@ static int ds278x_battery_probe(struct i2c_client *client)
}
static const struct i2c_device_id ds278x_id[] = {
- {"ds2782", DS2782},
- {"ds2786", DS2786},
- {},
+ { .name = "ds2782", .driver_data = DS2782 },
+ { .name = "ds2786", .driver_data = DS2786 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, ds278x_id);
diff --git a/drivers/power/supply/lp8727_charger.c b/drivers/power/supply/lp8727_charger.c
index 4186fcd37512..641e0445a410 100644
--- a/drivers/power/supply/lp8727_charger.c
+++ b/drivers/power/supply/lp8727_charger.c
@@ -584,7 +584,7 @@ static const struct of_device_id lp8727_dt_ids[] __maybe_unused = {
MODULE_DEVICE_TABLE(of, lp8727_dt_ids);
static const struct i2c_device_id lp8727_ids[] = {
- { "lp8727" },
+ { .name = "lp8727" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lp8727_ids);
diff --git a/drivers/power/supply/ltc2941-battery-gauge.c b/drivers/power/supply/ltc2941-battery-gauge.c
index a1ddc4b060ce..5b6760722f38 100644
--- a/drivers/power/supply/ltc2941-battery-gauge.c
+++ b/drivers/power/supply/ltc2941-battery-gauge.c
@@ -600,11 +600,11 @@ static SIMPLE_DEV_PM_OPS(ltc294x_pm_ops, ltc294x_suspend, ltc294x_resume);
static const struct i2c_device_id ltc294x_i2c_id[] = {
- { "ltc2941", LTC2941_ID, },
- { "ltc2942", LTC2942_ID, },
- { "ltc2943", LTC2943_ID, },
- { "ltc2944", LTC2944_ID, },
- { },
+ { .name = "ltc2941", .driver_data = LTC2941_ID },
+ { .name = "ltc2942", .driver_data = LTC2942_ID },
+ { .name = "ltc2943", .driver_data = LTC2943_ID },
+ { .name = "ltc2944", .driver_data = LTC2944_ID },
+ { }
};
MODULE_DEVICE_TABLE(i2c, ltc294x_i2c_id);
diff --git a/drivers/power/supply/ltc4162-l-charger.c b/drivers/power/supply/ltc4162-l-charger.c
index 9dd74fa9552d..5c09e0368e6f 100644
--- a/drivers/power/supply/ltc4162-l-charger.c
+++ b/drivers/power/supply/ltc4162-l-charger.c
@@ -1229,10 +1229,10 @@ static void ltc4162l_alert(struct i2c_client *client,
}
static const struct i2c_device_id ltc4162l_i2c_id_table[] = {
- { "ltc4015", (kernel_ulong_t)&ltc4015_chip_info },
- { "ltc4162-f", (kernel_ulong_t)&ltc4162f_chip_info },
- { "ltc4162-l", (kernel_ulong_t)&ltc4162l_chip_info },
- { "ltc4162-s", (kernel_ulong_t)&ltc4162s_chip_info },
+ { .name = "ltc4015", .driver_data = (kernel_ulong_t)&ltc4015_chip_info },
+ { .name = "ltc4162-f", .driver_data = (kernel_ulong_t)&ltc4162f_chip_info },
+ { .name = "ltc4162-l", .driver_data = (kernel_ulong_t)&ltc4162l_chip_info },
+ { .name = "ltc4162-s", .driver_data = (kernel_ulong_t)&ltc4162s_chip_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltc4162l_i2c_id_table);
diff --git a/drivers/power/supply/macsmc-power.c b/drivers/power/supply/macsmc-power.c
index 33ca07460f3a..ced07f71e0a8 100644
--- a/drivers/power/supply/macsmc-power.c
+++ b/drivers/power/supply/macsmc-power.c
@@ -834,7 +834,7 @@ static void macsmc_power_remove(struct platform_device *pdev)
}
static const struct platform_device_id macsmc_power_id[] = {
- { "macsmc-power" },
+ { .name = "macsmc-power" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, macsmc_power_id);
diff --git a/drivers/power/supply/max14577_charger.c b/drivers/power/supply/max14577_charger.c
index 63077d38ea30..a15d94942184 100644
--- a/drivers/power/supply/max14577_charger.c
+++ b/drivers/power/supply/max14577_charger.c
@@ -613,18 +613,16 @@ static void max14577_charger_remove(struct platform_device *pdev)
}
static const struct platform_device_id max14577_charger_id[] = {
- { "max14577-charger", MAXIM_DEVICE_TYPE_MAX14577, },
- { "max77836-charger", MAXIM_DEVICE_TYPE_MAX77836, },
+ { .name = "max14577-charger" },
+ { .name = "max77836-charger" },
{ }
};
MODULE_DEVICE_TABLE(platform, max14577_charger_id);
static const struct of_device_id of_max14577_charger_dt_match[] = {
- { .compatible = "maxim,max14577-charger",
- .data = (void *)MAXIM_DEVICE_TYPE_MAX14577, },
- { .compatible = "maxim,max77836-charger",
- .data = (void *)MAXIM_DEVICE_TYPE_MAX77836, },
- { },
+ { .compatible = "maxim,max14577-charger" },
+ { .compatible = "maxim,max77836-charger" },
+ { }
};
MODULE_DEVICE_TABLE(of, of_max14577_charger_dt_match);
diff --git a/drivers/power/supply/max14656_charger_detector.c b/drivers/power/supply/max14656_charger_detector.c
index a5b42b42d134..b6c3bc0d9ec1 100644
--- a/drivers/power/supply/max14656_charger_detector.c
+++ b/drivers/power/supply/max14656_charger_detector.c
@@ -300,8 +300,8 @@ static int max14656_probe(struct i2c_client *client)
}
static const struct i2c_device_id max14656_id[] = {
- { "max14656" },
- {}
+ { .name = "max14656" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, max14656_id);
diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c
index 48453508688a..e94d53b36aa4 100644
--- a/drivers/power/supply/max17040_battery.c
+++ b/drivers/power/supply/max17040_battery.c
@@ -598,15 +598,15 @@ static SIMPLE_DEV_PM_OPS(max17040_pm_ops, max17040_suspend, max17040_resume);
#endif /* CONFIG_PM_SLEEP */
static const struct i2c_device_id max17040_id[] = {
- { "max17040", ID_MAX17040 },
- { "max17041", ID_MAX17041 },
- { "max17043", ID_MAX17043 },
- { "max77836-battery", ID_MAX17043 },
- { "max17044", ID_MAX17044 },
- { "max17048", ID_MAX17048 },
- { "max17049", ID_MAX17049 },
- { "max17058", ID_MAX17058 },
- { "max17059", ID_MAX17059 },
+ { .name = "max17040", .driver_data = ID_MAX17040 },
+ { .name = "max17041", .driver_data = ID_MAX17041 },
+ { .name = "max17043", .driver_data = ID_MAX17043 },
+ { .name = "max77836-battery", .driver_data = ID_MAX17043 },
+ { .name = "max17044", .driver_data = ID_MAX17044 },
+ { .name = "max17048", .driver_data = ID_MAX17048 },
+ { .name = "max17049", .driver_data = ID_MAX17049 },
+ { .name = "max17058", .driver_data = ID_MAX17058 },
+ { .name = "max17059", .driver_data = ID_MAX17059 },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, max17040_id);
diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c
index 167fb3fb3732..639dacdb9b31 100644
--- a/drivers/power/supply/max17042_battery.c
+++ b/drivers/power/supply/max17042_battery.c
@@ -27,6 +27,7 @@
/* Status register bits */
#define STATUS_POR_BIT (1 << 1)
#define STATUS_BST_BIT (1 << 3)
+#define STATUS_DSOCI_BIT (1 << 7)
#define STATUS_VMN_BIT (1 << 8)
#define STATUS_TMN_BIT (1 << 9)
#define STATUS_SMN_BIT (1 << 10)
@@ -38,6 +39,7 @@
/* Interrupt mask bits */
#define CFG_ALRT_BIT_ENBL (1 << 2)
+#define CFG2_DSOCI_BIT_ENBL (1 << 7)
#define VFSOC0_LOCK 0x0000
#define VFSOC0_UNLOCK 0x0080
@@ -52,16 +54,32 @@
#define MAX17042_VMAX_TOLERANCE 50 /* 50 mV */
+#define MAX17042_CRITICAL_SOC 0x03
+
+#define MAX17042_CURRENT_LSB 1562500ll /* 1.5625µV/Rsense */
+#define MAX17042_CAPACITY_LSB 5000000ll /* 5.0µVH/Rsense */
+#define MAX17042_TIME_LSB 5625 / 1000 /* s */
+#define MAX17042_VOLTAGE_LSB 625 / 8 /* µV */
+#define MAX17042_RESISTANCE_LSB 1 / 4096 /* Ω */
+#define MAX17042_TEMPERATURE_LSB 1 / 256 /* °C */
+
struct max17042_chip {
struct device *dev;
struct regmap *regmap;
struct power_supply *battery;
enum max170xx_chip_type chip_type;
- struct max17042_platform_data *pdata;
+ struct max17042_config_data *config_data;
struct work_struct work;
int init_complete;
int irq;
int task_period;
+ bool enable_current_sense;
+ bool enable_por_init;
+ unsigned int r_sns;
+ int vmin; /* in millivolts */
+ int vmax; /* in millivolts */
+ int temp_min; /* in tenths of degree Celsius */
+ int temp_max; /* in tenths of degree Celsius */
};
static enum power_supply_property max17042_battery_props[] = {
@@ -107,15 +125,14 @@ static int max17042_get_temperature(struct max17042_chip *chip, int *temp)
*temp = sign_extend32(data, 15);
/* The value is converted into deci-centigrade scale */
- /* Units of LSB = 1 / 256 degree Celsius */
- *temp = *temp * 10 / 256;
+ *temp = *temp * 10 * MAX17042_TEMPERATURE_LSB;
return 0;
}
static int max17042_get_status(struct max17042_chip *chip, int *status)
{
int ret, charge_full, charge_now;
- int avg_current;
+ int current_now;
u32 data;
ret = power_supply_am_i_supplied(chip->battery);
@@ -155,19 +172,18 @@ static int max17042_get_status(struct max17042_chip *chip, int *status)
* Even though we are supplied, we may still be discharging if the
* supply is e.g. only delivering 5V 0.5A. Check current if available.
*/
- if (!chip->pdata->enable_current_sense) {
+ if (!chip->enable_current_sense) {
*status = POWER_SUPPLY_STATUS_CHARGING;
return 0;
}
- ret = regmap_read(chip->regmap, MAX17042_AvgCurrent, &data);
+ ret = regmap_read(chip->regmap, MAX17042_Current, &data);
if (ret < 0)
return ret;
- avg_current = sign_extend32(data, 15);
- avg_current *= 1562500 / chip->pdata->r_sns;
+ current_now = sign_extend32(data, 15);
- if (avg_current > 0)
+ if (current_now > 0)
*status = POWER_SUPPLY_STATUS_CHARGING;
else
*status = POWER_SUPPLY_STATUS_DISCHARGING;
@@ -185,7 +201,7 @@ static int max17042_get_battery_health(struct max17042_chip *chip, int *health)
goto health_error;
/* bits [0-3] unused */
- vavg = val * 625 / 8;
+ vavg = val * MAX17042_VOLTAGE_LSB;
/* Convert to millivolts */
vavg /= 1000;
@@ -194,16 +210,16 @@ static int max17042_get_battery_health(struct max17042_chip *chip, int *health)
goto health_error;
/* bits [0-3] unused */
- vbatt = val * 625 / 8;
+ vbatt = val * MAX17042_VOLTAGE_LSB;
/* Convert to millivolts */
vbatt /= 1000;
- if (vavg < chip->pdata->vmin) {
+ if (vavg < chip->vmin) {
*health = POWER_SUPPLY_HEALTH_DEAD;
goto out;
}
- if (vbatt > size_add(chip->pdata->vmax, MAX17042_VMAX_TOLERANCE)) {
+ if (vbatt > size_add(chip->vmax, MAX17042_VMAX_TOLERANCE)) {
*health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
goto out;
}
@@ -212,12 +228,12 @@ static int max17042_get_battery_health(struct max17042_chip *chip, int *health)
if (ret < 0)
goto health_error;
- if (temp < chip->pdata->temp_min) {
+ if (temp < chip->temp_min) {
*health = POWER_SUPPLY_HEALTH_COLD;
goto out;
}
- if (temp > chip->pdata->temp_max) {
+ if (temp > chip->temp_max) {
*health = POWER_SUPPLY_HEALTH_OVERHEAT;
goto out;
}
@@ -301,24 +317,24 @@ static int max17042_get_property(struct power_supply *psy,
if (ret < 0)
return ret;
- val->intval = data * 625 / 8;
+ val->intval = data * MAX17042_VOLTAGE_LSB;
break;
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
ret = regmap_read(map, MAX17042_AvgVCELL, &data);
if (ret < 0)
return ret;
- val->intval = data * 625 / 8;
+ val->intval = data * MAX17042_VOLTAGE_LSB;
break;
case POWER_SUPPLY_PROP_VOLTAGE_OCV:
ret = regmap_read(map, MAX17042_OCVInternal, &data);
if (ret < 0)
return ret;
- val->intval = data * 625 / 8;
+ val->intval = data * MAX17042_VOLTAGE_LSB;
break;
case POWER_SUPPLY_PROP_CAPACITY:
- if (chip->pdata->enable_current_sense)
+ if (chip->enable_current_sense)
ret = regmap_read(map, MAX17042_RepSOC, &data);
else
ret = regmap_read(map, MAX17042_VFSOC, &data);
@@ -332,10 +348,10 @@ static int max17042_get_property(struct power_supply *psy,
if (ret < 0)
return ret;
- data64 = data * 5000000ll;
+ data64 = data * MAX17042_CAPACITY_LSB;
data64 *= chip->task_period;
do_div(data64, MAX17042_DEFAULT_TASK_PERIOD);
- do_div(data64, chip->pdata->r_sns);
+ do_div(data64, chip->r_sns);
val->intval = data64;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
@@ -343,10 +359,10 @@ static int max17042_get_property(struct power_supply *psy,
if (ret < 0)
return ret;
- data64 = data * 5000000ll;
+ data64 = data * MAX17042_CAPACITY_LSB;
data64 *= chip->task_period;
do_div(data64, MAX17042_DEFAULT_TASK_PERIOD);
- do_div(data64, chip->pdata->r_sns);
+ do_div(data64, chip->r_sns);
val->intval = data64;
break;
case POWER_SUPPLY_PROP_CHARGE_NOW:
@@ -354,10 +370,10 @@ static int max17042_get_property(struct power_supply *psy,
if (ret < 0)
return ret;
- data64 = data * 5000000ll;
+ data64 = data * MAX17042_CAPACITY_LSB;
data64 *= chip->task_period;
do_div(data64, MAX17042_DEFAULT_TASK_PERIOD);
- do_div(data64, chip->pdata->r_sns);
+ do_div(data64, chip->r_sns);
val->intval = data64;
break;
case POWER_SUPPLY_PROP_CHARGE_COUNTER:
@@ -365,10 +381,10 @@ static int max17042_get_property(struct power_supply *psy,
if (ret < 0)
return ret;
- data64 = sign_extend64(data, 15) * 5000000ll;
+ data64 = sign_extend64(data, 15) * MAX17042_CAPACITY_LSB;
data64 *= chip->task_period;
data64 = div_s64(data64, MAX17042_DEFAULT_TASK_PERIOD);
- val->intval = div_s64(data64, chip->pdata->r_sns);
+ val->intval = div_s64(data64, chip->r_sns);
break;
case POWER_SUPPLY_PROP_TEMP:
ret = max17042_get_temperature(chip, &val->intval);
@@ -390,10 +406,10 @@ static int max17042_get_property(struct power_supply *psy,
val->intval = sign_extend32(data >> 8, 7) * 10;
break;
case POWER_SUPPLY_PROP_TEMP_MIN:
- val->intval = chip->pdata->temp_min;
+ val->intval = chip->temp_min;
break;
case POWER_SUPPLY_PROP_TEMP_MAX:
- val->intval = chip->pdata->temp_max;
+ val->intval = chip->temp_max;
break;
case POWER_SUPPLY_PROP_HEALTH:
ret = max17042_get_battery_health(chip, &val->intval);
@@ -404,25 +420,25 @@ static int max17042_get_property(struct power_supply *psy,
val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
- if (chip->pdata->enable_current_sense) {
+ if (chip->enable_current_sense) {
ret = regmap_read(map, MAX17042_Current, &data);
if (ret < 0)
return ret;
- data64 = sign_extend64(data, 15) * 1562500ll;
- val->intval = div_s64(data64, chip->pdata->r_sns);
+ data64 = sign_extend64(data, 15) * MAX17042_CURRENT_LSB;
+ val->intval = div_s64(data64, chip->r_sns);
} else {
return -EINVAL;
}
break;
case POWER_SUPPLY_PROP_CURRENT_AVG:
- if (chip->pdata->enable_current_sense) {
+ if (chip->enable_current_sense) {
ret = regmap_read(map, MAX17042_AvgCurrent, &data);
if (ret < 0)
return ret;
- data64 = sign_extend64(data, 15) * 1562500ll;
- val->intval = div_s64(data64, chip->pdata->r_sns);
+ data64 = sign_extend64(data, 15) * MAX17042_CURRENT_LSB;
+ val->intval = div_s64(data64, chip->r_sns);
} else {
return -EINVAL;
}
@@ -432,8 +448,8 @@ static int max17042_get_property(struct power_supply *psy,
if (ret < 0)
return ret;
- data64 = data * 1562500ll;
- val->intval = div_s64(data64, chip->pdata->r_sns);
+ data64 = data * MAX17042_CURRENT_LSB;
+ val->intval = div_s64(data64, chip->r_sns);
break;
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
ret = regmap_read(map, MAX17042_TTE, &data);
@@ -444,7 +460,7 @@ static int max17042_get_property(struct power_supply *psy,
if (data == U16_MAX)
return -ENODATA;
- val->intval = data * 5625 / 1000;
+ val->intval = data * MAX17042_TIME_LSB;
break;
case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
if (chip->chip_type != MAXIM_DEVICE_TYPE_MAX17055 &&
@@ -459,7 +475,7 @@ static int max17042_get_property(struct power_supply *psy,
if (data == U16_MAX)
return -ENODATA;
- val->intval = data * 5625 / 1000;
+ val->intval = data * MAX17042_TIME_LSB;
break;
default:
return -EINVAL;
@@ -582,7 +598,7 @@ static inline void max17042_write_model_data(struct max17042_chip *chip,
for (i = 0; i < size; i++)
regmap_write(map, addr + i,
- chip->pdata->config_data->cell_char_tbl[i]);
+ chip->config_data->cell_char_tbl[i]);
}
static inline void max17042_read_model_data(struct max17042_chip *chip,
@@ -617,7 +633,7 @@ static inline int max17042_model_data_compare(struct max17042_chip *chip,
static int max17042_init_model(struct max17042_chip *chip)
{
int ret;
- int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl);
+ int table_size = ARRAY_SIZE(chip->config_data->cell_char_tbl);
u16 *temp_data;
temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL);
@@ -632,7 +648,7 @@ static int max17042_init_model(struct max17042_chip *chip)
ret = max17042_model_data_compare(
chip,
- chip->pdata->config_data->cell_char_tbl,
+ chip->config_data->cell_char_tbl,
temp_data,
table_size);
@@ -645,7 +661,7 @@ static int max17042_init_model(struct max17042_chip *chip)
static int max17042_verify_model_lock(struct max17042_chip *chip)
{
int i;
- int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl);
+ int table_size = ARRAY_SIZE(chip->config_data->cell_char_tbl);
u16 *temp_data;
int ret = 0;
@@ -665,7 +681,7 @@ static int max17042_verify_model_lock(struct max17042_chip *chip)
static void max17042_write_config_regs(struct max17042_chip *chip)
{
- struct max17042_config_data *config = chip->pdata->config_data;
+ struct max17042_config_data *config = chip->config_data;
struct regmap *map = chip->regmap;
regmap_write(map, MAX17042_CONFIG, config->config);
@@ -683,7 +699,7 @@ static void max17042_write_config_regs(struct max17042_chip *chip)
static void max17042_write_custom_regs(struct max17042_chip *chip)
{
- struct max17042_config_data *config = chip->pdata->config_data;
+ struct max17042_config_data *config = chip->config_data;
struct regmap *map = chip->regmap;
max17042_write_verify_reg(map, MAX17042_RCOMP0, config->rcomp0);
@@ -707,7 +723,7 @@ static void max17042_write_custom_regs(struct max17042_chip *chip)
static void max17042_update_capacity_regs(struct max17042_chip *chip)
{
- struct max17042_config_data *config = chip->pdata->config_data;
+ struct max17042_config_data *config = chip->config_data;
struct regmap *map = chip->regmap;
max17042_write_verify_reg(map, MAX17042_FullCAP,
@@ -733,7 +749,7 @@ static void max17042_load_new_capacity_params(struct max17042_chip *chip)
u32 full_cap0, rep_cap, dq_acc, vfSoc;
u32 rem_cap;
- struct max17042_config_data *config = chip->pdata->config_data;
+ struct max17042_config_data *config = chip->config_data;
struct regmap *map = chip->regmap;
regmap_read(map, MAX17042_FullCAP0, &full_cap0);
@@ -765,14 +781,14 @@ static void max17042_load_new_capacity_params(struct max17042_chip *chip)
}
/*
- * Block write all the override values coming from platform data.
+ * Block write all the override values coming from config_data.
* This function MUST be called before the POR initialization procedure
* specified by maxim.
*/
static inline void max17042_override_por_values(struct max17042_chip *chip)
{
struct regmap *map = chip->regmap;
- struct max17042_config_data *config = chip->pdata->config_data;
+ struct max17042_config_data *config = chip->config_data;
max17042_override_por(map, MAX17042_TGAIN, config->tgain);
max17042_override_por(map, MAX17042_TOFF, config->toff);
@@ -827,6 +843,9 @@ static inline void max17042_override_por_values(struct max17042_chip *chip)
(chip->chip_type == MAXIM_DEVICE_TYPE_MAX77759)) {
max17042_override_por(map, MAX17047_V_empty, config->vempty);
}
+
+ if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055)
+ max17042_override_por(map, MAX17055_ModelCfg, config->model_cfg);
}
static int max17042_init_chip(struct max17042_chip *chip)
@@ -835,44 +854,53 @@ static int max17042_init_chip(struct max17042_chip *chip)
int ret;
max17042_override_por_values(chip);
+
+ if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055) {
+ regmap_write_bits(map, MAX17055_ModelCfg,
+ MAX17055_MODELCFG_REFRESH_BIT,
+ MAX17055_MODELCFG_REFRESH_BIT);
+ }
+
/* After Power up, the MAX17042 requires 500mS in order
* to perform signal debouncing and initial SOC reporting
*/
msleep(500);
- /* Initialize configuration */
- max17042_write_config_regs(chip);
+ if (chip->chip_type != MAXIM_DEVICE_TYPE_MAX17055) {
+ /* Initialize configuration */
+ max17042_write_config_regs(chip);
- /* write cell characterization data */
- ret = max17042_init_model(chip);
- if (ret) {
- dev_err(chip->dev, "%s init failed\n",
- __func__);
- return -EIO;
- }
+ /* write cell characterization data */
+ ret = max17042_init_model(chip);
+ if (ret) {
+ dev_err(chip->dev, "%s init failed\n",
+ __func__);
+ return -EIO;
+ }
- ret = max17042_verify_model_lock(chip);
- if (ret) {
- dev_err(chip->dev, "%s lock verify failed\n",
- __func__);
- return -EIO;
- }
- /* write custom parameters */
- max17042_write_custom_regs(chip);
+ ret = max17042_verify_model_lock(chip);
+ if (ret) {
+ dev_err(chip->dev, "%s lock verify failed\n",
+ __func__);
+ return -EIO;
+ }
+ /* write custom parameters */
+ max17042_write_custom_regs(chip);
- /* update capacity params */
- max17042_update_capacity_regs(chip);
+ /* update capacity params */
+ max17042_update_capacity_regs(chip);
- /* delay must be atleast 350mS to allow VFSOC
- * to be calculated from the new configuration
- */
- msleep(350);
+ /* delay must be atleast 350mS to allow VFSOC
+ * to be calculated from the new configuration
+ */
+ msleep(350);
- /* reset vfsoc0 reg */
- max17042_reset_vfsoc0_reg(chip);
+ /* reset vfsoc0 reg */
+ max17042_reset_vfsoc0_reg(chip);
- /* load new capacity params */
- max17042_load_new_capacity_params(chip);
+ /* load new capacity params */
+ max17042_load_new_capacity_params(chip);
+ }
/* Init complete, Clear the POR bit */
regmap_update_bits(map, MAX17042_STATUS, STATUS_POR_BIT, 0x0);
@@ -887,7 +915,7 @@ static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off)
/* program interrupt thresholds such that we should
* get interrupt for every 'off' perc change in the soc
*/
- if (chip->pdata->enable_current_sense)
+ if (chip->enable_current_sense)
regmap_read(map, MAX17042_RepSOC, &soc);
else
regmap_read(map, MAX17042_VFSOC, &soc);
@@ -898,6 +926,44 @@ static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off)
regmap_write(map, MAX17042_SALRT_Th, soc_tr);
}
+static void max17042_set_critical_soc_threshold(struct max17042_chip *chip)
+{
+ struct regmap *map = chip->regmap;
+ u32 soc;
+
+ if (chip->enable_current_sense)
+ regmap_read(map, MAX17042_RepSOC, &soc);
+ else
+ regmap_read(map, MAX17042_VFSOC, &soc);
+
+ regmap_write(map, MAX17042_SALRT_Th,
+ ((soc >> 8) >= MAX17042_CRITICAL_SOC) ?
+ 0xff00 + MAX17042_CRITICAL_SOC : 0xff00);
+}
+
+static void max17042_enable_soc_alerts(struct max17042_chip *chip)
+{
+ if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055) {
+ regmap_update_bits(chip->regmap, MAX17055_Config2,
+ CFG2_DSOCI_BIT_ENBL,
+ CFG2_DSOCI_BIT_ENBL);
+ max17042_set_critical_soc_threshold(chip);
+ return;
+ }
+
+ max17042_set_soc_threshold(chip, 1);
+}
+
+static void max17042_suspend_soc_alerts(struct max17042_chip *chip)
+{
+ if (chip->chip_type != MAXIM_DEVICE_TYPE_MAX17055)
+ return;
+
+ regmap_update_bits(chip->regmap, MAX17055_Config2,
+ CFG2_DSOCI_BIT_ENBL, 0);
+ max17042_set_critical_soc_threshold(chip);
+}
+
static irqreturn_t max17042_thread_handler(int id, void *dev)
{
struct max17042_chip *chip = dev;
@@ -908,9 +974,10 @@ static irqreturn_t max17042_thread_handler(int id, void *dev)
if (ret)
return IRQ_HANDLED;
- if ((val & STATUS_SMN_BIT) || (val & STATUS_SMX_BIT)) {
+ if ((val & STATUS_SMN_BIT) || (val & STATUS_SMX_BIT) ||
+ (val & STATUS_DSOCI_BIT)) {
dev_dbg(chip->dev, "SOC threshold INTR\n");
- max17042_set_soc_threshold(chip, 1);
+ max17042_enable_soc_alerts(chip);
}
/* we implicitly handle all alerts via power_supply_changed */
@@ -927,8 +994,8 @@ static void max17042_init_worker(struct work_struct *work)
struct max17042_chip, work);
int ret;
- /* Initialize registers according to values from the platform data */
- if (chip->pdata->enable_por_init && chip->pdata->config_data) {
+ /* Initialize registers according to values from config_data */
+ if (chip->enable_por_init && chip->config_data) {
ret = max17042_init_chip(chip);
if (ret)
return;
@@ -938,17 +1005,10 @@ static void max17042_init_worker(struct work_struct *work)
}
#ifdef CONFIG_OF
-static struct max17042_platform_data *
-max17042_get_of_pdata(struct max17042_chip *chip)
+static int max17042_parse_dt(struct max17042_chip *chip)
{
- struct device *dev = chip->dev;
- struct device_node *np = dev->of_node;
+ struct device_node *np = chip->dev->of_node;
u32 prop;
- struct max17042_platform_data *pdata;
-
- pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return NULL;
/*
* Require current sense resistor value to be specified for
@@ -959,85 +1019,46 @@ max17042_get_of_pdata(struct max17042_chip *chip)
if ((of_property_read_u32(np, "shunt-resistor-micro-ohms",
&prop) == 0) ||
(of_property_read_u32(np, "maxim,rsns-microohm", &prop) == 0)) {
- pdata->r_sns = prop;
- pdata->enable_current_sense = true;
+ chip->r_sns = prop;
+ chip->enable_current_sense = true;
}
- if (of_property_read_s32(np, "maxim,cold-temp", &pdata->temp_min))
- pdata->temp_min = INT_MIN;
- if (of_property_read_s32(np, "maxim,over-heat-temp", &pdata->temp_max))
- pdata->temp_max = INT_MAX;
- if (of_property_read_s32(np, "maxim,dead-volt", &pdata->vmin))
- pdata->vmin = INT_MIN;
- if (of_property_read_s32(np, "maxim,over-volt", &pdata->vmax))
- pdata->vmax = INT_MAX;
+ if (of_property_read_s32(np, "maxim,cold-temp", &chip->temp_min))
+ chip->temp_min = INT_MIN;
+ if (of_property_read_s32(np, "maxim,over-heat-temp", &chip->temp_max))
+ chip->temp_max = INT_MAX;
+ if (of_property_read_s32(np, "maxim,dead-volt", &chip->vmin))
+ chip->vmin = INT_MIN;
+ if (of_property_read_s32(np, "maxim,over-volt", &chip->vmax))
+ chip->vmax = INT_MAX;
- return pdata;
+ return 0;
}
#endif
-static struct max17042_reg_data max17047_default_pdata_init_regs[] = {
- /*
- * Some firmwares do not set FullSOCThr, Enable End-of-Charge Detection
- * when the voltage FG reports 95%, as recommended in the datasheet.
- */
- { MAX17047_FullSOCThr, MAX17042_BATTERY_FULL << 8 },
-};
-
-static struct max17042_platform_data *
-max17042_get_default_pdata(struct max17042_chip *chip)
+static int max17042_init_defaults(struct max17042_chip *chip)
{
- struct device *dev = chip->dev;
- struct max17042_platform_data *pdata;
int ret, misc_cfg;
/*
- * The MAX17047 gets used on x86 where we might not have pdata, assume
+ * The MAX17047 gets used on x86 where we might not have DT, assume
* the firmware will already have initialized the fuel-gauge and provide
* default values for the non init bits to make things work.
*/
- pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return pdata;
-
- if ((chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047) ||
- (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050)) {
- pdata->init_data = max17047_default_pdata_init_regs;
- pdata->num_init_data =
- ARRAY_SIZE(max17047_default_pdata_init_regs);
- }
ret = regmap_read(chip->regmap, MAX17042_MiscCFG, &misc_cfg);
if (ret < 0)
- return NULL;
+ return ret;
/* If bits 0-1 are set to 3 then only Voltage readings are used */
- if ((misc_cfg & 0x3) == 0x3)
- pdata->enable_current_sense = false;
- else
- pdata->enable_current_sense = true;
+ chip->enable_current_sense = (misc_cfg & 0x3) != 0x3;
- pdata->vmin = MAX17042_DEFAULT_VMIN;
- pdata->vmax = MAX17042_DEFAULT_VMAX;
- pdata->temp_min = MAX17042_DEFAULT_TEMP_MIN;
- pdata->temp_max = MAX17042_DEFAULT_TEMP_MAX;
+ chip->vmin = MAX17042_DEFAULT_VMIN;
+ chip->vmax = MAX17042_DEFAULT_VMAX;
+ chip->temp_min = MAX17042_DEFAULT_TEMP_MIN;
+ chip->temp_max = MAX17042_DEFAULT_TEMP_MAX;
- return pdata;
-}
-
-static struct max17042_platform_data *
-max17042_get_pdata(struct max17042_chip *chip)
-{
- struct device *dev = chip->dev;
-
-#ifdef CONFIG_OF
- if (dev->of_node)
- return max17042_get_of_pdata(chip);
-#endif
- if (dev->platform_data)
- return dev->platform_data;
-
- return max17042_get_default_pdata(chip);
+ return 0;
}
static const struct regmap_config max17042_regmap_config = {
@@ -1116,8 +1137,8 @@ static int max17042_probe(struct i2c_client *client, struct device *dev, int irq
struct power_supply_config psy_cfg = {};
struct max17042_chip *chip;
int ret;
- int i;
u32 val;
+ bool use_default_config = false;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
return -EIO;
@@ -1138,10 +1159,19 @@ static int max17042_probe(struct i2c_client *client, struct device *dev, int irq
return dev_err_probe(dev, PTR_ERR(chip->regmap),
"Failed to initialize regmap\n");
- chip->pdata = max17042_get_pdata(chip);
- if (!chip->pdata)
- return dev_err_probe(dev, -EINVAL,
- "no platform data provided\n");
+#ifdef CONFIG_OF
+ if (dev->of_node) {
+ ret = max17042_parse_dt(chip);
+ if (ret)
+ return ret;
+ } else
+#endif
+ {
+ ret = max17042_init_defaults(chip);
+ if (ret)
+ return ret;
+ use_default_config = true;
+ }
dev_set_drvdata(dev, chip);
psy_cfg.drv_data = chip;
@@ -1149,19 +1179,13 @@ static int max17042_probe(struct i2c_client *client, struct device *dev, int irq
/* When current is not measured,
* CURRENT_NOW and CURRENT_AVG properties should be invisible. */
- if (!chip->pdata->enable_current_sense)
+ if (!chip->enable_current_sense)
max17042_desc = &max17042_no_current_sense_psy_desc;
- if (chip->pdata->r_sns == 0)
- chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
-
- if (chip->pdata->init_data)
- for (i = 0; i < chip->pdata->num_init_data; i++)
- regmap_write(chip->regmap,
- chip->pdata->init_data[i].addr,
- chip->pdata->init_data[i].data);
+ if (chip->r_sns == 0)
+ chip->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
- if (!chip->pdata->enable_current_sense) {
+ if (!chip->enable_current_sense) {
regmap_write(chip->regmap, MAX17042_CGAIN, 0x0000);
regmap_write(chip->regmap, MAX17042_MiscCFG, 0x0003);
regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007);
@@ -1184,6 +1208,16 @@ static int max17042_probe(struct i2c_client *client, struct device *dev, int irq
return dev_err_probe(dev, PTR_ERR(chip->battery),
"failed: power supply register\n");
+ /*
+ * Some firmwares do not set FullSOCThr, Enable End-of-Charge Detection
+ * when the voltage FG reports 95%, as recommended in the datasheet.
+ */
+ if (use_default_config &&
+ (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047 ||
+ chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050))
+ regmap_write(chip->regmap, MAX17047_FullSOCThr,
+ MAX17042_BATTERY_FULL << 8);
+
if (irq) {
unsigned int flags = IRQF_ONESHOT | IRQF_SHARED | IRQF_PROBE_SHARED;
@@ -1196,7 +1230,7 @@ static int max17042_probe(struct i2c_client *client, struct device *dev, int irq
regmap_update_bits(chip->regmap, MAX17042_CONFIG,
CFG_ALRT_BIT_ENBL,
CFG_ALRT_BIT_ENBL);
- max17042_set_soc_threshold(chip, 1);
+ max17042_enable_soc_alerts(chip);
} else {
irq = 0;
if (ret != -EBUSY)
@@ -1254,14 +1288,14 @@ static int max17042_platform_probe(struct platform_device *pdev)
if (!i2c)
return -EINVAL;
- dev->of_node = dev->parent->of_node;
+ device_set_of_node_from_dev(dev, dev->parent);
+
id = platform_get_device_id(pdev);
irq = platform_get_irq(pdev, 0);
return max17042_probe(i2c, dev, irq, id->driver_data);
}
-#ifdef CONFIG_PM_SLEEP
static int max17042_suspend(struct device *dev)
{
struct max17042_chip *chip = dev_get_drvdata(dev);
@@ -1272,6 +1306,7 @@ static int max17042_suspend(struct device *dev)
*/
if (chip->irq) {
disable_irq(chip->irq);
+ max17042_suspend_soc_alerts(chip);
enable_irq_wake(chip->irq);
}
@@ -1285,16 +1320,15 @@ static int max17042_resume(struct device *dev)
if (chip->irq) {
disable_irq_wake(chip->irq);
enable_irq(chip->irq);
- /* re-program the SOC thresholds to 1% change */
- max17042_set_soc_threshold(chip, 1);
+ /* re-arm runtime SOC alerts */
+ max17042_enable_soc_alerts(chip);
}
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend,
- max17042_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend,
+ max17042_resume);
#ifdef CONFIG_ACPI
static const struct acpi_device_id max17042_acpi_match[] = {
@@ -1335,12 +1369,12 @@ MODULE_DEVICE_TABLE(of, max17042_dt_match);
#endif
static const struct i2c_device_id max17042_id[] = {
- { "max17042", MAXIM_DEVICE_TYPE_MAX17042 },
- { "max17047", MAXIM_DEVICE_TYPE_MAX17047 },
- { "max17050", MAXIM_DEVICE_TYPE_MAX17050 },
- { "max17055", MAXIM_DEVICE_TYPE_MAX17055 },
- { "max77759-fg", MAXIM_DEVICE_TYPE_MAX77759 },
- { "max77849-battery", MAXIM_DEVICE_TYPE_MAX17047 },
+ { .name = "max17042", .driver_data = MAXIM_DEVICE_TYPE_MAX17042 },
+ { .name = "max17047", .driver_data = MAXIM_DEVICE_TYPE_MAX17047 },
+ { .name = "max17050", .driver_data = MAXIM_DEVICE_TYPE_MAX17050 },
+ { .name = "max17055", .driver_data = MAXIM_DEVICE_TYPE_MAX17055 },
+ { .name = "max77759-fg", .driver_data = MAXIM_DEVICE_TYPE_MAX77759 },
+ { .name = "max77849-battery", .driver_data = MAXIM_DEVICE_TYPE_MAX17047 },
{ }
};
MODULE_DEVICE_TABLE(i2c, max17042_id);
@@ -1361,7 +1395,7 @@ static struct i2c_driver max17042_i2c_driver = {
.name = "max17042",
.acpi_match_table = ACPI_PTR(max17042_acpi_match),
.of_match_table = of_match_ptr(max17042_dt_match),
- .pm = &max17042_pm_ops,
+ .pm = pm_ptr(&max17042_pm_ops),
},
.probe = max17042_i2c_probe,
.id_table = max17042_id,
@@ -1371,7 +1405,7 @@ static struct platform_driver max17042_platform_driver = {
.driver = {
.name = "max17042",
.acpi_match_table = ACPI_PTR(max17042_acpi_match),
- .pm = &max17042_pm_ops,
+ .pm = pm_ptr(&max17042_pm_ops),
},
.probe = max17042_platform_probe,
.id_table = max17042_platform_id,
diff --git a/drivers/power/supply/max77693_charger.c b/drivers/power/supply/max77693_charger.c
index 027d6a539b65..76c58b32a374 100644
--- a/drivers/power/supply/max77693_charger.c
+++ b/drivers/power/supply/max77693_charger.c
@@ -788,7 +788,7 @@ static void max77693_charger_remove(struct platform_device *pdev)
}
static const struct platform_device_id max77693_charger_id[] = {
- { "max77693-charger", 0, },
+ { .name = "max77693-charger" },
{ }
};
MODULE_DEVICE_TABLE(platform, max77693_charger_id);
diff --git a/drivers/power/supply/max77759_charger.c b/drivers/power/supply/max77759_charger.c
index 9bb414599f16..c606d7bafcb8 100644
--- a/drivers/power/supply/max77759_charger.c
+++ b/drivers/power/supply/max77759_charger.c
@@ -754,7 +754,7 @@ static int max77759_charger_probe(struct platform_device *pdev)
}
static const struct platform_device_id max77759_charger_id[] = {
- { .name = "max77759-charger", },
+ { .name = "max77759-charger" },
{ }
};
MODULE_DEVICE_TABLE(platform, max77759_charger_id);
diff --git a/drivers/power/supply/max77976_charger.c b/drivers/power/supply/max77976_charger.c
index 3d6ff4005533..9a8a09d2a55e 100644
--- a/drivers/power/supply/max77976_charger.c
+++ b/drivers/power/supply/max77976_charger.c
@@ -484,7 +484,7 @@ static int max77976_probe(struct i2c_client *client)
}
static const struct i2c_device_id max77976_i2c_id[] = {
- { MAX77976_DRIVER_NAME },
+ { .name = MAX77976_DRIVER_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, max77976_i2c_id);
diff --git a/drivers/power/supply/max8971_charger.c b/drivers/power/supply/max8971_charger.c
index 26416d26f235..49a05858bef8 100644
--- a/drivers/power/supply/max8971_charger.c
+++ b/drivers/power/supply/max8971_charger.c
@@ -731,7 +731,7 @@ static const struct of_device_id max8971_match_ids[] = {
MODULE_DEVICE_TABLE(of, max8971_match_ids);
static const struct i2c_device_id max8971_i2c_id[] = {
- { "max8971" },
+ { .name = "max8971" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max8971_i2c_id);
diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c
index 1ec3535a257d..19da9eff0372 100644
--- a/drivers/power/supply/max8997_charger.c
+++ b/drivers/power/supply/max8997_charger.c
@@ -268,7 +268,7 @@ static int max8997_battery_probe(struct platform_device *pdev)
}
static const struct platform_device_id max8997_battery_id[] = {
- { "max8997-battery", 0 },
+ { .name = "max8997-battery" },
{ }
};
MODULE_DEVICE_TABLE(platform, max8997_battery_id);
diff --git a/drivers/power/supply/max8998_charger.c b/drivers/power/supply/max8998_charger.c
index 418b882b163d..b0eda2b51e7f 100644
--- a/drivers/power/supply/max8998_charger.c
+++ b/drivers/power/supply/max8998_charger.c
@@ -188,7 +188,7 @@ static int max8998_battery_probe(struct platform_device *pdev)
}
static const struct platform_device_id max8998_battery_id[] = {
- { "max8998-battery", TYPE_MAX8998 },
+ { .name = "max8998-battery" },
{ }
};
MODULE_DEVICE_TABLE(platform, max8998_battery_id);
diff --git a/drivers/power/supply/mm8013.c b/drivers/power/supply/mm8013.c
index 93c50cff31bc..819667a27cad 100644
--- a/drivers/power/supply/mm8013.c
+++ b/drivers/power/supply/mm8013.c
@@ -284,8 +284,8 @@ static int mm8013_probe(struct i2c_client *client)
}
static const struct i2c_device_id mm8013_id_table[] = {
- { "mm8013" },
- {}
+ { .name = "mm8013" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mm8013_id_table);
diff --git a/drivers/power/supply/mt6360_charger.c b/drivers/power/supply/mt6360_charger.c
index 77747eb51667..d3b0731f6562 100644
--- a/drivers/power/supply/mt6360_charger.c
+++ b/drivers/power/supply/mt6360_charger.c
@@ -841,15 +841,15 @@ static const struct of_device_id __maybe_unused mt6360_charger_of_id[] = {
MODULE_DEVICE_TABLE(of, mt6360_charger_of_id);
static const struct platform_device_id mt6360_charger_id[] = {
- { "mt6360-chg", 0 },
- {},
+ { .name = "mt6360-chg" },
+ { }
};
MODULE_DEVICE_TABLE(platform, mt6360_charger_id);
static struct platform_driver mt6360_charger_driver = {
.driver = {
.name = "mt6360-chg",
- .of_match_table = of_match_ptr(mt6360_charger_of_id),
+ .of_match_table = mt6360_charger_of_id,
},
.probe = mt6360_charger_probe,
.id_table = mt6360_charger_id,
diff --git a/drivers/power/supply/pf1550-charger.c b/drivers/power/supply/pf1550-charger.c
index a457862ef461..41036f4cb64a 100644
--- a/drivers/power/supply/pf1550-charger.c
+++ b/drivers/power/supply/pf1550-charger.c
@@ -622,7 +622,7 @@ static int pf1550_charger_probe(struct platform_device *pdev)
}
static const struct platform_device_id pf1550_charger_id[] = {
- { "pf1550-charger", },
+ { .name = "pf1550-charger" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, pf1550_charger_id);
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index a446d3d086fc..2532e221b2e1 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -292,18 +292,13 @@ static int power_supply_check_supplies(struct power_supply *psy)
if (cnt == 1)
return 0;
- /* All supplies found, allocate char ** array for filling */
- psy->supplied_from = devm_kzalloc(&psy->dev, sizeof(*psy->supplied_from),
+ /* All supplies found, allocate char * array for filling */
+ psy->supplied_from = devm_kcalloc(&psy->dev,
+ cnt - 1, sizeof(*psy->supplied_from),
GFP_KERNEL);
if (!psy->supplied_from)
return -ENOMEM;
- *psy->supplied_from = devm_kcalloc(&psy->dev,
- cnt - 1, sizeof(**psy->supplied_from),
- GFP_KERNEL);
- if (!*psy->supplied_from)
- return -ENOMEM;
-
return power_supply_populate_supplied_from(psy);
}
#else
diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c
index b2674adfa30b..63333f6aa819 100644
--- a/drivers/power/supply/rt5033_battery.c
+++ b/drivers/power/supply/rt5033_battery.c
@@ -174,7 +174,7 @@ static int rt5033_battery_probe(struct i2c_client *client)
}
static const struct i2c_device_id rt5033_battery_id[] = {
- { "rt5033-battery", },
+ { .name = "rt5033-battery" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5033_battery_id);
diff --git a/drivers/power/supply/rt5033_charger.c b/drivers/power/supply/rt5033_charger.c
index de724f23e453..536ab29b657d 100644
--- a/drivers/power/supply/rt5033_charger.c
+++ b/drivers/power/supply/rt5033_charger.c
@@ -727,7 +727,7 @@ out:
}
static const struct platform_device_id rt5033_charger_id[] = {
- { "rt5033-charger", },
+ { .name = "rt5033-charger" },
{ }
};
MODULE_DEVICE_TABLE(platform, rt5033_charger_id);
diff --git a/drivers/power/supply/rt9455_charger.c b/drivers/power/supply/rt9455_charger.c
index 5130d2395e88..7045d2908148 100644
--- a/drivers/power/supply/rt9455_charger.c
+++ b/drivers/power/supply/rt9455_charger.c
@@ -1719,7 +1719,7 @@ static void rt9455_remove(struct i2c_client *client)
}
static const struct i2c_device_id rt9455_i2c_id_table[] = {
- { RT9455_DRIVER_NAME },
+ { .name = RT9455_DRIVER_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt9455_i2c_id_table);
diff --git a/drivers/power/supply/s2m-charger.c b/drivers/power/supply/s2m-charger.c
new file mode 100644
index 000000000000..4d1f2c2c7144
--- /dev/null
+++ b/drivers/power/supply/s2m-charger.c
@@ -0,0 +1,313 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Battery Charger Driver for Samsung S2M series PMICs.
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd
+ * Copyright (c) 2026 Kaustabh Chakraborty <kauschluss@disroot.org>
+ * Copyright (c) 2026 Łukasz Lebiedziński <kernel@lvkasz.us>
+ */
+
+#include <linux/devm-helpers.h>
+#include <linux/extcon.h>
+#include <linux/mfd/samsung/core.h>
+#include <linux/mfd/samsung/s2mu005.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+
+struct s2m_chgr {
+ struct device *dev;
+ struct regmap *regmap;
+ struct power_supply *psy;
+ struct extcon_dev *extcon;
+ struct work_struct extcon_work;
+ struct notifier_block extcon_nb;
+};
+
+static int s2mu005_chgr_get_online(struct s2m_chgr *priv, int *value)
+{
+ u32 val;
+ int ret;
+
+ ret = regmap_read(priv->regmap, S2MU005_REG_CHGR_STATUS0, &val);
+ if (ret) {
+ dev_err(priv->dev, "failed to read register (%d)\n", ret);
+ return ret;
+ }
+
+ *value = !!(val & S2MU005_CHGR_CHG);
+
+ return 0;
+}
+
+static void s2mu005_chgr_get_usb_type(struct s2m_chgr *priv, int *value)
+{
+ if (extcon_get_state(priv->extcon, EXTCON_CHG_USB_CDP) > 0)
+ *value = POWER_SUPPLY_USB_TYPE_CDP;
+ else if (extcon_get_state(priv->extcon, EXTCON_CHG_USB_SDP) > 0)
+ *value = POWER_SUPPLY_USB_TYPE_SDP;
+ else if (extcon_get_state(priv->extcon, EXTCON_CHG_USB_DCP) > 0)
+ *value = POWER_SUPPLY_USB_TYPE_DCP;
+ else
+ *value = POWER_SUPPLY_USB_TYPE_UNKNOWN;
+}
+
+static int s2mu005_chgr_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct s2m_chgr *priv = power_supply_get_drvdata(psy);
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ ret = s2mu005_chgr_get_online(priv, &val->intval);
+ if (ret)
+ return ret;
+ break;
+ case POWER_SUPPLY_PROP_USB_TYPE:
+ s2mu005_chgr_get_usb_type(priv, &val->intval);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int s2mu005_chgr_mode_set_host(struct s2m_chgr *priv)
+{
+ int ret;
+
+ /* set mode to OTG */
+ ret = regmap_update_bits(priv->regmap, S2MU005_REG_CHGR_CTRL0,
+ S2MU005_CHGR_OP_MODE,
+ FIELD_PREP(S2MU005_CHGR_OP_MODE,
+ S2MU005_CHGR_OP_MODE_OTG));
+ if (ret) {
+ dev_err(priv->dev, "failed to set OTG mode (%d)\n", ret);
+ return ret;
+ }
+
+ /* set boost frequency to 2MHz */
+ ret = regmap_update_bits(priv->regmap, S2MU005_REG_CHGR_CTRL11,
+ S2MU005_CHGR_OSC_BOOST,
+ FIELD_PREP(S2MU005_CHGR_OSC_BOOST,
+ S2MU005_CHGR_OSC_BOOST_2MHZ));
+ if (ret) {
+ dev_err(priv->dev, "failed to set boost frequency (%d)\n", ret);
+ return ret;
+ }
+
+ /* set OTG current limit to 1.5 A */
+ ret = regmap_update_bits(priv->regmap, S2MU005_REG_CHGR_CTRL4,
+ S2MU005_CHGR_OTG_OCP,
+ FIELD_PREP(S2MU005_CHGR_OTG_OCP,
+ S2MU005_CHGR_OTG_OCP_1P5A));
+ if (ret) {
+ dev_err(priv->dev, "failed to set OTG current limit (%d)\n", ret);
+ return ret;
+ }
+
+ /* VBUS switches are OFF when OTG over-current happens */
+ ret = regmap_set_bits(priv->regmap, S2MU005_REG_CHGR_CTRL4,
+ S2MU005_CHGR_OTG_OCP_OFF);
+ if (ret) {
+ dev_err(priv->dev, "failed to set OTG OCP switch (%d)\n", ret);
+ return ret;
+ }
+
+ /* set OTG voltage to 5.1 V */
+ ret = regmap_update_bits(priv->regmap, S2MU005_REG_CHGR_CTRL5,
+ S2MU005_CHGR_VMID_BOOST,
+ FIELD_PREP(S2MU005_CHGR_VMID_BOOST,
+ S2MU005_CHGR_VMID_BOOST_5P1V));
+ if (ret) {
+ dev_err(priv->dev, "failed to set OTG voltage (%d)\n", ret);
+ return ret;
+ }
+
+ /* turn on OTG */
+ ret = regmap_update_bits(priv->regmap, S2MU005_REG_CHGR_CTRL15,
+ S2MU005_CHGR_OTG_EN,
+ FIELD_PREP(S2MU005_CHGR_OTG_EN,
+ S2MU005_CHGR_OTG_EN_ON));
+ if (ret) {
+ dev_err(priv->dev, "failed to turn on OTG (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int s2mu005_chgr_mode_set_charger(struct s2m_chgr *priv)
+{
+ int ret;
+
+ /* first reset to mode 0 */
+ ret = regmap_clear_bits(priv->regmap, S2MU005_REG_CHGR_CTRL0,
+ S2MU005_CHGR_OP_MODE);
+ if (ret) {
+ dev_err(priv->dev, "failed to reset opmode (%d)\n", ret);
+ return ret;
+ }
+
+ /* wait for the charger to settle before switching to charging mode */
+ msleep(50);
+ /* then set to charging mode */
+ ret = regmap_update_bits(priv->regmap, S2MU005_REG_CHGR_CTRL0,
+ S2MU005_CHGR_OP_MODE,
+ FIELD_PREP(S2MU005_CHGR_OP_MODE,
+ S2MU005_CHGR_OP_MODE_CHG));
+ if (ret) {
+ dev_err(priv->dev, "failed to set opmode to charging (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int s2mu005_chgr_mode_unset(struct s2m_chgr *priv)
+{
+ int ret;
+
+ /* turn off OTG */
+ ret = regmap_clear_bits(priv->regmap, S2MU005_REG_CHGR_CTRL15,
+ S2MU005_CHGR_OTG_EN);
+ if (ret) {
+ dev_err(priv->dev, "failed to turn off OTG (%d)\n", ret);
+ return ret;
+ }
+
+ /* reset operation mode */
+ ret = regmap_clear_bits(priv->regmap, S2MU005_REG_CHGR_CTRL0,
+ S2MU005_CHGR_OP_MODE);
+ if (ret) {
+ dev_err(priv->dev, "failed to reset opmode (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void s2mu005_chgr_extcon_work(struct work_struct *work)
+{
+ struct s2m_chgr *priv = container_of(work, struct s2m_chgr, extcon_work);
+
+ if (extcon_get_state(priv->extcon, EXTCON_USB_HOST) > 0)
+ s2mu005_chgr_mode_set_host(priv);
+ else if (extcon_get_state(priv->extcon, EXTCON_USB) > 0)
+ s2mu005_chgr_mode_set_charger(priv);
+ else
+ s2mu005_chgr_mode_unset(priv);
+
+ power_supply_changed(priv->psy);
+}
+
+static const enum power_supply_property s2mu005_chgr_properties[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_USB_TYPE,
+};
+
+static const struct power_supply_desc s2mu005_chgr_psy_desc = {
+ .name = "s2mu005-charger",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .properties = s2mu005_chgr_properties,
+ .num_properties = ARRAY_SIZE(s2mu005_chgr_properties),
+ .get_property = s2mu005_chgr_get_property,
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
+};
+
+static int s2m_chgr_extcon_notifier(struct notifier_block *nb,
+ unsigned long event, void *param)
+{
+ struct s2m_chgr *priv = container_of(nb, struct s2m_chgr, extcon_nb);
+
+ schedule_work(&priv->extcon_work);
+
+ return NOTIFY_OK;
+}
+
+static int s2m_chgr_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct sec_pmic_dev *pmic_drvdata = dev_get_drvdata(dev->parent);
+ struct s2m_chgr *priv;
+ struct device_node *extcon_node __free(device_node) = NULL;
+ struct power_supply_config psy_cfg = {};
+ const struct power_supply_desc *psy_desc;
+ work_func_t extcon_work_func;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+ priv->dev = dev;
+ priv->regmap = pmic_drvdata->regmap_pmic;
+
+ switch (platform_get_device_id(pdev)->driver_data) {
+ case S2MU005:
+ psy_desc = &s2mu005_chgr_psy_desc;
+ extcon_work_func = s2mu005_chgr_extcon_work;
+ break;
+ default:
+ return dev_err_probe(dev, -ENODEV,
+ "device type %d is not supported by driver\n",
+ pmic_drvdata->device_type);
+ }
+
+ /* MUIC is mandatory. If unavailable, request probe deferral */
+ extcon_node = of_get_child_by_name(dev->parent->of_node, "muic");
+ if (!extcon_node)
+ return dev_err_probe(dev, -ENODEV, "MUIC node required but not found\n");
+
+ priv->extcon = extcon_find_edev_by_node(extcon_node);
+ if (IS_ERR(priv->extcon))
+ return -EPROBE_DEFER;
+
+ psy_cfg.drv_data = priv;
+ psy_cfg.fwnode = dev_fwnode(dev->parent);
+ priv->psy = devm_power_supply_register(dev, psy_desc, &psy_cfg);
+ if (IS_ERR(priv->psy))
+ return dev_err_probe(dev, PTR_ERR(priv->psy),
+ "failed to register power supply subsystem\n");
+
+ ret = devm_work_autocancel(dev, &priv->extcon_work, extcon_work_func);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to initialize extcon work\n");
+
+ priv->extcon_nb.notifier_call = s2m_chgr_extcon_notifier;
+ ret = devm_extcon_register_notifier_all(dev, priv->extcon, &priv->extcon_nb);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register extcon notifier\n");
+
+ return 0;
+}
+
+static const struct platform_device_id s2m_chgr_id_table[] = {
+ { "s2mu005-charger", S2MU005 },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, s2m_chgr_id_table);
+
+static struct platform_driver s2m_chgr_driver = {
+ .driver = {
+ .name = "s2m-charger",
+ },
+ .probe = s2m_chgr_probe,
+ .id_table = s2m_chgr_id_table,
+};
+module_platform_driver(s2m_chgr_driver);
+
+MODULE_DESCRIPTION("Battery Charger Driver For Samsung S2M Series PMICs");
+MODULE_AUTHOR("Kaustabh Chakraborty <kauschluss@disroot.org>");
+MODULE_AUTHOR("Łukasz Lebiedziński <kernel@lvkasz.us>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c
index 43c48196c167..017ec06be766 100644
--- a/drivers/power/supply/sbs-battery.c
+++ b/drivers/power/supply/sbs-battery.c
@@ -1254,10 +1254,10 @@ static SIMPLE_DEV_PM_OPS(sbs_pm_ops, sbs_suspend, NULL);
#endif
static const struct i2c_device_id sbs_id[] = {
- { "bq20z65", SBS_FLAGS_TI_BQ20ZX5 },
- { "bq20z75", SBS_FLAGS_TI_BQ20ZX5 },
- { "sbs-battery", 0 },
- {}
+ { .name = "bq20z65", .driver_data = SBS_FLAGS_TI_BQ20ZX5 },
+ { .name = "bq20z75", .driver_data = SBS_FLAGS_TI_BQ20ZX5 },
+ { .name = "sbs-battery", .driver_data = 0 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, sbs_id);
diff --git a/drivers/power/supply/sbs-charger.c b/drivers/power/supply/sbs-charger.c
index 7d5e67620580..a00c710601e8 100644
--- a/drivers/power/supply/sbs-charger.c
+++ b/drivers/power/supply/sbs-charger.c
@@ -244,7 +244,7 @@ MODULE_DEVICE_TABLE(of, sbs_dt_ids);
#endif
static const struct i2c_device_id sbs_id[] = {
- { "sbs-charger" },
+ { .name = "sbs-charger" },
{ }
};
MODULE_DEVICE_TABLE(i2c, sbs_id);
diff --git a/drivers/power/supply/sbs-manager.c b/drivers/power/supply/sbs-manager.c
index 343ad4ab4082..9ad3fb117a4d 100644
--- a/drivers/power/supply/sbs-manager.c
+++ b/drivers/power/supply/sbs-manager.c
@@ -389,8 +389,8 @@ static int sbsm_probe(struct i2c_client *client)
}
static const struct i2c_device_id sbsm_ids[] = {
- { "sbs-manager" },
- { "ltc1760" },
+ { .name = "sbs-manager" },
+ { .name = "ltc1760" },
{ }
};
MODULE_DEVICE_TABLE(i2c, sbsm_ids);
diff --git a/drivers/power/supply/smb347-charger.c b/drivers/power/supply/smb347-charger.c
index 8b95f7e8712f..c1b67dac8ef6 100644
--- a/drivers/power/supply/smb347-charger.c
+++ b/drivers/power/supply/smb347-charger.c
@@ -1083,7 +1083,7 @@ static int smb347_get_charging_status(struct smb347_charger *smb,
} else {
/*
* in this case no charger error or termination
- * occured but charging is not in progress!!!
+ * occurred but charging is not in progress!!!
*/
status = POWER_SUPPLY_STATUS_NOT_CHARGING;
}
@@ -1609,10 +1609,10 @@ static void smb347_shutdown(struct i2c_client *client)
}
static const struct i2c_device_id smb347_id[] = {
- { "smb345", SMB345 },
- { "smb347", SMB347 },
- { "smb358", SMB358 },
- { },
+ { .name = "smb345", .driver_data = SMB345 },
+ { .name = "smb347", .driver_data = SMB347 },
+ { .name = "smb358", .driver_data = SMB358 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, smb347_id);
diff --git a/drivers/power/supply/stc3117_fuel_gauge.c b/drivers/power/supply/stc3117_fuel_gauge.c
index a1bc5970370a..469f2b359920 100644
--- a/drivers/power/supply/stc3117_fuel_gauge.c
+++ b/drivers/power/supply/stc3117_fuel_gauge.c
@@ -584,7 +584,7 @@ static int stc3117_probe(struct i2c_client *client)
}
static const struct i2c_device_id stc3117_id[] = {
- { "stc3117", 0 },
+ { .name = "stc3117", .driver_data = 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, stc3117_id);
diff --git a/drivers/power/supply/surface-rt-ec.c b/drivers/power/supply/surface-rt-ec.c
new file mode 100644
index 000000000000..a728ae0db858
--- /dev/null
+++ b/drivers/power/supply/surface-rt-ec.c
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/devm-helpers.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/power_supply.h>
+#include <linux/types.h>
+
+/* Register Addresses (B=byte; W=word; S=string) */
+#define REGB_STATUS 0x02
+#define REGW_VOLTAGE_NOW 0x20
+#define REGW_CURRENT_NOW 0x24
+#define REGW_CAPACITY 0x28
+#define REGW_CHARGE_NOW 0x2a
+#define REGW_CHARGE_FULL 0x2c
+#define REGW_CYCLE_COUNT 0x3a
+#define REGW_CHARGE_FULL_DESIGN 0x3c
+#define REGW_VOLTAGE_MAX_DESIGN 0x3e
+#define REGW_SERIAL_NUMBER 0x44
+#define REGS_MANUFACTURER 0x46
+#define REGS_MODEL_NAME 0x52
+#define REGS_TECHNOLOGY 0x5a
+#define REGB_ONLINE 0x67
+
+struct srt_ec_device {
+ struct i2c_client *client;
+
+ struct power_supply *bat;
+ struct power_supply *psy;
+
+ struct gpio_desc *enable_gpiod;
+ struct delayed_work poll_work;
+
+ unsigned int technology;
+ unsigned int capacity;
+
+ const char *serial;
+ char manufacturer[13];
+ char model_name[10];
+};
+
+static const enum power_supply_property srt_bat_power_supply_props[] = {
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CYCLE_COUNT,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_SERIAL_NUMBER,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+static const enum power_supply_property srt_psy_power_supply_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_PRESENT,
+};
+
+static int srt_bat_get_value(struct i2c_client *client, int reg, int *val)
+{
+ int ret;
+
+ switch (reg) {
+ case REGW_CHARGE_NOW:
+ case REGW_CHARGE_FULL_DESIGN:
+ case REGW_CHARGE_FULL:
+ case REGW_VOLTAGE_MAX_DESIGN:
+ case REGW_VOLTAGE_NOW:
+ ret = i2c_smbus_read_word_data(client, reg);
+ if (ret < 0)
+ return ret;
+
+ *val = ret * 1000;
+ break;
+
+ case REGW_CURRENT_NOW:
+ ret = i2c_smbus_read_word_data(client, reg);
+ if (ret < 0)
+ return ret;
+
+ *val = (s16)ret * 1000;
+ break;
+
+ case REGW_CAPACITY:
+ case REGW_CYCLE_COUNT:
+ ret = i2c_smbus_read_word_data(client, reg);
+ if (ret < 0)
+ return ret;
+
+ *val = ret;
+ break;
+
+ case REGB_STATUS:
+ ret = i2c_smbus_read_byte_data(client, reg);
+ if (ret < 0)
+ return ret;
+
+ if (ret & BIT(0))
+ *val = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ *val = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+
+ case REGB_ONLINE:
+ ret = i2c_smbus_read_byte_data(client, reg);
+ if (ret < 0)
+ return ret;
+
+ *val = (ret & BIT(1)) >> 1;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int srt_bat_power_supply_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct srt_ec_device *srt = power_supply_get_drvdata(psy);
+ struct i2c_client *client = srt->client;
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = srt->manufacturer;
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = srt->model_name;
+ break;
+ case POWER_SUPPLY_PROP_SERIAL_NUMBER:
+ val->strval = srt->serial;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = srt_bat_get_value(client, REGW_CAPACITY, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ ret = srt_bat_get_value(client, REGW_CHARGE_NOW, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ ret = srt_bat_get_value(client, REGW_CHARGE_FULL, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ ret = srt_bat_get_value(client, REGW_CHARGE_FULL_DESIGN,
+ &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ ret = srt_bat_get_value(client, REGW_CURRENT_NOW, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CYCLE_COUNT:
+ ret = srt_bat_get_value(client, REGW_CYCLE_COUNT, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = 1;
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ ret = srt_bat_get_value(client, REGB_ONLINE, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ if (srt->capacity < 100)
+ ret = srt_bat_get_value(client, REGB_STATUS, &val->intval);
+ else
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = srt->technology;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ ret = srt_bat_get_value(client, REGW_VOLTAGE_MAX_DESIGN,
+ &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ ret = srt_bat_get_value(client, REGW_VOLTAGE_NOW, &val->intval);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int srt_psy_power_supply_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct srt_ec_device *srt = power_supply_get_drvdata(psy);
+ struct i2c_client *client = srt->client;
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ case POWER_SUPPLY_PROP_PRESENT:
+ ret = i2c_smbus_read_byte_data(client, REGB_ONLINE);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret & BIT(0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void srt_bat_poll_work(struct work_struct *work)
+{
+ struct srt_ec_device *srt =
+ container_of(work, struct srt_ec_device, poll_work.work);
+ int ret, capacity;
+
+ ret = srt_bat_get_value(srt->client, REGW_CAPACITY, &capacity);
+ if (!ret && capacity != srt->capacity) {
+ srt->capacity = capacity;
+ power_supply_changed(srt->bat);
+ }
+
+ /* continuously send uevent notification */
+ schedule_delayed_work(&srt->poll_work, 30 * HZ);
+}
+
+static irqreturn_t srt_psy_detect_irq(int irq, void *dev_id)
+{
+ struct srt_ec_device *srt = dev_id;
+
+ power_supply_changed(srt->psy);
+
+ return IRQ_HANDLED;
+}
+
+static const struct power_supply_desc srt_bat_power_supply_desc = {
+ .name = "surface-rt-battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = srt_bat_power_supply_props,
+ .num_properties = ARRAY_SIZE(srt_bat_power_supply_props),
+ .get_property = srt_bat_power_supply_get_property,
+ .external_power_changed = power_supply_changed,
+};
+
+static const struct power_supply_desc srt_psy_power_supply_desc = {
+ .name = "surface-rt-ac-adapter",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .properties = srt_psy_power_supply_props,
+ .num_properties = ARRAY_SIZE(srt_psy_power_supply_props),
+ .get_property = srt_psy_power_supply_get_property,
+};
+
+static char *battery_supplied_to[] = { "surface-rt-battery" };
+
+static int srt_ec_probe(struct i2c_client *client)
+{
+ struct power_supply_config bat_cfg = {};
+ struct power_supply_config psy_cfg = {};
+ struct device *dev = &client->dev;
+ struct srt_ec_device *srt;
+ char str_buf[4];
+ int ret;
+
+ srt = devm_kzalloc(dev, sizeof(*srt), GFP_KERNEL);
+ if (!srt)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, srt);
+ srt->client = client;
+
+ srt->enable_gpiod = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
+ if (IS_ERR(srt->enable_gpiod))
+ return dev_err_probe(dev, PTR_ERR(srt->enable_gpiod),
+ "failed to get enable gpio\n");
+
+ /* wait till EC is ready */
+ usleep_range(1000, 1500);
+
+ ret = i2c_smbus_read_word_data(client, REGW_SERIAL_NUMBER);
+ if (ret < 0)
+ return ret;
+
+ srt->serial = devm_kasprintf(dev, GFP_KERNEL, "%04x", ret);
+ if (!srt->serial)
+ return -ENOMEM;
+
+ ret = i2c_smbus_read_i2c_block_data(client, REGS_MANUFACTURER,
+ sizeof(srt->manufacturer) - 1,
+ srt->manufacturer);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_read_i2c_block_data(client, REGS_MODEL_NAME,
+ sizeof(srt->model_name) - 1,
+ srt->model_name);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_read_i2c_block_data(client, REGS_TECHNOLOGY,
+ sizeof(str_buf), str_buf);
+ if (ret < 0)
+ return ret;
+
+ if (!strncmp(str_buf, "LION", 4))
+ srt->technology = POWER_SUPPLY_TECHNOLOGY_LION;
+ else
+ srt->technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
+
+ bat_cfg.drv_data = srt;
+ bat_cfg.fwnode = dev_fwnode(dev);
+
+ srt->bat = devm_power_supply_register(dev, &srt_bat_power_supply_desc,
+ &bat_cfg);
+ if (IS_ERR(srt->bat))
+ return dev_err_probe(dev, PTR_ERR(srt->bat),
+ "failed to register battery power supply\n");
+
+ psy_cfg.drv_data = srt;
+ psy_cfg.fwnode = dev_fwnode(dev);
+ psy_cfg.supplied_to = battery_supplied_to;
+ psy_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
+
+ srt->psy = devm_power_supply_register(dev, &srt_psy_power_supply_desc,
+ &psy_cfg);
+ if (IS_ERR(srt->psy))
+ return dev_err_probe(dev, PTR_ERR(srt->psy),
+ "failed to register AC power supply\n");
+
+ ret = devm_request_threaded_irq(dev, client->irq, NULL, srt_psy_detect_irq,
+ IRQF_ONESHOT, client->name, srt);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to request interrupt\n");
+
+ ret = devm_delayed_work_autocancel(dev, &srt->poll_work, srt_bat_poll_work);
+ if (ret < 0)
+ return ret;
+
+ schedule_delayed_work(&srt->poll_work, HZ);
+
+ return 0;
+}
+
+static int srt_ec_suspend(struct device *dev)
+{
+ struct srt_ec_device *srt = dev_get_drvdata(dev);
+
+ cancel_delayed_work_sync(&srt->poll_work);
+
+ return 0;
+}
+
+static int srt_ec_resume(struct device *dev)
+{
+ struct srt_ec_device *srt = dev_get_drvdata(dev);
+
+ schedule_delayed_work(&srt->poll_work, HZ);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(srt_ec_pm_ops, srt_ec_suspend, srt_ec_resume);
+
+static const struct of_device_id srt_ec_of_match[] = {
+ { .compatible = "microsoft,surface-rt-ec" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, srt_ec_of_match);
+
+static struct i2c_driver srt_ec_driver = {
+ .driver = {
+ .name = "surface-rt-ec",
+ .of_match_table = srt_ec_of_match,
+ .pm = &srt_ec_pm_ops,
+ },
+ .probe = srt_ec_probe,
+};
+module_i2c_driver(srt_ec_driver);
+
+MODULE_AUTHOR("Jonas Schwöbel <jonasschwoebel@yahoo.de>");
+MODULE_DESCRIPTION("Surface RT Embedded Controller driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/supply/ug3105_battery.c b/drivers/power/supply/ug3105_battery.c
index 210e0f9aa5e0..0cbf45856fac 100644
--- a/drivers/power/supply/ug3105_battery.c
+++ b/drivers/power/supply/ug3105_battery.c
@@ -195,7 +195,7 @@ static SIMPLE_DEV_PM_OPS(ug3105_pm_ops, ug3105_suspend,
ug3105_resume);
static const struct i2c_device_id ug3105_id[] = {
- { "ug3105" },
+ { .name = "ug3105" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ug3105_id);
diff --git a/include/linux/power/max17042_battery.h b/include/linux/power/max17042_battery.h
index d5b08313cf11..13aeab1597c6 100644
--- a/include/linux/power/max17042_battery.h
+++ b/include/linux/power/max17042_battery.h
@@ -24,6 +24,8 @@
#define MAX17042_CHARACTERIZATION_DATA_SIZE 48
+#define MAX17055_MODELCFG_REFRESH_BIT BIT(15)
+
enum max17042_register {
MAX17042_STATUS = 0x00,
MAX17042_VALRT_Th = 0x01,
@@ -198,16 +200,6 @@ enum max170xx_chip_type {
MAXIM_DEVICE_TYPE_NUM
};
-/*
- * used for setting a register to a desired value
- * addr : address for a register
- * data : setting value for the register
- */
-struct max17042_reg_data {
- u8 addr;
- u16 data;
-};
-
struct max17042_config_data {
/* External current sense resistor value in milli-ohms */
u32 cur_sense_val;
@@ -229,6 +221,7 @@ struct max17042_config_data {
u16 full_soc_thresh; /* 0x13 */
u16 design_cap; /* 0x18 */
u16 ichgt_term; /* 0x1E */
+ u16 model_cfg; /* 0xDB */
/* MG3 config */
u16 at_rate; /* 0x04 */
@@ -265,23 +258,4 @@ struct max17042_config_data {
u16 cell_char_tbl[MAX17042_CHARACTERIZATION_DATA_SIZE];
} __packed;
-struct max17042_platform_data {
- struct max17042_reg_data *init_data;
- struct max17042_config_data *config_data;
- int num_init_data; /* Number of enties in init_data array */
- bool enable_current_sense;
- bool enable_por_init; /* Use POR init from Maxim appnote */
-
- /*
- * R_sns in micro-ohms.
- * default 10000 (if r_sns = 0) as it is the recommended value by
- * the datasheet although it can be changed by board designers.
- */
- unsigned int r_sns;
- int vmin; /* in millivolts */
- int vmax; /* in millivolts */
- int temp_min; /* in tenths of degree Celsius */
- int temp_max; /* in tenths of degree Celsius */
-};
-
#endif /* __MAX17042_BATTERY_H_ */