Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'for-v6.14' 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 core:

- introduce power supply extensions, which allows adding properties
to a power supply device from a separate driver. This will be used
initially to extend the generic ACPI charger/battery driver with
vendor extensions for charge thresholds.

- convert all drivers from power_supply_for_each_device to new
power_supply_for_each_psy(), which avoids lots of casting being
done in the drivers.

- avoid LED trigger like values in uevent for
POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR

- introduce POWER_SUPPLY_PROP_CHARGE_TYPES, which is similar to the
POWER_SUPPLY_PROP_CHARGE_TYPE property, but also lists the
available options on the specific platform

Power-supply drivers

- dell-laptop: use new power_supply_charge_types_show/_parse helpers

- stc3117: new driver for equally named fuel gauge chip

- bq24190: add support for new POWER_SUPPLY_PROP_CHARGE_TYPES

- bq24190: add BQ24297 support

- bq27xxx: add voltage min design for bq27000/bq27200

- cros_charge-control: convert to new power supply extension API

- multiple drivers: constify 'struct bin_attribute'

- ds2782: convert to device managed resources

- max1720x: add charge full property

- max1720x: support extra thermistor temperatures

- max17042: add max77705 support

- ip5xxx-power: add support for IP5306

- ltc4162-l-charger: add ltc4162-f/s and ltc4015 support

- gpio-charger: support for default charge current limit

- misc small cleanups and fixes

Reset drivers:

- at91-poweroff: add sam9x7 support"

* tag 'for-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (77 commits)
power: supply: max1720x: add support for reading internal and thermistor temperatures
power: supply: ltc4162l: Use GENMASK macro in bitmask operation
power: supply: max17042: add max77705 fuel gauge support
dt-bindings: power: supply: max17042: add max77705 support
power: supply: add undervoltage health status property
power: supply: max17042: add platform driver variant
power: supply: max17042: make interrupt shared
power: reset: keystone: Use syscon_regmap_lookup_by_phandle_args
power: supply: Use str_enable_disable-like helpers
platform/x86: dell-laptop: Use power_supply_charge_types_show/_parse() helpers
power: supply: bq2415x_charger: Immediately reschedule delayed work on notifier events
power: supply: Add STC3117 fuel gauge unit driver
dt-bindings: power: supply: Add STC3117 Fuel Gauge
power: supply: ug3105_battery: Let the core handle POWER_SUPPLY_PROP_TECHNOLOGY
power: supply: gpio-charger: add support for default charge current limit
dt-bindings: power: supply: gpio-charger: add support for default charge current limit
power: supply: Use power_supply_external_power_changed() in __power_supply_changed_work()
power: supply: core: fix build of extension sysfs group if CONFIG_SYSFS=n
power: supply: bq2415x_charger: report charging state changes to userspace
bq27xxx: add voltage min design for bq27000 and bq27200
...

