diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-19 18:13:09 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-19 18:13:09 -0700 |
| commit | 390d73adf896bf4883c7d3bcd13c1b53d64351e3 (patch) | |
| tree | 74dc30d42adf8edf169efd51e3f5b6e2d8d3d118 | |
| parent | 1a3746ccbb0a97bed3c06ccde6b880013b1dddc1 (diff) | |
| parent | a888754e51e915731c8974c4d6d62709facb35d3 (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
...
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)<c4015_chip_info }, - { "ltc4162-f", (kernel_ulong_t)<c4162f_chip_info }, - { "ltc4162-l", (kernel_ulong_t)<c4162l_chip_info }, - { "ltc4162-s", (kernel_ulong_t)<c4162s_chip_info }, + { .name = "ltc4015", .driver_data = (kernel_ulong_t)<c4015_chip_info }, + { .name = "ltc4162-f", .driver_data = (kernel_ulong_t)<c4162f_chip_info }, + { .name = "ltc4162-l", .driver_data = (kernel_ulong_t)<c4162l_chip_info }, + { .name = "ltc4162-s", .driver_data = (kernel_ulong_t)<c4162s_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_ */ |