+2724 -711
+30 -1
Documentation/ABI/testing/sysfs-class-power
··· 407 407 408 408 Access: Read, Write 409 409 410 + Reading this returns the current active value, e.g. 'Standard'. 411 + Check charge_types to get the values supported by the battery. 412 + 410 413 Valid values: 411 414 "Unknown", "N/A", "Trickle", "Fast", "Standard", 412 415 "Adaptive", "Custom", "Long Life", "Bypass" 416 + 417 + What: /sys/class/power_supply/<supply_name>/charge_types 418 + Date: December 2024 419 + Contact: linux-pm@vger.kernel.org 420 + Description: 421 + Identical to charge_type but reading returns a list of supported 422 + charge-types with the currently active type surrounded by square 423 + brackets, e.g.: "Fast [Standard] Long_Life". 424 + 425 + power_supply class devices may support both charge_type and 426 + charge_types for backward compatibility. In this case both will 427 + always have the same active value and the active value can be 428 + changed by writing either property. 429 + 430 + Note charge-types which contain a space such as "Long Life" will 431 + have the space replaced by a '_' resulting in e.g. "Long_Life". 432 + When writing charge-types both variants are accepted. 413 433 414 434 What: /sys/class/power_supply/<supply_name>/charge_term_current 415 435 Date: July 2014 ··· 453 433 454 434 Valid values: 455 435 "Unknown", "Good", "Overheat", "Dead", 456 - "Over voltage", "Unspecified failure", "Cold", 436 + "Over voltage", "Under voltage", "Unspecified failure", "Cold", 457 437 "Watchdog timer expire", "Safety timer expire", 458 438 "Over current", "Calibration required", "Warm", 459 439 "Cool", "Hot", "No battery" ··· 813 793 814 794 Access: Read 815 795 Valid values: 1-31 796 + 797 + What: /sys/class/power_supply/<supply_name>/extensions/<extension_name> 798 + Date: March 2025 799 + Contact: linux-pm@vger.kernel.org 800 + Description: 801 + Reports the extensions registered to the power supply. 802 + Each entry is a link to the device which registered the extension. 803 + 804 + Access: Read
+32
Documentation/ABI/testing/sysfs-class-power-max1720x
··· 1 + What: /sys/class/power_supply/max1720x/temp_ain1 2 + Date: January 2025 3 + KernelVersion: 6.14 4 + Contact: Dimitri Fedrau <dimitri.fedrau@liebherr.com> 5 + Description: 6 + Reports the current temperature reading from AIN1 thermistor. 7 + 8 + Access: Read 9 + 10 + Valid values: Represented in 1/10 Degrees Celsius 11 + 12 + What: /sys/class/power_supply/max1720x/temp_ain2 13 + Date: January 2025 14 + KernelVersion: 6.14 15 + Contact: Dimitri Fedrau <dimitri.fedrau@liebherr.com> 16 + Description: 17 + Reports the current temperature reading from AIN2 thermistor. 18 + 19 + Access: Read 20 + 21 + Valid values: Represented in 1/10 Degrees Celsius 22 + 23 + What: /sys/class/power_supply/max1720x/temp_int 24 + Date: January 2025 25 + KernelVersion: 6.14 26 + Contact: Dimitri Fedrau <dimitri.fedrau@liebherr.com> 27 + Description: 28 + Reports the current temperature reading from internal die. 29 + 30 + Access: Read 31 + 32 + Valid values: Represented in 1/10 Degrees Celsius
+3
Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml
··· 22 22 - enum: 23 23 - atmel,sama5d2-shdwc 24 24 - microchip,sam9x60-shdwc 25 + - items: 26 + - const: microchip,sam9x7-shdwc 27 + - const: microchip,sam9x60-shdwc 25 28 26 29 reg: 27 30 maxItems: 1
+1
Documentation/devicetree/bindings/power/supply/bq24190.yaml
··· 21 21 - ti,bq24192i 22 22 - ti,bq24196 23 23 - ti,bq24296 24 + - ti,bq24297 24 25 25 26 reg: 26 27 maxItems: 1
+6
Documentation/devicetree/bindings/power/supply/gpio-charger.yaml
··· 58 58 charge-current-limit-gpios property. Bit 1 second to last 59 59 GPIO and so on. 60 60 61 + charge-current-limit-default-microamp: 62 + description: Default charge current limit. Must be listed in 63 + charge-current-limit-mapping. 64 + 61 65 required: 62 66 - compatible 63 67 ··· 76 72 dependencies: 77 73 charge-current-limit-gpios: [ charge-current-limit-mapping ] 78 74 charge-current-limit-mapping: [ charge-current-limit-gpios ] 75 + charge-current-limit-default-microamp: [charge-current-limit-mapping] 79 76 80 77 additionalProperties: false 81 78 ··· 96 91 charge-current-limit-mapping = <2500000 0x00>, // 2.5 A => both GPIOs low 97 92 <700000 0x01>, // 700 mA => GPIO A.12 high 98 93 <0 0x02>; // 0 mA => GPIO A.11 high 94 + charge-current-limit-default-microamp = <700000>; 99 95 };
+6
Documentation/devicetree/bindings/power/supply/ltc4162-l.yaml
··· 17 17 panels, etc., and a rechargeable Lithium-Ion/Polymer battery. 18 18 19 19 Specifications about the charger can be found at: 20 + https://www.analog.com/en/products/ltc4162-l.html 21 + https://www.analog.com/en/products/ltc4162-f.html 20 22 https://www.analog.com/en/products/ltc4162-s.html 23 + https://www.analog.com/en/products/ltc4015.html 21 24 22 25 properties: 23 26 compatible: 24 27 enum: 28 + - lltc,ltc4015 29 + - lltc,ltc4162-f 25 30 - lltc,ltc4162-l 31 + - lltc,ltc4162-s 26 32 27 33 reg: 28 34 maxItems: 1
+1
Documentation/devicetree/bindings/power/supply/maxim,max17042.yaml
··· 19 19 - maxim,max17047 20 20 - maxim,max17050 21 21 - maxim,max17055 22 + - maxim,max77705-battery 22 23 - maxim,max77849-battery 23 24 24 25 reg:
+74
Documentation/devicetree/bindings/power/supply/st,stc3117.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/power/supply/st,stc3117.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: STMicroelectronics STC3117 Fuel Gauge Unit Power Supply 8 + 9 + maintainers: 10 + - Hardevsinh Palaniya <hardevsinh.palaniya@siliconsignals.io> 11 + - Bhavin Sharma <bhavin.sharma@siliconsignals.io> 12 + 13 + description: | 14 + The STC3117 includes the STMicroelectronics OptimGauge algorithm. 15 + It provides accurate battery state-of-charge (SOC) monitoring, tracks 16 + battery parameter changes with operation conditions, temperature, 17 + and aging, and allows the application to get a battery state-of-health 18 + (SOH) indication. 19 + 20 + An alarm output signals low SOC or low voltage conditions and also 21 + indicates fault conditions like a missing or swapped battery. 22 + 23 + Datasheet is available at 24 + https://www.st.com/resource/en/datasheet/stc3117.pdf 25 + 26 + allOf: 27 + - $ref: power-supply.yaml# 28 + 29 + properties: 30 + compatible: 31 + enum: 32 + - st,stc3117 33 + 34 + reg: 35 + maxItems: 1 36 + 37 + monitored-battery: 38 + description: | 39 + The fuel gauge uses the following battery properties: 40 + - charge-full-design-microamp-hours 41 + - voltage-min-design-microvolt 42 + - voltage-max-design-microvolt 43 + 44 + shunt-resistor-micro-ohms: 45 + description: Current sense resistor 46 + 47 + interrupts: 48 + maxItems: 1 49 + 50 + required: 51 + - compatible 52 + - reg 53 + - monitored-battery 54 + - shunt-resistor-micro-ohms 55 + 56 + unevaluatedProperties: false 57 + 58 + examples: 59 + - | 60 + #include <dt-bindings/interrupt-controller/irq.h> 61 + 62 + i2c { 63 + #address-cells = <1>; 64 + #size-cells = <0>; 65 + 66 + battery@70 { 67 + compatible = "st,stc3117"; 68 + reg = <0x70>; 69 + interrupt-parent = <&gpio0>; 70 + interrupts = <31 IRQ_TYPE_LEVEL_LOW>; 71 + monitored-battery = <&bat>; 72 + shunt-resistor-micro-ohms = <10000>; 73 + }; 74 + };
+2
Documentation/devicetree/bindings/trivial-devices.yaml
··· 147 147 - injoinic,ip5207 148 148 # Injoinic IP5209 2.4A Power Bank IC with I2C 149 149 - injoinic,ip5209 150 + # Injoinic IP5306 2.1A Power Bank IC with I2C option 151 + - injoinic,ip5306 150 152 # Inspur Power System power supply unit version 1 151 153 - inspur,ipsps1 152 154 # Intel common redudant power supply crps185
+8
MAINTAINERS
··· 22309 22309 F: Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml 22310 22310 F: drivers/media/i2c/st-mipid02.c 22311 22311 22312 + ST STC3117 FUEL GAUGE DRIVER 22313 + M: Hardevsinh Palaniya <hardevsinh.palaniya@siliconsignals.io> 22314 + M: Bhavin Sharma <bhavin.sharma@siliconsignals.io> 22315 + L: linux-pm@vger.kernel.org 22316 + S: Maintained 22317 + F: Documentation/devicetree/bindings/power/supply/st,stc3117.yaml 22318 + F: drivers/power/supply/stc3117_fuel_gauge.c 22319 + 22312 22320 ST STM32 FIREWALL 22313 22321 M: Gatien Chevallier <gatien.chevallier@foss.st.com> 22314 22322 S: Maintained
+25 -29
drivers/platform/x86/dell/dell-laptop.c
··· 103 103 104 104 struct battery_mode_info { 105 105 int token; 106 - const char *label; 106 + enum power_supply_charge_type charge_type; 107 107 }; 108 108 109 109 static const struct battery_mode_info battery_modes[] = { 110 - { BAT_PRI_AC_MODE_TOKEN, "Trickle" }, 111 - { BAT_EXPRESS_MODE_TOKEN, "Fast" }, 112 - { BAT_STANDARD_MODE_TOKEN, "Standard" }, 113 - { BAT_ADAPTIVE_MODE_TOKEN, "Adaptive" }, 114 - { BAT_CUSTOM_MODE_TOKEN, "Custom" }, 110 + { BAT_PRI_AC_MODE_TOKEN, POWER_SUPPLY_CHARGE_TYPE_TRICKLE }, 111 + { BAT_EXPRESS_MODE_TOKEN, POWER_SUPPLY_CHARGE_TYPE_FAST }, 112 + { BAT_STANDARD_MODE_TOKEN, POWER_SUPPLY_CHARGE_TYPE_STANDARD }, 113 + { BAT_ADAPTIVE_MODE_TOKEN, POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE }, 114 + { BAT_CUSTOM_MODE_TOKEN, POWER_SUPPLY_CHARGE_TYPE_CUSTOM }, 115 115 }; 116 116 static u32 battery_supported_modes; 117 117 ··· 2261 2261 struct device_attribute *attr, 2262 2262 char *buf) 2263 2263 { 2264 - ssize_t count = 0; 2264 + enum power_supply_charge_type charge_type; 2265 2265 int i; 2266 2266 2267 2267 for (i = 0; i < ARRAY_SIZE(battery_modes); i++) { 2268 - bool active; 2268 + charge_type = battery_modes[i].charge_type; 2269 2269 2270 - if (!(battery_supported_modes & BIT(i))) 2270 + if (!(battery_supported_modes & BIT(charge_type))) 2271 2271 continue; 2272 2272 2273 - active = dell_battery_mode_is_active(battery_modes[i].token); 2274 - count += sysfs_emit_at(buf, count, active ? "[%s] " : "%s ", 2275 - battery_modes[i].label); 2273 + if (!dell_battery_mode_is_active(battery_modes[i].token)) 2274 + continue; 2275 + 2276 + return power_supply_charge_types_show(dev, battery_supported_modes, 2277 + charge_type, buf); 2276 2278 } 2277 2279 2278 - /* convert the last space to a newline */ 2279 - if (count > 0) 2280 - count--; 2281 - count += sysfs_emit_at(buf, count, "\n"); 2282 - 2283 - return count; 2280 + /* No active mode found */ 2281 + return -EIO; 2284 2282 } 2285 2283 2286 2284 static ssize_t charge_types_store(struct device *dev, 2287 2285 struct device_attribute *attr, 2288 2286 const char *buf, size_t size) 2289 2287 { 2290 - bool matched = false; 2291 - int err, i; 2288 + int charge_type, err, i; 2289 + 2290 + charge_type = power_supply_charge_types_parse(battery_supported_modes, buf); 2291 + if (charge_type < 0) 2292 + return charge_type; 2292 2293 2293 2294 for (i = 0; i < ARRAY_SIZE(battery_modes); i++) { 2294 - if (!(battery_supported_modes & BIT(i))) 2295 - continue; 2296 - 2297 - if (sysfs_streq(battery_modes[i].label, buf)) { 2298 - matched = true; 2295 + if (battery_modes[i].charge_type == charge_type) 2299 2296 break; 2300 - } 2301 2297 } 2302 - if (!matched) 2303 - return -EINVAL; 2298 + if (i == ARRAY_SIZE(battery_modes)) 2299 + return -ENOENT; 2304 2300 2305 2301 err = dell_battery_set_mode(battery_modes[i].token); 2306 2302 if (err) ··· 2426 2430 2427 2431 for (i = 0; i < ARRAY_SIZE(battery_modes); i++) { 2428 2432 if (dell_smbios_find_token(battery_modes[i].token)) 2429 - modes |= BIT(i); 2433 + modes |= BIT(battery_modes[i].charge_type); 2430 2434 } 2431 2435 2432 2436 return modes;
+2 -2
drivers/power/reset/Kconfig
··· 26 26 config POWER_RESET_AT91_RESET 27 27 tristate "Atmel AT91 reset driver" 28 28 depends on ARCH_AT91 29 - default SOC_AT91SAM9 || SOC_SAM9X60 || SOC_SAMA5 29 + default SOC_AT91SAM9 || SOC_SAM9X60 || SOC_SAM9X7 || SOC_SAMA5 30 30 help 31 31 This driver supports restart for Atmel AT91SAM9 and SAMA5 32 32 SoCs ··· 34 34 config POWER_RESET_AT91_SAMA5D2_SHDWC 35 35 tristate "Atmel AT91 SAMA5D2-Compatible shutdown controller driver" 36 36 depends on ARCH_AT91 37 - default SOC_SAM9X60 || SOC_SAMA5 37 + default SOC_SAM9X60 || SOC_SAM9X7 || SOC_SAMA5 38 38 help 39 39 This driver supports the alternate shutdown controller for some Atmel 40 40 SAMA5 SoCs. It is present for example on SAMA5D2 SoC.
-2
drivers/power/reset/as3722-poweroff.c
··· 57 57 SYS_OFF_PRIO_DEFAULT, 58 58 as3722_pm_power_off, 59 59 as3722_poweroff); 60 - 61 - return 0; 62 60 } 63 61 64 62 static struct platform_driver as3722_poweroff_driver = {
+1
drivers/power/reset/at91-sama5d2_shdwc.c
··· 326 326 { .compatible = "atmel,sama5d2-pmc" }, 327 327 { .compatible = "microchip,sam9x60-pmc" }, 328 328 { .compatible = "microchip,sama7g5-pmc" }, 329 + { .compatible = "microchip,sam9x7-pmc" }, 329 330 { /* Sentinel. */ } 330 331 }; 331 332
+7 -1
drivers/power/reset/gpio-poweroff.c
··· 44 44 /* give it some time */ 45 45 mdelay(gpio_poweroff->timeout_ms); 46 46 47 - WARN_ON(1); 47 + /* 48 + * If code reaches this point, it means that gpio-poweroff has failed 49 + * to actually power off the system. 50 + * Warn the user that the attempt to poweroff via gpio-poweroff 51 + * has gone wrong. 52 + */ 53 + WARN(1, "Failed to poweroff via gpio-poweroff mechanism\n"); 48 54 49 55 return NOTIFY_DONE; 50 56 }
+4 -14
drivers/power/reset/keystone-reset.c
··· 87 87 return -ENODEV; 88 88 89 89 /* get regmaps */ 90 - pllctrl_regs = syscon_regmap_lookup_by_phandle(np, "ti,syscon-pll"); 90 + pllctrl_regs = syscon_regmap_lookup_by_phandle_args(np, "ti,syscon-pll", 91 + 1, &rspll_offset); 91 92 if (IS_ERR(pllctrl_regs)) 92 93 return PTR_ERR(pllctrl_regs); 93 94 94 - devctrl_regs = syscon_regmap_lookup_by_phandle(np, "ti,syscon-dev"); 95 + devctrl_regs = syscon_regmap_lookup_by_phandle_args(np, "ti,syscon-dev", 96 + 1, &rsmux_offset); 95 97 if (IS_ERR(devctrl_regs)) 96 98 return PTR_ERR(devctrl_regs); 97 - 98 - ret = of_property_read_u32_index(np, "ti,syscon-pll", 1, &rspll_offset); 99 - if (ret) { 100 - dev_err(dev, "couldn't read the reset pll offset!\n"); 101 - return -EINVAL; 102 - } 103 - 104 - ret = of_property_read_u32_index(np, "ti,syscon-dev", 1, &rsmux_offset); 105 - if (ret) { 106 - dev_err(dev, "couldn't read the rsmux offset!\n"); 107 - return -EINVAL; 108 - } 109 99 110 100 /* set soft/hard reset */ 111 101 val = of_property_read_bool(np, "ti,soft-reset");
+2 -2
drivers/power/supply/88pm860x_battery.c
··· 14 14 #include <linux/mutex.h> 15 15 #include <linux/string.h> 16 16 #include <linux/power_supply.h> 17 + #include <linux/string_choices.h> 17 18 #include <linux/mfd/88pm860x.h> 18 19 #include <linux/delay.h> 19 20 ··· 504 503 data = pm860x_reg_read(info->i2c, PM8607_POWER_UP_LOG); 505 504 bat_remove = data & BAT_WU_LOG; 506 505 507 - dev_dbg(info->dev, "battery wake up? %s\n", 508 - bat_remove != 0 ? "yes" : "no"); 506 + dev_dbg(info->dev, "battery wake up? %s\n", str_yes_no(bat_remove)); 509 507 510 508 /* restore SOC from RTC domain register */ 511 509 if (bat_remove == 0) {
+9
drivers/power/supply/Kconfig
··· 918 918 Say Y here to enable support for fuel gauge with SC27XX 919 919 PMIC chips. 920 920 921 + config FUEL_GAUGE_STC3117 922 + tristate "STMicroelectronics STC3117 fuel gauge driver" 923 + depends on CRC8 924 + depends on I2C 925 + select REGMAP_I2C 926 + help 927 + Say Y here to enable support for fuel gauge with STC3117 928 + chip. 929 + 921 930 config CHARGER_UCS1002 922 931 tristate "Microchip UCS1002 USB Port Power Controller" 923 932 depends on I2C
+1
drivers/power/supply/Makefile
··· 108 108 obj-$(CONFIG_CHARGER_CROS_PCHG) += cros_peripheral_charger.o 109 109 obj-$(CONFIG_CHARGER_SC2731) += sc2731_charger.o 110 110 obj-$(CONFIG_FUEL_GAUGE_SC27XX) += sc27xx_fuel_gauge.o 111 + obj-$(CONFIG_FUEL_GAUGE_STC3117) += stc3117_fuel_gauge.o 111 112 obj-$(CONFIG_CHARGER_UCS1002) += ucs1002_power.o 112 113 obj-$(CONFIG_CHARGER_BD99954) += bd99954-charger.o 113 114 obj-$(CONFIG_CHARGER_WILCO) += wilco-charger.o
+2 -3
drivers/power/supply/ab8500_btemp.c
··· 540 540 return 0; 541 541 } 542 542 543 - static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data) 543 + static int ab8500_btemp_get_ext_psy_data(struct power_supply *ext, void *data) 544 544 { 545 545 struct power_supply *psy; 546 - struct power_supply *ext = dev_get_drvdata(dev); 547 546 const char **supplicants = (const char **)ext->supplied_to; 548 547 struct ab8500_btemp *di; 549 548 union power_supply_propval ret; ··· 616 617 */ 617 618 static void ab8500_btemp_external_power_changed(struct power_supply *psy) 618 619 { 619 - power_supply_for_each_device(psy, ab8500_btemp_get_ext_psy_data); 620 + power_supply_for_each_psy(psy, ab8500_btemp_get_ext_psy_data); 620 621 } 621 622 622 623 /* ab8500 btemp driver interrupts and their respective isr */
+2 -3
drivers/power/supply/ab8500_chargalg.c
··· 844 844 } 845 845 } 846 846 847 - static int ab8500_chargalg_get_ext_psy_data(struct device *dev, void *data) 847 + static int ab8500_chargalg_get_ext_psy_data(struct power_supply *ext, void *data) 848 848 { 849 849 struct power_supply *psy; 850 - struct power_supply *ext = dev_get_drvdata(dev); 851 850 const char **supplicants = (const char **)ext->supplied_to; 852 851 struct ab8500_chargalg *di; 853 852 union power_supply_propval ret; ··· 1230 1231 int ret; 1231 1232 1232 1233 /* Collect data from all power_supply class devices */ 1233 - power_supply_for_each_device(di->chargalg_psy, ab8500_chargalg_get_ext_psy_data); 1234 + power_supply_for_each_psy(di->chargalg_psy, ab8500_chargalg_get_ext_psy_data); 1234 1235 1235 1236 ab8500_chargalg_end_of_charge(di); 1236 1237 ab8500_chargalg_check_temp(di);
+2 -3
drivers/power/supply/ab8500_charger.c
··· 1894 1894 return ret; 1895 1895 } 1896 1896 1897 - static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data) 1897 + static int ab8500_charger_get_ext_psy_data(struct power_supply *ext, void *data) 1898 1898 { 1899 1899 struct power_supply *psy; 1900 - struct power_supply *ext = dev_get_drvdata(dev); 1901 1900 const char **supplicants = (const char **)ext->supplied_to; 1902 1901 struct ab8500_charger *di; 1903 1902 union power_supply_propval ret; ··· 1960 1961 struct ab8500_charger *di = container_of(work, 1961 1962 struct ab8500_charger, check_vbat_work.work); 1962 1963 1963 - power_supply_for_each_device(&di->usb_chg, ab8500_charger_get_ext_psy_data); 1964 + power_supply_for_each_psy(&di->usb_chg, ab8500_charger_get_ext_psy_data); 1964 1965 1965 1966 /* First run old_vbat is 0. */ 1966 1967 if (di->old_vbat == 0)
+16 -17
drivers/power/supply/ab8500_fg.c
··· 2174 2174 return 0; 2175 2175 } 2176 2176 2177 - static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data) 2177 + static int ab8500_fg_get_ext_psy_data(struct power_supply *ext, void *data) 2178 2178 { 2179 2179 struct power_supply *psy; 2180 - struct power_supply *ext = dev_get_drvdata(dev); 2181 2180 const char **supplicants = (const char **)ext->supplied_to; 2182 2181 struct ab8500_fg *di; 2183 2182 struct power_supply_battery_info *bi; ··· 2401 2402 */ 2402 2403 static void ab8500_fg_external_power_changed(struct power_supply *psy) 2403 2404 { 2404 - power_supply_for_each_device(psy, ab8500_fg_get_ext_psy_data); 2405 + power_supply_for_each_psy(psy, ab8500_fg_get_ext_psy_data); 2405 2406 } 2406 2407 2407 2408 /** ··· 2574 2575 { 2575 2576 int ret; 2576 2577 u8 reg_value; 2577 - struct power_supply *psy = dev_get_drvdata(dev); 2578 + struct power_supply *psy = dev_to_psy(dev); 2578 2579 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2579 2580 2580 2581 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, ··· 2597 2598 { 2598 2599 int ret; 2599 2600 int reg_value; 2600 - struct power_supply *psy = dev_get_drvdata(dev); 2601 + struct power_supply *psy = dev_to_psy(dev); 2601 2602 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2602 2603 2603 2604 if (kstrtoint(buf, 10, &reg_value)) ··· 2624 2625 { 2625 2626 int ret; 2626 2627 u8 reg_value; 2627 - struct power_supply *psy = dev_get_drvdata(dev); 2628 + struct power_supply *psy = dev_to_psy(dev); 2628 2629 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2629 2630 2630 2631 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, ··· 2648 2649 { 2649 2650 int ret; 2650 2651 int reg_value; 2651 - struct power_supply *psy = dev_get_drvdata(dev); 2652 + struct power_supply *psy = dev_to_psy(dev); 2652 2653 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2653 2654 2654 2655 if (kstrtoint(buf, 10, &reg_value)) ··· 2675 2676 { 2676 2677 int ret; 2677 2678 u8 reg_value; 2678 - struct power_supply *psy = dev_get_drvdata(dev); 2679 + struct power_supply *psy = dev_to_psy(dev); 2679 2680 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2680 2681 2681 2682 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, ··· 2698 2699 { 2699 2700 int ret; 2700 2701 int reg_value; 2701 - struct power_supply *psy = dev_get_drvdata(dev); 2702 + struct power_supply *psy = dev_to_psy(dev); 2702 2703 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2703 2704 2704 2705 if (kstrtoint(buf, 10, &reg_value)) ··· 2726 2727 { 2727 2728 int ret; 2728 2729 u8 reg_value; 2729 - struct power_supply *psy = dev_get_drvdata(dev); 2730 + struct power_supply *psy = dev_to_psy(dev); 2730 2731 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2731 2732 2732 2733 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, ··· 2749 2750 { 2750 2751 int ret; 2751 2752 u8 reg_value; 2752 - struct power_supply *psy = dev_get_drvdata(dev); 2753 + struct power_supply *psy = dev_to_psy(dev); 2753 2754 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2754 2755 2755 2756 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, ··· 2772 2773 { 2773 2774 int ret; 2774 2775 u8 reg_value; 2775 - struct power_supply *psy = dev_get_drvdata(dev); 2776 + struct power_supply *psy = dev_to_psy(dev); 2776 2777 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2777 2778 2778 2779 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, ··· 2793 2794 { 2794 2795 int ret; 2795 2796 int reg_value; 2796 - struct power_supply *psy = dev_get_drvdata(dev); 2797 + struct power_supply *psy = dev_to_psy(dev); 2797 2798 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2798 2799 2799 2800 if (kstrtoint(buf, 10, &reg_value)) ··· 2821 2822 2822 2823 int ret; 2823 2824 u8 reg_value; 2824 - struct power_supply *psy = dev_get_drvdata(dev); 2825 + struct power_supply *psy = dev_to_psy(dev); 2825 2826 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2826 2827 2827 2828 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, ··· 2844 2845 { 2845 2846 int ret; 2846 2847 u8 reg_value; 2847 - struct power_supply *psy = dev_get_drvdata(dev); 2848 + struct power_supply *psy = dev_to_psy(dev); 2848 2849 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2849 2850 2850 2851 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, ··· 2867 2868 { 2868 2869 int ret; 2869 2870 int reg_value; 2870 - struct power_supply *psy = dev_get_drvdata(dev); 2871 + struct power_supply *psy = dev_to_psy(dev); 2871 2872 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2872 2873 2873 2874 if (kstrtoint(buf, 10, &reg_value)) ··· 2894 2895 { 2895 2896 int ret; 2896 2897 u8 reg_value; 2897 - struct power_supply *psy = dev_get_drvdata(dev); 2898 + struct power_supply *psy = dev_to_psy(dev); 2898 2899 struct ab8500_fg *di = power_supply_get_drvdata(psy); 2899 2900 2900 2901 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
+3 -3
drivers/power/supply/apm_power.c
··· 42 42 int max_energy; 43 43 }; 44 44 45 - static int __find_main_battery(struct device *dev, void *data) 45 + static int __find_main_battery(struct power_supply *psy, void *data) 46 46 { 47 47 struct find_bat_param *bp = (struct find_bat_param *)data; 48 48 49 - bp->bat = dev_get_drvdata(dev); 49 + bp->bat = psy; 50 50 51 51 if (bp->bat->desc->use_for_apm) { 52 52 /* nice, we explicitly asked to report this battery. */ ··· 79 79 main_battery = NULL; 80 80 bp.main = main_battery; 81 81 82 - error = power_supply_for_each_device(&bp, __find_main_battery); 82 + error = power_supply_for_each_psy(&bp, __find_main_battery); 83 83 if (error) { 84 84 main_battery = bp.main; 85 85 return;
+23 -13
drivers/power/supply/bq2415x_charger.c
··· 171 171 char *name; 172 172 int autotimer; /* 1 - if driver automatically reset timer, 0 - not */ 173 173 int automode; /* 1 - enabled, 0 - disabled; -1 - not supported */ 174 + int charge_status; 174 175 int id; 175 176 }; 176 177 ··· 836 835 if (!bq2415x_update_reported_mode(bq, prop.intval)) 837 836 return NOTIFY_OK; 838 837 838 + power_supply_changed(bq->charger); 839 + 839 840 /* if automode is not enabled do not tell about reported_mode */ 840 841 if (bq->automode < 1) 841 842 return NOTIFY_OK; 842 843 843 - schedule_delayed_work(&bq->work, 0); 844 + mod_delayed_work(system_wq, &bq->work, 0); 844 845 845 846 return NOTIFY_OK; 846 847 } ··· 892 889 int ret; 893 890 int error; 894 891 int boost; 892 + int charge; 895 893 896 894 if (bq->automode > 0 && (bq->reported_mode != bq->mode)) { 897 895 sysfs_notify(&bq->charger->dev.kobj, NULL, "reported_mode"); 898 896 bq2415x_set_mode(bq, bq->reported_mode); 897 + } 898 + 899 + charge = bq2415x_exec_command(bq, BQ2415X_CHARGE_STATUS); 900 + if (bq->charge_status != charge) { 901 + power_supply_changed(bq->charger); 902 + bq->charge_status = charge; 899 903 } 900 904 901 905 if (!bq->autotimer) ··· 1060 1050 struct device_attribute *attr, 1061 1051 char *buf) 1062 1052 { 1063 - struct power_supply *psy = dev_get_drvdata(dev); 1053 + struct power_supply *psy = dev_to_psy(dev); 1064 1054 struct bq2415x_device *bq = power_supply_get_drvdata(psy); 1065 1055 enum bq2415x_command command; 1066 1056 int ret; ··· 1093 1083 const char *buf, 1094 1084 size_t count) 1095 1085 { 1096 - struct power_supply *psy = dev_get_drvdata(dev); 1086 + struct power_supply *psy = dev_to_psy(dev); 1097 1087 struct bq2415x_device *bq = power_supply_get_drvdata(psy); 1098 1088 int ret = 0; 1099 1089 ··· 1114 1104 struct device_attribute *attr, 1115 1105 char *buf) 1116 1106 { 1117 - struct power_supply *psy = dev_get_drvdata(dev); 1107 + struct power_supply *psy = dev_to_psy(dev); 1118 1108 struct bq2415x_device *bq = power_supply_get_drvdata(psy); 1119 1109 1120 1110 if (bq->timer_error) ··· 1138 1128 const char *buf, 1139 1129 size_t count) 1140 1130 { 1141 - struct power_supply *psy = dev_get_drvdata(dev); 1131 + struct power_supply *psy = dev_to_psy(dev); 1142 1132 struct bq2415x_device *bq = power_supply_get_drvdata(psy); 1143 1133 enum bq2415x_mode mode; 1144 1134 int ret = 0; ··· 1190 1180 struct device_attribute *attr, 1191 1181 char *buf) 1192 1182 { 1193 - struct power_supply *psy = dev_get_drvdata(dev); 1183 + struct power_supply *psy = dev_to_psy(dev); 1194 1184 struct bq2415x_device *bq = power_supply_get_drvdata(psy); 1195 1185 ssize_t ret = 0; 1196 1186 ··· 1227 1217 struct device_attribute *attr, 1228 1218 char *buf) 1229 1219 { 1230 - struct power_supply *psy = dev_get_drvdata(dev); 1220 + struct power_supply *psy = dev_to_psy(dev); 1231 1221 struct bq2415x_device *bq = power_supply_get_drvdata(psy); 1232 1222 1233 1223 if (bq->automode < 0) ··· 1255 1245 const char *buf, 1256 1246 size_t count) 1257 1247 { 1258 - struct power_supply *psy = dev_get_drvdata(dev); 1248 + struct power_supply *psy = dev_to_psy(dev); 1259 1249 struct bq2415x_device *bq = power_supply_get_drvdata(psy); 1260 1250 ssize_t ret = 0; 1261 1251 unsigned int reg; ··· 1290 1280 struct device_attribute *attr, 1291 1281 char *buf) 1292 1282 { 1293 - struct power_supply *psy = dev_get_drvdata(dev); 1283 + struct power_supply *psy = dev_to_psy(dev); 1294 1284 struct bq2415x_device *bq = power_supply_get_drvdata(psy); 1295 1285 ssize_t ret = 0; 1296 1286 ··· 1308 1298 const char *buf, 1309 1299 size_t count) 1310 1300 { 1311 - struct power_supply *psy = dev_get_drvdata(dev); 1301 + struct power_supply *psy = dev_to_psy(dev); 1312 1302 struct bq2415x_device *bq = power_supply_get_drvdata(psy); 1313 1303 long val; 1314 1304 int ret; ··· 1339 1329 struct device_attribute *attr, 1340 1330 char *buf) 1341 1331 { 1342 - struct power_supply *psy = dev_get_drvdata(dev); 1332 + struct power_supply *psy = dev_to_psy(dev); 1343 1333 struct bq2415x_device *bq = power_supply_get_drvdata(psy); 1344 1334 int ret; 1345 1335 ··· 1367 1357 const char *buf, 1368 1358 size_t count) 1369 1359 { 1370 - struct power_supply *psy = dev_get_drvdata(dev); 1360 + struct power_supply *psy = dev_to_psy(dev); 1371 1361 struct bq2415x_device *bq = power_supply_get_drvdata(psy); 1372 1362 enum bq2415x_command command; 1373 1363 long val; ··· 1402 1392 struct device_attribute *attr, 1403 1393 char *buf) 1404 1394 { 1405 - struct power_supply *psy = dev_get_drvdata(dev); 1395 + struct power_supply *psy = dev_to_psy(dev); 1406 1396 struct bq2415x_device *bq = power_supply_get_drvdata(psy); 1407 1397 enum bq2415x_command command; 1408 1398 int ret;
+26 -3
drivers/power/supply/bq24190_charger.c
··· 152 152 #define BQ24296_REG_VPRS_PN_MASK (BIT(7) | BIT(6) | BIT(5)) 153 153 #define BQ24296_REG_VPRS_PN_SHIFT 5 154 154 #define BQ24296_REG_VPRS_PN_24296 0x1 155 + #define BQ24296_REG_VPRS_PN_24297 0x3 155 156 #define BQ24190_REG_VPRS_TS_PROFILE_MASK BIT(2) 156 157 #define BQ24190_REG_VPRS_TS_PROFILE_SHIFT 2 157 158 #define BQ24190_REG_VPRS_DEV_REG_MASK (BIT(1) | BIT(0)) ··· 209 208 BQ24192i, 210 209 BQ24196, 211 210 BQ24296, 211 + BQ24297, 212 212 }; 213 213 214 214 /* ··· 424 422 BQ24190_SYSFS_FIELD_RO(watchdog, CTTC, WATCHDOG), 425 423 BQ24190_SYSFS_FIELD_RW(en_timer, CTTC, EN_TIMER), 426 424 BQ24190_SYSFS_FIELD_RW(chg_timer, CTTC, CHG_TIMER), 427 - BQ24190_SYSFS_FIELD_RW(jeta_iset, CTTC, JEITA_ISET), 425 + BQ24190_SYSFS_FIELD_RW(jeita_iset, CTTC, JEITA_ISET), 428 426 BQ24190_SYSFS_FIELD_RW(bat_comp, ICTRC, BAT_COMP), 429 427 BQ24190_SYSFS_FIELD_RW(vclamp, ICTRC, VCLAMP), 430 428 BQ24190_SYSFS_FIELD_RW(treg, ICTRC, TREG), ··· 482 480 static ssize_t bq24190_sysfs_show(struct device *dev, 483 481 struct device_attribute *attr, char *buf) 484 482 { 485 - struct power_supply *psy = dev_get_drvdata(dev); 483 + struct power_supply *psy = dev_to_psy(dev); 486 484 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy); 487 485 struct bq24190_sysfs_field_info *info; 488 486 ssize_t count; ··· 512 510 static ssize_t bq24190_sysfs_store(struct device *dev, 513 511 struct device_attribute *attr, const char *buf, size_t count) 514 512 { 515 - struct power_supply *psy = dev_get_drvdata(dev); 513 + struct power_supply *psy = dev_to_psy(dev); 516 514 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy); 517 515 struct bq24190_sysfs_field_info *info; 518 516 int ret; ··· 1321 1319 1322 1320 switch (psp) { 1323 1321 case POWER_SUPPLY_PROP_CHARGE_TYPE: 1322 + case POWER_SUPPLY_PROP_CHARGE_TYPES: 1324 1323 ret = bq24190_charger_get_charge_type(bdi, val); 1325 1324 break; 1326 1325 case POWER_SUPPLY_PROP_HEALTH: ··· 1402 1399 ret = bq24190_charger_set_temp_alert_max(bdi, val); 1403 1400 break; 1404 1401 case POWER_SUPPLY_PROP_CHARGE_TYPE: 1402 + case POWER_SUPPLY_PROP_CHARGE_TYPES: 1405 1403 ret = bq24190_charger_set_charge_type(bdi, val); 1406 1404 break; 1407 1405 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: ··· 1431 1427 case POWER_SUPPLY_PROP_ONLINE: 1432 1428 case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: 1433 1429 case POWER_SUPPLY_PROP_CHARGE_TYPE: 1430 + case POWER_SUPPLY_PROP_CHARGE_TYPES: 1434 1431 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 1435 1432 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 1436 1433 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: ··· 1480 1475 1481 1476 static enum power_supply_property bq24190_charger_properties[] = { 1482 1477 POWER_SUPPLY_PROP_CHARGE_TYPE, 1478 + POWER_SUPPLY_PROP_CHARGE_TYPES, 1483 1479 POWER_SUPPLY_PROP_HEALTH, 1484 1480 POWER_SUPPLY_PROP_ONLINE, 1485 1481 POWER_SUPPLY_PROP_STATUS, ··· 1510 1504 .set_property = bq24190_charger_set_property, 1511 1505 .property_is_writeable = bq24190_charger_property_is_writeable, 1512 1506 .external_power_changed = bq24190_charger_external_power_changed, 1507 + .charge_types = BIT(POWER_SUPPLY_CHARGE_TYPE_NONE) | 1508 + BIT(POWER_SUPPLY_CHARGE_TYPE_TRICKLE) | 1509 + BIT(POWER_SUPPLY_CHARGE_TYPE_FAST), 1513 1510 }; 1514 1511 1515 1512 /* Battery power supply property routines */ ··· 1906 1897 1907 1898 switch (v) { 1908 1899 case BQ24296_REG_VPRS_PN_24296: 1900 + case BQ24296_REG_VPRS_PN_24297: 1909 1901 break; 1910 1902 default: 1911 1903 dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v); ··· 2033 2023 .set_otg_vbus = bq24190_set_otg_vbus, 2034 2024 }, 2035 2025 [BQ24296] = { 2026 + .ichg_array_size = BQ24296_CCC_ICHG_VALUES_LEN, 2027 + #ifdef CONFIG_REGULATOR 2028 + .vbus_desc = &bq24296_vbus_desc, 2029 + #endif 2030 + .check_chip = bq24296_check_chip, 2031 + .set_chg_config = bq24296_battery_set_chg_config, 2032 + .ntc_fault_mask = BQ24296_REG_F_NTC_FAULT_MASK, 2033 + .get_ntc_status = bq24296_charger_get_ntc_status, 2034 + .set_otg_vbus = bq24296_set_otg_vbus, 2035 + }, 2036 + [BQ24297] = { 2036 2037 .ichg_array_size = BQ24296_CCC_ICHG_VALUES_LEN, 2037 2038 #ifdef CONFIG_REGULATOR 2038 2039 .vbus_desc = &bq24296_vbus_desc, ··· 2310 2289 { "bq24192i", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192i] }, 2311 2290 { "bq24196", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24196] }, 2312 2291 { "bq24296", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24296] }, 2292 + { "bq24297", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24297] }, 2313 2293 { }, 2314 2294 }; 2315 2295 MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids); ··· 2321 2299 { .compatible = "ti,bq24192i", .data = &bq24190_chip_info_tbl[BQ24192i] }, 2322 2300 { .compatible = "ti,bq24196", .data = &bq24190_chip_info_tbl[BQ24196] }, 2323 2301 { .compatible = "ti,bq24296", .data = &bq24190_chip_info_tbl[BQ24296] }, 2302 + { .compatible = "ti,bq24297", .data = &bq24190_chip_info_tbl[BQ24297] }, 2324 2303 { }, 2325 2304 }; 2326 2305 MODULE_DEVICE_TABLE(of, bq24190_of_match);
+4 -4
drivers/power/supply/bq24257_charger.c
··· 759 759 struct device_attribute *attr, 760 760 char *buf) 761 761 { 762 - struct power_supply *psy = dev_get_drvdata(dev); 762 + struct power_supply *psy = dev_to_psy(dev); 763 763 struct bq24257_device *bq = power_supply_get_drvdata(psy); 764 764 765 765 return sysfs_emit(buf, "%u\n", bq24257_vovp_map[bq->init_data.vovp]); ··· 769 769 struct device_attribute *attr, 770 770 char *buf) 771 771 { 772 - struct power_supply *psy = dev_get_drvdata(dev); 772 + struct power_supply *psy = dev_to_psy(dev); 773 773 struct bq24257_device *bq = power_supply_get_drvdata(psy); 774 774 775 775 return sysfs_emit(buf, "%u\n", bq24257_vindpm_map[bq->init_data.vindpm]); ··· 779 779 struct device_attribute *attr, 780 780 char *buf) 781 781 { 782 - struct power_supply *psy = dev_get_drvdata(dev); 782 + struct power_supply *psy = dev_to_psy(dev); 783 783 struct bq24257_device *bq = power_supply_get_drvdata(psy); 784 784 int ret; 785 785 ··· 801 801 const char *buf, 802 802 size_t count) 803 803 { 804 - struct power_supply *psy = dev_get_drvdata(dev); 804 + struct power_supply *psy = dev_to_psy(dev); 805 805 struct bq24257_device *bq = power_supply_get_drvdata(psy); 806 806 long val; 807 807 int ret;
+38 -1
drivers/power/supply/bq27xxx_battery.c
··· 123 123 BQ27XXX_DM_BLOCK, /* Data Block */ 124 124 BQ27XXX_DM_DATA, /* Block Data */ 125 125 BQ27XXX_DM_CKSUM, /* Block Data Checksum */ 126 + BQ27XXX_REG_SEDVF, /* End-of-discharge Voltage */ 126 127 BQ27XXX_REG_MAX, /* sentinel */ 127 128 }; 128 129 ··· 160 159 [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR, 161 160 [BQ27XXX_DM_DATA] = INVALID_REG_ADDR, 162 161 [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR, 162 + [BQ27XXX_REG_SEDVF] = 0x77, 163 163 }, 164 164 bq27010_regs[BQ27XXX_REG_MAX] = { 165 165 [BQ27XXX_REG_CTRL] = 0x00, ··· 186 184 [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR, 187 185 [BQ27XXX_DM_DATA] = INVALID_REG_ADDR, 188 186 [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR, 187 + [BQ27XXX_REG_SEDVF] = 0x77, 189 188 }, 190 189 bq2750x_regs[BQ27XXX_REG_MAX] = { 191 190 [BQ27XXX_REG_CTRL] = 0x00, ··· 582 579 POWER_SUPPLY_PROP_POWER_AVG, 583 580 POWER_SUPPLY_PROP_HEALTH, 584 581 POWER_SUPPLY_PROP_MANUFACTURER, 582 + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 585 583 }; 586 584 587 585 static enum power_supply_property bq27010_props[] = { ··· 603 599 POWER_SUPPLY_PROP_CYCLE_COUNT, 604 600 POWER_SUPPLY_PROP_HEALTH, 605 601 POWER_SUPPLY_PROP_MANUFACTURER, 602 + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 606 603 }; 607 604 608 605 #define bq2750x_props bq27510g3_props ··· 2044 2039 return 0; 2045 2040 } 2046 2041 2042 + /* 2043 + * Return the design minimum battery Voltage in microvolts 2044 + * Or < 0 if something fails. 2045 + */ 2046 + static int bq27xxx_battery_read_dmin_volt(struct bq27xxx_device_info *di, 2047 + union power_supply_propval *val) 2048 + { 2049 + int volt; 2050 + 2051 + /* We only have to read design minimum voltage once */ 2052 + if (di->voltage_min_design > 0) { 2053 + val->intval = di->voltage_min_design; 2054 + return 0; 2055 + } 2056 + 2057 + volt = bq27xxx_read(di, BQ27XXX_REG_SEDVF, true); 2058 + if (volt < 0) { 2059 + dev_err(di->dev, "error reading design min voltage\n"); 2060 + return volt; 2061 + } 2062 + 2063 + /* SEDVF = Design EDVF / 8 - 256 */ 2064 + val->intval = volt * 8000 + 2048000; 2065 + 2066 + /* Save for later reads */ 2067 + di->voltage_min_design = val->intval; 2068 + 2069 + return 0; 2070 + } 2071 + 2047 2072 static int bq27xxx_simple_value(int value, 2048 2073 union power_supply_propval *val) 2049 2074 { ··· 2154 2119 * power_supply_battery_info visible in sysfs. 2155 2120 */ 2156 2121 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: 2157 - case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 2158 2122 return -EINVAL; 2123 + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 2124 + ret = bq27xxx_battery_read_dmin_volt(di, val); 2125 + break; 2159 2126 case POWER_SUPPLY_PROP_CYCLE_COUNT: 2160 2127 ret = bq27xxx_battery_read_cyct(di, val); 2161 2128 break;
+2 -1
drivers/power/supply/charger-manager.c
··· 22 22 #include <linux/platform_device.h> 23 23 #include <linux/power/charger-manager.h> 24 24 #include <linux/regulator/consumer.h> 25 + #include <linux/string_choices.h> 25 26 #include <linux/sysfs.h> 26 27 #include <linux/of.h> 27 28 #include <linux/thermal.h> ··· 1089 1088 if (!charger->externally_control) 1090 1089 state = regulator_is_enabled(charger->consumer); 1091 1090 1092 - return sysfs_emit(buf, "%s\n", state ? "enabled" : "disabled"); 1091 + return sysfs_emit(buf, "%s\n", str_enabled_disabled(state)); 1093 1092 } 1094 1093 1095 1094 static ssize_t charger_externally_control_show(struct device *dev,
+2 -1
drivers/power/supply/cpcap-charger.c
··· 14 14 #include <linux/init.h> 15 15 #include <linux/module.h> 16 16 #include <linux/slab.h> 17 + #include <linux/string_choices.h> 17 18 #include <linux/err.h> 18 19 #include <linux/interrupt.h> 19 20 #include <linux/notifier.h> ··· 516 515 out_err: 517 516 cpcap_charger_update_state(ddata, POWER_SUPPLY_STATUS_UNKNOWN); 518 517 dev_err(ddata->dev, "%s could not %s vbus: %i\n", __func__, 519 - ddata->vbus_enabled ? "enable" : "disable", error); 518 + str_enable_disable(ddata->vbus_enabled), error); 520 519 } 521 520 522 521 static int cpcap_charger_set_vbus(struct phy_companion *comparator,
+92 -116
drivers/power/supply/cros_charge-control.c
··· 20 20 BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE) | \ 21 21 BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE)) 22 22 23 - enum CROS_CHCTL_ATTR { 24 - CROS_CHCTL_ATTR_START_THRESHOLD, 25 - CROS_CHCTL_ATTR_END_THRESHOLD, 26 - CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR, 27 - _CROS_CHCTL_ATTR_COUNT 28 - }; 29 - 30 23 /* 31 24 * Semantics of data *returned* from the EC API and Linux sysfs differ 32 25 * slightly, also the v1 API can not return any data. ··· 31 38 */ 32 39 33 40 struct cros_chctl_priv { 41 + struct device *dev; 34 42 struct cros_ec_device *cros_ec; 35 43 struct acpi_battery_hook battery_hook; 36 44 struct power_supply *hooked_battery; 37 45 u8 cmd_version; 38 46 39 - /* The callbacks need to access this priv structure. 40 - * As neither the struct device nor power_supply are under the drivers 41 - * control, embed the attributes within priv to use with container_of(). 42 - */ 43 - struct device_attribute device_attrs[_CROS_CHCTL_ATTR_COUNT]; 44 - struct attribute *attributes[_CROS_CHCTL_ATTR_COUNT]; 45 - struct attribute_group group; 47 + const struct power_supply_ext *psy_ext; 46 48 47 49 struct mutex lock; /* protects fields below and cros_ec */ 48 50 enum power_supply_charge_behaviour current_behaviour; ··· 107 119 return cros_chctl_send_charge_control_cmd(priv->cros_ec, priv->cmd_version, &req); 108 120 } 109 121 110 - static struct cros_chctl_priv *cros_chctl_attr_to_priv(struct attribute *attr, 111 - enum CROS_CHCTL_ATTR idx) 122 + static int cros_chctl_psy_ext_get_prop(struct power_supply *psy, 123 + const struct power_supply_ext *ext, 124 + void *data, 125 + enum power_supply_property psp, 126 + union power_supply_propval *val) 112 127 { 113 - struct device_attribute *dev_attr = container_of(attr, struct device_attribute, attr); 128 + struct cros_chctl_priv *priv = data; 114 129 115 - return container_of(dev_attr, struct cros_chctl_priv, device_attrs[idx]); 130 + switch (psp) { 131 + case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD: 132 + val->intval = priv->current_start_threshold; 133 + return 0; 134 + case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD: 135 + val->intval = priv->current_end_threshold; 136 + return 0; 137 + case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: 138 + val->intval = priv->current_behaviour; 139 + return 0; 140 + default: 141 + return -EINVAL; 142 + } 116 143 } 117 144 118 - static ssize_t cros_chctl_store_threshold(struct device *dev, struct cros_chctl_priv *priv, 119 - int is_end_threshold, const char *buf, size_t count) 145 + static int cros_chctl_psy_ext_set_threshold(struct cros_chctl_priv *priv, 146 + enum power_supply_property psp, 147 + int val) 120 148 { 121 - int ret, val; 149 + int ret; 122 150 123 - ret = kstrtoint(buf, 10, &val); 124 - if (ret < 0) 125 - return ret; 126 151 if (val < 0 || val > 100) 127 152 return -EINVAL; 128 153 129 - if (is_end_threshold) { 154 + if (psp == POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD) { 130 155 /* Start threshold is not exposed, use fixed value */ 131 156 if (priv->cmd_version == 2) 132 157 priv->current_start_threshold = val == 100 ? 0 : val; ··· 159 158 return ret; 160 159 } 161 160 162 - return count; 161 + return 0; 163 162 } 164 163 165 - static ssize_t charge_control_start_threshold_show(struct device *dev, 166 - struct device_attribute *attr, 167 - char *buf) 164 + 165 + static int cros_chctl_psy_ext_set_prop(struct power_supply *psy, 166 + const struct power_supply_ext *ext, 167 + void *data, 168 + enum power_supply_property psp, 169 + const union power_supply_propval *val) 168 170 { 169 - struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr, 170 - CROS_CHCTL_ATTR_START_THRESHOLD); 171 - 172 - guard(mutex)(&priv->lock); 173 - return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_start_threshold); 174 - } 175 - 176 - static ssize_t charge_control_start_threshold_store(struct device *dev, 177 - struct device_attribute *attr, 178 - const char *buf, size_t count) 179 - { 180 - struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr, 181 - CROS_CHCTL_ATTR_START_THRESHOLD); 182 - 183 - guard(mutex)(&priv->lock); 184 - return cros_chctl_store_threshold(dev, priv, 0, buf, count); 185 - } 186 - 187 - static ssize_t charge_control_end_threshold_show(struct device *dev, struct device_attribute *attr, 188 - char *buf) 189 - { 190 - struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr, 191 - CROS_CHCTL_ATTR_END_THRESHOLD); 192 - 193 - guard(mutex)(&priv->lock); 194 - return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_end_threshold); 195 - } 196 - 197 - static ssize_t charge_control_end_threshold_store(struct device *dev, struct device_attribute *attr, 198 - const char *buf, size_t count) 199 - { 200 - struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr, 201 - CROS_CHCTL_ATTR_END_THRESHOLD); 202 - 203 - guard(mutex)(&priv->lock); 204 - return cros_chctl_store_threshold(dev, priv, 1, buf, count); 205 - } 206 - 207 - static ssize_t charge_behaviour_show(struct device *dev, struct device_attribute *attr, char *buf) 208 - { 209 - struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr, 210 - CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR); 211 - 212 - guard(mutex)(&priv->lock); 213 - return power_supply_charge_behaviour_show(dev, EC_CHARGE_CONTROL_BEHAVIOURS, 214 - priv->current_behaviour, buf); 215 - } 216 - 217 - static ssize_t charge_behaviour_store(struct device *dev, struct device_attribute *attr, 218 - const char *buf, size_t count) 219 - { 220 - struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr, 221 - CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR); 171 + struct cros_chctl_priv *priv = data; 222 172 int ret; 223 173 224 - ret = power_supply_charge_behaviour_parse(EC_CHARGE_CONTROL_BEHAVIOURS, buf); 225 - if (ret < 0) 226 - return ret; 227 - 228 174 guard(mutex)(&priv->lock); 229 - priv->current_behaviour = ret; 230 175 231 - ret = cros_chctl_configure_ec(priv); 232 - if (ret < 0) 233 - return ret; 234 - 235 - return count; 176 + switch (psp) { 177 + case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD: 178 + case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD: 179 + return cros_chctl_psy_ext_set_threshold(priv, psp, val->intval); 180 + case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: 181 + priv->current_behaviour = val->intval; 182 + ret = cros_chctl_configure_ec(priv); 183 + if (ret < 0) 184 + return ret; 185 + return 0; 186 + default: 187 + return -EINVAL; 188 + } 236 189 } 237 190 238 - static umode_t cros_chtl_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) 191 + static int cros_chctl_psy_prop_is_writeable(struct power_supply *psy, 192 + const struct power_supply_ext *ext, 193 + void *data, 194 + enum power_supply_property psp) 239 195 { 240 - struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(attr, n); 241 - 242 - if (n == CROS_CHCTL_ATTR_START_THRESHOLD && priv->cmd_version < 3) 243 - return 0; 244 - else if (n == CROS_CHCTL_ATTR_END_THRESHOLD && priv->cmd_version < 2) 245 - return 0; 246 - 247 - return attr->mode; 196 + return true; 248 197 } 198 + 199 + #define DEFINE_CROS_CHCTL_POWER_SUPPLY_EXTENSION(_name, ...) \ 200 + static const enum power_supply_property _name ## _props[] = { \ 201 + __VA_ARGS__, \ 202 + }; \ 203 + \ 204 + static const struct power_supply_ext _name = { \ 205 + .name = "cros-charge-control", \ 206 + .properties = _name ## _props, \ 207 + .num_properties = ARRAY_SIZE(_name ## _props), \ 208 + .charge_behaviours = EC_CHARGE_CONTROL_BEHAVIOURS, \ 209 + .get_property = cros_chctl_psy_ext_get_prop, \ 210 + .set_property = cros_chctl_psy_ext_set_prop, \ 211 + .property_is_writeable = cros_chctl_psy_prop_is_writeable, \ 212 + } 213 + 214 + DEFINE_CROS_CHCTL_POWER_SUPPLY_EXTENSION(cros_chctl_psy_ext_v1, 215 + POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR 216 + ); 217 + 218 + DEFINE_CROS_CHCTL_POWER_SUPPLY_EXTENSION(cros_chctl_psy_ext_v2, 219 + POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR, 220 + POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD 221 + ); 222 + 223 + DEFINE_CROS_CHCTL_POWER_SUPPLY_EXTENSION(cros_chctl_psy_ext_v3, 224 + POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR, 225 + POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD, 226 + POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD 227 + ); 249 228 250 229 static int cros_chctl_add_battery(struct power_supply *battery, struct acpi_battery_hook *hook) 251 230 { ··· 235 254 return 0; 236 255 237 256 priv->hooked_battery = battery; 238 - return device_add_group(&battery->dev, &priv->group); 257 + return power_supply_register_extension(battery, priv->psy_ext, priv->dev, priv); 239 258 } 240 259 241 260 static int cros_chctl_remove_battery(struct power_supply *battery, struct acpi_battery_hook *hook) ··· 243 262 struct cros_chctl_priv *priv = container_of(hook, struct cros_chctl_priv, battery_hook); 244 263 245 264 if (priv->hooked_battery == battery) { 246 - device_remove_group(&battery->dev, &priv->group); 265 + power_supply_unregister_extension(battery, priv->psy_ext); 247 266 priv->hooked_battery = NULL; 248 267 } 249 268 ··· 269 288 struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent); 270 289 struct cros_ec_device *cros_ec = ec_dev->ec_dev; 271 290 struct cros_chctl_priv *priv; 272 - size_t i; 273 291 int ret; 274 292 275 293 ret = cros_chctl_fwk_charge_control_versions(cros_ec); ··· 301 321 302 322 dev_dbg(dev, "Command version: %u\n", (unsigned int)priv->cmd_version); 303 323 324 + priv->dev = dev; 304 325 priv->cros_ec = cros_ec; 305 - priv->device_attrs[CROS_CHCTL_ATTR_START_THRESHOLD] = 306 - (struct device_attribute)__ATTR_RW(charge_control_start_threshold); 307 - priv->device_attrs[CROS_CHCTL_ATTR_END_THRESHOLD] = 308 - (struct device_attribute)__ATTR_RW(charge_control_end_threshold); 309 - priv->device_attrs[CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR] = 310 - (struct device_attribute)__ATTR_RW(charge_behaviour); 311 - for (i = 0; i < _CROS_CHCTL_ATTR_COUNT; i++) { 312 - sysfs_attr_init(&priv->device_attrs[i].attr); 313 - priv->attributes[i] = &priv->device_attrs[i].attr; 314 - } 315 - priv->group.is_visible = cros_chtl_attr_is_visible; 316 - priv->group.attrs = priv->attributes; 326 + 327 + if (priv->cmd_version == 1) 328 + priv->psy_ext = &cros_chctl_psy_ext_v1; 329 + else if (priv->cmd_version == 2) 330 + priv->psy_ext = &cros_chctl_psy_ext_v2; 331 + else 332 + priv->psy_ext = &cros_chctl_psy_ext_v3; 317 333 318 334 priv->battery_hook.name = dev_name(dev); 319 335 priv->battery_hook.add_battery = cros_chctl_add_battery;
+2 -1
drivers/power/supply/da9030_battery.c
··· 15 15 #include <linux/module.h> 16 16 #include <linux/platform_device.h> 17 17 #include <linux/power_supply.h> 18 + #include <linux/string_choices.h> 18 19 #include <linux/mfd/da903x.h> 19 20 20 21 #include <linux/debugfs.h> ··· 139 138 { 140 139 struct da9030_charger *charger = s->private; 141 140 142 - seq_printf(s, "charger is %s\n", charger->is_on ? "on" : "off"); 141 + seq_printf(s, "charger is %s\n", str_on_off(charger->is_on)); 143 142 if (charger->chdet) { 144 143 seq_printf(s, "iset = %dmA, vset = %dmV\n", 145 144 charger->mA, charger->mV);
+4 -4
drivers/power/supply/ds2760_battery.c
··· 195 195 } 196 196 197 197 static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj, 198 - struct bin_attribute *bin_attr, char *buf, 198 + const struct bin_attribute *bin_attr, char *buf, 199 199 loff_t off, size_t count) 200 200 { 201 201 struct device *dev = kobj_to_dev(kobj); 202 202 return w1_ds2760_read(dev, buf, off, count); 203 203 } 204 204 205 - static BIN_ATTR_RO(w1_slave, DS2760_DATA_SIZE); 205 + static const BIN_ATTR_RO(w1_slave, DS2760_DATA_SIZE); 206 206 207 - static struct bin_attribute *w1_ds2760_bin_attrs[] = { 207 + static const struct bin_attribute *const w1_ds2760_bin_attrs[] = { 208 208 &bin_attr_w1_slave, 209 209 NULL, 210 210 }; 211 211 212 212 static const struct attribute_group w1_ds2760_group = { 213 - .bin_attrs = w1_ds2760_bin_attrs, 213 + .bin_attrs_new = w1_ds2760_bin_attrs, 214 214 }; 215 215 216 216 static const struct attribute_group *w1_ds2760_groups[] = {
+12 -12
drivers/power/supply/ds2780_battery.c
··· 621 621 622 622 static ssize_t ds2780_read_param_eeprom_bin(struct file *filp, 623 623 struct kobject *kobj, 624 - struct bin_attribute *bin_attr, 624 + const struct bin_attribute *bin_attr, 625 625 char *buf, loff_t off, size_t count) 626 626 { 627 627 struct device *dev = kobj_to_dev(kobj); ··· 634 634 635 635 static ssize_t ds2780_write_param_eeprom_bin(struct file *filp, 636 636 struct kobject *kobj, 637 - struct bin_attribute *bin_attr, 637 + const struct bin_attribute *bin_attr, 638 638 char *buf, loff_t off, size_t count) 639 639 { 640 640 struct device *dev = kobj_to_dev(kobj); ··· 654 654 return count; 655 655 } 656 656 657 - static struct bin_attribute ds2780_param_eeprom_bin_attr = { 657 + static const struct bin_attribute ds2780_param_eeprom_bin_attr = { 658 658 .attr = { 659 659 .name = "param_eeprom", 660 660 .mode = S_IRUGO | S_IWUSR, 661 661 }, 662 662 .size = DS2780_PARAM_EEPROM_SIZE, 663 - .read = ds2780_read_param_eeprom_bin, 664 - .write = ds2780_write_param_eeprom_bin, 663 + .read_new = ds2780_read_param_eeprom_bin, 664 + .write_new = ds2780_write_param_eeprom_bin, 665 665 }; 666 666 667 667 static ssize_t ds2780_read_user_eeprom_bin(struct file *filp, 668 668 struct kobject *kobj, 669 - struct bin_attribute *bin_attr, 669 + const struct bin_attribute *bin_attr, 670 670 char *buf, loff_t off, size_t count) 671 671 { 672 672 struct device *dev = kobj_to_dev(kobj); ··· 679 679 680 680 static ssize_t ds2780_write_user_eeprom_bin(struct file *filp, 681 681 struct kobject *kobj, 682 - struct bin_attribute *bin_attr, 682 + const struct bin_attribute *bin_attr, 683 683 char *buf, loff_t off, size_t count) 684 684 { 685 685 struct device *dev = kobj_to_dev(kobj); ··· 699 699 return count; 700 700 } 701 701 702 - static struct bin_attribute ds2780_user_eeprom_bin_attr = { 702 + static const struct bin_attribute ds2780_user_eeprom_bin_attr = { 703 703 .attr = { 704 704 .name = "user_eeprom", 705 705 .mode = S_IRUGO | S_IWUSR, 706 706 }, 707 707 .size = DS2780_USER_EEPROM_SIZE, 708 - .read = ds2780_read_user_eeprom_bin, 709 - .write = ds2780_write_user_eeprom_bin, 708 + .read_new = ds2780_read_user_eeprom_bin, 709 + .write_new = ds2780_write_user_eeprom_bin, 710 710 }; 711 711 712 712 static DEVICE_ATTR(pmod_enabled, S_IRUGO | S_IWUSR, ds2780_get_pmod_enabled, ··· 726 726 NULL 727 727 }; 728 728 729 - static struct bin_attribute *ds2780_sysfs_bin_attrs[] = { 729 + static const struct bin_attribute *const ds2780_sysfs_bin_attrs[] = { 730 730 &ds2780_param_eeprom_bin_attr, 731 731 &ds2780_user_eeprom_bin_attr, 732 732 NULL ··· 734 734 735 735 static const struct attribute_group ds2780_sysfs_group = { 736 736 .attrs = ds2780_sysfs_attrs, 737 - .bin_attrs = ds2780_sysfs_bin_attrs, 737 + .bin_attrs_new = ds2780_sysfs_bin_attrs, 738 738 }; 739 739 740 740 static const struct attribute_group *ds2780_sysfs_groups[] = {
+12 -12
drivers/power/supply/ds2781_battery.c
··· 623 623 624 624 static ssize_t ds2781_read_param_eeprom_bin(struct file *filp, 625 625 struct kobject *kobj, 626 - struct bin_attribute *bin_attr, 626 + const struct bin_attribute *bin_attr, 627 627 char *buf, loff_t off, size_t count) 628 628 { 629 629 struct device *dev = kobj_to_dev(kobj); ··· 636 636 637 637 static ssize_t ds2781_write_param_eeprom_bin(struct file *filp, 638 638 struct kobject *kobj, 639 - struct bin_attribute *bin_attr, 639 + const struct bin_attribute *bin_attr, 640 640 char *buf, loff_t off, size_t count) 641 641 { 642 642 struct device *dev = kobj_to_dev(kobj); ··· 656 656 return count; 657 657 } 658 658 659 - static struct bin_attribute ds2781_param_eeprom_bin_attr = { 659 + static const struct bin_attribute ds2781_param_eeprom_bin_attr = { 660 660 .attr = { 661 661 .name = "param_eeprom", 662 662 .mode = S_IRUGO | S_IWUSR, 663 663 }, 664 664 .size = DS2781_PARAM_EEPROM_SIZE, 665 - .read = ds2781_read_param_eeprom_bin, 666 - .write = ds2781_write_param_eeprom_bin, 665 + .read_new = ds2781_read_param_eeprom_bin, 666 + .write_new = ds2781_write_param_eeprom_bin, 667 667 }; 668 668 669 669 static ssize_t ds2781_read_user_eeprom_bin(struct file *filp, 670 670 struct kobject *kobj, 671 - struct bin_attribute *bin_attr, 671 + const struct bin_attribute *bin_attr, 672 672 char *buf, loff_t off, size_t count) 673 673 { 674 674 struct device *dev = kobj_to_dev(kobj); ··· 682 682 683 683 static ssize_t ds2781_write_user_eeprom_bin(struct file *filp, 684 684 struct kobject *kobj, 685 - struct bin_attribute *bin_attr, 685 + const struct bin_attribute *bin_attr, 686 686 char *buf, loff_t off, size_t count) 687 687 { 688 688 struct device *dev = kobj_to_dev(kobj); ··· 702 702 return count; 703 703 } 704 704 705 - static struct bin_attribute ds2781_user_eeprom_bin_attr = { 705 + static const struct bin_attribute ds2781_user_eeprom_bin_attr = { 706 706 .attr = { 707 707 .name = "user_eeprom", 708 708 .mode = S_IRUGO | S_IWUSR, 709 709 }, 710 710 .size = DS2781_USER_EEPROM_SIZE, 711 - .read = ds2781_read_user_eeprom_bin, 712 - .write = ds2781_write_user_eeprom_bin, 711 + .read_new = ds2781_read_user_eeprom_bin, 712 + .write_new = ds2781_write_user_eeprom_bin, 713 713 }; 714 714 715 715 static DEVICE_ATTR(pmod_enabled, S_IRUGO | S_IWUSR, ds2781_get_pmod_enabled, ··· 729 729 NULL 730 730 }; 731 731 732 - static struct bin_attribute *ds2781_sysfs_bin_attrs[] = { 732 + static const struct bin_attribute *const ds2781_sysfs_bin_attrs[] = { 733 733 &ds2781_param_eeprom_bin_attr, 734 734 &ds2781_user_eeprom_bin_attr, 735 735 NULL, ··· 737 737 738 738 static const struct attribute_group ds2781_sysfs_group = { 739 739 .attrs = ds2781_sysfs_attrs, 740 - .bin_attrs = ds2781_sysfs_bin_attrs, 740 + .bin_attrs_new = ds2781_sysfs_bin_attrs, 741 741 742 742 }; 743 743
+31 -56
drivers/power/supply/ds2782_battery.c
··· 11 11 * UEvent sending added by Evgeny Romanov <romanov@neurosoft.ru> 12 12 */ 13 13 14 + #include <linux/devm-helpers.h> 14 15 #include <linux/kernel.h> 15 16 #include <linux/module.h> 16 17 #include <linux/types.h> ··· 58 57 struct power_supply_desc battery_desc; 59 58 const struct ds278x_battery_ops *ops; 60 59 struct delayed_work bat_work; 61 - int id; 62 60 int rsns; 63 61 int capacity; 64 62 int status; /* State Of Charge */ 65 63 }; 66 64 67 - static DEFINE_IDR(battery_id); 68 - static DEFINE_MUTEX(battery_lock); 65 + static DEFINE_IDA(battery_id); 69 66 70 67 static inline int ds278x_read_reg(struct ds278x_info *info, int reg, u8 *val) 71 68 { ··· 311 312 battery->external_power_changed = NULL; 312 313 } 313 314 314 - static void ds278x_battery_remove(struct i2c_client *client) 315 - { 316 - struct ds278x_info *info = i2c_get_clientdata(client); 317 - int id = info->id; 318 - 319 - power_supply_unregister(info->battery); 320 - cancel_delayed_work_sync(&info->bat_work); 321 - kfree(info->battery_desc.name); 322 - kfree(info); 323 - 324 - mutex_lock(&battery_lock); 325 - idr_remove(&battery_id, id); 326 - mutex_unlock(&battery_lock); 327 - } 328 - 329 315 #ifdef CONFIG_PM_SLEEP 330 316 331 317 static int ds278x_suspend(struct device *dev) ··· 352 368 } 353 369 }; 354 370 371 + static void ds278x_free_ida(void *data) 372 + { 373 + int num = (uintptr_t)data; 374 + 375 + ida_free(&battery_id, num); 376 + } 377 + 355 378 static int ds278x_battery_probe(struct i2c_client *client) 356 379 { 357 380 const struct i2c_device_id *id = i2c_client_get_device_id(client); ··· 378 387 } 379 388 380 389 /* Get an ID for this battery */ 381 - mutex_lock(&battery_lock); 382 - ret = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL); 383 - mutex_unlock(&battery_lock); 384 - if (ret < 0) 385 - goto fail_id; 386 - num = ret; 390 + num = ida_alloc(&battery_id, GFP_KERNEL); 391 + if (num < 0) 392 + return num; 393 + ret = devm_add_action_or_reset(&client->dev, ds278x_free_ida, (void *)(uintptr_t)num); 394 + if (ret) 395 + return ret; 387 396 388 - info = kzalloc(sizeof(*info), GFP_KERNEL); 389 - if (!info) { 390 - ret = -ENOMEM; 391 - goto fail_info; 392 - } 397 + info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); 398 + if (!info) 399 + return -ENOMEM; 393 400 394 - info->battery_desc.name = kasprintf(GFP_KERNEL, "%s-%d", 395 - client->name, num); 396 - if (!info->battery_desc.name) { 397 - ret = -ENOMEM; 398 - goto fail_name; 399 - } 401 + info->battery_desc.name = devm_kasprintf(&client->dev, GFP_KERNEL, 402 + "%s-%d", client->name, num); 403 + if (!info->battery_desc.name) 404 + return -ENOMEM; 400 405 401 406 if (id->driver_data == DS2786) 402 407 info->rsns = pdata->rsns; 403 408 404 409 i2c_set_clientdata(client, info); 405 410 info->client = client; 406 - info->id = num; 407 411 info->ops = &ds278x_ops[id->driver_data]; 408 412 ds278x_power_supply_init(&info->battery_desc); 409 413 psy_cfg.drv_data = info; ··· 406 420 info->capacity = 100; 407 421 info->status = POWER_SUPPLY_STATUS_FULL; 408 422 409 - INIT_DELAYED_WORK(&info->bat_work, ds278x_bat_work); 410 - 411 - info->battery = power_supply_register(&client->dev, 412 - &info->battery_desc, &psy_cfg); 423 + info->battery = devm_power_supply_register(&client->dev, 424 + &info->battery_desc, 425 + &psy_cfg); 413 426 if (IS_ERR(info->battery)) { 414 427 dev_err(&client->dev, "failed to register battery\n"); 415 - ret = PTR_ERR(info->battery); 416 - goto fail_register; 417 - } else { 418 - schedule_delayed_work(&info->bat_work, DS278x_DELAY); 428 + return PTR_ERR(info->battery); 419 429 } 420 430 421 - return 0; 431 + ret = devm_delayed_work_autocancel(&client->dev, &info->bat_work, ds278x_bat_work); 432 + if (ret) 433 + return ret; 434 + schedule_delayed_work(&info->bat_work, DS278x_DELAY); 422 435 423 - fail_register: 424 - kfree(info->battery_desc.name); 425 - fail_name: 426 - kfree(info); 427 - fail_info: 428 - mutex_lock(&battery_lock); 429 - idr_remove(&battery_id, num); 430 - mutex_unlock(&battery_lock); 431 - fail_id: 432 - return ret; 436 + return 0; 433 437 } 434 438 435 439 static const struct i2c_device_id ds278x_id[] = { ··· 435 459 .pm = &ds278x_battery_pm_ops, 436 460 }, 437 461 .probe = ds278x_battery_probe, 438 - .remove = ds278x_battery_remove, 439 462 .id_table = ds278x_id, 440 463 }; 441 464 module_i2c_driver(ds278x_battery_driver);
+13
drivers/power/supply/gpio-charger.c
··· 195 195 { 196 196 int i, len; 197 197 u32 cur_limit = U32_MAX; 198 + bool set_def_limit; 199 + u32 def_limit; 198 200 199 201 gpio_charger->current_limit_gpios = devm_gpiod_get_array_optional(dev, 200 202 "charge-current-limit", GPIOD_OUT_LOW); ··· 230 228 if (len < 0) 231 229 return len; 232 230 231 + set_def_limit = !device_property_read_u32(dev, 232 + "charge-current-limit-default-microamp", 233 + &def_limit); 233 234 for (i=0; i < gpio_charger->current_limit_map_size; i++) { 234 235 if (gpio_charger->current_limit_map[i].limit_ua > cur_limit) { 235 236 dev_err(dev, "charge-current-limit-mapping not sorted by current in descending order\n"); ··· 240 235 } 241 236 242 237 cur_limit = gpio_charger->current_limit_map[i].limit_ua; 238 + if (set_def_limit && def_limit == cur_limit) { 239 + set_charge_current_limit(gpio_charger, cur_limit); 240 + return 0; 241 + } 243 242 } 243 + 244 + if (set_def_limit) 245 + dev_warn(dev, "charge-current-limit-default-microamp %u not listed in charge-current-limit-mapping\n", 246 + def_limit); 244 247 245 248 /* default to smallest current limitation for safety reasons */ 246 249 len = gpio_charger->current_limit_map_size - 1;
+410 -162
drivers/power/supply/ip5xxx_power.c
··· 7 7 #include <linux/power_supply.h> 8 8 #include <linux/regmap.h> 9 9 10 - #define IP5XXX_SYS_CTL0 0x01 11 - #define IP5XXX_SYS_CTL0_WLED_DET_EN BIT(4) 12 - #define IP5XXX_SYS_CTL0_WLED_EN BIT(3) 13 - #define IP5XXX_SYS_CTL0_BOOST_EN BIT(2) 14 - #define IP5XXX_SYS_CTL0_CHARGER_EN BIT(1) 15 - #define IP5XXX_SYS_CTL1 0x02 16 - #define IP5XXX_SYS_CTL1_LIGHT_SHDN_EN BIT(1) 17 - #define IP5XXX_SYS_CTL1_LOAD_PWRUP_EN BIT(0) 18 - #define IP5XXX_SYS_CTL2 0x0c 19 - #define IP5XXX_SYS_CTL2_LIGHT_SHDN_TH GENMASK(7, 3) 20 - #define IP5XXX_SYS_CTL3 0x03 21 - #define IP5XXX_SYS_CTL3_LONG_PRESS_TIME_SEL GENMASK(7, 6) 22 - #define IP5XXX_SYS_CTL3_BTN_SHDN_EN BIT(5) 23 - #define IP5XXX_SYS_CTL4 0x04 24 - #define IP5XXX_SYS_CTL4_SHDN_TIME_SEL GENMASK(7, 6) 25 - #define IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN BIT(5) 26 - #define IP5XXX_SYS_CTL5 0x07 27 - #define IP5XXX_SYS_CTL5_NTC_DIS BIT(6) 28 - #define IP5XXX_SYS_CTL5_WLED_MODE_SEL BIT(1) 29 - #define IP5XXX_SYS_CTL5_BTN_SHDN_SEL BIT(0) 30 - #define IP5XXX_CHG_CTL1 0x22 31 - #define IP5XXX_CHG_CTL1_BOOST_UVP_SEL GENMASK(3, 2) 32 - #define IP5XXX_CHG_CTL2 0x24 33 - #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL GENMASK(6, 5) 34 - #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V (0x0 << 5) 35 - #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V (0x1 << 5) 36 - #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V (0x2 << 5) 37 - #define IP5XXX_CHG_CTL2_CONST_VOLT_SEL GENMASK(2, 1) 38 - #define IP5XXX_CHG_CTL4 0x26 39 - #define IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN BIT(6) 40 - #define IP5XXX_CHG_CTL4A 0x25 41 - #define IP5XXX_CHG_CTL4A_CONST_CUR_SEL GENMASK(4, 0) 42 - #define IP5XXX_MFP_CTL0 0x51 43 - #define IP5XXX_MFP_CTL1 0x52 44 - #define IP5XXX_GPIO_CTL2 0x53 45 - #define IP5XXX_GPIO_CTL2A 0x54 46 - #define IP5XXX_GPIO_CTL3 0x55 47 - #define IP5XXX_READ0 0x71 48 - #define IP5XXX_READ0_CHG_STAT GENMASK(7, 5) 49 - #define IP5XXX_READ0_CHG_STAT_IDLE (0x0 << 5) 50 - #define IP5XXX_READ0_CHG_STAT_TRICKLE (0x1 << 5) 51 - #define IP5XXX_READ0_CHG_STAT_CONST_VOLT (0x2 << 5) 52 - #define IP5XXX_READ0_CHG_STAT_CONST_CUR (0x3 << 5) 53 - #define IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP (0x4 << 5) 54 - #define IP5XXX_READ0_CHG_STAT_FULL (0x5 << 5) 55 - #define IP5XXX_READ0_CHG_STAT_TIMEOUT (0x6 << 5) 56 - #define IP5XXX_READ0_CHG_OP BIT(4) 57 - #define IP5XXX_READ0_CHG_END BIT(3) 58 - #define IP5XXX_READ0_CONST_VOLT_TIMEOUT BIT(2) 59 - #define IP5XXX_READ0_CHG_TIMEOUT BIT(1) 60 - #define IP5XXX_READ0_TRICKLE_TIMEOUT BIT(0) 61 - #define IP5XXX_READ0_TIMEOUT GENMASK(2, 0) 62 - #define IP5XXX_READ1 0x72 63 - #define IP5XXX_READ1_WLED_PRESENT BIT(7) 64 - #define IP5XXX_READ1_LIGHT_LOAD BIT(6) 65 - #define IP5XXX_READ1_VIN_OVERVOLT BIT(5) 66 - #define IP5XXX_READ2 0x77 67 - #define IP5XXX_READ2_BTN_PRESS BIT(3) 68 - #define IP5XXX_READ2_BTN_LONG_PRESS BIT(1) 69 - #define IP5XXX_READ2_BTN_SHORT_PRESS BIT(0) 70 - #define IP5XXX_BATVADC_DAT0 0xa2 71 - #define IP5XXX_BATVADC_DAT1 0xa3 72 - #define IP5XXX_BATIADC_DAT0 0xa4 73 - #define IP5XXX_BATIADC_DAT1 0xa5 74 - #define IP5XXX_BATOCV_DAT0 0xa8 75 - #define IP5XXX_BATOCV_DAT1 0xa9 10 + #define IP5XXX_BAT_TYPE_4_2V 0x0 11 + #define IP5XXX_BAT_TYPE_4_3V 0x1 12 + #define IP5XXX_BAT_TYPE_4_35V 0x2 13 + #define IP5XXX_BAT_TYPE_4_4V 0x3 14 + #define IP5XXX_CHG_STAT_IDLE 0x0 15 + #define IP5XXX_CHG_STAT_TRICKLE 0x1 16 + #define IP5XXX_CHG_STAT_CONST_VOLT 0x2 17 + #define IP5XXX_CHG_STAT_CONST_CUR 0x3 18 + #define IP5XXX_CHG_STAT_CONST_VOLT_STOP 0x4 19 + #define IP5XXX_CHG_STAT_FULL 0x5 20 + #define IP5XXX_CHG_STAT_TIMEOUT 0x6 76 21 77 22 struct ip5xxx { 78 23 struct regmap *regmap; 79 24 bool initialized; 25 + struct { 26 + struct { 27 + /* Charger enable */ 28 + struct regmap_field *enable; 29 + /* Constant voltage value */ 30 + struct regmap_field *const_volt_sel; 31 + /* Constant current value */ 32 + struct regmap_field *const_curr_sel; 33 + /* Charger status */ 34 + struct regmap_field *status; 35 + /* Charging ended flag */ 36 + struct regmap_field *chg_end; 37 + /* Timeout flags (CV, charge, trickle) */ 38 + struct regmap_field *timeout; 39 + /* Overvoltage limit */ 40 + struct regmap_field *vin_overvolt; 41 + } charger; 42 + struct { 43 + /* Boost converter enable */ 44 + struct regmap_field *enable; 45 + struct { 46 + /* Light load shutdown enable */ 47 + struct regmap_field *enable; 48 + /* Light load shutdown current limit */ 49 + struct regmap_field *i_limit; 50 + } light_load_shutdown; 51 + /* Automatic powerup on increased load */ 52 + struct regmap_field *load_powerup_en; 53 + /* Automatic powerup on VIN pull-out */ 54 + struct regmap_field *vin_pullout_en; 55 + /* Undervoltage limit */ 56 + struct regmap_field *undervolt_limit; 57 + /* Light load status flag */ 58 + struct regmap_field *light_load_status; 59 + } boost; 60 + struct { 61 + /* NTC disable */ 62 + struct regmap_field *ntc_dis; 63 + /* Battery voltage type */ 64 + struct regmap_field *type; 65 + /* Battery voltage autoset from Vset pin */ 66 + struct regmap_field *vset_en; 67 + struct { 68 + /* Battery measurement registers */ 69 + struct ip5xxx_battery_adc_regs { 70 + struct regmap_field *low; 71 + struct regmap_field *high; 72 + } volt, curr, open_volt; 73 + } adc; 74 + } battery; 75 + struct { 76 + /* Double/long press shutdown enable */ 77 + struct regmap_field *shdn_enable; 78 + /* WLED activation: double press or long press */ 79 + struct regmap_field *wled_mode; 80 + /* Shutdown activation: double press or long press */ 81 + struct regmap_field *shdn_mode; 82 + /* Long press time */ 83 + struct regmap_field *long_press_time; 84 + /* Button pressed */ 85 + struct regmap_field *pressed; 86 + /* Button long-pressed */ 87 + struct regmap_field *long_pressed; 88 + /* Button short-pressed */ 89 + struct regmap_field *short_pressed; 90 + } btn; 91 + struct { 92 + /* WLED enable */ 93 + struct regmap_field *enable; 94 + /* WLED detect */ 95 + struct regmap_field *detect_en; 96 + /* WLED present */ 97 + struct regmap_field *present; 98 + } wled; 99 + } regs; 100 + 101 + /* Maximum supported battery voltage (via regs.battery.type) */ 102 + int vbat_max; 103 + /* Scaling constants for regs.boost.undervolt_limit */ 104 + struct { 105 + int setpoint; 106 + int microvolts_per_bit; 107 + } boost_undervolt; 108 + /* Scaling constants for regs.charger.const_curr_sel */ 109 + struct { 110 + int setpoint; 111 + } const_curr; 112 + /* Whether regs.charger.chg_end is inverted */ 113 + u8 chg_end_inverted; 114 + }; 115 + 116 + #define REG_FIELD_UNSUPPORTED { .lsb = 1 } 117 + /* Register fields layout. Unsupported registers marked as { .lsb = 1 } */ 118 + struct ip5xxx_regfield_config { 119 + const struct reg_field charger_enable; 120 + const struct reg_field charger_const_volt_sel; 121 + const struct reg_field charger_const_curr_sel; 122 + const struct reg_field charger_status; 123 + const struct reg_field charger_chg_end; 124 + const struct reg_field charger_timeout; 125 + const struct reg_field charger_vin_overvolt; 126 + const struct reg_field boost_enable; 127 + const struct reg_field boost_llshdn_enable; 128 + const struct reg_field boost_llshdn_i_limit; 129 + const struct reg_field boost_load_powerup_en; 130 + const struct reg_field boost_vin_pullout_en; 131 + const struct reg_field boost_undervolt_limit; 132 + const struct reg_field boost_light_load_status; 133 + const struct reg_field battery_ntc_dis; 134 + const struct reg_field battery_type; 135 + const struct reg_field battery_vset_en; 136 + const struct reg_field battery_adc_volt_low; 137 + const struct reg_field battery_adc_volt_high; 138 + const struct reg_field battery_adc_curr_low; 139 + const struct reg_field battery_adc_curr_high; 140 + const struct reg_field battery_adc_ovolt_low; 141 + const struct reg_field battery_adc_ovolt_high; 142 + const struct reg_field btn_shdn_enable; 143 + const struct reg_field btn_wled_mode; 144 + const struct reg_field btn_shdn_mode; 145 + const struct reg_field btn_long_press_time; 146 + const struct reg_field btn_pressed; 147 + const struct reg_field btn_long_pressed; 148 + const struct reg_field btn_short_pressed; 149 + const struct reg_field wled_enable; 150 + const struct reg_field wled_detect_en; 151 + const struct reg_field wled_present; 152 + 153 + int vbat_max; 154 + int boost_undervolt_setpoint; 155 + int boost_undervolt_uv_per_bit; 156 + int const_curr_setpoint; 157 + u8 chg_end_inverted; 80 158 }; 81 159 82 160 /* ··· 165 87 * 2) Attempt the initialization sequence on each subsequent register access 166 88 * until it succeeds. 167 89 */ 168 - static int ip5xxx_read(struct ip5xxx *ip5xxx, unsigned int reg, 90 + static int ip5xxx_read(struct ip5xxx *ip5xxx, struct regmap_field *field, 169 91 unsigned int *val) 170 92 { 171 93 int ret; 172 94 173 - ret = regmap_read(ip5xxx->regmap, reg, val); 95 + if (!field) 96 + return -EOPNOTSUPP; 97 + 98 + ret = regmap_field_read(field, val); 174 99 if (ret) 175 100 ip5xxx->initialized = false; 176 101 177 102 return ret; 178 103 } 179 104 180 - static int ip5xxx_update_bits(struct ip5xxx *ip5xxx, unsigned int reg, 181 - unsigned int mask, unsigned int val) 105 + static int ip5xxx_write(struct ip5xxx *ip5xxx, struct regmap_field *field, 106 + unsigned int val) 182 107 { 183 108 int ret; 184 109 185 - ret = regmap_update_bits(ip5xxx->regmap, reg, mask, val); 110 + if (!field) 111 + return -EOPNOTSUPP; 112 + 113 + ret = regmap_field_write(field, val); 186 114 if (ret) 187 115 ip5xxx->initialized = false; 188 116 ··· 207 123 * Disable shutdown under light load. 208 124 * Enable power on when under load. 209 125 */ 210 - ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL1, 211 - IP5XXX_SYS_CTL1_LIGHT_SHDN_EN | 212 - IP5XXX_SYS_CTL1_LOAD_PWRUP_EN, 213 - IP5XXX_SYS_CTL1_LOAD_PWRUP_EN); 126 + if (ip5xxx->regs.boost.light_load_shutdown.enable) { 127 + ret = ip5xxx_write(ip5xxx, ip5xxx->regs.boost.light_load_shutdown.enable, 0); 128 + if (ret) 129 + return ret; 130 + } 131 + ret = ip5xxx_write(ip5xxx, ip5xxx->regs.boost.load_powerup_en, 1); 214 132 if (ret) 215 133 return ret; 216 134 217 135 /* 218 136 * Enable shutdown after a long button press (as configured below). 219 137 */ 220 - ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL3, 221 - IP5XXX_SYS_CTL3_BTN_SHDN_EN, 222 - IP5XXX_SYS_CTL3_BTN_SHDN_EN); 138 + ret = ip5xxx_write(ip5xxx, ip5xxx->regs.btn.shdn_enable, 1); 223 139 if (ret) 224 140 return ret; 225 141 226 142 /* 227 143 * Power on automatically when VIN is removed. 228 144 */ 229 - ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL4, 230 - IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN, 231 - IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN); 145 + ret = ip5xxx_write(ip5xxx, ip5xxx->regs.boost.vin_pullout_en, 1); 232 146 if (ret) 233 147 return ret; 234 148 ··· 234 152 * Enable the NTC. 235 153 * Configure the button for two presses => LED, long press => shutdown. 236 154 */ 237 - ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL5, 238 - IP5XXX_SYS_CTL5_NTC_DIS | 239 - IP5XXX_SYS_CTL5_WLED_MODE_SEL | 240 - IP5XXX_SYS_CTL5_BTN_SHDN_SEL, 241 - IP5XXX_SYS_CTL5_WLED_MODE_SEL | 242 - IP5XXX_SYS_CTL5_BTN_SHDN_SEL); 155 + if (ip5xxx->regs.battery.ntc_dis) { 156 + ret = ip5xxx_write(ip5xxx, ip5xxx->regs.battery.ntc_dis, 0); 157 + if (ret) 158 + return ret; 159 + } 160 + ret = ip5xxx_write(ip5xxx, ip5xxx->regs.btn.wled_mode, 1); 161 + if (ret) 162 + return ret; 163 + ret = ip5xxx_write(ip5xxx, ip5xxx->regs.btn.shdn_mode, 1); 243 164 if (ret) 244 165 return ret; 245 166 ··· 271 186 unsigned int rval; 272 187 int ret; 273 188 274 - ret = ip5xxx_read(ip5xxx, IP5XXX_READ0, &rval); 189 + if (!ip5xxx->regs.charger.status) { 190 + // Fall-back to Charging Ended bit 191 + ret = ip5xxx_read(ip5xxx, ip5xxx->regs.charger.chg_end, &rval); 192 + if (ret) 193 + return ret; 194 + 195 + if (rval == ip5xxx->chg_end_inverted) 196 + *val = POWER_SUPPLY_STATUS_CHARGING; 197 + else 198 + *val = POWER_SUPPLY_STATUS_NOT_CHARGING; 199 + return 0; 200 + } 201 + 202 + ret = ip5xxx_read(ip5xxx, ip5xxx->regs.charger.status, &rval); 275 203 if (ret) 276 204 return ret; 277 205 278 - switch (rval & IP5XXX_READ0_CHG_STAT) { 279 - case IP5XXX_READ0_CHG_STAT_IDLE: 206 + switch (rval) { 207 + case IP5XXX_CHG_STAT_IDLE: 280 208 *val = POWER_SUPPLY_STATUS_DISCHARGING; 281 209 break; 282 - case IP5XXX_READ0_CHG_STAT_TRICKLE: 283 - case IP5XXX_READ0_CHG_STAT_CONST_CUR: 284 - case IP5XXX_READ0_CHG_STAT_CONST_VOLT: 210 + case IP5XXX_CHG_STAT_TRICKLE: 211 + case IP5XXX_CHG_STAT_CONST_CUR: 212 + case IP5XXX_CHG_STAT_CONST_VOLT: 285 213 *val = POWER_SUPPLY_STATUS_CHARGING; 286 214 break; 287 - case IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP: 288 - case IP5XXX_READ0_CHG_STAT_FULL: 215 + case IP5XXX_CHG_STAT_CONST_VOLT_STOP: 216 + case IP5XXX_CHG_STAT_FULL: 289 217 *val = POWER_SUPPLY_STATUS_FULL; 290 218 break; 291 - case IP5XXX_READ0_CHG_STAT_TIMEOUT: 219 + case IP5XXX_CHG_STAT_TIMEOUT: 292 220 *val = POWER_SUPPLY_STATUS_NOT_CHARGING; 293 221 break; 294 222 default: ··· 316 218 unsigned int rval; 317 219 int ret; 318 220 319 - ret = ip5xxx_read(ip5xxx, IP5XXX_READ0, &rval); 221 + ret = ip5xxx_read(ip5xxx, ip5xxx->regs.charger.status, &rval); 320 222 if (ret) 321 223 return ret; 322 224 323 - switch (rval & IP5XXX_READ0_CHG_STAT) { 324 - case IP5XXX_READ0_CHG_STAT_IDLE: 325 - case IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP: 326 - case IP5XXX_READ0_CHG_STAT_FULL: 327 - case IP5XXX_READ0_CHG_STAT_TIMEOUT: 225 + switch (rval) { 226 + case IP5XXX_CHG_STAT_IDLE: 227 + case IP5XXX_CHG_STAT_CONST_VOLT_STOP: 228 + case IP5XXX_CHG_STAT_FULL: 229 + case IP5XXX_CHG_STAT_TIMEOUT: 328 230 *val = POWER_SUPPLY_CHARGE_TYPE_NONE; 329 231 break; 330 - case IP5XXX_READ0_CHG_STAT_TRICKLE: 232 + case IP5XXX_CHG_STAT_TRICKLE: 331 233 *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 332 234 break; 333 - case IP5XXX_READ0_CHG_STAT_CONST_CUR: 334 - case IP5XXX_READ0_CHG_STAT_CONST_VOLT: 235 + case IP5XXX_CHG_STAT_CONST_CUR: 236 + case IP5XXX_CHG_STAT_CONST_VOLT: 335 237 *val = POWER_SUPPLY_CHARGE_TYPE_STANDARD; 336 238 break; 337 239 default: ··· 346 248 unsigned int rval; 347 249 int ret; 348 250 349 - ret = ip5xxx_read(ip5xxx, IP5XXX_READ0, &rval); 251 + ret = ip5xxx_read(ip5xxx, ip5xxx->regs.charger.timeout, &rval); 350 252 if (ret) 351 253 return ret; 352 254 353 - if (rval & IP5XXX_READ0_TIMEOUT) 255 + if (rval) 354 256 *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; 355 257 else 356 258 *val = POWER_SUPPLY_HEALTH_GOOD; ··· 363 265 unsigned int rval; 364 266 int ret; 365 267 366 - ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL2, &rval); 268 + ret = ip5xxx_read(ip5xxx, ip5xxx->regs.battery.type, &rval); 367 269 if (ret) 368 270 return ret; 369 271 ··· 371 273 * It is not clear what this will return if 372 274 * IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN is not set... 373 275 */ 374 - switch (rval & IP5XXX_CHG_CTL2_BAT_TYPE_SEL) { 375 - case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V: 276 + switch (rval) { 277 + case IP5XXX_BAT_TYPE_4_2V: 376 278 *val = 4200000; 377 279 break; 378 - case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V: 280 + case IP5XXX_BAT_TYPE_4_3V: 379 281 *val = 4300000; 380 282 break; 381 - case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V: 283 + case IP5XXX_BAT_TYPE_4_35V: 382 284 *val = 4350000; 285 + break; 286 + case IP5XXX_BAT_TYPE_4_4V: 287 + *val = 4400000; 383 288 break; 384 289 default: 385 290 return -EINVAL; ··· 392 291 } 393 292 394 293 static int ip5xxx_battery_read_adc(struct ip5xxx *ip5xxx, 395 - u8 lo_reg, u8 hi_reg, int *val) 294 + struct ip5xxx_battery_adc_regs *regs, int *val) 396 295 { 397 296 unsigned int hi, lo; 398 297 int ret; 399 298 400 - ret = ip5xxx_read(ip5xxx, lo_reg, &lo); 299 + ret = ip5xxx_read(ip5xxx, regs->low, &lo); 401 300 if (ret) 402 301 return ret; 403 302 404 - ret = ip5xxx_read(ip5xxx, hi_reg, &hi); 303 + ret = ip5xxx_read(ip5xxx, regs->high, &hi); 405 304 if (ret) 406 305 return ret; 407 306 ··· 436 335 return ip5xxx_battery_get_voltage_max(ip5xxx, &val->intval); 437 336 438 337 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 439 - ret = ip5xxx_battery_read_adc(ip5xxx, IP5XXX_BATVADC_DAT0, 440 - IP5XXX_BATVADC_DAT1, &raw); 338 + ret = ip5xxx_battery_read_adc(ip5xxx, &ip5xxx->regs.battery.adc.volt, &raw); 339 + if (ret) 340 + return ret; 441 341 442 342 val->intval = 2600000 + DIV_ROUND_CLOSEST(raw * 26855, 100); 443 343 return 0; 444 344 445 345 case POWER_SUPPLY_PROP_VOLTAGE_OCV: 446 - ret = ip5xxx_battery_read_adc(ip5xxx, IP5XXX_BATOCV_DAT0, 447 - IP5XXX_BATOCV_DAT1, &raw); 346 + ret = ip5xxx_battery_read_adc(ip5xxx, &ip5xxx->regs.battery.adc.open_volt, &raw); 347 + if (ret) 348 + return ret; 448 349 449 350 val->intval = 2600000 + DIV_ROUND_CLOSEST(raw * 26855, 100); 450 351 return 0; 451 352 452 353 case POWER_SUPPLY_PROP_CURRENT_NOW: 453 - ret = ip5xxx_battery_read_adc(ip5xxx, IP5XXX_BATIADC_DAT0, 454 - IP5XXX_BATIADC_DAT1, &raw); 354 + ret = ip5xxx_battery_read_adc(ip5xxx, &ip5xxx->regs.battery.adc.curr, &raw); 355 + if (ret) 356 + return ret; 455 357 456 358 val->intval = DIV_ROUND_CLOSEST(raw * 149197, 200); 457 359 return 0; 458 360 459 361 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 460 - ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL4A, &rval); 362 + ret = ip5xxx_read(ip5xxx, ip5xxx->regs.charger.const_curr_sel, &rval); 461 363 if (ret) 462 364 return ret; 463 365 464 - rval &= IP5XXX_CHG_CTL4A_CONST_CUR_SEL; 465 - val->intval = 100000 * rval; 366 + val->intval = ip5xxx->const_curr.setpoint + 100000 * rval; 466 367 return 0; 467 368 468 369 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: ··· 476 373 if (ret) 477 374 return ret; 478 375 479 - ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL2, &rval); 376 + ret = ip5xxx_read(ip5xxx, ip5xxx->regs.charger.const_volt_sel, &rval); 480 377 if (ret) 481 378 return ret; 482 379 483 - rval &= IP5XXX_CHG_CTL2_CONST_VOLT_SEL; 484 - val->intval = vmax + 14000 * (rval >> 1); 380 + val->intval = vmax + 14000 * rval; 485 381 return 0; 486 382 487 383 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: ··· 501 399 unsigned int rval; 502 400 int ret; 503 401 402 + if (val > ip5xxx->vbat_max) 403 + return -EINVAL; 404 + 504 405 switch (val) { 505 406 case 4200000: 506 - rval = IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V; 407 + rval = IP5XXX_BAT_TYPE_4_2V; 507 408 break; 508 409 case 4300000: 509 - rval = IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V; 410 + rval = IP5XXX_BAT_TYPE_4_3V; 510 411 break; 511 412 case 4350000: 512 - rval = IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V; 413 + rval = IP5XXX_BAT_TYPE_4_35V; 414 + break; 415 + case 4400000: 416 + rval = IP5XXX_BAT_TYPE_4_4V; 513 417 break; 514 418 default: 515 419 return -EINVAL; 516 420 } 517 421 518 - ret = ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL2, 519 - IP5XXX_CHG_CTL2_BAT_TYPE_SEL, rval); 422 + ret = ip5xxx_write(ip5xxx, ip5xxx->regs.battery.type, rval); 520 423 if (ret) 521 424 return ret; 522 425 523 - ret = ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL4, 524 - IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN, 525 - IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN); 526 - if (ret) 527 - return ret; 426 + /* Don't try to auto-detect battery type, even if the IC could */ 427 + if (ip5xxx->regs.battery.vset_en) { 428 + ret = ip5xxx_write(ip5xxx, ip5xxx->regs.battery.vset_en, 1); 429 + if (ret) 430 + return ret; 431 + } 528 432 529 433 return 0; 530 434 } ··· 551 443 case POWER_SUPPLY_PROP_STATUS: 552 444 switch (val->intval) { 553 445 case POWER_SUPPLY_STATUS_CHARGING: 554 - rval = IP5XXX_SYS_CTL0_CHARGER_EN; 446 + rval = 1; 555 447 break; 556 448 case POWER_SUPPLY_STATUS_DISCHARGING: 557 449 case POWER_SUPPLY_STATUS_NOT_CHARGING: ··· 560 452 default: 561 453 return -EINVAL; 562 454 } 563 - return ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL0, 564 - IP5XXX_SYS_CTL0_CHARGER_EN, rval); 455 + return ip5xxx_write(ip5xxx, ip5xxx->regs.charger.enable, rval); 565 456 566 457 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 567 458 return ip5xxx_battery_set_voltage_max(ip5xxx, val->intval); 568 459 569 460 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 570 - rval = val->intval / 100000; 571 - return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL4A, 572 - IP5XXX_CHG_CTL4A_CONST_CUR_SEL, rval); 461 + rval = (val->intval - ip5xxx->const_curr.setpoint) / 100000; 462 + return ip5xxx_write(ip5xxx, ip5xxx->regs.charger.const_curr_sel, rval); 573 463 574 464 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 575 465 ret = ip5xxx_battery_get_voltage_max(ip5xxx, &vmax); 576 466 if (ret) 577 467 return ret; 578 468 579 - rval = ((val->intval - vmax) / 14000) << 1; 580 - return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL2, 581 - IP5XXX_CHG_CTL2_CONST_VOLT_SEL, rval); 469 + rval = (val->intval - vmax) / 14000; 470 + return ip5xxx_write(ip5xxx, ip5xxx->regs.charger.const_volt_sel, rval); 582 471 583 472 default: 584 473 return -EINVAL; ··· 620 515 621 516 switch (psp) { 622 517 case POWER_SUPPLY_PROP_ONLINE: 623 - ret = ip5xxx_read(ip5xxx, IP5XXX_SYS_CTL0, &rval); 518 + ret = ip5xxx_read(ip5xxx, ip5xxx->regs.boost.enable, &rval); 624 519 if (ret) 625 520 return ret; 626 521 627 - val->intval = !!(rval & IP5XXX_SYS_CTL0_BOOST_EN); 522 + val->intval = !!rval; 628 523 return 0; 629 524 630 525 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 631 - ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL1, &rval); 526 + ret = ip5xxx_read(ip5xxx, ip5xxx->regs.boost.undervolt_limit, &rval); 632 527 if (ret) 633 528 return ret; 634 529 635 - rval &= IP5XXX_CHG_CTL1_BOOST_UVP_SEL; 636 - val->intval = 4530000 + 100000 * (rval >> 2); 530 + val->intval = ip5xxx->boost_undervolt.setpoint + 531 + ip5xxx->boost_undervolt.microvolts_per_bit * rval; 637 532 return 0; 638 533 639 534 default: ··· 655 550 656 551 switch (psp) { 657 552 case POWER_SUPPLY_PROP_ONLINE: 658 - rval = val->intval ? IP5XXX_SYS_CTL0_BOOST_EN : 0; 659 - return ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL0, 660 - IP5XXX_SYS_CTL0_BOOST_EN, rval); 553 + return ip5xxx_write(ip5xxx, ip5xxx->regs.boost.enable, !!val->intval); 661 554 662 555 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 663 - rval = ((val->intval - 4530000) / 100000) << 2; 664 - return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL1, 665 - IP5XXX_CHG_CTL1_BOOST_UVP_SEL, rval); 556 + rval = (val->intval - ip5xxx->boost_undervolt.setpoint) / 557 + ip5xxx->boost_undervolt.microvolts_per_bit; 558 + return ip5xxx_write(ip5xxx, ip5xxx->regs.boost.undervolt_limit, rval); 666 559 667 560 default: 668 561 return -EINVAL; ··· 686 583 static const struct regmap_config ip5xxx_regmap_config = { 687 584 .reg_bits = 8, 688 585 .val_bits = 8, 689 - .max_register = IP5XXX_BATOCV_DAT1, 586 + .max_register = 0xa9, 690 587 }; 588 + 589 + static struct ip5xxx_regfield_config ip51xx_fields = { 590 + .charger_enable = REG_FIELD(0x01, 1, 1), 591 + .charger_const_volt_sel = REG_FIELD(0x24, 1, 2), 592 + .charger_const_curr_sel = REG_FIELD(0x25, 0, 4), 593 + .charger_status = REG_FIELD(0x71, 5, 7), 594 + .charger_chg_end = REG_FIELD(0x71, 3, 3), 595 + .charger_timeout = REG_FIELD(0x71, 0, 2), 596 + .charger_vin_overvolt = REG_FIELD(0x72, 5, 5), 597 + .boost_enable = REG_FIELD(0x01, 2, 2), 598 + .boost_llshdn_enable = REG_FIELD(0x02, 1, 1), 599 + .boost_llshdn_i_limit = REG_FIELD(0x0c, 3, 7), 600 + .boost_load_powerup_en = REG_FIELD(0x02, 0, 0), 601 + .boost_vin_pullout_en = REG_FIELD(0x04, 5, 5), 602 + .boost_undervolt_limit = REG_FIELD(0x22, 2, 3), 603 + .boost_light_load_status = REG_FIELD(0x72, 6, 6), 604 + .battery_ntc_dis = REG_FIELD(0x07, 6, 6), 605 + .battery_type = REG_FIELD(0x24, 5, 6), 606 + .battery_vset_en = REG_FIELD(0x26, 6, 6), 607 + .battery_adc_volt_low = REG_FIELD(0xa2, 0, 7), 608 + .battery_adc_volt_high = REG_FIELD(0xa3, 0, 5), 609 + .battery_adc_curr_low = REG_FIELD(0xa4, 0, 7), 610 + .battery_adc_curr_high = REG_FIELD(0xa5, 0, 5), 611 + .battery_adc_ovolt_low = REG_FIELD(0xa8, 0, 7), 612 + .battery_adc_ovolt_high = REG_FIELD(0xa9, 0, 5), 613 + .btn_shdn_enable = REG_FIELD(0x03, 5, 5), 614 + .btn_wled_mode = REG_FIELD(0x07, 1, 1), 615 + .btn_shdn_mode = REG_FIELD(0x07, 0, 0), 616 + .btn_long_press_time = REG_FIELD(0x03, 6, 7), 617 + .btn_pressed = REG_FIELD(0x77, 3, 3), 618 + .btn_long_pressed = REG_FIELD(0x77, 1, 1), 619 + .btn_short_pressed = REG_FIELD(0x77, 0, 0), 620 + .wled_enable = REG_FIELD(0x01, 3, 3), 621 + .wled_detect_en = REG_FIELD(0x01, 4, 4), 622 + .wled_present = REG_FIELD(0x72, 7, 7), 623 + 624 + .vbat_max = 4350000, 625 + .boost_undervolt_setpoint = 4530000, 626 + .boost_undervolt_uv_per_bit = 100000, 627 + }; 628 + 629 + static struct ip5xxx_regfield_config ip5306_fields = { 630 + .charger_enable = REG_FIELD(0x00, 4, 4), 631 + .charger_const_volt_sel = REG_FIELD(0x22, 0, 1), 632 + .charger_const_curr_sel = REG_FIELD(0x24, 0, 4), 633 + .charger_status = REG_FIELD_UNSUPPORTED, // other bits... 634 + .charger_chg_end = REG_FIELD(0x71, 3, 3), 635 + .charger_timeout = REG_FIELD_UNSUPPORTED, 636 + .charger_vin_overvolt = REG_FIELD_UNSUPPORTED, 637 + .boost_enable = REG_FIELD(0x00, 5, 5), 638 + .boost_llshdn_enable = REG_FIELD_UNSUPPORTED, 639 + .boost_llshdn_i_limit = REG_FIELD_UNSUPPORTED, 640 + .boost_load_powerup_en = REG_FIELD(0x00, 2, 2), 641 + .boost_vin_pullout_en = REG_FIELD(0x01, 2, 2), 642 + .boost_undervolt_limit = REG_FIELD(0x21, 2, 4), 643 + .boost_light_load_status = REG_FIELD(0x72, 2, 2), 644 + .battery_ntc_dis = REG_FIELD_UNSUPPORTED, 645 + .battery_type = REG_FIELD(0x22, 2, 3), 646 + .battery_vset_en = REG_FIELD_UNSUPPORTED, 647 + .battery_adc_volt_low = REG_FIELD_UNSUPPORTED, 648 + .battery_adc_volt_high = REG_FIELD_UNSUPPORTED, 649 + .battery_adc_curr_low = REG_FIELD_UNSUPPORTED, 650 + .battery_adc_curr_high = REG_FIELD_UNSUPPORTED, 651 + .battery_adc_ovolt_low = REG_FIELD_UNSUPPORTED, 652 + .battery_adc_ovolt_high = REG_FIELD_UNSUPPORTED, 653 + .btn_shdn_enable = REG_FIELD(0x00, 0, 0), 654 + .btn_wled_mode = REG_FIELD(0x01, 6, 6), 655 + .btn_shdn_mode = REG_FIELD(0x01, 7, 7), 656 + .btn_long_press_time = REG_FIELD(0x02, 4, 4), // +1s 657 + .btn_pressed = REG_FIELD_UNSUPPORTED, 658 + /* TODO: double press */ 659 + .btn_long_pressed = REG_FIELD(0x77, 1, 1), 660 + .btn_short_pressed = REG_FIELD(0x77, 0, 0), 661 + .wled_enable = REG_FIELD_UNSUPPORTED, 662 + .wled_detect_en = REG_FIELD_UNSUPPORTED, 663 + .wled_present = REG_FIELD_UNSUPPORTED, 664 + 665 + .vbat_max = 4400000, 666 + .boost_undervolt_setpoint = 4450000, 667 + .boost_undervolt_uv_per_bit = 50000, 668 + .const_curr_setpoint = 50000, 669 + .chg_end_inverted = 1, 670 + }; 671 + 672 + #define ip5xxx_setup_reg(_field, _reg) \ 673 + do { \ 674 + if (likely(cfg->_field.lsb <= cfg->_field.msb)) { \ 675 + struct regmap_field *_tmp = devm_regmap_field_alloc(dev, \ 676 + ip5xxx->regmap, cfg->_field); \ 677 + if (!IS_ERR(_tmp)) \ 678 + ip5xxx->regs._reg = _tmp; \ 679 + } \ 680 + } while (0) 681 + 682 + static void ip5xxx_setup_regs(struct device *dev, struct ip5xxx *ip5xxx, 683 + const struct ip5xxx_regfield_config *cfg) 684 + { 685 + ip5xxx_setup_reg(charger_enable, charger.enable); 686 + ip5xxx_setup_reg(charger_const_volt_sel, charger.const_volt_sel); 687 + ip5xxx_setup_reg(charger_const_curr_sel, charger.const_curr_sel); 688 + ip5xxx_setup_reg(charger_status, charger.status); 689 + ip5xxx_setup_reg(charger_chg_end, charger.chg_end); 690 + ip5xxx_setup_reg(charger_timeout, charger.timeout); 691 + ip5xxx_setup_reg(charger_vin_overvolt, charger.vin_overvolt); 692 + ip5xxx_setup_reg(boost_enable, boost.enable); 693 + ip5xxx_setup_reg(boost_llshdn_enable, boost.light_load_shutdown.enable); 694 + ip5xxx_setup_reg(boost_llshdn_i_limit, boost.light_load_shutdown.i_limit); 695 + ip5xxx_setup_reg(boost_load_powerup_en, boost.load_powerup_en); 696 + ip5xxx_setup_reg(boost_vin_pullout_en, boost.vin_pullout_en); 697 + ip5xxx_setup_reg(boost_undervolt_limit, boost.undervolt_limit); 698 + ip5xxx_setup_reg(boost_light_load_status, boost.light_load_status); 699 + ip5xxx_setup_reg(battery_ntc_dis, battery.ntc_dis); 700 + ip5xxx_setup_reg(battery_type, battery.type); 701 + ip5xxx_setup_reg(battery_vset_en, battery.vset_en); 702 + ip5xxx_setup_reg(battery_adc_volt_low, battery.adc.volt.low); 703 + ip5xxx_setup_reg(battery_adc_volt_high, battery.adc.volt.high); 704 + ip5xxx_setup_reg(battery_adc_curr_low, battery.adc.curr.low); 705 + ip5xxx_setup_reg(battery_adc_curr_high, battery.adc.curr.high); 706 + ip5xxx_setup_reg(battery_adc_ovolt_low, battery.adc.open_volt.low); 707 + ip5xxx_setup_reg(battery_adc_ovolt_high, battery.adc.open_volt.high); 708 + ip5xxx_setup_reg(btn_shdn_enable, btn.shdn_enable); 709 + ip5xxx_setup_reg(btn_wled_mode, btn.wled_mode); 710 + ip5xxx_setup_reg(btn_shdn_mode, btn.shdn_mode); 711 + ip5xxx_setup_reg(btn_long_press_time, btn.long_press_time); 712 + ip5xxx_setup_reg(btn_pressed, btn.pressed); 713 + ip5xxx_setup_reg(btn_long_pressed, btn.long_pressed); 714 + ip5xxx_setup_reg(btn_short_pressed, btn.short_pressed); 715 + ip5xxx_setup_reg(wled_enable, wled.enable); 716 + ip5xxx_setup_reg(wled_detect_en, wled.detect_en); 717 + ip5xxx_setup_reg(wled_present, wled.present); 718 + 719 + ip5xxx->vbat_max = cfg->vbat_max; 720 + ip5xxx->boost_undervolt.setpoint = cfg->boost_undervolt_setpoint; 721 + ip5xxx->boost_undervolt.microvolts_per_bit = cfg->boost_undervolt_uv_per_bit; 722 + ip5xxx->const_curr.setpoint = cfg->const_curr_setpoint; 723 + ip5xxx->chg_end_inverted = cfg->chg_end_inverted; 724 + } 691 725 692 726 static int ip5xxx_power_probe(struct i2c_client *client) 693 727 { 728 + const struct ip5xxx_regfield_config *fields = &ip51xx_fields; 694 729 struct power_supply_config psy_cfg = {}; 695 730 struct device *dev = &client->dev; 731 + const struct of_device_id *of_id; 696 732 struct power_supply *psy; 697 733 struct ip5xxx *ip5xxx; 698 734 ··· 842 600 ip5xxx->regmap = devm_regmap_init_i2c(client, &ip5xxx_regmap_config); 843 601 if (IS_ERR(ip5xxx->regmap)) 844 602 return PTR_ERR(ip5xxx->regmap); 603 + 604 + of_id = i2c_of_match_device(dev->driver->of_match_table, client); 605 + if (of_id) 606 + fields = (const struct ip5xxx_regfield_config *)of_id->data; 607 + ip5xxx_setup_regs(dev, ip5xxx, fields); 845 608 846 609 psy_cfg.of_node = dev->of_node; 847 610 psy_cfg.drv_data = ip5xxx; ··· 863 616 } 864 617 865 618 static const struct of_device_id ip5xxx_power_of_match[] = { 866 - { .compatible = "injoinic,ip5108" }, 867 - { .compatible = "injoinic,ip5109" }, 868 - { .compatible = "injoinic,ip5207" }, 869 - { .compatible = "injoinic,ip5209" }, 619 + { .compatible = "injoinic,ip5108", .data = &ip51xx_fields }, 620 + { .compatible = "injoinic,ip5109", .data = &ip51xx_fields }, 621 + { .compatible = "injoinic,ip5207", .data = &ip51xx_fields }, 622 + { .compatible = "injoinic,ip5209", .data = &ip51xx_fields }, 623 + { .compatible = "injoinic,ip5306", .data = &ip5306_fields }, 870 624 { } 871 625 }; 872 626 MODULE_DEVICE_TABLE(of, ip5xxx_power_of_match);
+385 -53
drivers/power/supply/ltc4162-l-charger.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 /* 3 - * Driver for Analog Devices (Linear Technology) LTC4162-L charger IC. 3 + * Driver for Analog Devices (Linear Technology) 4 + * LTC4162-L 35V/3.2A Multi-Cell Lithium-Ion Step-Down Battery Charger 5 + * LTC4162-F 35V/3.2A Multi-Cell LiFePO4 Step-Down Battery Charger 6 + * LTC4162-S 35V/3.2A Lead-Acid Step-Down Battery Charger 7 + * LTC4015 35V/3.2A Multichemistry Buck Battery Charger Controller 4 8 * Copyright (C) 2020, Topic Embedded Products 5 9 */ 6 10 11 + #include <linux/bitfield.h> 7 12 #include <linux/module.h> 8 13 #include <linux/delay.h> 9 14 #include <linux/of.h> ··· 52 47 #define LTC4162L_VBAT_FILT 0x47 53 48 #define LTC4162L_INPUT_UNDERVOLTAGE_DAC 0x4B 54 49 50 + #define LTC4162L_CHEM_MASK GENMASK(11, 8) 51 + 52 + enum ltc4162_chem { 53 + ltc4162_lad, 54 + ltc4162_l42, 55 + ltc4162_l41, 56 + ltc4162_l40, 57 + ltc4162_fad, 58 + ltc4162_ffs, 59 + ltc4162_fst, 60 + ltc4162_sst = 8, 61 + ltc4162_sad, 62 + }; 63 + 55 64 /* Enumeration as in datasheet. Individual bits are mutually exclusive. */ 56 65 enum ltc4162l_state { 57 66 battery_detection = 2048, ··· 94 75 /* Magic number to write to ARM_SHIP_MODE register */ 95 76 #define LTC4162L_ARM_SHIP_MODE_MAGIC 21325 96 77 78 + struct ltc4162l_info; 79 + 80 + struct ltc4162l_chip_info { 81 + const char *name; 82 + int (*get_vbat)(struct ltc4162l_info *info, unsigned int reg, 83 + union power_supply_propval *val); 84 + int (*get_vcharge)(struct ltc4162l_info *info, unsigned int reg, 85 + union power_supply_propval *val); 86 + int (*set_vcharge)(struct ltc4162l_info *info, unsigned int reg, 87 + unsigned int value); 88 + int (*get_die_temp)(struct ltc4162l_info *info, 89 + union power_supply_propval *val); 90 + unsigned int ibat_resolution_pv; 91 + unsigned int vin_resolution_uv; 92 + u8 telemetry_mask; 93 + }; 94 + 97 95 struct ltc4162l_info { 98 96 struct i2c_client *client; 99 97 struct regmap *regmap; 100 98 struct power_supply *charger; 99 + const struct ltc4162l_chip_info *chip_info; 101 100 u32 rsnsb; /* Series resistor that sets charge current, microOhm */ 102 101 u32 rsnsi; /* Series resistor to measure input current, microOhm */ 103 102 u8 cell_count; /* Number of connected cells, 0 while unknown */ ··· 143 106 info->cell_count = val; 144 107 145 108 return val; 109 + }; 110 + 111 + static u8 ltc4162l_get_chem_type(struct ltc4162l_info *info) 112 + { 113 + int ret; 114 + unsigned int val; 115 + 116 + ret = regmap_read(info->regmap, LTC4162L_CHEM_CELLS_REG, &val); 117 + if (ret) 118 + return ret; 119 + 120 + return FIELD_GET(LTC4162L_CHEM_MASK, val); 146 121 }; 147 122 148 123 /* Convert enum value to POWER_SUPPLY_STATUS value */ ··· 272 223 unsigned int reg, 273 224 union power_supply_propval *val) 274 225 { 275 - unsigned int regval; 226 + unsigned int regval, chem_type; 276 227 int ret; 277 228 278 229 ret = regmap_read(info->regmap, reg, &regval); 279 230 if (ret) 280 231 return ret; 281 232 282 - /* cell_count × 192.4μV/LSB */ 283 - regval *= 1924; 284 - regval *= ltc4162l_get_cell_count(info); 285 - regval /= 10; 286 - val->intval = regval; 233 + /* 234 + * cell_count × scaling factor 235 + * For ltc4162-s, it uses a cell_count value of 2 for each group of 3 236 + * physical (2V) cells, thus will return 2, 4, 6, 8 for 6V, 12V, 18V, 237 + * and 24V respectively, and has to divide by 2 to multiply the scale 238 + * factor by 1, 2, 3, or 4 to represent a 6V, 12V, 18V, or 24V battery 239 + * respectively. 240 + */ 241 + chem_type = ltc4162l_get_chem_type(info); 242 + switch (chem_type) { 243 + case ltc4162_lad ... ltc4162_fst: 244 + regval *= 1924; 245 + regval *= ltc4162l_get_cell_count(info); 246 + regval /= 10; 247 + val->intval = regval; 287 248 288 - return 0; 249 + return 0; 250 + case ltc4162_sst ... ltc4162_sad: 251 + regval *= 3848; 252 + regval *= ltc4162l_get_cell_count(info) / 2; 253 + regval /= 10; 254 + val->intval = regval; 255 + 256 + return 0; 257 + default: 258 + return -EINVAL; 259 + } 260 + } 261 + 262 + static int ltc4015_get_vbat(struct ltc4162l_info *info, 263 + unsigned int reg, 264 + union power_supply_propval *val) 265 + { 266 + unsigned int regval, chem_type; 267 + int ret; 268 + 269 + ret = regmap_read(info->regmap, reg, &regval); 270 + if (ret) 271 + return ret; 272 + 273 + /* 274 + * cell count x scaling factor 275 + * ltc4015 lead-acid fixed and lead-acid programmable corresponds to 276 + * 0x7 and 0x8 chem respectively 277 + */ 278 + chem_type = ltc4162l_get_chem_type(info); 279 + switch (chem_type) { 280 + case ltc4162_lad ... ltc4162_fst: 281 + regval *= 192264; 282 + regval *= ltc4162l_get_cell_count(info); 283 + regval /= 1000; 284 + val->intval = regval; 285 + 286 + return 0; 287 + case ltc4162_sst - 1 ... ltc4162_sad - 1: 288 + regval *= 128176; 289 + regval *= ltc4162l_get_cell_count(info); 290 + regval /= 1000; 291 + val->intval = regval; 292 + 293 + return 0; 294 + default: 295 + return -EINVAL; 296 + } 289 297 } 290 298 291 299 static int ltc4162l_get_ibat(struct ltc4162l_info *info, 292 300 union power_supply_propval *val) 293 301 { 302 + const struct ltc4162l_chip_info *chip_info = info->chip_info; 294 303 unsigned int regval; 295 304 int ret; 296 305 ··· 356 249 if (ret) 357 250 return ret; 358 251 359 - /* Signed 16-bit number, 1.466μV / RSNSB amperes/LSB. */ 360 252 ret = (s16)(regval & 0xFFFF); 361 - val->intval = 100 * mult_frac(ret, 14660, (int)info->rsnsb); 253 + val->intval = mult_frac(ret, chip_info->ibat_resolution_pv, info->rsnsb); 362 254 363 255 return 0; 364 256 } ··· 366 260 static int ltc4162l_get_input_voltage(struct ltc4162l_info *info, 367 261 union power_supply_propval *val) 368 262 { 263 + const struct ltc4162l_chip_info *chip_info = info->chip_info; 369 264 unsigned int regval; 370 265 int ret; 371 266 ··· 374 267 if (ret) 375 268 return ret; 376 269 377 - /* 1.649mV/LSB */ 378 - val->intval = regval * 1694; 270 + val->intval = regval * chip_info->vin_resolution_uv; 379 271 380 272 return 0; 381 273 } ··· 382 276 static int ltc4162l_get_input_current(struct ltc4162l_info *info, 383 277 union power_supply_propval *val) 384 278 { 279 + const struct ltc4162l_chip_info *chip_info = info->chip_info; 385 280 unsigned int regval; 386 281 int ret; 387 282 ··· 390 283 if (ret) 391 284 return ret; 392 285 393 - /* Signed 16-bit number, 1.466μV / RSNSI amperes/LSB. */ 394 286 ret = (s16)(regval & 0xFFFF); 395 - ret *= 14660; 287 + ret *= chip_info->ibat_resolution_pv; 396 288 ret /= info->rsnsi; 397 - ret *= 100; 398 289 399 290 val->intval = ret; 400 291 ··· 410 305 if (ret) 411 306 return ret; 412 307 413 - regval &= BIT(6) - 1; /* Only the lower 5 bits */ 308 + regval &= GENMASK(5, 0); 414 309 415 310 /* The charge current servo level: (icharge_dac + 1) × 1mV/RSNSB */ 416 311 ++regval; ··· 441 336 unsigned int reg, 442 337 union power_supply_propval *val) 443 338 { 444 - unsigned int regval; 339 + unsigned int regval, chem_type; 445 340 int ret; 446 341 u32 voltage; 447 342 ··· 449 344 if (ret) 450 345 return ret; 451 346 452 - regval &= BIT(6) - 1; /* Only the lower 5 bits */ 347 + regval &= GENMASK(5, 0); 453 348 454 349 /* 455 350 * charge voltage setting can be computed from 456 - * cell_count × (vcharge_setting × 12.5mV + 3.8125V) 457 - * where vcharge_setting ranges from 0 to 31 (4.2V max). 351 + * cell_count × (vcharge_setting × a + b) 352 + * where vcharge_setting ranges from 0 to c (d). 353 + * for ltc4162l: a = 12.5mV , b = 3.8125V, c = 31, d = 4.2Vmax 354 + * for ltc4162f: a = 12.5mV , b = 3.4125V, c = 31, d = 3.8Vmax 355 + * 356 + * for ltc4162s, the charge voltage setting can be computed from 357 + * N x (vcharge_setting x 28.571mV + 6.0V) 358 + * where N is 1, 2, 3, or 4 for 6V, 12V, 18V, or 24V battery respectively, 359 + * and vcharge_setting ranges from 0 to 31 458 360 */ 459 - voltage = 3812500 + (regval * 12500); 460 - voltage *= ltc4162l_get_cell_count(info); 461 - val->intval = voltage; 361 + chem_type = ltc4162l_get_chem_type(info); 362 + switch (chem_type) { 363 + case ltc4162_lad ... ltc4162_l40: 364 + voltage = 3812500 + (regval * 12500); 365 + voltage *= ltc4162l_get_cell_count(info); 366 + val->intval = voltage; 462 367 463 - return 0; 368 + return 0; 369 + case ltc4162_fad ... ltc4162_fst: 370 + voltage = 3412500 + (regval * 12500); 371 + voltage *= ltc4162l_get_cell_count(info); 372 + val->intval = voltage; 373 + 374 + return 0; 375 + case ltc4162_sst ... ltc4162_sad: 376 + voltage = 6000000 + (regval * 28571); 377 + voltage *= ltc4162l_get_cell_count(info) / 2; 378 + val->intval = voltage; 379 + 380 + return 0; 381 + default: 382 + return -EINVAL; 383 + } 384 + } 385 + 386 + static int ltc4015_get_vcharge(struct ltc4162l_info *info, 387 + unsigned int reg, 388 + union power_supply_propval *val) 389 + { 390 + unsigned int regval, chem_type; 391 + int ret; 392 + u32 voltage; 393 + 394 + ret = regmap_read(info->regmap, reg, &regval); 395 + if (ret) 396 + return ret; 397 + 398 + regval &= GENMASK(5, 0); 399 + 400 + /* 401 + * charge voltage setting can be computed from: 402 + * cell_count × (vcharge_setting × a + b) 403 + * where vcharge_setting ranges from 0 to c (d). 404 + * Li-Ion: a = 1/80V, b = 3.8125V, c = 31, d = 4.2Vmax 405 + * LiFePO4: a = 1/80V, b = 3.4125V, c = 31, d = 3.8Vmax 406 + * Lead Acid: a = 1/105V, b = 2V, c = 35, d = 2.6Vmax 407 + */ 408 + chem_type = ltc4162l_get_chem_type(info); 409 + switch (chem_type) { 410 + case ltc4162_lad ... ltc4162_l40: 411 + voltage = 3812500 + (regval * 12500); 412 + voltage *= ltc4162l_get_cell_count(info); 413 + val->intval = voltage; 414 + 415 + return 0; 416 + case ltc4162_fad ... ltc4162_fst: 417 + voltage = 3412500 + (regval * 12500); 418 + voltage *= ltc4162l_get_cell_count(info); 419 + val->intval = voltage; 420 + 421 + return 0; 422 + case ltc4162_sst - 1 ... ltc4162_sad - 1: 423 + voltage = 2000000 + mult_frac(regval, 1000000, 105); 424 + voltage *= ltc4162l_get_cell_count(info); 425 + val->intval = voltage; 426 + 427 + return 0; 428 + default: 429 + return -EINVAL; 430 + } 431 + } 432 + 433 + static int ltc4162l_vcharge(unsigned int base_voltage, 434 + unsigned int scale_factor, 435 + unsigned int range, 436 + unsigned int value, 437 + u8 cell_count) 438 + { 439 + value /= cell_count; 440 + 441 + if (value < base_voltage) 442 + return -EINVAL; 443 + 444 + value -= base_voltage; 445 + value /= scale_factor; 446 + 447 + if (value > range) 448 + return -EINVAL; 449 + 450 + return value; 464 451 } 465 452 466 453 static int ltc4162l_set_vcharge(struct ltc4162l_info *info, 467 454 unsigned int reg, 468 455 unsigned int value) 469 456 { 470 - u8 cell_count = ltc4162l_get_cell_count(info); 457 + unsigned int chem_type; 458 + u8 cell_count; 471 459 472 - if (!cell_count) 473 - return -EBUSY; /* Not available yet, try again later */ 460 + chem_type = ltc4162l_get_chem_type(info); 461 + switch (chem_type) { 462 + case ltc4162_lad ... ltc4162_l40: 463 + cell_count = ltc4162l_get_cell_count(info); 464 + if (!cell_count) 465 + return -EBUSY; 474 466 475 - value /= cell_count; 467 + value = ltc4162l_vcharge(3812500, 12500, 31, value, cell_count); 468 + return regmap_write(info->regmap, reg, value); 469 + case ltc4162_fad ... ltc4162_fst: 470 + cell_count = ltc4162l_get_cell_count(info); 471 + if (!cell_count) 472 + return -EBUSY; 476 473 477 - if (value < 3812500) 474 + value = ltc4162l_vcharge(3412500, 12500, 31, value, cell_count); 475 + return regmap_write(info->regmap, reg, value); 476 + case ltc4162_sst ... ltc4162_sad: 477 + cell_count = ltc4162l_get_cell_count(info) / 2; 478 + if (!cell_count) 479 + return -EBUSY; 480 + 481 + value = ltc4162l_vcharge(6000000, 28571, 31, value, cell_count); 482 + return regmap_write(info->regmap, reg, value); 483 + default: 478 484 return -EINVAL; 485 + } 486 + } 479 487 480 - value -= 3812500; 481 - value /= 12500; 488 + static int ltc4015_set_vcharge(struct ltc4162l_info *info, 489 + unsigned int reg, 490 + unsigned int value) 491 + { 492 + unsigned int chem_type; 493 + u8 cell_count; 482 494 483 - if (value > 31) 495 + chem_type = ltc4162l_get_chem_type(info); 496 + switch (chem_type) { 497 + case ltc4162_lad ... ltc4162_l40: 498 + cell_count = ltc4162l_get_cell_count(info); 499 + if (!cell_count) 500 + return -EBUSY; 501 + 502 + value = ltc4162l_vcharge(3812500, 12500, 31, value, cell_count); 503 + return regmap_write(info->regmap, reg, value); 504 + case ltc4162_fad ... ltc4162_fst: 505 + cell_count = ltc4162l_get_cell_count(info); 506 + if (!cell_count) 507 + return -EBUSY; 508 + 509 + value = ltc4162l_vcharge(3412500, 12500, 31, value, cell_count); 510 + return regmap_write(info->regmap, reg, value); 511 + case ltc4162_sst - 1 ... ltc4162_sad - 1: 512 + cell_count = ltc4162l_get_cell_count(info); 513 + if (!cell_count) 514 + return -EBUSY; 515 + 516 + value = ltc4162l_vcharge(2000000, 1000000 / 105, 35, 517 + value, cell_count); 518 + return regmap_write(info->regmap, reg, value); 519 + default: 484 520 return -EINVAL; 485 - 486 - return regmap_write(info->regmap, reg, value); 521 + } 487 522 } 488 523 489 524 static int ltc4162l_get_iin_limit_dac(struct ltc4162l_info *info, ··· 636 391 if (ret) 637 392 return ret; 638 393 639 - regval &= BIT(6) - 1; /* Only 6 bits */ 394 + regval &= GENMASK(5, 0); 640 395 641 396 /* (iin_limit_dac + 1) × 500μV / RSNSI */ 642 397 ++regval; ··· 682 437 return 0; 683 438 } 684 439 440 + static int ltc4015_get_die_temp(struct ltc4162l_info *info, 441 + union power_supply_propval *val) 442 + { 443 + unsigned int regval; 444 + int ret; 445 + 446 + ret = regmap_read(info->regmap, LTC4162L_DIE_TEMPERATURE, &regval); 447 + if (ret) 448 + return ret; 449 + 450 + /* (die_temp - 12010) / 45.6°C */ 451 + ret = (s16)(regval & 0xFFFF); 452 + ret -= 12010; 453 + ret *= 1000; 454 + ret /= 456; 455 + val->intval = ret; 456 + 457 + return 0; 458 + } 459 + 685 460 static int ltc4162l_get_term_current(struct ltc4162l_info *info, 686 461 union power_supply_propval *val) 687 462 { 463 + const struct ltc4162l_chip_info *chip_info = info->chip_info; 688 464 unsigned int regval; 689 465 int ret; 690 466 ··· 723 457 if (ret) 724 458 return ret; 725 459 726 - /* 1.466μV / RSNSB amperes/LSB */ 727 - regval *= 14660u; 460 + regval *= chip_info->ibat_resolution_pv; 728 461 regval /= info->rsnsb; 729 - val->intval = 100 * regval; 462 + val->intval = regval; 730 463 731 464 return 0; 732 465 } ··· 799 534 { 800 535 struct power_supply *psy = to_power_supply(dev); 801 536 struct ltc4162l_info *info = power_supply_get_drvdata(psy); 537 + const struct ltc4162l_chip_info *chip_info = info->chip_info; 802 538 union power_supply_propval val; 803 539 int ret; 804 540 805 - ret = ltc4162l_get_vbat(info, LTC4162L_VBAT, &val); 541 + ret = chip_info->get_vbat(info, LTC4162L_VBAT, &val); 806 542 if (ret) 807 543 return ret; 808 544 ··· 816 550 { 817 551 struct power_supply *psy = to_power_supply(dev); 818 552 struct ltc4162l_info *info = power_supply_get_drvdata(psy); 553 + const struct ltc4162l_chip_info *chip_info = info->chip_info; 819 554 union power_supply_propval val; 820 555 int ret; 821 556 822 - ret = ltc4162l_get_vbat(info, LTC4162L_VBAT_FILT, &val); 557 + ret = chip_info->get_vbat(info, LTC4162L_VBAT_FILT, &val); 823 558 if (ret) 824 559 return ret; 825 560 ··· 856 589 if (ret) 857 590 return ret; 858 591 859 - return sysfs_emit(buf, "%u\n", regval & BIT(2) ? 1 : 0); 592 + return sysfs_emit(buf, "%u\n", regval & 593 + info->chip_info->telemetry_mask ? 1 : 0); 860 594 } 861 595 862 596 static ssize_t force_telemetry_store(struct device *dev, ··· 875 607 return ret; 876 608 877 609 ret = regmap_update_bits(info->regmap, LTC4162L_CONFIG_BITS_REG, 878 - BIT(2), value ? BIT(2) : 0); 610 + info->chip_info->telemetry_mask, 611 + value ? info->chip_info->telemetry_mask : 0); 879 612 if (ret < 0) 880 613 return ret; 881 614 ··· 950 681 union power_supply_propval *val) 951 682 { 952 683 struct ltc4162l_info *info = power_supply_get_drvdata(psy); 684 + const struct ltc4162l_chip_info *chip_info = info->chip_info; 953 685 954 686 switch (psp) { 955 687 case POWER_SUPPLY_PROP_STATUS: ··· 972 702 return ltc4162l_get_icharge(info, 973 703 LTC4162L_CHARGE_CURRENT_SETTING, val); 974 704 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 975 - return ltc4162l_get_vcharge(info, 976 - LTC4162L_VCHARGE_DAC, val); 705 + return chip_info->get_vcharge(info, LTC4162L_VCHARGE_DAC, val); 977 706 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 978 - return ltc4162l_get_vcharge(info, 979 - LTC4162L_VCHARGE_SETTING, val); 707 + return chip_info->get_vcharge(info, LTC4162L_VCHARGE_SETTING, val); 980 708 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 981 709 return ltc4162l_get_iin_limit_dac(info, val); 982 710 case POWER_SUPPLY_PROP_TEMP: 983 - return ltc4162l_get_die_temp(info, val); 711 + return chip_info->get_die_temp(info, val); 984 712 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 985 713 return ltc4162l_get_term_current(info, val); 986 714 default: ··· 1040 772 }; 1041 773 1042 774 static const struct power_supply_desc ltc4162l_desc = { 1043 - .name = "ltc4162-l", 1044 775 .type = POWER_SUPPLY_TYPE_MAINS, 1045 776 .properties = ltc4162l_properties, 1046 777 .num_properties = ARRAY_SIZE(ltc4162l_properties), 1047 778 .get_property = ltc4162l_get_property, 1048 779 .set_property = ltc4162l_set_property, 1049 780 .property_is_writeable = ltc4162l_property_is_writeable, 781 + }; 782 + 783 + static const struct ltc4162l_chip_info ltc4162l_chip_info = { 784 + .name = "ltc4162-l", 785 + .get_vbat = ltc4162l_get_vbat, 786 + .get_vcharge = ltc4162l_get_vcharge, 787 + .set_vcharge = ltc4162l_set_vcharge, 788 + .get_die_temp = ltc4162l_get_die_temp, 789 + .ibat_resolution_pv = 1466000, 790 + .vin_resolution_uv = 1649, 791 + .telemetry_mask = BIT(2), 792 + }; 793 + 794 + static const struct ltc4162l_chip_info ltc4162f_chip_info = { 795 + .name = "ltc4162-f", 796 + .get_vbat = ltc4162l_get_vbat, 797 + .get_vcharge = ltc4162l_get_vcharge, 798 + .set_vcharge = ltc4162l_set_vcharge, 799 + .get_die_temp = ltc4162l_get_die_temp, 800 + .ibat_resolution_pv = 1466000, 801 + .vin_resolution_uv = 1649, 802 + .telemetry_mask = BIT(2), 803 + }; 804 + 805 + static const struct ltc4162l_chip_info ltc4162s_chip_info = { 806 + .name = "ltc4162-s", 807 + .get_vbat = ltc4162l_get_vbat, 808 + .get_vcharge = ltc4162l_get_vcharge, 809 + .set_vcharge = ltc4162l_set_vcharge, 810 + .get_die_temp = ltc4162l_get_die_temp, 811 + .ibat_resolution_pv = 1466000, 812 + .vin_resolution_uv = 1649, 813 + .telemetry_mask = BIT(2), 814 + }; 815 + 816 + static const struct ltc4162l_chip_info ltc4015_chip_info = { 817 + .name = "ltc4015", 818 + .get_vbat = ltc4015_get_vbat, 819 + .get_vcharge = ltc4015_get_vcharge, 820 + .set_vcharge = ltc4015_set_vcharge, 821 + .get_die_temp = ltc4015_get_die_temp, 822 + .ibat_resolution_pv = 1464870, 823 + .vin_resolution_uv = 1648, 824 + .telemetry_mask = BIT(4), 1050 825 }; 1051 826 1052 827 static bool ltc4162l_is_writeable_reg(struct device *dev, unsigned int reg) ··· 1136 825 struct device *dev = &client->dev; 1137 826 struct ltc4162l_info *info; 1138 827 struct power_supply_config ltc4162l_config = {}; 828 + struct power_supply_desc *desc; 829 + const struct ltc4162l_chip_info *chip_info; 1139 830 u32 value; 1140 831 int ret; 1141 832 ··· 1151 838 1152 839 info->client = client; 1153 840 i2c_set_clientdata(client, info); 841 + 842 + chip_info = i2c_get_match_data(client); 843 + if (!chip_info) 844 + return -ENODEV; 845 + 846 + info->chip_info = chip_info; 1154 847 1155 848 info->regmap = devm_regmap_init_i2c(client, &ltc4162l_regmap_config); 1156 849 if (IS_ERR(info->regmap)) { ··· 1189 870 ltc4162l_config.drv_data = info; 1190 871 ltc4162l_config.attr_grp = ltc4162l_attr_groups; 1191 872 1192 - info->charger = devm_power_supply_register(dev, &ltc4162l_desc, 1193 - &ltc4162l_config); 873 + /* Duplicate the default descriptor to set name based on chip_info. */ 874 + desc = devm_kmemdup(dev, &ltc4162l_desc, 875 + sizeof(struct power_supply_desc), GFP_KERNEL); 876 + if (!desc) 877 + return -ENOMEM; 878 + 879 + desc->name = chip_info->name; 880 + 881 + info->charger = devm_power_supply_register(dev, desc, &ltc4162l_config); 1194 882 if (IS_ERR(info->charger)) { 1195 883 dev_err(dev, "Failed to register charger\n"); 1196 884 return PTR_ERR(info->charger); ··· 1229 903 } 1230 904 1231 905 static const struct i2c_device_id ltc4162l_i2c_id_table[] = { 1232 - { "ltc4162-l" }, 906 + { "ltc4015", (kernel_ulong_t)&ltc4015_chip_info }, 907 + { "ltc4162-f", (kernel_ulong_t)&ltc4162f_chip_info }, 908 + { "ltc4162-l", (kernel_ulong_t)&ltc4162l_chip_info }, 909 + { "ltc4162-s", (kernel_ulong_t)&ltc4162s_chip_info }, 1233 910 { } 1234 911 }; 1235 912 MODULE_DEVICE_TABLE(i2c, ltc4162l_i2c_id_table); 1236 913 1237 914 static const struct of_device_id ltc4162l_of_match[] __maybe_unused = { 1238 - { .compatible = "lltc,ltc4162-l", }, 1239 - { }, 915 + { .compatible = "lltc,ltc4015", .data = &ltc4015_chip_info }, 916 + { .compatible = "lltc,ltc4162-f", .data = &ltc4162f_chip_info }, 917 + { .compatible = "lltc,ltc4162-l", .data = &ltc4162l_chip_info }, 918 + { .compatible = "lltc,ltc4162-s", .data = &ltc4162s_chip_info }, 919 + { } 1240 920 }; 1241 921 MODULE_DEVICE_TABLE(of, ltc4162l_of_match); 1242 922
+145 -58
drivers/power/supply/max17042_battery.c
··· 16 16 #include <linux/i2c.h> 17 17 #include <linux/delay.h> 18 18 #include <linux/interrupt.h> 19 + #include <linux/platform_device.h> 19 20 #include <linux/pm.h> 20 21 #include <linux/mod_devicetable.h> 21 22 #include <linux/power_supply.h> ··· 53 52 #define MAX17042_VMAX_TOLERANCE 50 /* 50 mV */ 54 53 55 54 struct max17042_chip { 56 - struct i2c_client *client; 55 + struct device *dev; 57 56 struct regmap *regmap; 58 57 struct power_supply *battery; 59 58 enum max170xx_chip_type chip_type; 60 59 struct max17042_platform_data *pdata; 61 60 struct work_struct work; 62 61 int init_complete; 62 + int irq; 63 63 }; 64 64 65 65 static enum power_supply_property max17042_battery_props[] = { ··· 575 573 int i; 576 574 577 575 if (memcmp(data1, data2, size)) { 578 - dev_err(&chip->client->dev, "%s compare failed\n", __func__); 576 + dev_err(chip->dev, "%s compare failed\n", __func__); 579 577 for (i = 0; i < size; i++) 580 - dev_info(&chip->client->dev, "0x%x, 0x%x", 578 + dev_info(chip->dev, "0x%x, 0x%x", 581 579 data1[i], data2[i]); 582 - dev_info(&chip->client->dev, "\n"); 580 + dev_info(chip->dev, "\n"); 583 581 return -EINVAL; 584 582 } 585 583 return 0; ··· 814 812 /* write cell characterization data */ 815 813 ret = max17042_init_model(chip); 816 814 if (ret) { 817 - dev_err(&chip->client->dev, "%s init failed\n", 815 + dev_err(chip->dev, "%s init failed\n", 818 816 __func__); 819 817 return -EIO; 820 818 } 821 819 822 820 ret = max17042_verify_model_lock(chip); 823 821 if (ret) { 824 - dev_err(&chip->client->dev, "%s lock verify failed\n", 822 + dev_err(chip->dev, "%s lock verify failed\n", 825 823 __func__); 826 824 return -EIO; 827 825 } ··· 877 875 return IRQ_HANDLED; 878 876 879 877 if ((val & STATUS_SMN_BIT) || (val & STATUS_SMX_BIT)) { 880 - dev_dbg(&chip->client->dev, "SOC threshold INTR\n"); 878 + dev_dbg(chip->dev, "SOC threshold INTR\n"); 881 879 max17042_set_soc_threshold(chip, 1); 882 880 } 883 881 ··· 909 907 static struct max17042_platform_data * 910 908 max17042_get_of_pdata(struct max17042_chip *chip) 911 909 { 912 - struct device *dev = &chip->client->dev; 910 + struct device *dev = chip->dev; 913 911 struct device_node *np = dev->of_node; 914 912 u32 prop; 915 913 struct max17042_platform_data *pdata; ··· 951 949 static struct max17042_platform_data * 952 950 max17042_get_default_pdata(struct max17042_chip *chip) 953 951 { 954 - struct device *dev = &chip->client->dev; 952 + struct device *dev = chip->dev; 955 953 struct max17042_platform_data *pdata; 956 954 int ret, misc_cfg; 957 955 ··· 992 990 static struct max17042_platform_data * 993 991 max17042_get_pdata(struct max17042_chip *chip) 994 992 { 995 - struct device *dev = &chip->client->dev; 993 + struct device *dev = chip->dev; 996 994 997 995 #ifdef CONFIG_OF 998 996 if (dev->of_node) ··· 1005 1003 } 1006 1004 1007 1005 static const struct regmap_config max17042_regmap_config = { 1006 + .name = "max17042", 1008 1007 .reg_bits = 8, 1009 1008 .val_bits = 16, 1010 1009 .val_format_endian = REGMAP_ENDIAN_NATIVE, ··· 1032 1029 .num_properties = ARRAY_SIZE(max17042_battery_props) - 2, 1033 1030 }; 1034 1031 1035 - static int max17042_probe(struct i2c_client *client) 1032 + static int max17042_probe(struct i2c_client *client, struct device *dev, int irq, 1033 + enum max170xx_chip_type chip_type) 1036 1034 { 1037 - const struct i2c_device_id *id = i2c_client_get_device_id(client); 1038 1035 struct i2c_adapter *adapter = client->adapter; 1039 1036 const struct power_supply_desc *max17042_desc = &max17042_psy_desc; 1040 1037 struct power_supply_config psy_cfg = {}; 1041 - const struct acpi_device_id *acpi_id = NULL; 1042 - struct device *dev = &client->dev; 1043 1038 struct max17042_chip *chip; 1044 1039 int ret; 1045 1040 int i; ··· 1046 1045 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) 1047 1046 return -EIO; 1048 1047 1049 - chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 1048 + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); 1050 1049 if (!chip) 1051 1050 return -ENOMEM; 1052 1051 1053 - chip->client = client; 1054 - if (id) { 1055 - chip->chip_type = id->driver_data; 1056 - } else { 1057 - acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); 1058 - if (!acpi_id) 1059 - return -ENODEV; 1060 - 1061 - chip->chip_type = acpi_id->driver_data; 1062 - } 1052 + chip->dev = dev; 1053 + chip->chip_type = chip_type; 1063 1054 chip->regmap = devm_regmap_init_i2c(client, &max17042_regmap_config); 1064 1055 if (IS_ERR(chip->regmap)) { 1065 - dev_err(&client->dev, "Failed to initialize regmap\n"); 1056 + dev_err(dev, "Failed to initialize regmap\n"); 1066 1057 return -EINVAL; 1067 1058 } 1068 1059 1069 1060 chip->pdata = max17042_get_pdata(chip); 1070 1061 if (!chip->pdata) { 1071 - dev_err(&client->dev, "no platform data provided\n"); 1062 + dev_err(dev, "no platform data provided\n"); 1072 1063 return -EINVAL; 1073 1064 } 1074 1065 1075 - i2c_set_clientdata(client, chip); 1066 + dev_set_drvdata(dev, chip); 1076 1067 psy_cfg.drv_data = chip; 1077 1068 psy_cfg.of_node = dev->of_node; 1078 1069 ··· 1088 1095 regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007); 1089 1096 } 1090 1097 1091 - chip->battery = devm_power_supply_register(&client->dev, max17042_desc, 1098 + chip->battery = devm_power_supply_register(dev, max17042_desc, 1092 1099 &psy_cfg); 1093 1100 if (IS_ERR(chip->battery)) { 1094 - dev_err(&client->dev, "failed: power supply register\n"); 1101 + dev_err(dev, "failed: power supply register\n"); 1095 1102 return PTR_ERR(chip->battery); 1096 1103 } 1097 1104 1098 - if (client->irq) { 1099 - unsigned int flags = IRQF_ONESHOT; 1105 + if (irq) { 1106 + unsigned int flags = IRQF_ONESHOT | IRQF_SHARED | IRQF_PROBE_SHARED; 1100 1107 1101 - /* 1102 - * On ACPI systems the IRQ may be handled by ACPI-event code, 1103 - * so we need to share (if the ACPI code is willing to share). 1104 - */ 1105 - if (acpi_id) 1106 - flags |= IRQF_SHARED | IRQF_PROBE_SHARED; 1107 - 1108 - ret = devm_request_threaded_irq(&client->dev, client->irq, 1108 + ret = devm_request_threaded_irq(dev, irq, 1109 1109 NULL, 1110 1110 max17042_thread_handler, flags, 1111 1111 chip->battery->desc->name, ··· 1109 1123 CFG_ALRT_BIT_ENBL); 1110 1124 max17042_set_soc_threshold(chip, 1); 1111 1125 } else { 1112 - client->irq = 0; 1126 + irq = 0; 1113 1127 if (ret != -EBUSY) 1114 - dev_err(&client->dev, "Failed to get IRQ\n"); 1128 + dev_err(dev, "Failed to get IRQ\n"); 1115 1129 } 1116 1130 } 1117 1131 /* Not able to update the charge threshold when exceeded? -> disable */ 1118 - if (!client->irq) 1132 + if (!irq) 1119 1133 regmap_write(chip->regmap, MAX17042_SALRT_Th, 0xff00); 1134 + 1135 + chip->irq = irq; 1120 1136 1121 1137 regmap_read(chip->regmap, MAX17042_STATUS, &val); 1122 1138 if (val & STATUS_POR_BIT) { 1123 - ret = devm_work_autocancel(&client->dev, &chip->work, 1139 + ret = devm_work_autocancel(dev, &chip->work, 1124 1140 max17042_init_worker); 1125 1141 if (ret) 1126 1142 return ret; ··· 1134 1146 return 0; 1135 1147 } 1136 1148 1149 + static int max17042_i2c_probe(struct i2c_client *client) 1150 + { 1151 + const struct i2c_device_id *id = i2c_client_get_device_id(client); 1152 + const struct acpi_device_id *acpi_id = NULL; 1153 + struct device *dev = &client->dev; 1154 + enum max170xx_chip_type chip_type; 1155 + 1156 + if (id) { 1157 + chip_type = id->driver_data; 1158 + } else { 1159 + acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); 1160 + if (!acpi_id) 1161 + return -ENODEV; 1162 + 1163 + chip_type = acpi_id->driver_data; 1164 + } 1165 + 1166 + return max17042_probe(client, dev, client->irq, chip_type); 1167 + } 1168 + 1169 + static int max17042_platform_probe(struct platform_device *pdev) 1170 + { 1171 + struct device *dev = &pdev->dev; 1172 + struct i2c_client *i2c; 1173 + const struct platform_device_id *id; 1174 + int irq; 1175 + 1176 + i2c = to_i2c_client(pdev->dev.parent); 1177 + if (!i2c) 1178 + return -EINVAL; 1179 + 1180 + dev->of_node = dev->parent->of_node; 1181 + id = platform_get_device_id(pdev); 1182 + irq = platform_get_irq(pdev, 0); 1183 + 1184 + return max17042_probe(i2c, dev, irq, id->driver_data); 1185 + } 1186 + 1137 1187 #ifdef CONFIG_PM_SLEEP 1138 1188 static int max17042_suspend(struct device *dev) 1139 1189 { ··· 1181 1155 * disable the irq and enable irq_wake 1182 1156 * capability to the interrupt line. 1183 1157 */ 1184 - if (chip->client->irq) { 1185 - disable_irq(chip->client->irq); 1186 - enable_irq_wake(chip->client->irq); 1158 + if (chip->irq) { 1159 + disable_irq(chip->irq); 1160 + enable_irq_wake(chip->irq); 1187 1161 } 1188 1162 1189 1163 return 0; ··· 1193 1167 { 1194 1168 struct max17042_chip *chip = dev_get_drvdata(dev); 1195 1169 1196 - if (chip->client->irq) { 1197 - disable_irq_wake(chip->client->irq); 1198 - enable_irq(chip->client->irq); 1170 + if (chip->irq) { 1171 + disable_irq_wake(chip->irq); 1172 + enable_irq(chip->irq); 1199 1173 /* re-program the SOC thresholds to 1% change */ 1200 1174 max17042_set_soc_threshold(chip, 1); 1201 1175 } ··· 1216 1190 #endif 1217 1191 1218 1192 #ifdef CONFIG_OF 1219 - static const struct of_device_id max17042_dt_match[] = { 1220 - { .compatible = "maxim,max17042" }, 1221 - { .compatible = "maxim,max17047" }, 1222 - { .compatible = "maxim,max17050" }, 1223 - { .compatible = "maxim,max17055" }, 1224 - { .compatible = "maxim,max77849-battery" }, 1193 + /* 1194 + * Device may be instantiated through parent MFD device and device matching is done 1195 + * through platform_device_id. 1196 + * 1197 + * However if device's DT node contains proper clock compatible and driver is 1198 + * built as a module, then the *module* matching will be done trough DT aliases. 1199 + * This requires of_device_id table. In the same time this will not change the 1200 + * actual *device* matching so do not add .of_match_table. 1201 + */ 1202 + static const struct of_device_id max17042_dt_match[] __used = { 1203 + { .compatible = "maxim,max17042", 1204 + .data = (void *) MAXIM_DEVICE_TYPE_MAX17042 }, 1205 + { .compatible = "maxim,max17047", 1206 + .data = (void *) MAXIM_DEVICE_TYPE_MAX17047 }, 1207 + { .compatible = "maxim,max17050", 1208 + .data = (void *) MAXIM_DEVICE_TYPE_MAX17050 }, 1209 + { .compatible = "maxim,max17055", 1210 + .data = (void *) MAXIM_DEVICE_TYPE_MAX17055 }, 1211 + { .compatible = "maxim,max77705-battery", 1212 + .data = (void *) MAXIM_DEVICE_TYPE_MAX17047 }, 1213 + { .compatible = "maxim,max77849-battery", 1214 + .data = (void *) MAXIM_DEVICE_TYPE_MAX17047 }, 1225 1215 { }, 1226 1216 }; 1227 1217 MODULE_DEVICE_TABLE(of, max17042_dt_match); ··· 1253 1211 }; 1254 1212 MODULE_DEVICE_TABLE(i2c, max17042_id); 1255 1213 1214 + static const struct platform_device_id max17042_platform_id[] = { 1215 + { "max17042", MAXIM_DEVICE_TYPE_MAX17042 }, 1216 + { "max17047", MAXIM_DEVICE_TYPE_MAX17047 }, 1217 + { "max17050", MAXIM_DEVICE_TYPE_MAX17050 }, 1218 + { "max17055", MAXIM_DEVICE_TYPE_MAX17055 }, 1219 + { "max77705-battery", MAXIM_DEVICE_TYPE_MAX17047 }, 1220 + { "max77849-battery", MAXIM_DEVICE_TYPE_MAX17047 }, 1221 + { } 1222 + }; 1223 + MODULE_DEVICE_TABLE(platform, max17042_platform_id); 1224 + 1256 1225 static struct i2c_driver max17042_i2c_driver = { 1257 1226 .driver = { 1258 1227 .name = "max17042", ··· 1271 1218 .of_match_table = of_match_ptr(max17042_dt_match), 1272 1219 .pm = &max17042_pm_ops, 1273 1220 }, 1274 - .probe = max17042_probe, 1221 + .probe = max17042_i2c_probe, 1275 1222 .id_table = max17042_id, 1276 1223 }; 1277 - module_i2c_driver(max17042_i2c_driver); 1224 + 1225 + static struct platform_driver max17042_platform_driver = { 1226 + .driver = { 1227 + .name = "max17042", 1228 + .acpi_match_table = ACPI_PTR(max17042_acpi_match), 1229 + .pm = &max17042_pm_ops, 1230 + }, 1231 + .probe = max17042_platform_probe, 1232 + .id_table = max17042_platform_id, 1233 + }; 1234 + 1235 + static int __init max17042_init(void) 1236 + { 1237 + int ret; 1238 + 1239 + ret = platform_driver_register(&max17042_platform_driver); 1240 + if (ret) 1241 + return ret; 1242 + 1243 + ret = i2c_add_driver(&max17042_i2c_driver); 1244 + if (ret) { 1245 + platform_driver_unregister(&max17042_platform_driver); 1246 + return ret; 1247 + } 1248 + 1249 + return 0; 1250 + } 1251 + module_init(max17042_init); 1252 + 1253 + static void __exit max17042_exit(void) 1254 + { 1255 + i2c_del_driver(&max17042_i2c_driver); 1256 + platform_driver_unregister(&max17042_platform_driver); 1257 + } 1258 + module_exit(max17042_exit); 1278 1259 1279 1260 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); 1280 1261 MODULE_DESCRIPTION("MAX17042 Fuel Gauge");
+65 -1
drivers/power/supply/max1720x_battery.c
··· 16 16 17 17 #include <linux/unaligned.h> 18 18 19 + /* SBS compliant registers */ 20 + #define MAX172XX_TEMP1 0x34 21 + #define MAX172XX_INT_TEMP 0x35 22 + #define MAX172XX_TEMP2 0x3B 23 + 19 24 /* Nonvolatile registers */ 20 25 #define MAX1720X_NXTABLE0 0x80 21 26 #define MAX1720X_NRSENSE 0xCF /* RSense in 10^-5 Ohm */ ··· 34 29 #define MAX172XX_TEMP 0x08 /* Temperature */ 35 30 #define MAX172XX_CURRENT 0x0A /* Actual current */ 36 31 #define MAX172XX_AVG_CURRENT 0x0B /* Average current */ 32 + #define MAX172XX_FULL_CAP 0x10 /* Calculated full capacity */ 37 33 #define MAX172XX_TTE 0x11 /* Time to empty */ 38 34 #define MAX172XX_AVG_TA 0x16 /* Average temperature */ 39 35 #define MAX172XX_CYCLES 0x17 ··· 118 112 }; 119 113 120 114 static const struct regmap_range max1720x_nvmem_allow[] = { 115 + regmap_reg_range(MAX172XX_TEMP1, MAX172XX_INT_TEMP), 116 + regmap_reg_range(MAX172XX_TEMP2, MAX172XX_TEMP2), 121 117 regmap_reg_range(MAX1720X_NXTABLE0, MAX1720X_NDEVICE_NAME4), 122 118 }; 123 119 124 120 static const struct regmap_range max1720x_nvmem_deny[] = { 125 - regmap_reg_range(0x00, 0x7F), 121 + regmap_reg_range(0x00, 0x33), 122 + regmap_reg_range(0x36, 0x3A), 123 + regmap_reg_range(0x3C, 0x7F), 126 124 regmap_reg_range(0xE0, 0xFF), 127 125 }; 128 126 ··· 260 250 POWER_SUPPLY_PROP_TEMP, 261 251 POWER_SUPPLY_PROP_CURRENT_NOW, 262 252 POWER_SUPPLY_PROP_CURRENT_AVG, 253 + POWER_SUPPLY_PROP_CHARGE_FULL, 263 254 POWER_SUPPLY_PROP_MODEL_NAME, 264 255 POWER_SUPPLY_PROP_MANUFACTURER, 265 256 }; ··· 373 362 ret = regmap_read(info->regmap, MAX172XX_AVG_CURRENT, &reg_val); 374 363 val->intval = max172xx_current_to_voltage(reg_val) / info->rsense; 375 364 break; 365 + case POWER_SUPPLY_PROP_CHARGE_FULL: 366 + ret = regmap_read(info->regmap, MAX172XX_FULL_CAP, &reg_val); 367 + val->intval = max172xx_capacity_to_ps(reg_val); 368 + break; 376 369 case POWER_SUPPLY_PROP_MODEL_NAME: 377 370 ret = regmap_read(info->regmap, MAX172XX_DEV_NAME, &reg_val); 378 371 reg_val = FIELD_GET(MAX172XX_DEV_NAME_TYPE_MASK, reg_val); ··· 396 381 397 382 return ret; 398 383 } 384 + 385 + static int max1720x_read_temp(struct device *dev, u8 reg, char *buf) 386 + { 387 + struct power_supply *psy = dev_get_drvdata(dev); 388 + struct max1720x_device_info *info = power_supply_get_drvdata(psy); 389 + unsigned int val; 390 + int ret; 391 + 392 + ret = regmap_read(info->regmap_nv, reg, &val); 393 + if (ret < 0) 394 + return ret; 395 + 396 + /* 397 + * Temperature in degrees Celsius starting at absolute zero, -273C or 398 + * 0K with an LSb of 0.1C 399 + */ 400 + return sysfs_emit(buf, "%d\n", val - 2730); 401 + } 402 + 403 + static ssize_t temp_ain1_show(struct device *dev, struct device_attribute *attr, 404 + char *buf) 405 + { 406 + return max1720x_read_temp(dev, MAX172XX_TEMP1, buf); 407 + } 408 + 409 + static ssize_t temp_ain2_show(struct device *dev, struct device_attribute *attr, 410 + char *buf) 411 + { 412 + return max1720x_read_temp(dev, MAX172XX_TEMP2, buf); 413 + } 414 + 415 + static ssize_t temp_int_show(struct device *dev, struct device_attribute *attr, 416 + char *buf) 417 + { 418 + return max1720x_read_temp(dev, MAX172XX_INT_TEMP, buf); 419 + } 420 + 421 + static DEVICE_ATTR_RO(temp_ain1); 422 + static DEVICE_ATTR_RO(temp_ain2); 423 + static DEVICE_ATTR_RO(temp_int); 424 + 425 + static struct attribute *max1720x_attrs[] = { 426 + &dev_attr_temp_ain1.attr, 427 + &dev_attr_temp_ain2.attr, 428 + &dev_attr_temp_int.attr, 429 + NULL 430 + }; 431 + ATTRIBUTE_GROUPS(max1720x); 399 432 400 433 static 401 434 int max1720x_nvmem_reg_read(void *priv, unsigned int off, void *val, size_t len) ··· 545 482 546 483 psy_cfg.drv_data = info; 547 484 psy_cfg.fwnode = dev_fwnode(dev); 485 + psy_cfg.attr_grp = max1720x_groups; 548 486 i2c_set_clientdata(client, info); 549 487 info->regmap = devm_regmap_init_i2c(client, &max1720x_regmap_cfg); 550 488 if (IS_ERR(info->regmap))
+1 -1
drivers/power/supply/mm8013.c
··· 90 90 enum power_supply_property psp, 91 91 union power_supply_propval *val) 92 92 { 93 - struct mm8013_chip *chip = psy->drv_data; 93 + struct mm8013_chip *chip = power_supply_get_drvdata(psy); 94 94 int ret = 0; 95 95 u32 regval; 96 96
+5 -6
drivers/power/supply/olpc_battery.c
··· 527 527 #define EEPROM_SIZE (EEPROM_END - EEPROM_START) 528 528 529 529 static ssize_t olpc_bat_eeprom_read(struct file *filp, struct kobject *kobj, 530 - struct bin_attribute *attr, char *buf, loff_t off, size_t count) 530 + const struct bin_attribute *attr, char *buf, loff_t off, size_t count) 531 531 { 532 532 uint8_t ec_byte; 533 533 int ret; ··· 547 547 return count; 548 548 } 549 549 550 - static struct bin_attribute olpc_bat_eeprom = { 550 + static const struct bin_attribute olpc_bat_eeprom = { 551 551 .attr = { 552 552 .name = "eeprom", 553 553 .mode = S_IRUGO, 554 554 }, 555 555 .size = EEPROM_SIZE, 556 - .read = olpc_bat_eeprom_read, 556 + .read_new = olpc_bat_eeprom_read, 557 557 }; 558 558 559 559 /* Allow userspace to see the specific error value pulled from the EC */ ··· 584 584 NULL 585 585 }; 586 586 587 - static struct bin_attribute *olpc_bat_sysfs_bin_attrs[] = { 587 + static const struct bin_attribute *const olpc_bat_sysfs_bin_attrs[] = { 588 588 &olpc_bat_eeprom, 589 589 NULL 590 590 }; 591 591 592 592 static const struct attribute_group olpc_bat_sysfs_group = { 593 593 .attrs = olpc_bat_sysfs_attrs, 594 - .bin_attrs = olpc_bat_sysfs_bin_attrs, 595 - 594 + .bin_attrs_new = olpc_bat_sysfs_bin_attrs, 596 595 }; 597 596 598 597 static const struct attribute_group *olpc_bat_sysfs_groups[] = {
+31
drivers/power/supply/power_supply.h
··· 9 9 * Modified: 2004, Oct Szabolcs Gyurko 10 10 */ 11 11 12 + #include <linux/lockdep.h> 13 + 12 14 struct device; 13 15 struct device_type; 14 16 struct power_supply; 15 17 16 18 extern int power_supply_property_is_writeable(struct power_supply *psy, 17 19 enum power_supply_property psp); 20 + extern bool power_supply_has_property(struct power_supply *psy, 21 + enum power_supply_property psp); 22 + extern bool power_supply_ext_has_property(const struct power_supply_ext *ext, 23 + enum power_supply_property psp); 24 + 25 + struct power_supply_ext_registration { 26 + struct list_head list_head; 27 + const struct power_supply_ext *ext; 28 + struct device *dev; 29 + void *data; 30 + }; 31 + 32 + /* Make sure that the macro is a single expression */ 33 + #define power_supply_for_each_extension(pos, psy) \ 34 + if ( ({ lockdep_assert_held(&(psy)->extensions_sem); 0; }) ) \ 35 + ; \ 36 + else \ 37 + list_for_each_entry(pos, &(psy)->extensions, list_head) \ 18 38 19 39 #ifdef CONFIG_SYSFS 20 40 21 41 extern void __init power_supply_init_attrs(void); 22 42 extern int power_supply_uevent(const struct device *dev, struct kobj_uevent_env *env); 23 43 extern const struct attribute_group *power_supply_attr_groups[]; 44 + extern int power_supply_sysfs_add_extension(struct power_supply *psy, 45 + const struct power_supply_ext *ext, 46 + struct device *dev); 47 + extern void power_supply_sysfs_remove_extension(struct power_supply *psy, 48 + const struct power_supply_ext *ext); 24 49 25 50 #else 26 51 27 52 static inline void power_supply_init_attrs(void) {} 28 53 #define power_supply_attr_groups NULL 29 54 #define power_supply_uevent NULL 55 + static inline int power_supply_sysfs_add_extension(struct power_supply *psy, 56 + const struct power_supply_ext *ext, 57 + struct device *dev) 58 + { return 0; } 59 + static inline void power_supply_sysfs_remove_extension(struct power_supply *psy, 60 + const struct power_supply_ext *ext) {} 30 61 31 62 #endif /* CONFIG_SYSFS */ 32 63
+223 -43
drivers/power/supply/power_supply_core.c
··· 66 66 return false; 67 67 } 68 68 69 - static int __power_supply_changed_work(struct device *dev, void *data) 69 + static int __power_supply_changed_work(struct power_supply *pst, void *data) 70 70 { 71 71 struct power_supply *psy = data; 72 - struct power_supply *pst = dev_get_drvdata(dev); 73 72 74 - if (__power_supply_is_supplied_by(psy, pst)) { 75 - if (pst->desc->external_power_changed) 76 - pst->desc->external_power_changed(pst); 77 - } 73 + if (__power_supply_is_supplied_by(psy, pst)) 74 + power_supply_external_power_changed(pst); 78 75 79 76 return 0; 80 77 } 81 78 82 79 static void power_supply_changed_work(struct work_struct *work) 83 80 { 81 + int ret; 84 82 unsigned long flags; 85 83 struct power_supply *psy = container_of(work, struct power_supply, 86 84 changed_work); ··· 86 88 dev_dbg(&psy->dev, "%s\n", __func__); 87 89 88 90 spin_lock_irqsave(&psy->changed_lock, flags); 91 + 92 + if (unlikely(psy->update_groups)) { 93 + psy->update_groups = false; 94 + spin_unlock_irqrestore(&psy->changed_lock, flags); 95 + ret = sysfs_update_groups(&psy->dev.kobj, power_supply_dev_type.groups); 96 + if (ret) 97 + dev_warn(&psy->dev, "failed to update sysfs groups: %pe\n", ERR_PTR(ret)); 98 + spin_lock_irqsave(&psy->changed_lock, flags); 99 + } 100 + 89 101 /* 90 102 * Check 'changed' here to avoid issues due to race between 91 103 * power_supply_changed() and this routine. In worst case ··· 106 98 if (likely(psy->changed)) { 107 99 psy->changed = false; 108 100 spin_unlock_irqrestore(&psy->changed_lock, flags); 109 - power_supply_for_each_device(psy, __power_supply_changed_work); 101 + power_supply_for_each_psy(psy, __power_supply_changed_work); 110 102 power_supply_update_leds(psy); 111 103 blocking_notifier_call_chain(&power_supply_notifier, 112 104 PSY_EVENT_PROP_CHANGED, psy); ··· 124 116 spin_unlock_irqrestore(&psy->changed_lock, flags); 125 117 } 126 118 127 - int power_supply_for_each_device(void *data, int (*fn)(struct device *dev, void *data)) 119 + struct psy_for_each_psy_cb_data { 120 + int (*fn)(struct power_supply *psy, void *data); 121 + void *data; 122 + }; 123 + 124 + static int psy_for_each_psy_cb(struct device *dev, void *data) 128 125 { 129 - return class_for_each_device(&power_supply_class, NULL, data, fn); 126 + struct psy_for_each_psy_cb_data *cb_data = data; 127 + struct power_supply *psy = dev_to_psy(dev); 128 + 129 + return cb_data->fn(psy, cb_data->data); 130 130 } 131 - EXPORT_SYMBOL_GPL(power_supply_for_each_device); 131 + 132 + int power_supply_for_each_psy(void *data, int (*fn)(struct power_supply *psy, void *data)) 133 + { 134 + struct psy_for_each_psy_cb_data cb_data = { 135 + .fn = fn, 136 + .data = data, 137 + }; 138 + 139 + return class_for_each_device(&power_supply_class, NULL, &cb_data, psy_for_each_psy_cb); 140 + } 141 + EXPORT_SYMBOL_GPL(power_supply_for_each_psy); 132 142 133 143 void power_supply_changed(struct power_supply *psy) 134 144 { ··· 192 166 } 193 167 194 168 #ifdef CONFIG_OF 195 - static int __power_supply_populate_supplied_from(struct device *dev, 169 + static int __power_supply_populate_supplied_from(struct power_supply *epsy, 196 170 void *data) 197 171 { 198 172 struct power_supply *psy = data; 199 - struct power_supply *epsy = dev_get_drvdata(dev); 200 173 struct device_node *np; 201 174 int i = 0; 202 175 ··· 222 197 { 223 198 int error; 224 199 225 - error = power_supply_for_each_device(psy, __power_supply_populate_supplied_from); 200 + error = power_supply_for_each_psy(psy, __power_supply_populate_supplied_from); 226 201 227 202 dev_dbg(&psy->dev, "%s %d\n", __func__, error); 228 203 229 204 return error; 230 205 } 231 206 232 - static int __power_supply_find_supply_from_node(struct device *dev, 207 + static int __power_supply_find_supply_from_node(struct power_supply *epsy, 233 208 void *data) 234 209 { 235 210 struct device_node *np = data; 236 - struct power_supply *epsy = dev_get_drvdata(dev); 237 211 238 - /* returning non-zero breaks out of power_supply_for_each_device loop */ 212 + /* returning non-zero breaks out of power_supply_for_each_psy loop */ 239 213 if (epsy->of_node == np) 240 214 return 1; 241 215 ··· 246 222 int error; 247 223 248 224 /* 249 - * power_supply_for_each_device() either returns its own errors or values 225 + * power_supply_for_each_psy() either returns its own errors or values 250 226 * returned by __power_supply_find_supply_from_node(). 251 227 * 252 228 * __power_supply_find_supply_from_node() will return 0 (no match) 253 229 * or 1 (match). 254 230 * 255 - * We return 0 if power_supply_for_each_device() returned 1, -EPROBE_DEFER if 231 + * We return 0 if power_supply_for_each_psy() returned 1, -EPROBE_DEFER if 256 232 * it returned 0, or error as returned by it. 257 233 */ 258 - error = power_supply_for_each_device(supply_node, __power_supply_find_supply_from_node); 234 + error = power_supply_for_each_psy(supply_node, __power_supply_find_supply_from_node); 259 235 260 236 return error ? (error == 1 ? 0 : error) : -EPROBE_DEFER; 261 237 } ··· 340 316 unsigned int count; 341 317 }; 342 318 343 - static int __power_supply_am_i_supplied(struct device *dev, void *_data) 319 + static int __power_supply_am_i_supplied(struct power_supply *epsy, void *_data) 344 320 { 345 321 union power_supply_propval ret = {0,}; 346 - struct power_supply *epsy = dev_get_drvdata(dev); 347 322 struct psy_am_i_supplied_data *data = _data; 348 323 349 324 if (__power_supply_is_supplied_by(epsy, data->psy)) { ··· 360 337 struct psy_am_i_supplied_data data = { psy, 0 }; 361 338 int error; 362 339 363 - error = power_supply_for_each_device(&data, __power_supply_am_i_supplied); 340 + error = power_supply_for_each_psy(&data, __power_supply_am_i_supplied); 364 341 365 342 dev_dbg(&psy->dev, "%s count %u err %d\n", __func__, data.count, error); 366 343 ··· 371 348 } 372 349 EXPORT_SYMBOL_GPL(power_supply_am_i_supplied); 373 350 374 - static int __power_supply_is_system_supplied(struct device *dev, void *data) 351 + static int __power_supply_is_system_supplied(struct power_supply *psy, void *data) 375 352 { 376 353 union power_supply_propval ret = {0,}; 377 - struct power_supply *psy = dev_get_drvdata(dev); 378 354 unsigned int *count = data; 379 355 380 356 if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_SCOPE, &ret)) ··· 394 372 int error; 395 373 unsigned int count = 0; 396 374 397 - error = power_supply_for_each_device(&count, __power_supply_is_system_supplied); 375 + error = power_supply_for_each_psy(&count, __power_supply_is_system_supplied); 398 376 399 377 /* 400 378 * If no system scope power class device was found at all, most probably we ··· 413 391 union power_supply_propval *val; 414 392 }; 415 393 416 - static int __power_supply_get_supplier_property(struct device *dev, void *_data) 394 + static int __power_supply_get_supplier_property(struct power_supply *epsy, void *_data) 417 395 { 418 - struct power_supply *epsy = dev_get_drvdata(dev); 419 396 struct psy_get_supplier_prop_data *data = _data; 420 397 421 398 if (__power_supply_is_supplied_by(epsy, data->psy)) ··· 439 418 * This function is not intended for use with a supply with multiple 440 419 * suppliers, we simply pick the first supply to report the psp. 441 420 */ 442 - ret = power_supply_for_each_device(&data, __power_supply_get_supplier_property); 421 + ret = power_supply_for_each_psy(&data, __power_supply_get_supplier_property); 443 422 if (ret < 0) 444 423 return ret; 445 424 if (ret == 0) ··· 465 444 static int power_supply_match_device_by_name(struct device *dev, const void *data) 466 445 { 467 446 const char *name = data; 468 - struct power_supply *psy = dev_get_drvdata(dev); 447 + struct power_supply *psy = dev_to_psy(dev); 469 448 470 449 return strcmp(psy->desc->name, name) == 0; 471 450 } ··· 488 467 power_supply_match_device_by_name); 489 468 490 469 if (dev) { 491 - psy = dev_get_drvdata(dev); 470 + psy = dev_to_psy(dev); 492 471 atomic_inc(&psy->use_cnt); 493 472 } 494 473 ··· 545 524 of_node_put(power_supply_np); 546 525 547 526 if (dev) { 548 - psy = dev_get_drvdata(dev); 527 + psy = dev_to_psy(dev); 549 528 atomic_inc(&psy->use_cnt); 550 529 } 551 530 ··· 1201 1180 } 1202 1181 EXPORT_SYMBOL_GPL(power_supply_battery_bti_in_range); 1203 1182 1204 - static bool psy_has_property(const struct power_supply_desc *psy_desc, 1205 - enum power_supply_property psp) 1183 + static bool psy_desc_has_property(const struct power_supply_desc *psy_desc, 1184 + enum power_supply_property psp) 1206 1185 { 1207 1186 bool found = false; 1208 1187 int i; ··· 1217 1196 return found; 1218 1197 } 1219 1198 1199 + bool power_supply_ext_has_property(const struct power_supply_ext *psy_ext, 1200 + enum power_supply_property psp) 1201 + { 1202 + int i; 1203 + 1204 + for (i = 0; i < psy_ext->num_properties; i++) 1205 + if (psy_ext->properties[i] == psp) 1206 + return true; 1207 + 1208 + return false; 1209 + } 1210 + 1211 + bool power_supply_has_property(struct power_supply *psy, 1212 + enum power_supply_property psp) 1213 + { 1214 + struct power_supply_ext_registration *reg; 1215 + 1216 + if (psy_desc_has_property(psy->desc, psp)) 1217 + return true; 1218 + 1219 + if (power_supply_battery_info_has_prop(psy->battery_info, psp)) 1220 + return true; 1221 + 1222 + power_supply_for_each_extension(reg, psy) { 1223 + if (power_supply_ext_has_property(reg->ext, psp)) 1224 + return true; 1225 + } 1226 + 1227 + return false; 1228 + } 1229 + 1220 1230 int power_supply_get_property(struct power_supply *psy, 1221 1231 enum power_supply_property psp, 1222 1232 union power_supply_propval *val) 1223 1233 { 1234 + struct power_supply_ext_registration *reg; 1235 + 1224 1236 if (atomic_read(&psy->use_cnt) <= 0) { 1225 1237 if (!psy->initialized) 1226 1238 return -EAGAIN; 1227 1239 return -ENODEV; 1228 1240 } 1229 1241 1230 - if (psy_has_property(psy->desc, psp)) 1242 + scoped_guard(rwsem_read, &psy->extensions_sem) { 1243 + power_supply_for_each_extension(reg, psy) { 1244 + if (power_supply_ext_has_property(reg->ext, psp)) 1245 + return reg->ext->get_property(psy, reg->ext, reg->data, psp, val); 1246 + } 1247 + } 1248 + 1249 + if (psy_desc_has_property(psy->desc, psp)) 1231 1250 return psy->desc->get_property(psy, psp, val); 1232 1251 else if (power_supply_battery_info_has_prop(psy->battery_info, psp)) 1233 1252 return power_supply_battery_info_get_prop(psy->battery_info, psp, val); ··· 1280 1219 enum power_supply_property psp, 1281 1220 const union power_supply_propval *val) 1282 1221 { 1283 - if (atomic_read(&psy->use_cnt) <= 0 || !psy->desc->set_property) 1222 + struct power_supply_ext_registration *reg; 1223 + 1224 + if (atomic_read(&psy->use_cnt) <= 0) 1225 + return -ENODEV; 1226 + 1227 + scoped_guard(rwsem_read, &psy->extensions_sem) { 1228 + power_supply_for_each_extension(reg, psy) { 1229 + if (power_supply_ext_has_property(reg->ext, psp)) { 1230 + if (reg->ext->set_property) 1231 + return reg->ext->set_property(psy, reg->ext, reg->data, 1232 + psp, val); 1233 + else 1234 + return -ENODEV; 1235 + } 1236 + } 1237 + } 1238 + 1239 + if (!psy->desc->set_property) 1284 1240 return -ENODEV; 1285 1241 1286 1242 return psy->desc->set_property(psy, psp, val); ··· 1307 1229 int power_supply_property_is_writeable(struct power_supply *psy, 1308 1230 enum power_supply_property psp) 1309 1231 { 1310 - return psy->desc->property_is_writeable && psy->desc->property_is_writeable(psy, psp); 1232 + struct power_supply_ext_registration *reg; 1233 + 1234 + power_supply_for_each_extension(reg, psy) { 1235 + if (power_supply_ext_has_property(reg->ext, psp)) { 1236 + if (reg->ext->property_is_writeable) 1237 + return reg->ext->property_is_writeable(psy, reg->ext, 1238 + reg->data, psp); 1239 + else 1240 + return 0; 1241 + } 1242 + } 1243 + 1244 + if (!psy->desc->property_is_writeable) 1245 + return 0; 1246 + 1247 + return psy->desc->property_is_writeable(psy, psp); 1311 1248 } 1312 1249 1313 1250 void power_supply_external_power_changed(struct power_supply *psy) ··· 1340 1247 return sysfs_create_link(&psy->dev.kobj, &dev->kobj, "powers"); 1341 1248 } 1342 1249 EXPORT_SYMBOL_GPL(power_supply_powers); 1250 + 1251 + static int power_supply_update_sysfs_and_hwmon(struct power_supply *psy) 1252 + { 1253 + unsigned long flags; 1254 + 1255 + spin_lock_irqsave(&psy->changed_lock, flags); 1256 + psy->update_groups = true; 1257 + spin_unlock_irqrestore(&psy->changed_lock, flags); 1258 + 1259 + power_supply_changed(psy); 1260 + 1261 + power_supply_remove_hwmon_sysfs(psy); 1262 + return power_supply_add_hwmon_sysfs(psy); 1263 + } 1264 + 1265 + int power_supply_register_extension(struct power_supply *psy, const struct power_supply_ext *ext, 1266 + struct device *dev, void *data) 1267 + { 1268 + struct power_supply_ext_registration *reg; 1269 + size_t i; 1270 + int ret; 1271 + 1272 + if (!psy || !dev || !ext || !ext->name || !ext->properties || !ext->num_properties) 1273 + return -EINVAL; 1274 + 1275 + guard(rwsem_write)(&psy->extensions_sem); 1276 + 1277 + power_supply_for_each_extension(reg, psy) 1278 + if (strcmp(ext->name, reg->ext->name) == 0) 1279 + return -EEXIST; 1280 + 1281 + for (i = 0; i < ext->num_properties; i++) 1282 + if (power_supply_has_property(psy, ext->properties[i])) 1283 + return -EEXIST; 1284 + 1285 + reg = kmalloc(sizeof(*reg), GFP_KERNEL); 1286 + if (!reg) 1287 + return -ENOMEM; 1288 + 1289 + reg->ext = ext; 1290 + reg->dev = dev; 1291 + reg->data = data; 1292 + list_add(&reg->list_head, &psy->extensions); 1293 + 1294 + ret = power_supply_sysfs_add_extension(psy, ext, dev); 1295 + if (ret) 1296 + goto sysfs_add_failed; 1297 + 1298 + ret = power_supply_update_sysfs_and_hwmon(psy); 1299 + if (ret) 1300 + goto sysfs_hwmon_failed; 1301 + 1302 + return 0; 1303 + 1304 + sysfs_hwmon_failed: 1305 + power_supply_sysfs_remove_extension(psy, ext); 1306 + sysfs_add_failed: 1307 + list_del(&reg->list_head); 1308 + kfree(reg); 1309 + return ret; 1310 + } 1311 + EXPORT_SYMBOL_GPL(power_supply_register_extension); 1312 + 1313 + void power_supply_unregister_extension(struct power_supply *psy, const struct power_supply_ext *ext) 1314 + { 1315 + struct power_supply_ext_registration *reg; 1316 + 1317 + guard(rwsem_write)(&psy->extensions_sem); 1318 + 1319 + power_supply_for_each_extension(reg, psy) { 1320 + if (reg->ext == ext) { 1321 + list_del(&reg->list_head); 1322 + power_supply_sysfs_remove_extension(psy, ext); 1323 + kfree(reg); 1324 + power_supply_update_sysfs_and_hwmon(psy); 1325 + return; 1326 + } 1327 + } 1328 + 1329 + dev_warn(&psy->dev, "Trying to unregister invalid extension"); 1330 + } 1331 + EXPORT_SYMBOL_GPL(power_supply_unregister_extension); 1343 1332 1344 1333 static void power_supply_dev_release(struct device *dev) 1345 1334 { ··· 1475 1300 return 0; 1476 1301 1477 1302 /* Register battery zone device psy reports temperature */ 1478 - if (psy_has_property(psy->desc, POWER_SUPPLY_PROP_TEMP)) { 1303 + if (psy_desc_has_property(psy->desc, POWER_SUPPLY_PROP_TEMP)) { 1479 1304 /* Prefer our hwmon device and avoid duplicates */ 1480 1305 struct thermal_zone_params tzp = { 1481 1306 .no_hwmon = IS_ENABLED(CONFIG_POWER_SUPPLY_HWMON) ··· 1577 1402 } 1578 1403 1579 1404 spin_lock_init(&psy->changed_lock); 1405 + init_rwsem(&psy->extensions_sem); 1406 + INIT_LIST_HEAD(&psy->extensions); 1407 + 1580 1408 rc = device_add(dev); 1581 1409 if (rc) 1582 1410 goto device_add_failed; ··· 1592 1414 if (rc) 1593 1415 goto register_thermal_failed; 1594 1416 1595 - rc = power_supply_create_triggers(psy); 1596 - if (rc) 1597 - goto create_triggers_failed; 1417 + scoped_guard(rwsem_read, &psy->extensions_sem) { 1418 + rc = power_supply_create_triggers(psy); 1419 + if (rc) 1420 + goto create_triggers_failed; 1598 1421 1599 - rc = power_supply_add_hwmon_sysfs(psy); 1600 - if (rc) 1601 - goto add_hwmon_sysfs_failed; 1422 + rc = power_supply_add_hwmon_sysfs(psy); 1423 + if (rc) 1424 + goto add_hwmon_sysfs_failed; 1425 + } 1602 1426 1603 1427 /* 1604 1428 * Update use_cnt after any uevents (most notably from device_add()).
+23 -25
drivers/power/supply/power_supply_hwmon.c
··· 349 349 .info = power_supply_hwmon_info, 350 350 }; 351 351 352 + static const enum power_supply_property power_supply_hwmon_props[] = { 353 + POWER_SUPPLY_PROP_CURRENT_AVG, 354 + POWER_SUPPLY_PROP_CURRENT_MAX, 355 + POWER_SUPPLY_PROP_CURRENT_NOW, 356 + POWER_SUPPLY_PROP_POWER_AVG, 357 + POWER_SUPPLY_PROP_POWER_NOW, 358 + POWER_SUPPLY_PROP_TEMP, 359 + POWER_SUPPLY_PROP_TEMP_MAX, 360 + POWER_SUPPLY_PROP_TEMP_MIN, 361 + POWER_SUPPLY_PROP_TEMP_ALERT_MIN, 362 + POWER_SUPPLY_PROP_TEMP_ALERT_MAX, 363 + POWER_SUPPLY_PROP_TEMP_AMBIENT, 364 + POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN, 365 + POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX, 366 + POWER_SUPPLY_PROP_VOLTAGE_AVG, 367 + POWER_SUPPLY_PROP_VOLTAGE_MIN, 368 + POWER_SUPPLY_PROP_VOLTAGE_MAX, 369 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 370 + }; 371 + 352 372 int power_supply_add_hwmon_sysfs(struct power_supply *psy) 353 373 { 354 - const struct power_supply_desc *desc = psy->desc; 355 374 struct power_supply_hwmon *psyhw; 356 375 struct device *dev = &psy->dev; 357 376 struct device *hwmon; ··· 396 377 goto error; 397 378 } 398 379 399 - for (i = 0; i < desc->num_properties; i++) { 400 - const enum power_supply_property prop = desc->properties[i]; 380 + for (i = 0; i < ARRAY_SIZE(power_supply_hwmon_props); i++) { 381 + const enum power_supply_property prop = power_supply_hwmon_props[i]; 401 382 402 - switch (prop) { 403 - case POWER_SUPPLY_PROP_CURRENT_AVG: 404 - case POWER_SUPPLY_PROP_CURRENT_MAX: 405 - case POWER_SUPPLY_PROP_CURRENT_NOW: 406 - case POWER_SUPPLY_PROP_POWER_AVG: 407 - case POWER_SUPPLY_PROP_POWER_NOW: 408 - case POWER_SUPPLY_PROP_TEMP: 409 - case POWER_SUPPLY_PROP_TEMP_MAX: 410 - case POWER_SUPPLY_PROP_TEMP_MIN: 411 - case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: 412 - case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: 413 - case POWER_SUPPLY_PROP_TEMP_AMBIENT: 414 - case POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN: 415 - case POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX: 416 - case POWER_SUPPLY_PROP_VOLTAGE_AVG: 417 - case POWER_SUPPLY_PROP_VOLTAGE_MIN: 418 - case POWER_SUPPLY_PROP_VOLTAGE_MAX: 419 - case POWER_SUPPLY_PROP_VOLTAGE_NOW: 383 + if (power_supply_has_property(psy, prop)) 420 384 set_bit(prop, psyhw->props); 421 - break; 422 - default: 423 - break; 424 - } 425 385 } 426 386 427 387 name = psy->desc->name;
+144 -48
drivers/power/supply/power_supply_sysfs.c
··· 99 99 [POWER_SUPPLY_HEALTH_OVERHEAT] = "Overheat", 100 100 [POWER_SUPPLY_HEALTH_DEAD] = "Dead", 101 101 [POWER_SUPPLY_HEALTH_OVERVOLTAGE] = "Over voltage", 102 + [POWER_SUPPLY_HEALTH_UNDERVOLTAGE] = "Under voltage", 102 103 [POWER_SUPPLY_HEALTH_UNSPEC_FAILURE] = "Unspecified failure", 103 104 [POWER_SUPPLY_HEALTH_COLD] = "Cold", 104 105 [POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE] = "Watchdog timer expire", ··· 183 182 POWER_SUPPLY_ATTR(CHARGE_CONTROL_START_THRESHOLD), 184 183 POWER_SUPPLY_ATTR(CHARGE_CONTROL_END_THRESHOLD), 185 184 POWER_SUPPLY_ENUM_ATTR(CHARGE_BEHAVIOUR), 185 + /* Same enum value texts as "charge_type" without the 's' at the end */ 186 + _POWER_SUPPLY_ENUM_ATTR(CHARGE_TYPES, POWER_SUPPLY_CHARGE_TYPE_TEXT), 186 187 POWER_SUPPLY_ATTR(INPUT_CURRENT_LIMIT), 187 188 POWER_SUPPLY_ATTR(INPUT_VOLTAGE_LIMIT), 188 189 POWER_SUPPLY_ATTR(INPUT_POWER_LIMIT), ··· 240 237 return to_ps_attr(attr) - power_supply_attrs; 241 238 } 242 239 240 + static void power_supply_escape_spaces(const char *str, char *buf, size_t bufsize) 241 + { 242 + strscpy(buf, str, bufsize); 243 + strreplace(buf, ' ', '_'); 244 + } 245 + 246 + static int power_supply_match_string(const char * const *array, size_t n, const char *s) 247 + { 248 + int ret; 249 + 250 + /* First try an exact match */ 251 + ret = __sysfs_match_string(array, n, s); 252 + if (ret >= 0) 253 + return ret; 254 + 255 + /* Second round, try matching with spaces replaced by '_' */ 256 + for (size_t i = 0; i < n; i++) { 257 + char buf[32]; 258 + 259 + power_supply_escape_spaces(array[i], buf, sizeof(buf)); 260 + if (sysfs_streq(buf, s)) 261 + return i; 262 + } 263 + 264 + return -EINVAL; 265 + } 266 + 243 267 static ssize_t power_supply_show_enum_with_available( 244 268 struct device *dev, const char * const labels[], int label_count, 245 269 unsigned int available_values, int value, char *buf) 246 270 { 247 271 bool match = false, available, active; 272 + char escaped_label[32]; 248 273 ssize_t count = 0; 249 274 int i; 250 275 251 276 for (i = 0; i < label_count; i++) { 252 277 available = available_values & BIT(i); 253 278 active = i == value; 279 + power_supply_escape_spaces(labels[i], escaped_label, sizeof(escaped_label)); 254 280 255 281 if (available && active) { 256 - count += sysfs_emit_at(buf, count, "[%s] ", labels[i]); 282 + count += sysfs_emit_at(buf, count, "[%s] ", escaped_label); 257 283 match = true; 258 284 } else if (available) { 259 - count += sysfs_emit_at(buf, count, "%s ", labels[i]); 285 + count += sysfs_emit_at(buf, count, "%s ", escaped_label); 260 286 } 261 287 } 262 288 ··· 300 268 return count; 301 269 } 302 270 303 - static ssize_t power_supply_show_property(struct device *dev, 304 - struct device_attribute *attr, 305 - char *buf) { 271 + static ssize_t power_supply_show_charge_behaviour(struct device *dev, 272 + struct power_supply *psy, 273 + union power_supply_propval *value, 274 + char *buf) 275 + { 276 + struct power_supply_ext_registration *reg; 277 + 278 + scoped_guard(rwsem_read, &psy->extensions_sem) { 279 + power_supply_for_each_extension(reg, psy) { 280 + if (power_supply_ext_has_property(reg->ext, 281 + POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR)) 282 + return power_supply_charge_behaviour_show(dev, 283 + reg->ext->charge_behaviours, 284 + value->intval, buf); 285 + } 286 + } 287 + 288 + return power_supply_charge_behaviour_show(dev, psy->desc->charge_behaviours, 289 + value->intval, buf); 290 + } 291 + 292 + static ssize_t power_supply_format_property(struct device *dev, 293 + bool uevent, 294 + struct device_attribute *attr, 295 + char *buf) 296 + { 306 297 ssize_t ret; 307 - struct power_supply *psy = dev_get_drvdata(dev); 298 + struct power_supply *psy = dev_to_psy(dev); 308 299 const struct power_supply_attr *ps_attr = to_ps_attr(attr); 309 300 enum power_supply_property psp = dev_attr_psp(attr); 310 301 union power_supply_propval value; ··· 342 287 dev_dbg_ratelimited(dev, 343 288 "driver has no data for `%s' property\n", 344 289 attr->attr.name); 345 - else if (ret != -ENODEV && ret != -EAGAIN) 290 + else if (ret != -ENODEV && ret != -EAGAIN && ret != -EINVAL) 346 291 dev_err_ratelimited(dev, 347 292 "driver failed to report `%s' property: %zd\n", 348 293 attr->attr.name, ret); ··· 358 303 psy->desc->usb_types, value.intval, buf); 359 304 break; 360 305 case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: 361 - ret = power_supply_charge_behaviour_show(dev, psy->desc->charge_behaviours, 362 - value.intval, buf); 306 + if (uevent) /* no possible values in uevents */ 307 + goto default_format; 308 + ret = power_supply_show_charge_behaviour(dev, psy, &value, buf); 309 + break; 310 + case POWER_SUPPLY_PROP_CHARGE_TYPES: 311 + if (uevent) /* no possible values in uevents */ 312 + goto default_format; 313 + ret = power_supply_charge_types_show(dev, psy->desc->charge_types, 314 + value.intval, buf); 363 315 break; 364 316 case POWER_SUPPLY_PROP_MODEL_NAME ... POWER_SUPPLY_PROP_SERIAL_NUMBER: 365 317 ret = sysfs_emit(buf, "%s\n", value.strval); 366 318 break; 367 319 default: 320 + default_format: 368 321 if (ps_attr->text_values_len > 0 && 369 322 value.intval < ps_attr->text_values_len && value.intval >= 0) { 370 323 ret = sysfs_emit(buf, "%s\n", ps_attr->text_values[value.intval]); ··· 384 321 return ret; 385 322 } 386 323 324 + static ssize_t power_supply_show_property(struct device *dev, 325 + struct device_attribute *attr, 326 + char *buf) 327 + { 328 + return power_supply_format_property(dev, false, attr, buf); 329 + } 330 + 387 331 static ssize_t power_supply_store_property(struct device *dev, 388 332 struct device_attribute *attr, 389 333 const char *buf, size_t count) { 390 334 ssize_t ret; 391 - struct power_supply *psy = dev_get_drvdata(dev); 335 + struct power_supply *psy = dev_to_psy(dev); 392 336 const struct power_supply_attr *ps_attr = to_ps_attr(attr); 393 337 enum power_supply_property psp = dev_attr_psp(attr); 394 338 union power_supply_propval value; 395 339 396 340 ret = -EINVAL; 397 341 if (ps_attr->text_values_len > 0) { 398 - ret = __sysfs_match_string(ps_attr->text_values, 399 - ps_attr->text_values_len, buf); 342 + ret = power_supply_match_string(ps_attr->text_values, 343 + ps_attr->text_values_len, buf); 400 344 } 401 345 402 346 /* ··· 434 364 int attrno) 435 365 { 436 366 struct device *dev = kobj_to_dev(kobj); 437 - struct power_supply *psy = dev_get_drvdata(dev); 367 + struct power_supply *psy = dev_to_psy(dev); 438 368 umode_t mode = S_IRUSR | S_IRGRP | S_IROTH; 439 - int i; 440 369 441 370 if (!power_supply_attrs[attrno].prop_name) 442 371 return 0; ··· 443 374 if (attrno == POWER_SUPPLY_PROP_TYPE) 444 375 return mode; 445 376 446 - for (i = 0; i < psy->desc->num_properties; i++) { 447 - int property = psy->desc->properties[i]; 377 + guard(rwsem_read)(&psy->extensions_sem); 448 378 449 - if (property == attrno) { 450 - if (power_supply_property_is_writeable(psy, property) > 0) 451 - mode |= S_IWUSR; 452 - 453 - return mode; 454 - } 455 - } 456 - 457 - if (power_supply_battery_info_has_prop(psy->battery_info, attrno)) 379 + if (power_supply_has_property(psy, attrno)) { 380 + if (power_supply_property_is_writeable(psy, attrno) > 0) 381 + mode |= S_IWUSR; 458 382 return mode; 383 + } 459 384 460 385 return 0; 461 386 } ··· 459 396 .is_visible = power_supply_attr_is_visible, 460 397 }; 461 398 399 + static struct attribute *power_supply_extension_attrs[] = { 400 + NULL 401 + }; 402 + 403 + static const struct attribute_group power_supply_extension_group = { 404 + .name = "extensions", 405 + .attrs = power_supply_extension_attrs, 406 + }; 407 + 462 408 const struct attribute_group *power_supply_attr_groups[] = { 463 409 &power_supply_attr_group, 410 + &power_supply_extension_group, 464 411 NULL 465 412 }; 466 413 ··· 510 437 pwr_attr = &power_supply_attrs[prop]; 511 438 dev_attr = &pwr_attr->dev_attr; 512 439 513 - ret = power_supply_show_property((struct device *)dev, dev_attr, prop_buf); 514 - if (ret == -ENODEV || ret == -ENODATA) { 440 + ret = power_supply_format_property((struct device *)dev, true, dev_attr, prop_buf); 441 + if (ret == -ENODEV || ret == -ENODATA || ret == -EINVAL) { 515 442 /* 516 443 * When a battery is absent, we expect -ENODEV. Don't abort; 517 444 * send the uevent with at least the PRESENT=0 property ··· 532 459 533 460 int power_supply_uevent(const struct device *dev, struct kobj_uevent_env *env) 534 461 { 535 - const struct power_supply *psy = dev_get_drvdata(dev); 536 - const enum power_supply_property *battery_props = 537 - power_supply_battery_info_properties; 538 - unsigned long psy_drv_properties[POWER_SUPPLY_ATTR_CNT / 539 - sizeof(unsigned long) + 1] = {0}; 462 + const struct power_supply *psy = dev_to_psy(dev); 540 463 int ret = 0, j; 541 464 char *prop_buf; 542 465 ··· 560 491 if (ret) 561 492 goto out; 562 493 563 - for (j = 0; j < psy->desc->num_properties; j++) { 564 - set_bit(psy->desc->properties[j], psy_drv_properties); 565 - ret = add_prop_uevent(dev, env, psy->desc->properties[j], 566 - prop_buf); 567 - if (ret) 568 - goto out; 569 - } 570 - 571 - for (j = 0; j < power_supply_battery_info_properties_size; j++) { 572 - if (test_bit(battery_props[j], psy_drv_properties)) 573 - continue; 574 - if (!power_supply_battery_info_has_prop(psy->battery_info, 575 - battery_props[j])) 576 - continue; 577 - ret = add_prop_uevent(dev, env, battery_props[j], 578 - prop_buf); 494 + for (j = 0; j < POWER_SUPPLY_ATTR_CNT; j++) { 495 + ret = add_prop_uevent(dev, env, j, prop_buf); 579 496 if (ret) 580 497 goto out; 581 498 } ··· 597 542 return -EINVAL; 598 543 } 599 544 EXPORT_SYMBOL_GPL(power_supply_charge_behaviour_parse); 545 + 546 + ssize_t power_supply_charge_types_show(struct device *dev, 547 + unsigned int available_types, 548 + enum power_supply_charge_type current_type, 549 + char *buf) 550 + { 551 + return power_supply_show_enum_with_available( 552 + dev, POWER_SUPPLY_CHARGE_TYPE_TEXT, 553 + ARRAY_SIZE(POWER_SUPPLY_CHARGE_TYPE_TEXT), 554 + available_types, current_type, buf); 555 + } 556 + EXPORT_SYMBOL_GPL(power_supply_charge_types_show); 557 + 558 + int power_supply_charge_types_parse(unsigned int available_types, const char *buf) 559 + { 560 + int i = power_supply_match_string(POWER_SUPPLY_CHARGE_TYPE_TEXT, 561 + ARRAY_SIZE(POWER_SUPPLY_CHARGE_TYPE_TEXT), 562 + buf); 563 + 564 + if (i < 0) 565 + return i; 566 + 567 + if (available_types & BIT(i)) 568 + return i; 569 + 570 + return -EINVAL; 571 + } 572 + EXPORT_SYMBOL_GPL(power_supply_charge_types_parse); 573 + 574 + int power_supply_sysfs_add_extension(struct power_supply *psy, const struct power_supply_ext *ext, 575 + struct device *dev) 576 + { 577 + return sysfs_add_link_to_group(&psy->dev.kobj, power_supply_extension_group.name, 578 + &dev->kobj, ext->name); 579 + } 580 + 581 + void power_supply_sysfs_remove_extension(struct power_supply *psy, 582 + const struct power_supply_ext *ext) 583 + { 584 + sysfs_remove_link_from_group(&psy->dev.kobj, power_supply_extension_group.name, ext->name); 585 + }
+3 -2
drivers/power/supply/sbs-battery.c
··· 21 21 #include <linux/power_supply.h> 22 22 #include <linux/slab.h> 23 23 #include <linux/stat.h> 24 + #include <linux/string_choices.h> 24 25 25 26 enum { 26 27 REG_MANUFACTURER_DATA, ··· 321 320 client->flags &= ~I2C_CLIENT_PEC; 322 321 } 323 322 324 - dev_dbg(&client->dev, "PEC: %s\n", (client->flags & I2C_CLIENT_PEC) ? 325 - "enabled" : "disabled"); 323 + dev_dbg(&client->dev, "PEC: %s\n", 324 + str_enabled_disabled(client->flags & I2C_CLIENT_PEC)); 326 325 327 326 if (!chip->is_present && is_present && !chip->charger_broadcasts) 328 327 sbs_disable_charger_broadcasts(chip);
+612
drivers/power/supply/stc3117_fuel_gauge.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * stc3117_fuel_gauge.c - STMicroelectronics STC3117 Fuel Gauge Driver 4 + * 5 + * Copyright (c) 2024 Silicon Signals Pvt Ltd. 6 + * Author: Hardevsinh Palaniya <hardevsinh.palaniya@siliconsignals.io> 7 + * Bhavin Sharma <bhavin.sharma@siliconsignals.io> 8 + */ 9 + 10 + #include <linux/crc8.h> 11 + #include <linux/devm-helpers.h> 12 + #include <linux/i2c.h> 13 + #include <linux/power_supply.h> 14 + #include <linux/regmap.h> 15 + #include <linux/workqueue.h> 16 + 17 + #define STC3117_ADDR_MODE 0x00 18 + #define STC3117_ADDR_CTRL 0x01 19 + #define STC3117_ADDR_SOC_L 0x02 20 + #define STC3117_ADDR_SOC_H 0x03 21 + #define STC3117_ADDR_COUNTER_L 0x04 22 + #define STC3117_ADDR_COUNTER_H 0x05 23 + #define STC3117_ADDR_CURRENT_L 0x06 24 + #define STC3117_ADDR_CURRENT_H 0x07 25 + #define STC3117_ADDR_VOLTAGE_L 0x08 26 + #define STC3117_ADDR_VOLTAGE_H 0x09 27 + #define STC3117_ADDR_TEMPERATURE 0x0A 28 + #define STC3117_ADDR_AVG_CURRENT_L 0x0B 29 + #define STC3117_ADDR_AVG_CURRENT_H 0x0C 30 + #define STC3117_ADDR_OCV_L 0x0D 31 + #define STC3117_ADDR_OCV_H 0x0E 32 + #define STC3117_ADDR_CC_CNF_L 0x0F 33 + #define STC3117_ADDR_CC_CNF_H 0x10 34 + #define STC3117_ADDR_VM_CNF_L 0x11 35 + #define STC3117_ADDR_VM_CNF_H 0x12 36 + #define STC3117_ADDR_ALARM_soc 0x13 37 + #define STC3117_ADDR_ALARM_VOLTAGE 0x14 38 + #define STC3117_ADDR_ID 0x18 39 + #define STC3117_ADDR_CC_ADJ_L 0x1B 40 + #define STC3117_ADDR_CC_ADJ_H 0x1C 41 + #define STC3117_ADDR_VM_ADJ_L 0x1D 42 + #define STC3117_ADDR_VM_ADJ_H 0x1E 43 + #define STC3117_ADDR_RAM 0x20 44 + #define STC3117_ADDR_OCV_TABLE 0x30 45 + #define STC3117_ADDR_SOC_TABLE 0x30 46 + 47 + /* Bit mask definition */ 48 + #define STC3117_ID 0x16 49 + #define STC3117_MIXED_MODE 0x00 50 + #define STC3117_VMODE BIT(0) 51 + #define STC3117_GG_RUN BIT(4) 52 + #define STC3117_CC_MODE BIT(5) 53 + #define STC3117_BATFAIL BIT(3) 54 + #define STC3117_PORDET BIT(4) 55 + #define STC3117_RAM_SIZE 16 56 + #define STC3117_OCV_TABLE_SIZE 16 57 + #define STC3117_RAM_TESTWORD 0x53A9 58 + #define STC3117_SOFT_RESET 0x11 59 + #define STC3117_NOMINAL_CAPACITY 2600 60 + 61 + #define VOLTAGE_LSB_VALUE 9011 62 + #define CURRENT_LSB_VALUE 24084 63 + #define APP_CUTOFF_VOLTAGE 2500 64 + #define MAX_HRSOC 51200 65 + #define MAX_SOC 1000 66 + #define CHG_MIN_CURRENT 200 67 + #define CHG_END_CURRENT 20 68 + #define APP_MIN_CURRENT (-5) 69 + #define BATTERY_FULL 95 70 + #define CRC8_POLYNOMIAL 0x07 71 + #define CRC8_INIT 0x00 72 + 73 + DECLARE_CRC8_TABLE(stc3117_crc_table); 74 + 75 + enum stc3117_state { 76 + STC3117_INIT, 77 + STC3117_RUNNING, 78 + STC3117_POWERDN, 79 + }; 80 + 81 + /* Default ocv curve Li-ion battery */ 82 + static const int ocv_value[16] = { 83 + 3400, 3582, 3669, 3676, 3699, 3737, 3757, 3774, 84 + 3804, 3844, 3936, 3984, 4028, 4131, 4246, 4320 85 + }; 86 + 87 + union stc3117_internal_ram { 88 + u8 ram_bytes[STC3117_RAM_SIZE]; 89 + struct { 90 + u16 testword; /* 0-1 Bytes */ 91 + u16 hrsoc; /* 2-3 Bytes */ 92 + u16 cc_cnf; /* 4-5 Bytes */ 93 + u16 vm_cnf; /* 6-7 Bytes */ 94 + u8 soc; /* 8 Byte */ 95 + u8 state; /* 9 Byte */ 96 + u8 unused[5]; /* 10-14 Bytes */ 97 + u8 crc; /* 15 Byte */ 98 + } reg; 99 + }; 100 + 101 + struct stc3117_battery_info { 102 + int voltage_min_mv; 103 + int voltage_max_mv; 104 + int battery_capacity_mah; 105 + int sense_resistor; 106 + }; 107 + 108 + struct stc3117_data { 109 + struct i2c_client *client; 110 + struct regmap *regmap; 111 + struct delayed_work update_work; 112 + struct power_supply *battery; 113 + union stc3117_internal_ram ram_data; 114 + struct stc3117_battery_info battery_info; 115 + 116 + u8 soc_tab[16]; 117 + int cc_cnf; 118 + int vm_cnf; 119 + int cc_adj; 120 + int vm_adj; 121 + int avg_current; 122 + int avg_voltage; 123 + int batt_current; 124 + int voltage; 125 + int temp; 126 + int soc; 127 + int ocv; 128 + int hrsoc; 129 + int presence; 130 + }; 131 + 132 + static int stc3117_convert(int value, int factor) 133 + { 134 + value = (value * factor) / 4096; 135 + return value * 1000; 136 + } 137 + 138 + static int stc3117_get_battery_data(struct stc3117_data *data) 139 + { 140 + u8 reg_list[16]; 141 + u8 data_adjust[4]; 142 + int value, mode; 143 + 144 + regmap_bulk_read(data->regmap, STC3117_ADDR_MODE, 145 + reg_list, sizeof(reg_list)); 146 + 147 + /* soc */ 148 + value = (reg_list[3] << 8) + reg_list[2]; 149 + data->hrsoc = value; 150 + data->soc = (value * 10 + 256) / 512; 151 + 152 + /* current in uA*/ 153 + value = (reg_list[7] << 8) + reg_list[6]; 154 + data->batt_current = stc3117_convert(value, 155 + CURRENT_LSB_VALUE / data->battery_info.sense_resistor); 156 + 157 + /* voltage in uV */ 158 + value = (reg_list[9] << 8) + reg_list[8]; 159 + data->voltage = stc3117_convert(value, VOLTAGE_LSB_VALUE); 160 + 161 + /* temp in 1/10 °C */ 162 + data->temp = reg_list[10] * 10; 163 + 164 + /* Avg current in uA */ 165 + value = (reg_list[12] << 8) + reg_list[11]; 166 + regmap_read(data->regmap, STC3117_ADDR_MODE, &mode); 167 + if (!(mode & STC3117_VMODE)) { 168 + value = stc3117_convert(value, 169 + CURRENT_LSB_VALUE / data->battery_info.sense_resistor); 170 + value = value / 4; 171 + } else { 172 + value = stc3117_convert(value, 36 * STC3117_NOMINAL_CAPACITY); 173 + } 174 + data->avg_current = value; 175 + 176 + /* ocv in uV */ 177 + value = (reg_list[14] << 8) + reg_list[13]; 178 + value = stc3117_convert(value, VOLTAGE_LSB_VALUE); 179 + value = (value + 2) / 4; 180 + data->ocv = value; 181 + 182 + /* CC & VM adjustment counters */ 183 + regmap_bulk_read(data->regmap, STC3117_ADDR_CC_ADJ_L, 184 + data_adjust, sizeof(data_adjust)); 185 + value = (data_adjust[1] << 8) + data_adjust[0]; 186 + data->cc_adj = value; 187 + 188 + value = (data_adjust[3] << 8) + data_adjust[2]; 189 + data->vm_adj = value; 190 + 191 + return 0; 192 + } 193 + 194 + static int ram_write(struct stc3117_data *data) 195 + { 196 + int ret; 197 + 198 + ret = regmap_bulk_write(data->regmap, STC3117_ADDR_RAM, 199 + data->ram_data.ram_bytes, STC3117_RAM_SIZE); 200 + if (ret) 201 + return ret; 202 + 203 + return 0; 204 + }; 205 + 206 + static int ram_read(struct stc3117_data *data) 207 + { 208 + int ret; 209 + 210 + ret = regmap_bulk_read(data->regmap, STC3117_ADDR_RAM, 211 + data->ram_data.ram_bytes, STC3117_RAM_SIZE); 212 + if (ret) 213 + return ret; 214 + 215 + return 0; 216 + }; 217 + 218 + static int stc3117_set_para(struct stc3117_data *data) 219 + { 220 + int ret; 221 + 222 + ret = regmap_write(data->regmap, STC3117_ADDR_MODE, STC3117_VMODE); 223 + 224 + for (int i = 0; i < STC3117_OCV_TABLE_SIZE; i++) 225 + ret |= regmap_write(data->regmap, STC3117_ADDR_OCV_TABLE + i, 226 + ocv_value[i] * 100 / 55); 227 + if (data->soc_tab[1] != 0) 228 + ret |= regmap_bulk_write(data->regmap, STC3117_ADDR_SOC_TABLE, 229 + data->soc_tab, STC3117_OCV_TABLE_SIZE); 230 + 231 + ret |= regmap_write(data->regmap, STC3117_ADDR_CC_CNF_H, 232 + (data->ram_data.reg.cc_cnf >> 8) & 0xFF); 233 + 234 + ret |= regmap_write(data->regmap, STC3117_ADDR_CC_CNF_L, 235 + data->ram_data.reg.cc_cnf & 0xFF); 236 + 237 + ret |= regmap_write(data->regmap, STC3117_ADDR_VM_CNF_H, 238 + (data->ram_data.reg.vm_cnf >> 8) & 0xFF); 239 + 240 + ret |= regmap_write(data->regmap, STC3117_ADDR_VM_CNF_L, 241 + data->ram_data.reg.vm_cnf & 0xFF); 242 + 243 + ret |= regmap_write(data->regmap, STC3117_ADDR_CTRL, 0x03); 244 + 245 + ret |= regmap_write(data->regmap, STC3117_ADDR_MODE, 246 + STC3117_MIXED_MODE | STC3117_GG_RUN); 247 + 248 + return ret; 249 + }; 250 + 251 + static int stc3117_init(struct stc3117_data *data) 252 + { 253 + int id, ret; 254 + int ctrl; 255 + int ocv_m, ocv_l; 256 + 257 + regmap_read(data->regmap, STC3117_ADDR_ID, &id); 258 + if (id != STC3117_ID) 259 + return -EINVAL; 260 + 261 + data->cc_cnf = (data->battery_info.battery_capacity_mah * 262 + data->battery_info.sense_resistor * 250 + 6194) / 12389; 263 + data->vm_cnf = (data->battery_info.battery_capacity_mah 264 + * 200 * 50 + 24444) / 48889; 265 + 266 + /* Battery has not been removed */ 267 + data->presence = 1; 268 + 269 + /* Read RAM data */ 270 + ret = ram_read(data); 271 + if (ret) 272 + return ret; 273 + 274 + if (data->ram_data.reg.testword != STC3117_RAM_TESTWORD || 275 + (crc8(stc3117_crc_table, data->ram_data.ram_bytes, 276 + STC3117_RAM_SIZE, CRC8_INIT)) != 0) { 277 + data->ram_data.reg.testword = STC3117_RAM_TESTWORD; 278 + data->ram_data.reg.cc_cnf = data->cc_cnf; 279 + data->ram_data.reg.vm_cnf = data->vm_cnf; 280 + data->ram_data.reg.crc = crc8(stc3117_crc_table, 281 + data->ram_data.ram_bytes, 282 + STC3117_RAM_SIZE - 1, CRC8_INIT); 283 + 284 + ret = regmap_read(data->regmap, STC3117_ADDR_OCV_H, &ocv_m); 285 + 286 + ret |= regmap_read(data->regmap, STC3117_ADDR_OCV_L, &ocv_l); 287 + 288 + ret |= stc3117_set_para(data); 289 + 290 + ret |= regmap_write(data->regmap, STC3117_ADDR_OCV_H, ocv_m); 291 + 292 + ret |= regmap_write(data->regmap, STC3117_ADDR_OCV_L, ocv_l); 293 + if (ret) 294 + return ret; 295 + } else { 296 + ret = regmap_read(data->regmap, STC3117_ADDR_CTRL, &ctrl); 297 + if (ret) 298 + return ret; 299 + 300 + if ((ctrl & STC3117_BATFAIL) != 0 || 301 + (ctrl & STC3117_PORDET) != 0) { 302 + ret = regmap_read(data->regmap, 303 + STC3117_ADDR_OCV_H, &ocv_m); 304 + 305 + ret |= regmap_read(data->regmap, 306 + STC3117_ADDR_OCV_L, &ocv_l); 307 + 308 + ret |= stc3117_set_para(data); 309 + 310 + ret |= regmap_write(data->regmap, 311 + STC3117_ADDR_OCV_H, ocv_m); 312 + 313 + ret |= regmap_write(data->regmap, 314 + STC3117_ADDR_OCV_L, ocv_l); 315 + if (ret) 316 + return ret; 317 + } else { 318 + ret = stc3117_set_para(data); 319 + ret |= regmap_write(data->regmap, STC3117_ADDR_SOC_H, 320 + (data->ram_data.reg.hrsoc >> 8 & 0xFF)); 321 + ret |= regmap_write(data->regmap, STC3117_ADDR_SOC_L, 322 + (data->ram_data.reg.hrsoc & 0xFF)); 323 + if (ret) 324 + return ret; 325 + } 326 + } 327 + 328 + data->ram_data.reg.state = STC3117_INIT; 329 + data->ram_data.reg.crc = crc8(stc3117_crc_table, 330 + data->ram_data.ram_bytes, 331 + STC3117_RAM_SIZE - 1, CRC8_INIT); 332 + ret = ram_write(data); 333 + if (ret) 334 + return ret; 335 + 336 + return 0; 337 + }; 338 + 339 + static int stc3117_task(struct stc3117_data *data) 340 + { 341 + int id, mode, ret; 342 + int count_l, count_m; 343 + int ocv_l, ocv_m; 344 + 345 + regmap_read(data->regmap, STC3117_ADDR_ID, &id); 346 + if (id != STC3117_ID) { 347 + data->presence = 0; 348 + return -EINVAL; 349 + } 350 + 351 + stc3117_get_battery_data(data); 352 + 353 + /* Read RAM data */ 354 + ret = ram_read(data); 355 + if (ret) 356 + return ret; 357 + 358 + if (data->ram_data.reg.testword != STC3117_RAM_TESTWORD || 359 + (crc8(stc3117_crc_table, data->ram_data.ram_bytes, 360 + STC3117_RAM_SIZE, CRC8_INIT) != 0)) { 361 + data->ram_data.reg.testword = STC3117_RAM_TESTWORD; 362 + data->ram_data.reg.cc_cnf = data->cc_cnf; 363 + data->ram_data.reg.vm_cnf = data->vm_cnf; 364 + data->ram_data.reg.crc = crc8(stc3117_crc_table, 365 + data->ram_data.ram_bytes, 366 + STC3117_RAM_SIZE - 1, CRC8_INIT); 367 + data->ram_data.reg.state = STC3117_INIT; 368 + } 369 + 370 + /* check battery presence status */ 371 + ret = regmap_read(data->regmap, STC3117_ADDR_CTRL, &mode); 372 + if ((mode & STC3117_BATFAIL) != 0) { 373 + data->presence = 0; 374 + data->ram_data.reg.testword = 0; 375 + data->ram_data.reg.state = STC3117_INIT; 376 + ret = ram_write(data); 377 + ret |= regmap_write(data->regmap, STC3117_ADDR_CTRL, STC3117_PORDET); 378 + if (ret) 379 + return ret; 380 + } 381 + 382 + data->presence = 1; 383 + 384 + ret = regmap_read(data->regmap, STC3117_ADDR_MODE, &mode); 385 + if (ret) 386 + return ret; 387 + if ((mode & STC3117_GG_RUN) == 0) { 388 + if (data->ram_data.reg.state > STC3117_INIT) { 389 + ret = stc3117_set_para(data); 390 + 391 + ret |= regmap_write(data->regmap, STC3117_ADDR_SOC_H, 392 + (data->ram_data.reg.hrsoc >> 8 & 0xFF)); 393 + ret |= regmap_write(data->regmap, STC3117_ADDR_SOC_L, 394 + (data->ram_data.reg.hrsoc & 0xFF)); 395 + if (ret) 396 + return ret; 397 + } else { 398 + ret = regmap_read(data->regmap, STC3117_ADDR_OCV_H, &ocv_m); 399 + 400 + ret |= regmap_read(data->regmap, STC3117_ADDR_OCV_L, &ocv_l); 401 + 402 + ret |= stc3117_set_para(data); 403 + 404 + ret |= regmap_write(data->regmap, STC3117_ADDR_OCV_H, ocv_m); 405 + 406 + ret |= regmap_write(data->regmap, STC3117_ADDR_OCV_L, ocv_l); 407 + if (ret) 408 + return ret; 409 + } 410 + data->ram_data.reg.state = STC3117_INIT; 411 + } 412 + 413 + regmap_read(data->regmap, STC3117_ADDR_COUNTER_L, &count_l); 414 + regmap_read(data->regmap, STC3117_ADDR_COUNTER_H, &count_m); 415 + 416 + count_m = (count_m << 8) + count_l; 417 + 418 + /* INIT state, wait for batt_current & temperature value available: */ 419 + if (data->ram_data.reg.state == STC3117_INIT && count_m > 4) { 420 + data->avg_voltage = data->voltage; 421 + data->avg_current = data->batt_current; 422 + data->ram_data.reg.state = STC3117_RUNNING; 423 + } 424 + 425 + if (data->ram_data.reg.state != STC3117_RUNNING) { 426 + data->batt_current = -ENODATA; 427 + data->temp = -ENODATA; 428 + } else { 429 + if (data->voltage < APP_CUTOFF_VOLTAGE) 430 + data->soc = -ENODATA; 431 + 432 + if (mode & STC3117_VMODE) { 433 + data->avg_current = -ENODATA; 434 + data->batt_current = -ENODATA; 435 + } 436 + } 437 + 438 + data->ram_data.reg.hrsoc = data->hrsoc; 439 + data->ram_data.reg.soc = (data->soc + 5) / 10; 440 + data->ram_data.reg.crc = crc8(stc3117_crc_table, 441 + data->ram_data.ram_bytes, 442 + STC3117_RAM_SIZE - 1, CRC8_INIT); 443 + 444 + ret = ram_write(data); 445 + if (ret) 446 + return ret; 447 + return 0; 448 + }; 449 + 450 + static void fuel_gauge_update_work(struct work_struct *work) 451 + { 452 + struct stc3117_data *data = 453 + container_of(work, struct stc3117_data, update_work.work); 454 + 455 + stc3117_task(data); 456 + 457 + /* Schedule the work to run again in 2 seconds */ 458 + schedule_delayed_work(&data->update_work, msecs_to_jiffies(2000)); 459 + } 460 + 461 + static int stc3117_get_property(struct power_supply *psy, 462 + enum power_supply_property psp, union power_supply_propval *val) 463 + { 464 + struct stc3117_data *data = power_supply_get_drvdata(psy); 465 + 466 + switch (psp) { 467 + case POWER_SUPPLY_PROP_STATUS: 468 + if (data->soc > BATTERY_FULL) 469 + val->intval = POWER_SUPPLY_STATUS_FULL; 470 + else if (data->batt_current < 0) 471 + val->intval = POWER_SUPPLY_STATUS_CHARGING; 472 + else if (data->batt_current > 0) 473 + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 474 + else 475 + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 476 + break; 477 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 478 + val->intval = data->voltage; 479 + break; 480 + case POWER_SUPPLY_PROP_CURRENT_NOW: 481 + val->intval = data->batt_current; 482 + break; 483 + case POWER_SUPPLY_PROP_VOLTAGE_OCV: 484 + val->intval = data->ocv; 485 + break; 486 + case POWER_SUPPLY_PROP_CURRENT_AVG: 487 + val->intval = data->avg_current; 488 + break; 489 + case POWER_SUPPLY_PROP_CAPACITY: 490 + val->intval = data->soc; 491 + break; 492 + case POWER_SUPPLY_PROP_TEMP: 493 + val->intval = data->temp; 494 + break; 495 + case POWER_SUPPLY_PROP_PRESENT: 496 + val->intval = data->presence; 497 + break; 498 + default: 499 + return -EINVAL; 500 + } 501 + return 0; 502 + } 503 + 504 + static enum power_supply_property stc3117_battery_props[] = { 505 + POWER_SUPPLY_PROP_STATUS, 506 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 507 + POWER_SUPPLY_PROP_CURRENT_NOW, 508 + POWER_SUPPLY_PROP_VOLTAGE_OCV, 509 + POWER_SUPPLY_PROP_CURRENT_AVG, 510 + POWER_SUPPLY_PROP_CAPACITY, 511 + POWER_SUPPLY_PROP_TEMP, 512 + POWER_SUPPLY_PROP_PRESENT, 513 + }; 514 + 515 + static const struct power_supply_desc stc3117_battery_desc = { 516 + .name = "stc3117-battery", 517 + .type = POWER_SUPPLY_TYPE_BATTERY, 518 + .get_property = stc3117_get_property, 519 + .properties = stc3117_battery_props, 520 + .num_properties = ARRAY_SIZE(stc3117_battery_props), 521 + }; 522 + 523 + static const struct regmap_config stc3117_regmap_config = { 524 + .reg_bits = 8, 525 + .val_bits = 8, 526 + }; 527 + 528 + static int stc3117_probe(struct i2c_client *client) 529 + { 530 + struct stc3117_data *data; 531 + struct power_supply_config psy_cfg = {}; 532 + struct power_supply_battery_info *info; 533 + int ret; 534 + 535 + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 536 + if (!data) 537 + return -ENOMEM; 538 + 539 + data->client = client; 540 + data->regmap = devm_regmap_init_i2c(client, &stc3117_regmap_config); 541 + if (IS_ERR(data->regmap)) 542 + return PTR_ERR(data->regmap); 543 + 544 + psy_cfg.drv_data = data; 545 + psy_cfg.fwnode = dev_fwnode(&client->dev); 546 + 547 + crc8_populate_msb(stc3117_crc_table, CRC8_POLYNOMIAL); 548 + 549 + data->battery = devm_power_supply_register(&client->dev, 550 + &stc3117_battery_desc, &psy_cfg); 551 + if (IS_ERR(data->battery)) 552 + return dev_err_probe(&client->dev, PTR_ERR(data->battery), 553 + "failed to register battery\n"); 554 + 555 + ret = device_property_read_u32(&client->dev, "shunt-resistor-micro-ohms", 556 + &data->battery_info.sense_resistor); 557 + if (ret) 558 + return dev_err_probe(&client->dev, ret, 559 + "failed to get shunt-resistor-micro-ohms\n"); 560 + data->battery_info.sense_resistor = data->battery_info.sense_resistor / 1000; 561 + 562 + ret = power_supply_get_battery_info(data->battery, &info); 563 + if (ret) 564 + return dev_err_probe(&client->dev, ret, 565 + "failed to get battery information\n"); 566 + 567 + data->battery_info.battery_capacity_mah = info->charge_full_design_uah / 1000; 568 + data->battery_info.voltage_min_mv = info->voltage_min_design_uv / 1000; 569 + data->battery_info.voltage_max_mv = info->voltage_max_design_uv / 1000; 570 + 571 + ret = stc3117_init(data); 572 + if (ret) 573 + return dev_err_probe(&client->dev, ret, 574 + "failed to initialize of stc3117\n"); 575 + 576 + ret = devm_delayed_work_autocancel(&client->dev, &data->update_work, 577 + fuel_gauge_update_work); 578 + if (ret) 579 + return ret; 580 + 581 + schedule_delayed_work(&data->update_work, 0); 582 + 583 + return 0; 584 + } 585 + 586 + static const struct i2c_device_id stc3117_id[] = { 587 + { "stc3117", 0 }, 588 + { } 589 + }; 590 + MODULE_DEVICE_TABLE(i2c, stc3117_id); 591 + 592 + static const struct of_device_id stc3117_of_match[] = { 593 + { .compatible = "st,stc3117" }, 594 + { } 595 + }; 596 + MODULE_DEVICE_TABLE(of, stc3117_of_match); 597 + 598 + static struct i2c_driver stc3117_i2c_driver = { 599 + .driver = { 600 + .name = "stc3117_i2c_driver", 601 + .of_match_table = stc3117_of_match, 602 + }, 603 + .probe = stc3117_probe, 604 + .id_table = stc3117_id, 605 + }; 606 + 607 + module_i2c_driver(stc3117_i2c_driver); 608 + 609 + MODULE_LICENSE("GPL"); 610 + MODULE_AUTHOR("Hardevsinh Palaniya <hardevsinh.palaniya@siliconsignals.io>"); 611 + MODULE_AUTHOR("Bhavin Sharma <bhavin.sharma@siliconsignals.io>"); 612 + MODULE_DESCRIPTION("STC3117 Fuel Gauge Driver");
+2 -2
drivers/power/supply/surface_battery.c
··· 667 667 668 668 static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, char *buf) 669 669 { 670 - struct power_supply *psy = dev_get_drvdata(dev); 670 + struct power_supply *psy = dev_to_psy(dev); 671 671 struct spwr_battery_device *bat = power_supply_get_drvdata(psy); 672 672 int status; 673 673 ··· 681 681 static ssize_t alarm_store(struct device *dev, struct device_attribute *attr, const char *buf, 682 682 size_t count) 683 683 { 684 - struct power_supply *psy = dev_get_drvdata(dev); 684 + struct power_supply *psy = dev_to_psy(dev); 685 685 struct spwr_battery_device *bat = power_supply_get_drvdata(psy); 686 686 unsigned long value; 687 687 int status;
+113
drivers/power/supply/test_power.c
··· 37 37 static int battery_current = -1600; 38 38 static enum power_supply_charge_behaviour battery_charge_behaviour = 39 39 POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO; 40 + static bool battery_extension; 40 41 41 42 static bool module_initialized; 42 43 ··· 239 238 }, 240 239 }; 241 240 241 + static int test_power_battery_extmanufacture_year = 1234; 242 + static int test_power_battery_exttemp_max = 1000; 243 + static const enum power_supply_property test_power_battery_extprops[] = { 244 + POWER_SUPPLY_PROP_MANUFACTURE_YEAR, 245 + POWER_SUPPLY_PROP_TEMP_MAX, 246 + }; 247 + 248 + static int test_power_battery_extget_property(struct power_supply *psy, 249 + const struct power_supply_ext *ext, 250 + void *ext_data, 251 + enum power_supply_property psp, 252 + union power_supply_propval *val) 253 + { 254 + switch (psp) { 255 + case POWER_SUPPLY_PROP_MANUFACTURE_YEAR: 256 + val->intval = test_power_battery_extmanufacture_year; 257 + break; 258 + case POWER_SUPPLY_PROP_TEMP_MAX: 259 + val->intval = test_power_battery_exttemp_max; 260 + break; 261 + default: 262 + return -EINVAL; 263 + } 264 + return 0; 265 + } 266 + 267 + static int test_power_battery_extset_property(struct power_supply *psy, 268 + const struct power_supply_ext *ext, 269 + void *ext_data, 270 + enum power_supply_property psp, 271 + const union power_supply_propval *val) 272 + { 273 + switch (psp) { 274 + case POWER_SUPPLY_PROP_MANUFACTURE_YEAR: 275 + test_power_battery_extmanufacture_year = val->intval; 276 + break; 277 + case POWER_SUPPLY_PROP_TEMP_MAX: 278 + test_power_battery_exttemp_max = val->intval; 279 + break; 280 + default: 281 + return -EINVAL; 282 + } 283 + return 0; 284 + } 285 + 286 + static int test_power_battery_extproperty_is_writeable(struct power_supply *psy, 287 + const struct power_supply_ext *ext, 288 + void *ext_data, 289 + enum power_supply_property psp) 290 + { 291 + return true; 292 + } 293 + 294 + static const struct power_supply_ext test_power_battery_ext = { 295 + .name = "test_power", 296 + .properties = test_power_battery_extprops, 297 + .num_properties = ARRAY_SIZE(test_power_battery_extprops), 298 + .get_property = test_power_battery_extget_property, 299 + .set_property = test_power_battery_extset_property, 300 + .property_is_writeable = test_power_battery_extproperty_is_writeable, 301 + }; 302 + 303 + static void test_power_configure_battery_extension(bool enable) 304 + { 305 + struct power_supply *psy; 306 + 307 + psy = test_power_supplies[TEST_BATTERY]; 308 + 309 + if (enable) { 310 + if (power_supply_register_extension(psy, &test_power_battery_ext, &psy->dev, 311 + NULL)) { 312 + pr_err("registering battery extension failed\n"); 313 + return; 314 + } 315 + } else { 316 + power_supply_unregister_extension(psy, &test_power_battery_ext); 317 + } 318 + 319 + battery_extension = enable; 320 + } 321 + 242 322 static int __init test_power_init(void) 243 323 { 244 324 int i; ··· 339 257 goto failed; 340 258 } 341 259 } 260 + 261 + test_power_configure_battery_extension(true); 342 262 343 263 module_initialized = true; 344 264 return 0; ··· 608 524 609 525 #define param_get_battery_current param_get_int 610 526 527 + static int param_set_battery_extension(const char *key, 528 + const struct kernel_param *kp) 529 + { 530 + bool prev_battery_extension; 531 + int ret; 532 + 533 + prev_battery_extension = battery_extension; 534 + 535 + ret = param_set_bool(key, kp); 536 + if (ret) 537 + return ret; 538 + 539 + if (prev_battery_extension != battery_extension) 540 + test_power_configure_battery_extension(battery_extension); 541 + 542 + return 0; 543 + } 544 + 545 + #define param_get_battery_extension param_get_bool 546 + 611 547 static const struct kernel_param_ops param_ops_ac_online = { 612 548 .set = param_set_ac_online, 613 549 .get = param_get_ac_online, ··· 678 574 .get = param_get_battery_current, 679 575 }; 680 576 577 + static const struct kernel_param_ops param_ops_battery_extension = { 578 + .set = param_set_battery_extension, 579 + .get = param_get_battery_extension, 580 + }; 581 + 681 582 #define param_check_ac_online(name, p) __param_check(name, p, void); 682 583 #define param_check_usb_online(name, p) __param_check(name, p, void); 683 584 #define param_check_battery_status(name, p) __param_check(name, p, void); ··· 693 584 #define param_check_battery_voltage(name, p) __param_check(name, p, void); 694 585 #define param_check_battery_charge_counter(name, p) __param_check(name, p, void); 695 586 #define param_check_battery_current(name, p) __param_check(name, p, void); 587 + #define param_check_battery_extension(name, p) __param_check(name, p, void); 696 588 697 589 698 590 module_param(ac_online, ac_online, 0644); ··· 730 620 731 621 module_param(battery_current, battery_current, 0644); 732 622 MODULE_PARM_DESC(battery_current, "battery current (milliampere)"); 623 + 624 + module_param(battery_extension, battery_extension, 0644); 625 + MODULE_PARM_DESC(battery_extension, "battery extension"); 733 626 734 627 MODULE_DESCRIPTION("Power supply driver for testing"); 735 628 MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
-4
drivers/power/supply/ug3105_battery.c
··· 287 287 static enum power_supply_property ug3105_battery_props[] = { 288 288 POWER_SUPPLY_PROP_STATUS, 289 289 POWER_SUPPLY_PROP_PRESENT, 290 - POWER_SUPPLY_PROP_TECHNOLOGY, 291 290 POWER_SUPPLY_PROP_SCOPE, 292 291 POWER_SUPPLY_PROP_VOLTAGE_NOW, 293 292 POWER_SUPPLY_PROP_VOLTAGE_OCV, ··· 314 315 break; 315 316 case POWER_SUPPLY_PROP_PRESENT: 316 317 val->intval = 1; 317 - break; 318 - case POWER_SUPPLY_PROP_TECHNOLOGY: 319 - val->intval = chip->info->technology; 320 318 break; 321 319 case POWER_SUPPLY_PROP_SCOPE: 322 320 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
+1
include/linux/power/bq27xxx_battery.h
··· 61 61 struct bq27xxx_access_methods bus; 62 62 struct bq27xxx_reg_cache cache; 63 63 int charge_design_full; 64 + int voltage_min_design; 64 65 bool removed; 65 66 unsigned long last_update; 66 67 union power_supply_propval last_status;
+61 -2
include/linux/power_supply.h
··· 15 15 #include <linux/device.h> 16 16 #include <linux/workqueue.h> 17 17 #include <linux/leds.h> 18 + #include <linux/rwsem.h> 19 + #include <linux/list.h> 18 20 #include <linux/spinlock.h> 19 21 #include <linux/notifier.h> 20 22 ··· 42 40 }; 43 41 44 42 /* What algorithm is the charger using? */ 45 - enum { 43 + enum power_supply_charge_type { 46 44 POWER_SUPPLY_CHARGE_TYPE_UNKNOWN = 0, 47 45 POWER_SUPPLY_CHARGE_TYPE_NONE, 48 46 POWER_SUPPLY_CHARGE_TYPE_TRICKLE, /* slow speed */ ··· 60 58 POWER_SUPPLY_HEALTH_OVERHEAT, 61 59 POWER_SUPPLY_HEALTH_DEAD, 62 60 POWER_SUPPLY_HEALTH_OVERVOLTAGE, 61 + POWER_SUPPLY_HEALTH_UNDERVOLTAGE, 63 62 POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, 64 63 POWER_SUPPLY_HEALTH_COLD, 65 64 POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE, ··· 102 99 /* Properties of type `int' */ 103 100 POWER_SUPPLY_PROP_STATUS = 0, 104 101 POWER_SUPPLY_PROP_CHARGE_TYPE, 102 + POWER_SUPPLY_PROP_CHARGE_TYPES, 105 103 POWER_SUPPLY_PROP_HEALTH, 106 104 POWER_SUPPLY_PROP_PRESENT, 107 105 POWER_SUPPLY_PROP_ONLINE, ··· 249 245 const char *name; 250 246 enum power_supply_type type; 251 247 u8 charge_behaviours; 248 + u32 charge_types; 252 249 u32 usb_types; 253 250 const enum power_supply_property *properties; 254 251 size_t num_properties; ··· 286 281 int use_for_apm; 287 282 }; 288 283 284 + struct power_supply_ext { 285 + const char *const name; 286 + u8 charge_behaviours; 287 + const enum power_supply_property *properties; 288 + size_t num_properties; 289 + 290 + int (*get_property)(struct power_supply *psy, 291 + const struct power_supply_ext *ext, 292 + void *data, 293 + enum power_supply_property psp, 294 + union power_supply_propval *val); 295 + int (*set_property)(struct power_supply *psy, 296 + const struct power_supply_ext *ext, 297 + void *data, 298 + enum power_supply_property psp, 299 + const union power_supply_propval *val); 300 + int (*property_is_writeable)(struct power_supply *psy, 301 + const struct power_supply_ext *ext, 302 + void *data, 303 + enum power_supply_property psp); 304 + }; 305 + 289 306 struct power_supply { 290 307 const struct power_supply_desc *desc; 291 308 ··· 327 300 struct delayed_work deferred_register_work; 328 301 spinlock_t changed_lock; 329 302 bool changed; 303 + bool update_groups; 330 304 bool initialized; 331 305 bool removing; 332 306 atomic_t use_cnt; 333 307 struct power_supply_battery_info *battery_info; 308 + struct rw_semaphore extensions_sem; /* protects "extensions" */ 309 + struct list_head extensions; 334 310 #ifdef CONFIG_THERMAL 335 311 struct thermal_zone_device *tzd; 336 312 struct thermal_cooling_device *tcd; ··· 347 317 struct led_trigger *charging_orange_full_green_trig; 348 318 #endif 349 319 }; 320 + 321 + #define dev_to_psy(__dev) container_of_const(__dev, struct power_supply, dev) 350 322 351 323 /* 352 324 * This is recommended structure to specify static power supply parameters. ··· 910 878 extern void power_supply_unregister(struct power_supply *psy); 911 879 extern int power_supply_powers(struct power_supply *psy, struct device *dev); 912 880 881 + extern int __must_check 882 + power_supply_register_extension(struct power_supply *psy, 883 + const struct power_supply_ext *ext, 884 + struct device *dev, 885 + void *data); 886 + extern void power_supply_unregister_extension(struct power_supply *psy, 887 + const struct power_supply_ext *ext); 888 + 913 889 #define to_power_supply(device) container_of(device, struct power_supply, dev) 914 890 915 891 extern void *power_supply_get_drvdata(struct power_supply *psy); 916 - extern int power_supply_for_each_device(void *data, int (*fn)(struct device *dev, void *data)); 892 + extern int power_supply_for_each_psy(void *data, int (*fn)(struct power_supply *psy, void *data)); 917 893 918 894 static inline bool power_supply_is_amp_property(enum power_supply_property psp) 919 895 { ··· 984 944 char *buf); 985 945 986 946 int power_supply_charge_behaviour_parse(unsigned int available_behaviours, const char *buf); 947 + ssize_t power_supply_charge_types_show(struct device *dev, 948 + unsigned int available_types, 949 + enum power_supply_charge_type current_type, 950 + char *buf); 951 + int power_supply_charge_types_parse(unsigned int available_types, const char *buf); 987 952 #else 988 953 static inline 989 954 ssize_t power_supply_charge_behaviour_show(struct device *dev, ··· 1001 956 1002 957 static inline int power_supply_charge_behaviour_parse(unsigned int available_behaviours, 1003 958 const char *buf) 959 + { 960 + return -EOPNOTSUPP; 961 + } 962 + 963 + static inline 964 + ssize_t power_supply_charge_types_show(struct device *dev, 965 + unsigned int available_types, 966 + enum power_supply_charge_type current_type, 967 + char *buf) 968 + { 969 + return -EOPNOTSUPP; 970 + } 971 + 972 + static inline int power_supply_charge_types_parse(unsigned int available_types, const char *buf) 1004 973 { 1005 974 return -EOPNOTSUPP; 1006 975 }