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

Merge tag 'for-v5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply

Pull power supply and reset updates from Sebastian Reichel:
"This time there are lots of changes. Quite a few changes to the core,
lots of driver changes and one change to kobject core (with Ack from
Greg).

Summary:

kobject:
- Increase number of allowed uevent variables

power-supply core:
- Add power-supply type in uevent
- Cleanup property handling in core
- Make property and usb_type pointers const
- Convert core power-supply DT binding to YAML
- Cleanup HWMON code
- Add new health status "calibration required"
- Add new properties for manufacture date and capacity error margin

battery drivers:
- new cw2015 battery driver used by pine64 Pinebook Pro laptop
- axp22: blacklist on Meegopad T02
- sc27xx: support current/voltage reading
- max17042: support time-to-empty reading
- simple-battery: add more battery parameters
- bq27xxx: convert DT binding document to YAML
- sbs-battery: add TI BQ20Z65 support, fix technology property,
convert DT binding to YAML, add option to disable charger
broadcasts, add new properties: manufacture date, capacity
error margin, average current, charge current and voltage and
support calibration required health status
- misc fixes

charger drivers:
- bq25890: cleanup, implement charge type, precharge current and
input current limiting properties
- bd70528: use new linear range helper library
- bd99954: new charger driver
- mp2629: new charger driver
- misc fixes

reboot drivers:
- oxnas-restart: introduce new driver
- syscon-reboot: convert DT binding to YAML, add parent syscon device
support
- misc fixes"

* tag 'for-v5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (85 commits)
power: supply: cw2015: Attach OF ID table to the driver
power: reset: gpio-poweroff: add missing '\n' in dev_err()
Revert "power: supply: sbs-battery: simplify read_read_string_data"
Revert "power: supply: sbs-battery: add PEC support"
dt-bindings: power: sbs-battery: Convert to yaml
power: supply: sbs-battery: constify power-supply property array
power: supply: sbs-battery: switch to i2c's probe_new
power: supply: sbs-battery: switch from of_property_* to device_property_*
power: supply: sbs-battery: add ability to disable charger broadcasts
power: supply: sbs-battery: fix idle battery status
power: supply: sbs-battery: add POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED support
power: supply: sbs-battery: add MANUFACTURE_DATE support
power: supply: sbs-battery: add POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT/VOLTAGE_MAX support
power: supply: sbs-battery: Improve POWER_SUPPLY_PROP_TECHNOLOGY support
power: supply: sbs-battery: add POWER_SUPPLY_PROP_CURRENT_AVG support
power: supply: sbs-battery: add PEC support
power: supply: sbs-battery: simplify read_read_string_data
power: supply: sbs-battery: add POWER_SUPPLY_PROP_CAPACITY_ERROR_MARGIN support
power: supply: sbs-battery: Add TI BQ20Z65 support
power: supply: core: add POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED
...

+4691 -676
+44 -1
Documentation/ABI/testing/sysfs-class-power
··· 74 74 Access: Read, Write 75 75 Valid values: 0 - 100 (percent) 76 76 77 + What: /sys/class/power_supply/<supply_name>/capacity_error_margin 78 + Date: April 2019 79 + Contact: linux-pm@vger.kernel.org 80 + Description: 81 + Battery capacity measurement becomes unreliable without 82 + recalibration. This values provides the maximum error 83 + margin expected to exist by the fuel gauge in percent. 84 + Values close to 0% will be returned after (re-)calibration 85 + has happened. Over time the error margin will increase. 86 + 100% means, that the capacity related values are basically 87 + completely useless. 88 + 89 + Access: Read 90 + Valid values: 0 - 100 (percent) 91 + 77 92 What: /sys/class/power_supply/<supply_name>/capacity_level 78 93 Date: June 2009 79 94 Contact: linux-pm@vger.kernel.org ··· 205 190 Valid values: "Unknown", "Good", "Overheat", "Dead", 206 191 "Over voltage", "Unspecified failure", "Cold", 207 192 "Watchdog timer expire", "Safety timer expire", 208 - "Over current" 193 + "Over current", "Calibration required" 209 194 210 195 What: /sys/class/power_supply/<supply_name>/precharge_current 211 196 Date: June 2017 ··· 680 665 Valid values: 681 666 - 1: enabled 682 667 - 0: disabled 668 + 669 + What: /sys/class/power_supply/<supply_name>/manufacture_year 670 + Date: January 2020 671 + Contact: linux-pm@vger.kernel.org 672 + Description: 673 + Reports the year (following Gregorian calendar) when the device has been 674 + manufactured. 675 + 676 + Access: Read 677 + Valid values: Reported as integer 678 + 679 + What: /sys/class/power_supply/<supply_name>/manufacture_month 680 + Date: January 2020 681 + Contact: linux-pm@vger.kernel.org 682 + Description: 683 + Reports the month when the device has been manufactured. 684 + 685 + Access: Read 686 + Valid values: 1-12 687 + 688 + What: /sys/class/power_supply/<supply_name>/manufacture_day 689 + Date: January 2020 690 + Contact: linux-pm@vger.kernel.org 691 + Description: 692 + Reports the day of month when the device has been manufactured. 693 + 694 + Access: Read 695 + Valid values: 1-31
-35
Documentation/devicetree/bindings/power/reset/syscon-reboot-mode.txt
··· 1 - SYSCON reboot mode driver 2 - 3 - This driver gets reboot mode magic value form reboot-mode driver 4 - and stores it in a SYSCON mapped register. Then the bootloader 5 - can read it and take different action according to the magic 6 - value stored. 7 - 8 - This DT node should be represented as a sub-node of a "syscon", "simple-mfd" 9 - node. 10 - 11 - Required properties: 12 - - compatible: should be "syscon-reboot-mode" 13 - - offset: offset in the register map for the storage register (in bytes) 14 - 15 - Optional property: 16 - - mask: bits mask of the bits in the register to store the reboot mode magic value, 17 - default set to 0xffffffff if missing. 18 - 19 - The rest of the properties should follow the generic reboot-mode description 20 - found in reboot-mode.txt 21 - 22 - Example: 23 - pmu: pmu@20004000 { 24 - compatible = "rockchip,rk3066-pmu", "syscon", "simple-mfd"; 25 - reg = <0x20004000 0x100>; 26 - 27 - reboot-mode { 28 - compatible = "syscon-reboot-mode"; 29 - offset = <0x40>; 30 - mode-normal = <BOOT_NORMAL>; 31 - mode-recovery = <BOOT_RECOVERY>; 32 - mode-bootloader = <BOOT_FASTBOOT>; 33 - mode-loader = <BOOT_BL_DOWNLOAD>; 34 - }; 35 - };
+55
Documentation/devicetree/bindings/power/reset/syscon-reboot-mode.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/power/reset/syscon-reboot-mode.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Generic SYSCON reboot mode driver 8 + 9 + maintainers: 10 + - Sebastian Reichel <sre@kernel.org> 11 + 12 + description: | 13 + This driver gets reboot mode magic value from reboot-mode driver 14 + and stores it in a SYSCON mapped register. Then the bootloader 15 + can read it and take different action according to the magic 16 + value stored. The SYSCON mapped register is retrieved from the 17 + parental dt-node plus the offset. So the SYSCON reboot-mode node 18 + should be represented as a sub-node of a "syscon", "simple-mfd" node. 19 + 20 + properties: 21 + compatible: 22 + const: syscon-reboot-mode 23 + 24 + mask: 25 + $ref: /schemas/types.yaml#/definitions/uint32 26 + description: Update only the register bits defined by the mask (32 bit) 27 + 28 + offset: 29 + $ref: /schemas/types.yaml#/definitions/uint32 30 + description: Offset in the register map for the mode register (in bytes) 31 + 32 + patternProperties: 33 + "^mode-.+": 34 + $ref: /schemas/types.yaml#/definitions/uint32 35 + description: Vendor-specific mode value written to the mode register 36 + 37 + additionalProperties: false 38 + 39 + required: 40 + - compatible 41 + - offset 42 + 43 + examples: 44 + - | 45 + #include <dt-bindings/soc/rockchip,boot-mode.h> 46 + 47 + reboot-mode { 48 + compatible = "syscon-reboot-mode"; 49 + offset = <0x40>; 50 + mode-normal = <BOOT_NORMAL>; 51 + mode-recovery = <BOOT_RECOVERY>; 52 + mode-bootloader = <BOOT_FASTBOOT>; 53 + mode-loader = <BOOT_BL_DOWNLOAD>; 54 + }; 55 + ...
+10 -5
Documentation/devicetree/bindings/power/reset/syscon-reboot.yaml
··· 12 12 description: |+ 13 13 This is a generic reset driver using syscon to map the reset register. 14 14 The reset is generally performed with a write to the reset register 15 - defined by the register map pointed by syscon reference plus the offset 16 - with the value and mask defined in the reboot node. 17 - Default will be little endian mode, 32 bit access only. 15 + defined by the SYSCON register map base plus the offset with the value and 16 + mask defined in the reboot node. Default will be little endian mode, 32 bit 17 + access only. The SYSCON registers map is normally retrieved from the 18 + parental dt-node. So the SYSCON reboot node should be represented as a 19 + sub-node of a "syscon", "simple-mfd" node. Though the regmap property 20 + pointing to the system controller node is also supported. 18 21 19 22 properties: 20 23 compatible: ··· 33 30 34 31 regmap: 35 32 $ref: /schemas/types.yaml#/definitions/phandle 36 - description: Phandle to the register map node. 33 + deprecated: true 34 + description: | 35 + Phandle to the register map node. This property is deprecated in favor of 36 + the syscon-reboot node been a child of a system controller node. 37 37 38 38 value: 39 39 $ref: /schemas/types.yaml#/definitions/uint32 ··· 44 38 45 39 required: 46 40 - compatible 47 - - regmap 48 41 - offset 49 42 50 43 additionalProperties: false
+6
Documentation/devicetree/bindings/power/supply/battery.txt
··· 11 11 behavior should a replacement that changes the battery type occur 12 12 without a corresponding update to the dtb. 13 13 14 + Please note that not all charger drivers respect all of the properties. 15 + 14 16 Required Properties: 15 17 - compatible: Must be "simple-battery" 16 18 17 19 Optional Properties: 20 + - over-voltage-threshold-microvolt: battery over-voltage limit 21 + - re-charge-voltage-microvolt: limit to automatically start charging again 18 22 - voltage-min-design-microvolt: drained battery voltage 19 23 - voltage-max-design-microvolt: fully charged battery voltage 20 24 - energy-full-design-microwatt-hours: battery design energy 21 25 - charge-full-design-microamp-hours: battery design capacity 26 + - trickle-charge-current-microamp: current for trickle-charge phase 22 27 - precharge-current-microamp: current for pre-charge phase 28 + - precharge-upper-limit-microvolt: limit when to change to constant charging 23 29 - charge-term-current-microamp: current for charge termination phase 24 30 - constant-charge-current-max-microamp: maximum constant input current 25 31 - constant-charge-voltage-max-microvolt: maximum constant input voltage
-56
Documentation/devicetree/bindings/power/supply/bq27xxx.txt
··· 1 - TI BQ27XXX fuel gauge family 2 - 3 - Required properties: 4 - - compatible: contains one of the following: 5 - * "ti,bq27200" - BQ27200 6 - * "ti,bq27210" - BQ27210 7 - * "ti,bq27500" - deprecated, use revision specific property below 8 - * "ti,bq27510" - deprecated, use revision specific property below 9 - * "ti,bq27520" - deprecated, use revision specific property below 10 - * "ti,bq27500-1" - BQ27500/1 11 - * "ti,bq27510g1" - BQ27510-g1 12 - * "ti,bq27510g2" - BQ27510-g2 13 - * "ti,bq27510g3" - BQ27510-g3 14 - * "ti,bq27520g1" - BQ27520-g1 15 - * "ti,bq27520g2" - BQ27520-g2 16 - * "ti,bq27520g3" - BQ27520-g3 17 - * "ti,bq27520g4" - BQ27520-g4 18 - * "ti,bq27521" - BQ27521 19 - * "ti,bq27530" - BQ27530 20 - * "ti,bq27531" - BQ27531 21 - * "ti,bq27541" - BQ27541 22 - * "ti,bq27542" - BQ27542 23 - * "ti,bq27546" - BQ27546 24 - * "ti,bq27742" - BQ27742 25 - * "ti,bq27545" - BQ27545 26 - * "ti,bq27411" - BQ27411 27 - * "ti,bq27421" - BQ27421 28 - * "ti,bq27425" - BQ27425 29 - * "ti,bq27426" - BQ27426 30 - * "ti,bq27441" - BQ27441 31 - * "ti,bq27621" - BQ27621 32 - - reg: integer, I2C address of the fuel gauge. 33 - 34 - Optional properties: 35 - - monitored-battery: phandle of battery characteristics node 36 - The fuel gauge uses the following battery properties: 37 - + energy-full-design-microwatt-hours 38 - + charge-full-design-microamp-hours 39 - + voltage-min-design-microvolt 40 - Both or neither of the *-full-design-*-hours properties must be set. 41 - See Documentation/devicetree/bindings/power/supply/battery.txt 42 - 43 - Example: 44 - 45 - bat: battery { 46 - compatible = "simple-battery"; 47 - voltage-min-design-microvolt = <3200000>; 48 - energy-full-design-microwatt-hours = <5290000>; 49 - charge-full-design-microamp-hours = <1430000>; 50 - }; 51 - 52 - bq27510g3: fuel-gauge@55 { 53 - compatible = "ti,bq27510g3"; 54 - reg = <0x55>; 55 - monitored-battery = <&bat>; 56 - };
+91
Documentation/devicetree/bindings/power/supply/bq27xxx.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Copyright (C) 2020 Texas Instruments Incorporated 3 + %YAML 1.2 4 + --- 5 + $id: "http://devicetree.org/schemas/power/supply/bq27xxx.yaml#" 6 + $schema: "http://devicetree.org/meta-schemas/core.yaml#" 7 + 8 + title: TI BQ27XXX fuel gauge family 9 + 10 + maintainers: 11 + - Pali Rohár <pali@kernel.org> 12 + - Andrew F. Davis <afd@ti.com> 13 + - Sebastian Reichel <sre@kernel.org> 14 + 15 + description: | 16 + Support various Texas Instruments fuel gauge devices that share similar 17 + register maps and power supply properties 18 + 19 + allOf: 20 + - $ref: power-supply.yaml# 21 + 22 + properties: 23 + compatible: 24 + enum: 25 + - ti,bq27200 26 + - ti,bq27210 27 + - ti,bq27500 # deprecated, use revision specific property below 28 + - ti,bq27510 # deprecated, use revision specific property below 29 + - ti,bq27520 # deprecated, use revision specific property below 30 + - ti,bq27500-1 31 + - ti,bq27510g1 32 + - ti,bq27510g2 33 + - ti,bq27510g3 34 + - ti,bq27520g1 35 + - ti,bq27520g2 36 + - ti,bq27520g3 37 + - ti,bq27520g4 38 + - ti,bq27521 39 + - ti,bq27530 40 + - ti,bq27531 41 + - ti,bq27541 42 + - ti,bq27542 43 + - ti,bq27546 44 + - ti,bq27742 45 + - ti,bq27545 46 + - ti,bq27411 47 + - ti,bq27421 48 + - ti,bq27425 49 + - ti,bq27426 50 + - ti,bq27441 51 + - ti,bq27621 52 + 53 + reg: 54 + maxItems: 1 55 + description: integer, I2C address of the fuel gauge. 56 + 57 + monitored-battery: 58 + description: | 59 + phandle of battery characteristics node. 60 + The fuel gauge uses the following battery properties: 61 + - energy-full-design-microwatt-hours 62 + - charge-full-design-microamp-hours 63 + - voltage-min-design-microvolt 64 + Both or neither of the *-full-design-*-hours properties must be set. 65 + See Documentation/devicetree/bindings/power/supply/battery.txt 66 + 67 + power-supplies: true 68 + 69 + required: 70 + - compatible 71 + - reg 72 + additionalProperties: false 73 + 74 + examples: 75 + - | 76 + i2c0 { 77 + #address-cells = <1>; 78 + #size-cells = <0>; 79 + bat: battery { 80 + compatible = "simple-battery"; 81 + voltage-min-design-microvolt = <3200000>; 82 + energy-full-design-microwatt-hours = <5290000>; 83 + charge-full-design-microamp-hours = <1430000>; 84 + }; 85 + 86 + bq27510g3: fuel-gauge@55 { 87 + compatible = "ti,bq27510g3"; 88 + reg = <0x55>; 89 + monitored-battery = <&bat>; 90 + }; 91 + };
+82
Documentation/devicetree/bindings/power/supply/cw2015_battery.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/cw2015_battery.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Battery driver for CW2015 shuntless fuel gauge by CellWise. 8 + 9 + maintainers: 10 + - Tobias Schramm <t.schramm@manjaro.org> 11 + 12 + description: | 13 + The driver can utilize information from a simple-battery linked via a 14 + phandle in monitored-battery. If specified the driver uses the 15 + charge-full-design-microamp-hours property of the battery. 16 + 17 + properties: 18 + compatible: 19 + const: cellwise,cw2015 20 + 21 + reg: 22 + maxItems: 1 23 + 24 + cellwise,battery-profile: 25 + description: | 26 + This property specifies characteristics of the battery used. The format 27 + of this binary blob is kept secret by CellWise. The only way to obtain 28 + it is to mail two batteries to a test facility of CellWise and receive 29 + back a test report with the binary blob. 30 + allOf: 31 + - $ref: /schemas/types.yaml#definitions/uint8-array 32 + items: 33 + - minItems: 64 34 + maxItems: 64 35 + 36 + cellwise,monitor-interval-ms: 37 + description: 38 + Specifies the interval in milliseconds gauge values are polled at 39 + minimum: 250 40 + 41 + power-supplies: 42 + description: 43 + Specifies supplies used for charging the battery connected to this gauge 44 + allOf: 45 + - $ref: /schemas/types.yaml#/definitions/phandle-array 46 + - minItems: 1 47 + maxItems: 8 # Should be enough 48 + 49 + monitored-battery: 50 + description: 51 + Specifies the phandle of a simple-battery connected to this gauge 52 + $ref: /schemas/types.yaml#/definitions/phandle 53 + 54 + required: 55 + - compatible 56 + - reg 57 + 58 + examples: 59 + - | 60 + i2c { 61 + #address-cells = <1>; 62 + #size-cells = <0>; 63 + 64 + cw2015@62 { 65 + compatible = "cellwise,cw201x"; 66 + reg = <0x62>; 67 + cellwise,battery-profile = /bits/ 8 < 68 + 0x17 0x67 0x80 0x73 0x6E 0x6C 0x6B 0x63 69 + 0x77 0x51 0x5C 0x58 0x50 0x4C 0x48 0x36 70 + 0x15 0x0C 0x0C 0x19 0x5B 0x7D 0x6F 0x69 71 + 0x69 0x5B 0x0C 0x29 0x20 0x40 0x52 0x59 72 + 0x57 0x56 0x54 0x4F 0x3B 0x1F 0x7F 0x17 73 + 0x06 0x1A 0x30 0x5A 0x85 0x93 0x96 0x2D 74 + 0x48 0x77 0x9C 0xB3 0x80 0x52 0x94 0xCB 75 + 0x2F 0x00 0x64 0xA5 0xB5 0x11 0xF0 0x11 76 + >; 77 + cellwise,monitor-interval-ms = <5000>; 78 + monitored-battery = <&bat>; 79 + power-supplies = <&mains_charger>, <&usb_charger>; 80 + }; 81 + }; 82 +
+40
Documentation/devicetree/bindings/power/supply/power-supply.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + %YAML 1.2 3 + --- 4 + $id: "http://devicetree.org/schemas/power/supply/power-supply.yaml#" 5 + $schema: "http://devicetree.org/meta-schemas/core.yaml#" 6 + 7 + title: Power Supply Core Support 8 + 9 + maintainers: 10 + - Sebastian Reichel <sre@kernel.org> 11 + 12 + properties: 13 + power-supplies: 14 + $ref: /schemas/types.yaml#/definitions/phandle-array 15 + description: 16 + This property is added to a supply in order to list the devices which 17 + supply it power, referenced by their phandles. 18 + 19 + examples: 20 + - | 21 + power { 22 + #address-cells = <1>; 23 + #size-cells = <0>; 24 + 25 + usb_charger:charger@e { 26 + compatible = "some,usb-charger"; 27 + reg = <0xe>; 28 + }; 29 + 30 + ac_charger:charger@c { 31 + compatible = "some,ac-charger"; 32 + reg = <0xc>; 33 + }; 34 + 35 + battery:battery@b { 36 + compatible = "some,battery"; 37 + reg = <0xb>; 38 + power-supplies = <&usb_charger>, <&ac_charger>; 39 + }; 40 + };
+2 -23
Documentation/devicetree/bindings/power/supply/power_supply.txt
··· 1 - Power Supply Core Support 2 - 3 - Optional Properties: 4 - - power-supplies : This property is added to a supply in order to list the 5 - devices which supply it power, referenced by their phandles. 6 - 7 - Example: 8 - 9 - usb-charger: power@e { 10 - compatible = "some,usb-charger"; 11 - ... 12 - }; 13 - 14 - ac-charger: power@c { 15 - compatible = "some,ac-charger"; 16 - ... 17 - }; 18 - 19 - battery@b { 20 - compatible = "some,battery"; 21 - ... 22 - power-supplies = <&usb-charger>, <&ac-charger>; 23 - }; 1 + This binding has been converted to yaml please see power-supply.yaml in this 2 + directory.
+155
Documentation/devicetree/bindings/power/supply/rohm,bd99954.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/rohm,bd99954.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: ROHM BD99954 Battery charger 8 + 9 + maintainers: 10 + - Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> 11 + - Markus Laine <markus.laine@fi.rohmeurope.com> 12 + - Mikko Mutanen <mikko.mutanen@fi.rohmeurope.com> 13 + 14 + description: | 15 + The ROHM BD99954 is a Battery Management LSI for 1-4 cell Lithium-Ion 16 + secondary battery intended to be used in space-constraint equipment such 17 + as Low profile Notebook PC, Tablets and other applications. BD99954 18 + provides a Dual-source Battery Charger, two port BC1.2 detection and a 19 + Battery Monitor. 20 + 21 + 22 + properties: 23 + compatible: 24 + const: rohm,bd99954 25 + # 26 + # The battery charging profile of BD99954. 27 + # 28 + # Curve (1) represents charging current. 29 + # Curve (2) represents battery voltage. 30 + # 31 + # The BD99954 data sheet divides charging to three phases. 32 + # a) Trickle-charge with constant current (8). 33 + # b) pre-charge with constant current (6) 34 + # c) fast-charge with: 35 + # First a constant current (5) phase (CC) 36 + # Then constant voltage (CV) phase (after the battery voltage has reached 37 + # target level - until charging current has dropped to termination 38 + # level (7) 39 + # 40 + # V ^ ^ I 41 + # . . 42 + # . . 43 + # (4)- -.- - - - - - - - - - - - - - +++++++++++++++++++++++++++. 44 + # . / . 45 + # . ++++++/++ - - - - - - - - - - - - -.- - (5) 46 + # . + / + . 47 + # . + - -- . 48 + # . + - + . 49 + # . +.- -: . 50 + # . .+ +` . 51 + # . .- + | `/ . 52 + # . .." + .: . 53 + # . -" + -- . 54 + # . (2) ..." + | :- . 55 + # . ..."" + -: . 56 + # (3)- -.-.""- - - - -+++++++++ - - - - - - -.:- - - - - - - - - .- - (6) 57 + # . + `:. . 58 + # . + | -: . 59 + # . + -: . 60 + # . + .. . 61 + # . (1) + | "+++- - - -.- - (7) 62 + # -++++++++++++++- - - - - - - - - - - - - - - - - + - - - .- - (8) 63 + # . + - 64 + # -------------------------------------------------+++++++++--> 65 + # | | | CC | CV | 66 + # | --trickle-- | -pre- | ---------fast----------- | 67 + # 68 + # The charger uses the following battery properties 69 + # - trickle-charge-current-microamp: 70 + # Current used at trickle-charge phase (8 in above chart) 71 + # minimum: 64000 72 + # maximum: 1024000 73 + # multipleOf: 64000 74 + # - precharge-current-microamp: 75 + # Current used at pre-charge phase (6 in above chart) 76 + # minimum: 64000 77 + # maximum: 1024000 78 + # multipleOf: 64000 79 + # - constant-charge-current-max-microamp 80 + # Current used at fast charge constant current phase (5 in above chart) 81 + # minimum: 64000 82 + # maximum: 1024000 83 + # multipleOf: 64000 84 + # - constant-charge-voltage-max-microvolt 85 + # The constant voltage used in fast charging phase (4 in above chart) 86 + # minimum: 2560000 87 + # maximum: 19200000 88 + # multipleOf: 16000 89 + # - precharge-upper-limit-microvolt 90 + # charging mode is changed from trickle charging to pre-charging 91 + # when battery voltage exceeds this limit voltage (3 in above chart) 92 + # minimum: 2048000 93 + # maximum: 19200000 94 + # multipleOf: 64000 95 + # - re-charge-voltage-microvolt 96 + # minimum: 2560000 97 + # maximum: 19200000 98 + # multipleOf: 16000 99 + # re-charging is automatically started when battry has been discharging 100 + # to the point where the battery voltage drops below this limit 101 + # - over-voltage-threshold-microvolt 102 + # battery is expected to be faulty if battery voltage exceeds this limit. 103 + # Charger will then enter to a "battery faulty" -state 104 + # minimum: 2560000 105 + # maximum: 19200000 106 + # multipleOf: 16000 107 + # - charge-term-current-microamp 108 + # minimum: 0 109 + # maximum: 1024000 110 + # multipleOf: 64000 111 + # a charge cycle terminates when the battery voltage is above recharge 112 + # threshold, and the current is below this setting (7 in above chart) 113 + # See also Documentation/devicetree/bindings/power/supply/battery.txt 114 + 115 + monitored-battery: 116 + description: 117 + phandle of battery characteristics devicetree node 118 + 119 + rohm,vsys-regulation-microvolt: 120 + description: system specific lower limit for system voltage. 121 + minimum: 2560000 122 + maximum: 19200000 123 + multipleOf: 64000 124 + 125 + rohm,vbus-input-current-limit-microamp: 126 + description: system specific VBUS input current limit (in microamps). 127 + minimum: 32000 128 + maximum: 16352000 129 + multipleOf: 32000 130 + 131 + rohm,vcc-input-current-limit-microamp: 132 + description: system specific VCC/VACP input current limit (in microamps). 133 + minimum: 32000 134 + maximum: 16352000 135 + multipleOf: 32000 136 + 137 + required: 138 + - compatible 139 + 140 + examples: 141 + - | 142 + i2c { 143 + #address-cells = <1>; 144 + #size-cells = <0>; 145 + charger@9 { 146 + compatible = "rohm,bd99954"; 147 + monitored-battery = <&battery>; 148 + reg = <0x9>; 149 + interrupt-parent = <&gpio1>; 150 + interrupts = <29 8>; 151 + rohm,vsys-regulation-microvolt = <8960000>; 152 + rohm,vbus-input-current-limit-microamp = <1472000>; 153 + rohm,vcc-input-current-limit-microamp = <1472000>; 154 + }; 155 + };
+83
Documentation/devicetree/bindings/power/supply/sbs,sbs-battery.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/power/supply/sbs,sbs-battery.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: SBS compliant battery 8 + 9 + maintainers: 10 + - Sebastian Reichel <sre@kernel.org> 11 + 12 + description: | 13 + Battery compatible with the smart battery system specifications 14 + 15 + properties: 16 + 17 + compatible: 18 + oneOf: 19 + - items: 20 + - enum: 21 + - ti,bq20z65 22 + - ti,bq20z75 23 + - enum: 24 + - sbs,sbs-battery 25 + - items: 26 + - const: sbs,sbs-battery 27 + 28 + reg: 29 + maxItems: 1 30 + 31 + sbs,i2c-retry-count: 32 + description: 33 + The number of times to retry I2C transactions on I2C IO failure. 34 + default: 0 35 + allOf: 36 + - $ref: /schemas/types.yaml#/definitions/uint32 37 + 38 + sbs,poll-retry-count: 39 + description: 40 + The number of times to try looking for new status after an external 41 + change notification. 42 + default: 0 43 + allOf: 44 + - $ref: /schemas/types.yaml#/definitions/uint32 45 + 46 + sbs,battery-detect-gpios: 47 + description: 48 + GPIO which signals battery detection. If this is not supplied, the bus 49 + needs to be polled to detect the battery. 50 + maxItems: 1 51 + 52 + sbs,disable-charger-broadcasts: 53 + description: 54 + SBS batteries by default send broadcast messages to SBS compliant chargers to 55 + configure max. charge current/voltage. If your hardware does not have an SBS 56 + compliant charger it should be disabled via this property to avoid blocking 57 + the bus. Also some SBS battery fuel gauges are known to have a buggy multi- 58 + master implementation. 59 + type: boolean 60 + 61 + required: 62 + - compatible 63 + - reg 64 + 65 + additionalProperties: false 66 + 67 + examples: 68 + - | 69 + #include <dt-bindings/gpio/gpio.h> 70 + 71 + i2c { 72 + #address-cells = <1>; 73 + #size-cells = <0>; 74 + 75 + battery@b { 76 + compatible = "ti,bq20z75", "sbs,sbs-battery"; 77 + reg = <0xb>; 78 + sbs,i2c-retry-count = <2>; 79 + sbs,poll-retry-count = <10>; 80 + sbs,battery-detect-gpios = <&gpio 122 GPIO_ACTIVE_HIGH>; 81 + sbs,disable-charger-broadcasts; 82 + }; 83 + };
-27
Documentation/devicetree/bindings/power/supply/sbs_sbs-battery.txt
··· 1 - SBS sbs-battery 2 - ~~~~~~~~~~ 3 - 4 - Required properties : 5 - - compatible: "<vendor>,<part-number>", "sbs,sbs-battery" as fallback. The 6 - part number compatible string might be used in order to take care of 7 - vendor specific registers. 8 - Known <vendor>,<part-number>: 9 - ti,bq20z75 10 - 11 - Optional properties : 12 - - sbs,i2c-retry-count : The number of times to retry i2c transactions on i2c 13 - IO failure. 14 - - sbs,poll-retry-count : The number of times to try looking for new status 15 - after an external change notification. 16 - - sbs,battery-detect-gpios : The gpio which signals battery detection and 17 - a flag specifying its polarity. 18 - 19 - Example: 20 - 21 - battery@b { 22 - compatible = "ti,bq20z75", "sbs,sbs-battery"; 23 - reg = <0xb>; 24 - sbs,i2c-retry-count = <2>; 25 - sbs,poll-retry-count = <10>; 26 - sbs,battery-detect-gpios = <&gpio-controller 122 1>; 27 - }
+2
Documentation/devicetree/bindings/vendor-prefixes.yaml
··· 187 187 description: Cadence Design Systems Inc. 188 188 "^cdtech,.*": 189 189 description: CDTech(H.K.) Electronics Limited 190 + "^cellwise,.*": 191 + description: CellWise Microelectronics Co., Ltd 190 192 "^ceva,.*": 191 193 description: Ceva, Inc. 192 194 "^checkpoint,.*":
+7
MAINTAINERS
··· 2190 2190 S: Maintained 2191 2191 F: arch/arm/boot/dts/ox8*.dts* 2192 2192 F: arch/arm/mach-oxnas/ 2193 + F: drivers/power/reset/oxnas-restart.c 2193 2194 N: oxnas 2194 2195 2195 2196 ARM/PALM TREO SUPPORT ··· 3978 3977 F: arch/powerpc/include/uapi/asm/spu*.h 3979 3978 F: arch/powerpc/oprofile/*cell* 3980 3979 F: arch/powerpc/platforms/cell/ 3980 + 3981 + CELLWISE CW2015 BATTERY DRIVER 3982 + M: Tobias Schrammm <t.schramm@manjaro.org> 3983 + S: Maintained 3984 + F: Documentation/devicetree/bindings/power/supply/cw2015_battery.yaml 3985 + F: drivers/power/supply/cw2015_battery.c 3981 3986 3982 3987 CEPH COMMON CODE (LIBCEPH) 3983 3988 M: Ilya Dryomov <idryomov@gmail.com>
+2 -2
arch/x86/platform/olpc/olpc-xo1-sci.c
··· 52 52 53 53 static void battery_status_changed(void) 54 54 { 55 - struct power_supply *psy = power_supply_get_by_name("olpc-battery"); 55 + struct power_supply *psy = power_supply_get_by_name("olpc_battery"); 56 56 57 57 if (psy) { 58 58 power_supply_changed(psy); ··· 62 62 63 63 static void ac_status_changed(void) 64 64 { 65 - struct power_supply *psy = power_supply_get_by_name("olpc-ac"); 65 + struct power_supply *psy = power_supply_get_by_name("olpc_ac"); 66 66 67 67 if (psy) { 68 68 power_supply_changed(psy);
+2 -2
arch/x86/platform/olpc/olpc-xo15-sci.c
··· 75 75 76 76 static void battery_status_changed(void) 77 77 { 78 - struct power_supply *psy = power_supply_get_by_name("olpc-battery"); 78 + struct power_supply *psy = power_supply_get_by_name("olpc_battery"); 79 79 80 80 if (psy) { 81 81 power_supply_changed(psy); ··· 85 85 86 86 static void ac_status_changed(void) 87 87 { 88 - struct power_supply *psy = power_supply_get_by_name("olpc-ac"); 88 + struct power_supply *psy = power_supply_get_by_name("olpc_ac"); 89 89 90 90 if (psy) { 91 91 power_supply_changed(psy);
+2 -2
drivers/platform/olpc/olpc-xo175-ec.c
··· 410 410 dev_dbg(dev, "got event %.2x\n", byte); 411 411 switch (byte) { 412 412 case EVENT_AC_CHANGE: 413 - psy = power_supply_get_by_name("olpc-ac"); 413 + psy = power_supply_get_by_name("olpc_ac"); 414 414 if (psy) { 415 415 power_supply_changed(psy); 416 416 power_supply_put(psy); ··· 420 420 case EVENT_BATTERY_CRITICAL: 421 421 case EVENT_BATTERY_SOC_CHANGE: 422 422 case EVENT_BATTERY_ERROR: 423 - psy = power_supply_get_by_name("olpc-battery"); 423 + psy = power_supply_get_by_name("olpc_battery"); 424 424 if (psy) { 425 425 power_supply_changed(psy); 426 426 power_supply_put(psy);
+7
drivers/power/reset/Kconfig
··· 123 123 help 124 124 This driver supports restart for Microsemi Ocelot SoC. 125 125 126 + config POWER_RESET_OXNAS 127 + bool "OXNAS SoC restart driver" 128 + depends on ARCH_OXNAS 129 + default MACH_OX820 130 + help 131 + Restart support for OXNAS/PLXTECH OX820 SoC. 132 + 126 133 config POWER_RESET_PIIX4_POWEROFF 127 134 tristate "Intel PIIX4 power-off driver" 128 135 depends on PCI
+1
drivers/power/reset/Makefile
··· 12 12 obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o 13 13 obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o 14 14 obj-$(CONFIG_POWER_RESET_MT6323) += mt6323-poweroff.o 15 + obj-$(CONFIG_POWER_RESET_OXNAS) += oxnas-restart.o 15 16 obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o 16 17 obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o 17 18 obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o
+1 -1
drivers/power/reset/gpio-poweroff.c
··· 54 54 /* If a pm_power_off function has already been added, leave it alone */ 55 55 if (pm_power_off != NULL) { 56 56 dev_err(&pdev->dev, 57 - "%s: pm_power_off function already registered", 57 + "%s: pm_power_off function already registered\n", 58 58 __func__); 59 59 return -EBUSY; 60 60 }
+1 -2
drivers/power/reset/ltc2952-poweroff.c
··· 94 94 { 95 95 ktime_t now; 96 96 int state; 97 - unsigned long overruns; 98 97 struct ltc2952_poweroff *data = to_ltc2952(timer, timer_wde); 99 98 100 99 if (data->kernel_panic) ··· 103 104 gpiod_set_value(data->gpio_watchdog, !state); 104 105 105 106 now = hrtimer_cb_get_time(timer); 106 - overruns = hrtimer_forward(timer, now, data->wde_interval); 107 + hrtimer_forward(timer, now, data->wde_interval); 107 108 108 109 return HRTIMER_RESTART; 109 110 }
+233
drivers/power/reset/oxnas-restart.c
··· 1 + // SPDX-License-Identifier: (GPL-2.0) 2 + /* 3 + * oxnas SoC reset driver 4 + * based on: 5 + * Microsemi MIPS SoC reset driver 6 + * and ox820_assert_system_reset() written by Ma Hajun <mahaijuns@gmail.com> 7 + * 8 + * Copyright (c) 2013 Ma Hajun <mahaijuns@gmail.com> 9 + * Copyright (c) 2017 Microsemi Corporation 10 + * Copyright (c) 2020 Daniel Golle <daniel@makrotopia.org> 11 + */ 12 + #include <linux/delay.h> 13 + #include <linux/io.h> 14 + #include <linux/notifier.h> 15 + #include <linux/mfd/syscon.h> 16 + #include <linux/of_address.h> 17 + #include <linux/of_device.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/reboot.h> 20 + #include <linux/regmap.h> 21 + 22 + /* bit numbers of reset control register */ 23 + #define OX820_SYS_CTRL_RST_SCU 0 24 + #define OX820_SYS_CTRL_RST_COPRO 1 25 + #define OX820_SYS_CTRL_RST_ARM0 2 26 + #define OX820_SYS_CTRL_RST_ARM1 3 27 + #define OX820_SYS_CTRL_RST_USBHS 4 28 + #define OX820_SYS_CTRL_RST_USBHSPHYA 5 29 + #define OX820_SYS_CTRL_RST_MACA 6 30 + #define OX820_SYS_CTRL_RST_MAC OX820_SYS_CTRL_RST_MACA 31 + #define OX820_SYS_CTRL_RST_PCIEA 7 32 + #define OX820_SYS_CTRL_RST_SGDMA 8 33 + #define OX820_SYS_CTRL_RST_CIPHER 9 34 + #define OX820_SYS_CTRL_RST_DDR 10 35 + #define OX820_SYS_CTRL_RST_SATA 11 36 + #define OX820_SYS_CTRL_RST_SATA_LINK 12 37 + #define OX820_SYS_CTRL_RST_SATA_PHY 13 38 + #define OX820_SYS_CTRL_RST_PCIEPHY 14 39 + #define OX820_SYS_CTRL_RST_STATIC 15 40 + #define OX820_SYS_CTRL_RST_GPIO 16 41 + #define OX820_SYS_CTRL_RST_UART1 17 42 + #define OX820_SYS_CTRL_RST_UART2 18 43 + #define OX820_SYS_CTRL_RST_MISC 19 44 + #define OX820_SYS_CTRL_RST_I2S 20 45 + #define OX820_SYS_CTRL_RST_SD 21 46 + #define OX820_SYS_CTRL_RST_MACB 22 47 + #define OX820_SYS_CTRL_RST_PCIEB 23 48 + #define OX820_SYS_CTRL_RST_VIDEO 24 49 + #define OX820_SYS_CTRL_RST_DDR_PHY 25 50 + #define OX820_SYS_CTRL_RST_USBHSPHYB 26 51 + #define OX820_SYS_CTRL_RST_USBDEV 27 52 + #define OX820_SYS_CTRL_RST_ARMDBG 29 53 + #define OX820_SYS_CTRL_RST_PLLA 30 54 + #define OX820_SYS_CTRL_RST_PLLB 31 55 + 56 + /* bit numbers of clock control register */ 57 + #define OX820_SYS_CTRL_CLK_COPRO 0 58 + #define OX820_SYS_CTRL_CLK_DMA 1 59 + #define OX820_SYS_CTRL_CLK_CIPHER 2 60 + #define OX820_SYS_CTRL_CLK_SD 3 61 + #define OX820_SYS_CTRL_CLK_SATA 4 62 + #define OX820_SYS_CTRL_CLK_I2S 5 63 + #define OX820_SYS_CTRL_CLK_USBHS 6 64 + #define OX820_SYS_CTRL_CLK_MACA 7 65 + #define OX820_SYS_CTRL_CLK_MAC OX820_SYS_CTRL_CLK_MACA 66 + #define OX820_SYS_CTRL_CLK_PCIEA 8 67 + #define OX820_SYS_CTRL_CLK_STATIC 9 68 + #define OX820_SYS_CTRL_CLK_MACB 10 69 + #define OX820_SYS_CTRL_CLK_PCIEB 11 70 + #define OX820_SYS_CTRL_CLK_REF600 12 71 + #define OX820_SYS_CTRL_CLK_USBDEV 13 72 + #define OX820_SYS_CTRL_CLK_DDR 14 73 + #define OX820_SYS_CTRL_CLK_DDRPHY 15 74 + #define OX820_SYS_CTRL_CLK_DDRCK 16 75 + 76 + /* Regmap offsets */ 77 + #define OX820_CLK_SET_REGOFFSET 0x2c 78 + #define OX820_CLK_CLR_REGOFFSET 0x30 79 + #define OX820_RST_SET_REGOFFSET 0x34 80 + #define OX820_RST_CLR_REGOFFSET 0x38 81 + #define OX820_SECONDARY_SEL_REGOFFSET 0x14 82 + #define OX820_TERTIARY_SEL_REGOFFSET 0x8c 83 + #define OX820_QUATERNARY_SEL_REGOFFSET 0x94 84 + #define OX820_DEBUG_SEL_REGOFFSET 0x9c 85 + #define OX820_ALTERNATIVE_SEL_REGOFFSET 0xa4 86 + #define OX820_PULLUP_SEL_REGOFFSET 0xac 87 + #define OX820_SEC_SECONDARY_SEL_REGOFFSET 0x100014 88 + #define OX820_SEC_TERTIARY_SEL_REGOFFSET 0x10008c 89 + #define OX820_SEC_QUATERNARY_SEL_REGOFFSET 0x100094 90 + #define OX820_SEC_DEBUG_SEL_REGOFFSET 0x10009c 91 + #define OX820_SEC_ALTERNATIVE_SEL_REGOFFSET 0x1000a4 92 + #define OX820_SEC_PULLUP_SEL_REGOFFSET 0x1000ac 93 + 94 + struct oxnas_restart_context { 95 + struct regmap *sys_ctrl; 96 + struct notifier_block restart_handler; 97 + }; 98 + 99 + static int ox820_restart_handle(struct notifier_block *this, 100 + unsigned long mode, void *cmd) 101 + { 102 + struct oxnas_restart_context *ctx = container_of(this, struct 103 + oxnas_restart_context, 104 + restart_handler); 105 + u32 value; 106 + 107 + /* 108 + * Assert reset to cores as per power on defaults 109 + * Don't touch the DDR interface as things will come to an impromptu 110 + * stop NB Possibly should be asserting reset for PLLB, but there are 111 + * timing concerns here according to the docs 112 + */ 113 + value = BIT(OX820_SYS_CTRL_RST_COPRO) | 114 + BIT(OX820_SYS_CTRL_RST_USBHS) | 115 + BIT(OX820_SYS_CTRL_RST_USBHSPHYA) | 116 + BIT(OX820_SYS_CTRL_RST_MACA) | 117 + BIT(OX820_SYS_CTRL_RST_PCIEA) | 118 + BIT(OX820_SYS_CTRL_RST_SGDMA) | 119 + BIT(OX820_SYS_CTRL_RST_CIPHER) | 120 + BIT(OX820_SYS_CTRL_RST_SATA) | 121 + BIT(OX820_SYS_CTRL_RST_SATA_LINK) | 122 + BIT(OX820_SYS_CTRL_RST_SATA_PHY) | 123 + BIT(OX820_SYS_CTRL_RST_PCIEPHY) | 124 + BIT(OX820_SYS_CTRL_RST_STATIC) | 125 + BIT(OX820_SYS_CTRL_RST_UART1) | 126 + BIT(OX820_SYS_CTRL_RST_UART2) | 127 + BIT(OX820_SYS_CTRL_RST_MISC) | 128 + BIT(OX820_SYS_CTRL_RST_I2S) | 129 + BIT(OX820_SYS_CTRL_RST_SD) | 130 + BIT(OX820_SYS_CTRL_RST_MACB) | 131 + BIT(OX820_SYS_CTRL_RST_PCIEB) | 132 + BIT(OX820_SYS_CTRL_RST_VIDEO) | 133 + BIT(OX820_SYS_CTRL_RST_USBHSPHYB) | 134 + BIT(OX820_SYS_CTRL_RST_USBDEV); 135 + 136 + regmap_write(ctx->sys_ctrl, OX820_RST_SET_REGOFFSET, value); 137 + 138 + /* Release reset to cores as per power on defaults */ 139 + regmap_write(ctx->sys_ctrl, OX820_RST_CLR_REGOFFSET, 140 + BIT(OX820_SYS_CTRL_RST_GPIO)); 141 + 142 + /* 143 + * Disable clocks to cores as per power-on defaults - must leave DDR 144 + * related clocks enabled otherwise we'll stop rather abruptly. 145 + */ 146 + value = BIT(OX820_SYS_CTRL_CLK_COPRO) | 147 + BIT(OX820_SYS_CTRL_CLK_DMA) | 148 + BIT(OX820_SYS_CTRL_CLK_CIPHER) | 149 + BIT(OX820_SYS_CTRL_CLK_SD) | 150 + BIT(OX820_SYS_CTRL_CLK_SATA) | 151 + BIT(OX820_SYS_CTRL_CLK_I2S) | 152 + BIT(OX820_SYS_CTRL_CLK_USBHS) | 153 + BIT(OX820_SYS_CTRL_CLK_MAC) | 154 + BIT(OX820_SYS_CTRL_CLK_PCIEA) | 155 + BIT(OX820_SYS_CTRL_CLK_STATIC) | 156 + BIT(OX820_SYS_CTRL_CLK_MACB) | 157 + BIT(OX820_SYS_CTRL_CLK_PCIEB) | 158 + BIT(OX820_SYS_CTRL_CLK_REF600) | 159 + BIT(OX820_SYS_CTRL_CLK_USBDEV); 160 + 161 + regmap_write(ctx->sys_ctrl, OX820_CLK_CLR_REGOFFSET, value); 162 + 163 + /* Enable clocks to cores as per power-on defaults */ 164 + 165 + /* Set sys-control pin mux'ing as per power-on defaults */ 166 + regmap_write(ctx->sys_ctrl, OX820_SECONDARY_SEL_REGOFFSET, 0); 167 + regmap_write(ctx->sys_ctrl, OX820_TERTIARY_SEL_REGOFFSET, 0); 168 + regmap_write(ctx->sys_ctrl, OX820_QUATERNARY_SEL_REGOFFSET, 0); 169 + regmap_write(ctx->sys_ctrl, OX820_DEBUG_SEL_REGOFFSET, 0); 170 + regmap_write(ctx->sys_ctrl, OX820_ALTERNATIVE_SEL_REGOFFSET, 0); 171 + regmap_write(ctx->sys_ctrl, OX820_PULLUP_SEL_REGOFFSET, 0); 172 + 173 + regmap_write(ctx->sys_ctrl, OX820_SEC_SECONDARY_SEL_REGOFFSET, 0); 174 + regmap_write(ctx->sys_ctrl, OX820_SEC_TERTIARY_SEL_REGOFFSET, 0); 175 + regmap_write(ctx->sys_ctrl, OX820_SEC_QUATERNARY_SEL_REGOFFSET, 0); 176 + regmap_write(ctx->sys_ctrl, OX820_SEC_DEBUG_SEL_REGOFFSET, 0); 177 + regmap_write(ctx->sys_ctrl, OX820_SEC_ALTERNATIVE_SEL_REGOFFSET, 0); 178 + regmap_write(ctx->sys_ctrl, OX820_SEC_PULLUP_SEL_REGOFFSET, 0); 179 + 180 + /* 181 + * No need to save any state, as the ROM loader can determine whether 182 + * reset is due to power cycling or programatic action, just hit the 183 + * (self-clearing) CPU reset bit of the block reset register 184 + */ 185 + value = 186 + BIT(OX820_SYS_CTRL_RST_SCU) | 187 + BIT(OX820_SYS_CTRL_RST_ARM0) | 188 + BIT(OX820_SYS_CTRL_RST_ARM1); 189 + 190 + regmap_write(ctx->sys_ctrl, OX820_RST_SET_REGOFFSET, value); 191 + 192 + pr_emerg("Unable to restart system\n"); 193 + return NOTIFY_DONE; 194 + } 195 + 196 + static int ox820_restart_probe(struct platform_device *pdev) 197 + { 198 + struct oxnas_restart_context *ctx; 199 + struct regmap *sys_ctrl; 200 + struct device *dev = &pdev->dev; 201 + int err = 0; 202 + 203 + sys_ctrl = syscon_node_to_regmap(pdev->dev.of_node); 204 + if (IS_ERR(sys_ctrl)) 205 + return PTR_ERR(sys_ctrl); 206 + 207 + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 208 + if (!ctx) 209 + return -ENOMEM; 210 + 211 + ctx->sys_ctrl = sys_ctrl; 212 + ctx->restart_handler.notifier_call = ox820_restart_handle; 213 + ctx->restart_handler.priority = 192; 214 + err = register_restart_handler(&ctx->restart_handler); 215 + if (err) 216 + dev_err(dev, "can't register restart notifier (err=%d)\n", err); 217 + 218 + return err; 219 + } 220 + 221 + static const struct of_device_id ox820_restart_of_match[] = { 222 + { .compatible = "oxsemi,ox820-sys-ctrl" }, 223 + {} 224 + }; 225 + 226 + static struct platform_driver ox820_restart_driver = { 227 + .probe = ox820_restart_probe, 228 + .driver = { 229 + .name = "ox820-chip-reset", 230 + .of_match_table = ox820_restart_of_match, 231 + }, 232 + }; 233 + builtin_platform_driver(ox820_restart_driver);
+2 -1
drivers/power/reset/qcom-pon.c
··· 34 34 35 35 ret = regmap_update_bits(pon->regmap, 36 36 pon->baseaddr + PON_SOFT_RB_SPARE, 37 - 0xfc, magic << pon->reason_shift); 37 + GENMASK(7, pon->reason_shift), 38 + magic << pon->reason_shift); 38 39 if (ret < 0) 39 40 dev_err(pon->dev, "update reboot mode bits failed\n"); 40 41
+5 -2
drivers/power/reset/syscon-reboot.c
··· 51 51 return -ENOMEM; 52 52 53 53 ctx->map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap"); 54 - if (IS_ERR(ctx->map)) 55 - return PTR_ERR(ctx->map); 54 + if (IS_ERR(ctx->map)) { 55 + ctx->map = syscon_node_to_regmap(dev->parent->of_node); 56 + if (IS_ERR(ctx->map)) 57 + return PTR_ERR(ctx->map); 58 + } 56 59 57 60 if (of_property_read_u32(pdev->dev.of_node, "offset", &ctx->offset)) 58 61 return -EINVAL;
+2 -6
drivers/power/supply/88pm860x_battery.c
··· 919 919 return -ENOMEM; 920 920 921 921 info->irq_cc = platform_get_irq(pdev, 0); 922 - if (info->irq_cc <= 0) { 923 - dev_err(&pdev->dev, "No IRQ resource!\n"); 922 + if (info->irq_cc <= 0) 924 923 return -EINVAL; 925 - } 926 924 927 925 info->irq_batt = platform_get_irq(pdev, 1); 928 - if (info->irq_batt <= 0) { 929 - dev_err(&pdev->dev, "No IRQ resource!\n"); 926 + if (info->irq_batt <= 0) 930 927 return -EINVAL; 931 - } 932 928 933 929 info->chip = chip; 934 930 info->i2c =
+34 -15
drivers/power/supply/Kconfig
··· 116 116 Say Y here to enable support for battery on Motorola 117 117 phones and tablets such as droid 4. 118 118 119 + config BATTERY_CW2015 120 + tristate "CW2015 Battery driver" 121 + depends on I2C 122 + select REGMAP_I2C 123 + help 124 + Say Y here to enable support for the cellwise cw2015 125 + battery fuel gauge (used in the Pinebook Pro & others) 126 + 127 + This driver can also be built as a module. If so, the module will be 128 + called cw2015_battery. 129 + 119 130 config BATTERY_DS2760 120 131 tristate "DS2760 battery driver (HP iPAQ & others)" 121 132 depends on W1 ··· 426 415 tristate "NXP PCF50633 MBC" 427 416 depends on MFD_PCF50633 428 417 help 429 - Say Y to include support for NXP PCF50633 Main Battery Charger. 418 + Say Y to include support for NXP PCF50633 Main Battery Charger. 430 419 431 420 config BATTERY_RX51 432 421 tristate "Nokia RX-51 (N900) battery driver" ··· 598 587 tristate "TI BQ24250/24251/24257 battery charger driver" 599 588 depends on I2C 600 589 depends on GPIOLIB || COMPILE_TEST 601 - depends on REGMAP_I2C 590 + select REGMAP_I2C 602 591 help 603 592 Say Y to enable support for the TI BQ24250, BQ24251, and BQ24257 battery 604 593 chargers. ··· 630 619 tristate "TPS65090 battery charger driver" 631 620 depends on MFD_TPS65090 632 621 help 633 - Say Y here to enable support for battery charging with TPS65090 634 - PMIC chips. 622 + Say Y here to enable support for battery charging with TPS65090 623 + PMIC chips. 635 624 636 625 config CHARGER_TPS65217 637 626 tristate "TPS65217 battery charger driver" 638 627 depends on MFD_TPS65217 639 628 help 640 - Say Y here to enable support for battery charging with TPS65217 641 - PMIC chips. 629 + Say Y here to enable support for battery charging with TPS65217 630 + PMIC chips. 642 631 643 632 config BATTERY_GAUGE_LTC2941 644 633 tristate "LTC2941/LTC2943 Battery Gauge Driver" ··· 681 670 config CHARGER_CROS_USBPD 682 671 tristate "ChromeOS EC based USBPD charger" 683 672 depends on CROS_USBPD_NOTIFY 684 - default n 685 673 help 686 674 Say Y here to enable ChromeOS EC based USBPD charger 687 675 driver. This driver gets various bits of information about ··· 691 681 tristate "Spreadtrum SC2731 charger driver" 692 682 depends on MFD_SC27XX_PMIC || COMPILE_TEST 693 683 help 694 - Say Y here to enable support for battery charging with SC2731 695 - PMIC chips. 684 + Say Y here to enable support for battery charging with SC2731 685 + PMIC chips. 696 686 697 687 config FUEL_GAUGE_SC27XX 698 688 tristate "Spreadtrum SC27XX fuel gauge driver" 699 689 depends on MFD_SC27XX_PMIC || COMPILE_TEST 700 690 depends on IIO 701 691 help 702 - Say Y here to enable support for fuel gauge with SC27XX 703 - PMIC chips. 692 + Say Y here to enable support for fuel gauge with SC27XX 693 + PMIC chips. 704 694 705 695 config CHARGER_UCS1002 706 696 tristate "Microchip UCS1002 USB Port Power Controller" ··· 715 705 config CHARGER_BD70528 716 706 tristate "ROHM bd70528 charger driver" 717 707 depends on MFD_ROHM_BD70528 718 - default n 708 + select LINEAR_RANGES 719 709 help 720 - Say Y here to enable support for getting battery status 721 - information and altering charger configurations from charger 722 - block of the ROHM BD70528 Power Management IC. 710 + Say Y here to enable support for getting battery status 711 + information and altering charger configurations from charger 712 + block of the ROHM BD70528 Power Management IC. 713 + 714 + config CHARGER_BD99954 715 + tristate "ROHM bd99954 charger driver" 716 + depends on I2C 717 + select LINEAR_RANGES 718 + help 719 + Say Y here to enable support for getting battery and charger 720 + information and altering charger configurations from the ROHM 721 + BD99954 charger IC. 723 722 724 723 config CHARGER_WILCO 725 724 tristate "Wilco EC based charger for ChromeOS"
+2
drivers/power/supply/Makefile
··· 24 24 obj-$(CONFIG_BATTERY_AXP20X) += axp20x_battery.o 25 25 obj-$(CONFIG_CHARGER_AXP20X) += axp20x_ac_power.o 26 26 obj-$(CONFIG_BATTERY_CPCAP) += cpcap-battery.o 27 + obj-$(CONFIG_BATTERY_CW2015) += cw2015_battery.o 27 28 obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o 28 29 obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o 29 30 obj-$(CONFIG_BATTERY_DS2781) += ds2781_battery.o ··· 93 92 obj-$(CONFIG_FUEL_GAUGE_SC27XX) += sc27xx_fuel_gauge.o 94 93 obj-$(CONFIG_CHARGER_UCS1002) += ucs1002_power.o 95 94 obj-$(CONFIG_CHARGER_BD70528) += bd70528-charger.o 95 + obj-$(CONFIG_CHARGER_BD99954) += bd99954-charger.o 96 96 obj-$(CONFIG_CHARGER_WILCO) += wilco-charger.o
+1 -1
drivers/power/supply/ab8500_fg.c
··· 2399 2399 struct ab8500_fg *di = container_of(work, struct ab8500_fg, 2400 2400 fg_reinit_work.work); 2401 2401 2402 - if (di->flags.calibrate == false) { 2402 + if (!di->flags.calibrate) { 2403 2403 dev_dbg(di->dev, "Resetting FG state machine to init.\n"); 2404 2404 ab8500_fg_clear_cap_samples(di); 2405 2405 ab8500_fg_calc_cap_discharge_voltage(di, true);
+2 -3
drivers/power/supply/axp288_charger.c
··· 880 880 /* Register charger interrupts */ 881 881 for (i = 0; i < CHRG_INTR_END; i++) { 882 882 pirq = platform_get_irq(info->pdev, i); 883 - if (pirq < 0) { 884 - dev_err(&pdev->dev, "Failed to get IRQ: %d\n", pirq); 883 + if (pirq < 0) 885 884 return pirq; 886 - } 885 + 887 886 info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq); 888 887 if (info->irq[i] < 0) { 889 888 dev_warn(&info->pdev->dev,
+6
drivers/power/supply/axp288_fuel_gauge.c
··· 718 718 }, 719 719 }, 720 720 { 721 + /* Meegopad T02 */ 722 + .matches = { 723 + DMI_MATCH(DMI_PRODUCT_NAME, "MEEGOPAD T02"), 724 + }, 725 + }, 726 + { 721 727 /* Meegopad T08 */ 722 728 .matches = { 723 729 DMI_MATCH(DMI_SYS_VENDOR, "Default string"),
+55 -89
drivers/power/supply/bd70528-charger.c
··· 72 72 #include <linux/module.h> 73 73 #include <linux/platform_device.h> 74 74 #include <linux/power_supply.h> 75 + #include <linux/linear_range.h> 75 76 76 77 #define CHG_STAT_SUSPEND 0x0 77 78 #define CHG_STAT_TRICKLE 0x1 ··· 336 335 return 0; 337 336 } 338 337 339 - struct bd70528_linear_range { 340 - int min; 341 - int step; 342 - int vals; 343 - int low_sel; 344 - }; 345 - 346 - static const struct bd70528_linear_range current_limit_ranges[] = { 338 + static const struct linear_range current_limit_ranges[] = { 347 339 { 348 340 .min = 5, 349 341 .step = 1, 350 - .vals = 36, 351 - .low_sel = 0, 342 + .min_sel = 0, 343 + .max_sel = 0x22, 352 344 }, 353 345 { 354 346 .min = 40, 355 347 .step = 5, 356 - .vals = 5, 357 - .low_sel = 0x23, 348 + .min_sel = 0x23, 349 + .max_sel = 0x26, 358 350 }, 359 351 { 360 352 .min = 60, 361 353 .step = 20, 362 - .vals = 8, 363 - .low_sel = 0x27, 354 + .min_sel = 0x27, 355 + .max_sel = 0x2d, 364 356 }, 365 357 { 366 358 .min = 200, 367 359 .step = 50, 368 - .vals = 7, 369 - .low_sel = 0x2e, 370 - } 360 + .min_sel = 0x2e, 361 + .max_sel = 0x34, 362 + }, 363 + { 364 + .min = 500, 365 + .step = 0, 366 + .min_sel = 0x35, 367 + .max_sel = 0x3f, 368 + }, 371 369 }; 372 370 373 371 /* ··· 374 374 * voltage for low temperatures. The driver currently only reads 375 375 * the charge current at room temperature. We do set both though. 376 376 */ 377 - static const struct bd70528_linear_range warm_charge_curr[] = { 377 + static const struct linear_range warm_charge_curr[] = { 378 378 { 379 379 .min = 10, 380 380 .step = 10, 381 - .vals = 20, 382 - .low_sel = 0, 381 + .min_sel = 0, 382 + .max_sel = 0x12, 383 383 }, 384 384 { 385 385 .min = 200, 386 386 .step = 25, 387 - .vals = 13, 388 - .low_sel = 0x13, 387 + .min_sel = 0x13, 388 + .max_sel = 0x1f, 389 389 }, 390 390 }; 391 391 ··· 397 397 #define MAX_COLD_CHG_CURR_SEL 0x15 398 398 #define MAX_WARM_CHG_CURR_SEL 0x1f 399 399 #define MIN_CHG_CURR_SEL 0x0 400 - 401 - static int find_value_for_selector_low(const struct bd70528_linear_range *r, 402 - int selectors, unsigned int sel, 403 - unsigned int *val) 404 - { 405 - int i; 406 - 407 - for (i = 0; i < selectors; i++) { 408 - if (r[i].low_sel <= sel && r[i].low_sel + r[i].vals >= sel) { 409 - *val = r[i].min + (sel - r[i].low_sel) * r[i].step; 410 - return 0; 411 - } 412 - } 413 - return -EINVAL; 414 - } 415 - 416 - /* 417 - * For BD70528 voltage/current limits we happily accept any value which 418 - * belongs the range. We could check if value matching the selector is 419 - * desired by computing the range min + (sel - sel_low) * range step - but 420 - * I guess it is enough if we use voltage/current which is closest (below) 421 - * the requested? 422 - */ 423 - static int find_selector_for_value_low(const struct bd70528_linear_range *r, 424 - int selectors, unsigned int val, 425 - unsigned int *sel, bool *found) 426 - { 427 - int i; 428 - int ret = -EINVAL; 429 - 430 - *found = false; 431 - for (i = 0; i < selectors; i++) { 432 - if (r[i].min <= val) { 433 - if (r[i].min + r[i].step * r[i].vals >= val) { 434 - *found = true; 435 - *sel = r[i].low_sel + (val - r[i].min) / 436 - r[i].step; 437 - ret = 0; 438 - break; 439 - } 440 - /* 441 - * If the range max is smaller than requested 442 - * we can set the max supported value from range 443 - */ 444 - *sel = r[i].low_sel + r[i].vals; 445 - ret = 0; 446 - } 447 - } 448 - return ret; 449 - } 450 400 451 401 static int get_charge_current(struct bd70528_psy *bdpsy, int *ma) 452 402 { ··· 413 463 414 464 sel &= BD70528_MASK_CHG_CHG_CURR; 415 465 416 - ret = find_value_for_selector_low(&warm_charge_curr[0], 417 - ARRAY_SIZE(warm_charge_curr), sel, 418 - ma); 466 + ret = linear_range_get_value_array(&warm_charge_curr[0], 467 + ARRAY_SIZE(warm_charge_curr), 468 + sel, ma); 419 469 if (ret) { 420 470 dev_err(bdpsy->dev, 421 471 "Unknown charge current value 0x%x\n", ··· 441 491 442 492 sel &= BD70528_MASK_CHG_DCIN_ILIM; 443 493 444 - ret = find_value_for_selector_low(&current_limit_ranges[0], 445 - ARRAY_SIZE(current_limit_ranges), sel, 446 - ma); 447 - 494 + ret = linear_range_get_value_array(&current_limit_ranges[0], 495 + ARRAY_SIZE(current_limit_ranges), 496 + sel, ma); 448 497 if (ret) { 449 498 /* Unspecified values mean 500 mA */ 450 499 *ma = 500; ··· 537 588 goto set; 538 589 } 539 590 540 - ret = find_selector_for_value_low(&warm_charge_curr[0], 541 - ARRAY_SIZE(warm_charge_curr), ma, 542 - &reg, &found); 591 + /* 592 + * For BD70528 voltage/current limits we happily accept any value which 593 + * belongs the range. We could check if value matching the selector is 594 + * desired by computing the range min + (sel - sel_low) * range step - but 595 + * I guess it is enough if we use voltage/current which is closest (below) 596 + * the requested? 597 + */ 598 + 599 + ret = linear_range_get_selector_low_array(warm_charge_curr, 600 + ARRAY_SIZE(warm_charge_curr), 601 + ma, &reg, &found); 543 602 if (ret) { 603 + dev_err(bdpsy->dev, 604 + "Unsupported charge current %u mA\n", ma); 544 605 reg = MIN_CHG_CURR_SEL; 545 606 goto set; 546 607 } 547 608 if (!found) { 548 - /* There was a gap in supported values and we hit it */ 609 + /* 610 + * There was a gap in supported values and we hit it. 611 + * Yet a smaller value was found so we use it. 612 + */ 549 613 dev_warn(bdpsy->dev, 550 614 "Unsupported charge current %u mA\n", ma); 551 615 } ··· 610 648 goto set; 611 649 } 612 650 613 - ret = find_selector_for_value_low(&current_limit_ranges[0], 614 - ARRAY_SIZE(current_limit_ranges), ma, 615 - &reg, &found); 651 + ret = linear_range_get_selector_low_array(current_limit_ranges, 652 + ARRAY_SIZE(current_limit_ranges), 653 + ma, &reg, &found); 616 654 if (ret) { 655 + dev_err(bdpsy->dev, "Unsupported current limit %umA\n", ma); 617 656 reg = MIN_CURR_LIMIT_SEL; 618 657 goto set; 619 658 } 620 659 if (!found) { 621 - /* There was a gap in supported values and we hit it ?*/ 622 - dev_warn(bdpsy->dev, "Unsupported current limit %umA\n", 623 - ma); 660 + /* 661 + * There was a gap in supported values and we hit it. 662 + * We found a smaller value from ranges and use it. 663 + * Warn user though. 664 + */ 665 + dev_warn(bdpsy->dev, "Unsupported current limit %umA\n", ma); 624 666 } 625 667 626 668 set:
+1142
drivers/power/supply/bd99954-charger.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * ROHM BD99954 charger driver 4 + * 5 + * Copyright (C) 2020 Rohm Semiconductors 6 + * Originally written by: 7 + * Mikko Mutanen <mikko.mutanen@fi.rohmeurope.com> 8 + * Markus Laine <markus.laine@fi.rohmeurope.com> 9 + * Bugs added by: 10 + * Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> 11 + */ 12 + 13 + /* 14 + * The battery charging profile of BD99954. 15 + * 16 + * Curve (1) represents charging current. 17 + * Curve (2) represents battery voltage. 18 + * 19 + * The BD99954 data sheet divides charging to three phases. 20 + * a) Trickle-charge with constant current (8). 21 + * b) pre-charge with constant current (6) 22 + * c) fast-charge, first with constant current (5) phase. After 23 + * the battery voltage has reached target level (4) we have constant 24 + * voltage phase until charging current has dropped to termination 25 + * level (7) 26 + * 27 + * V ^ ^ I 28 + * . . 29 + * . . 30 + *(4)` `.` ` ` ` ` ` ` ` ` ` ` ` ` ` ----------------------------. 31 + * . :/ . 32 + * . o----+/:/ ` ` ` ` ` ` ` ` ` ` ` ` `.` ` (5) 33 + * . + :: + . 34 + * . + /- -- . 35 + * . +`/- + . 36 + * . o/- -: . 37 + * . .s. +` . 38 + * . .--+ `/ . 39 + * . ..`` + .: . 40 + * . -` + -- . 41 + * . (2) ...`` + :- . 42 + * . ...`` + -: . 43 + *(3)` `.`."" ` ` ` `+-------- ` ` ` ` ` ` `.:` ` ` ` ` ` ` ` ` .` ` (6) 44 + * . + `:. . 45 + * . + -: . 46 + * . + -:. . 47 + * . + .--. . 48 + * . (1) + `.+` ` ` `.` ` (7) 49 + * -..............` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` + ` ` ` .` ` (8) 50 + * . + - 51 + * -------------------------------------------------+++++++++--> 52 + * | trickle | pre | fast | 53 + * 54 + * Details of DT properties for different limits can be found from BD99954 55 + * device tree binding documentation. 56 + */ 57 + 58 + #include <linux/delay.h> 59 + #include <linux/gpio/consumer.h> 60 + #include <linux/interrupt.h> 61 + #include <linux/i2c.h> 62 + #include <linux/kernel.h> 63 + #include <linux/linear_range.h> 64 + #include <linux/module.h> 65 + #include <linux/mod_devicetable.h> 66 + #include <linux/power_supply.h> 67 + #include <linux/property.h> 68 + #include <linux/regmap.h> 69 + #include <linux/types.h> 70 + 71 + #include "bd99954-charger.h" 72 + 73 + struct battery_data { 74 + u16 precharge_current; /* Trickle-charge Current */ 75 + u16 fc_reg_voltage; /* Fast Charging Regulation Voltage */ 76 + u16 voltage_min; 77 + u16 voltage_max; 78 + }; 79 + 80 + /* Initial field values, converted to initial register values */ 81 + struct bd9995x_init_data { 82 + u16 vsysreg_set; /* VSYS Regulation Setting */ 83 + u16 ibus_lim_set; /* VBUS input current limitation */ 84 + u16 icc_lim_set; /* VCC/VACP Input Current Limit Setting */ 85 + u16 itrich_set; /* Trickle-charge Current Setting */ 86 + u16 iprech_set; /* Pre-Charge Current Setting */ 87 + u16 ichg_set; /* Fast-Charge constant current */ 88 + u16 vfastchg_reg_set1; /* Fast Charging Regulation Voltage */ 89 + u16 vprechg_th_set; /* Pre-charge Voltage Threshold Setting */ 90 + u16 vrechg_set; /* Re-charge Battery Voltage Setting */ 91 + u16 vbatovp_set; /* Battery Over Voltage Threshold Setting */ 92 + u16 iterm_set; /* Charging termination current */ 93 + }; 94 + 95 + struct bd9995x_state { 96 + u8 online; 97 + u16 chgstm_status; 98 + u16 vbat_vsys_status; 99 + u16 vbus_vcc_status; 100 + }; 101 + 102 + struct bd9995x_device { 103 + struct i2c_client *client; 104 + struct device *dev; 105 + struct power_supply *charger; 106 + 107 + struct regmap *rmap; 108 + struct regmap_field *rmap_fields[F_MAX_FIELDS]; 109 + 110 + int chip_id; 111 + int chip_rev; 112 + struct bd9995x_init_data init_data; 113 + struct bd9995x_state state; 114 + 115 + struct mutex lock; /* Protect state data */ 116 + }; 117 + 118 + static const struct regmap_range bd9995x_readonly_reg_ranges[] = { 119 + regmap_reg_range(CHGSTM_STATUS, SEL_ILIM_VAL), 120 + regmap_reg_range(IOUT_DACIN_VAL, IOUT_DACIN_VAL), 121 + regmap_reg_range(VCC_UCD_STATUS, VCC_IDD_STATUS), 122 + regmap_reg_range(VBUS_UCD_STATUS, VBUS_IDD_STATUS), 123 + regmap_reg_range(CHIP_ID, CHIP_REV), 124 + regmap_reg_range(SYSTEM_STATUS, SYSTEM_STATUS), 125 + regmap_reg_range(IBATP_VAL, VBAT_AVE_VAL), 126 + regmap_reg_range(VTH_VAL, EXTIADP_AVE_VAL), 127 + }; 128 + 129 + static const struct regmap_access_table bd9995x_writeable_regs = { 130 + .no_ranges = bd9995x_readonly_reg_ranges, 131 + .n_no_ranges = ARRAY_SIZE(bd9995x_readonly_reg_ranges), 132 + }; 133 + 134 + static const struct regmap_range bd9995x_volatile_reg_ranges[] = { 135 + regmap_reg_range(CHGSTM_STATUS, WDT_STATUS), 136 + regmap_reg_range(VCC_UCD_STATUS, VCC_IDD_STATUS), 137 + regmap_reg_range(VBUS_UCD_STATUS, VBUS_IDD_STATUS), 138 + regmap_reg_range(INT0_STATUS, INT7_STATUS), 139 + regmap_reg_range(SYSTEM_STATUS, SYSTEM_CTRL_SET), 140 + regmap_reg_range(IBATP_VAL, EXTIADP_AVE_VAL), /* Measurement regs */ 141 + }; 142 + 143 + static const struct regmap_access_table bd9995x_volatile_regs = { 144 + .yes_ranges = bd9995x_volatile_reg_ranges, 145 + .n_yes_ranges = ARRAY_SIZE(bd9995x_volatile_reg_ranges), 146 + }; 147 + 148 + static const struct regmap_range_cfg regmap_range_cfg[] = { 149 + { 150 + .selector_reg = MAP_SET, 151 + .selector_mask = 0xFFFF, 152 + .selector_shift = 0, 153 + .window_start = 0, 154 + .window_len = 0x100, 155 + .range_min = 0 * 0x100, 156 + .range_max = 3 * 0x100, 157 + }, 158 + }; 159 + 160 + static const struct regmap_config bd9995x_regmap_config = { 161 + .reg_bits = 8, 162 + .val_bits = 16, 163 + .reg_stride = 1, 164 + 165 + .max_register = 3 * 0x100, 166 + .cache_type = REGCACHE_RBTREE, 167 + 168 + .ranges = regmap_range_cfg, 169 + .num_ranges = ARRAY_SIZE(regmap_range_cfg), 170 + .val_format_endian = REGMAP_ENDIAN_LITTLE, 171 + .wr_table = &bd9995x_writeable_regs, 172 + .volatile_table = &bd9995x_volatile_regs, 173 + }; 174 + 175 + enum bd9995x_chrg_fault { 176 + CHRG_FAULT_NORMAL, 177 + CHRG_FAULT_INPUT, 178 + CHRG_FAULT_THERMAL_SHUTDOWN, 179 + CHRG_FAULT_TIMER_EXPIRED, 180 + }; 181 + 182 + static int bd9995x_get_prop_batt_health(struct bd9995x_device *bd) 183 + { 184 + int ret, tmp; 185 + 186 + ret = regmap_field_read(bd->rmap_fields[F_BATTEMP], &tmp); 187 + if (ret) 188 + return POWER_SUPPLY_HEALTH_UNKNOWN; 189 + 190 + /* TODO: Check these against datasheet page 34 */ 191 + 192 + switch (tmp) { 193 + case ROOM: 194 + return POWER_SUPPLY_HEALTH_GOOD; 195 + case HOT1: 196 + case HOT2: 197 + case HOT3: 198 + return POWER_SUPPLY_HEALTH_OVERHEAT; 199 + case COLD1: 200 + case COLD2: 201 + return POWER_SUPPLY_HEALTH_COLD; 202 + case TEMP_DIS: 203 + case BATT_OPEN: 204 + default: 205 + return POWER_SUPPLY_HEALTH_UNKNOWN; 206 + } 207 + } 208 + 209 + static int bd9995x_get_prop_charge_type(struct bd9995x_device *bd) 210 + { 211 + int ret, tmp; 212 + 213 + ret = regmap_field_read(bd->rmap_fields[F_CHGSTM_STATE], &tmp); 214 + if (ret) 215 + return POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; 216 + 217 + switch (tmp) { 218 + case CHGSTM_TRICKLE_CHARGE: 219 + case CHGSTM_PRE_CHARGE: 220 + return POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 221 + case CHGSTM_FAST_CHARGE: 222 + return POWER_SUPPLY_CHARGE_TYPE_FAST; 223 + case CHGSTM_TOP_OFF: 224 + case CHGSTM_DONE: 225 + case CHGSTM_SUSPEND: 226 + return POWER_SUPPLY_CHARGE_TYPE_NONE; 227 + default: /* Rest of the states are error related, no charging */ 228 + return POWER_SUPPLY_CHARGE_TYPE_NONE; 229 + } 230 + } 231 + 232 + static bool bd9995x_get_prop_batt_present(struct bd9995x_device *bd) 233 + { 234 + int ret, tmp; 235 + 236 + ret = regmap_field_read(bd->rmap_fields[F_BATTEMP], &tmp); 237 + if (ret) 238 + return false; 239 + 240 + return tmp != BATT_OPEN; 241 + } 242 + 243 + static int bd9995x_get_prop_batt_voltage(struct bd9995x_device *bd) 244 + { 245 + int ret, tmp; 246 + 247 + ret = regmap_field_read(bd->rmap_fields[F_VBAT_VAL], &tmp); 248 + if (ret) 249 + return 0; 250 + 251 + tmp = min(tmp, 19200); 252 + 253 + return tmp * 1000; 254 + } 255 + 256 + static int bd9995x_get_prop_batt_current(struct bd9995x_device *bd) 257 + { 258 + int ret, tmp; 259 + 260 + ret = regmap_field_read(bd->rmap_fields[F_IBATP_VAL], &tmp); 261 + if (ret) 262 + return 0; 263 + 264 + return tmp * 1000; 265 + } 266 + 267 + #define DEFAULT_BATTERY_TEMPERATURE 250 268 + 269 + static int bd9995x_get_prop_batt_temp(struct bd9995x_device *bd) 270 + { 271 + int ret, tmp; 272 + 273 + ret = regmap_field_read(bd->rmap_fields[F_THERM_VAL], &tmp); 274 + if (ret) 275 + return DEFAULT_BATTERY_TEMPERATURE; 276 + 277 + return (200 - tmp) * 10; 278 + } 279 + 280 + static int bd9995x_power_supply_get_property(struct power_supply *psy, 281 + enum power_supply_property psp, 282 + union power_supply_propval *val) 283 + { 284 + int ret, tmp; 285 + struct bd9995x_device *bd = power_supply_get_drvdata(psy); 286 + struct bd9995x_state state; 287 + 288 + mutex_lock(&bd->lock); 289 + state = bd->state; 290 + mutex_unlock(&bd->lock); 291 + 292 + switch (psp) { 293 + case POWER_SUPPLY_PROP_STATUS: 294 + switch (state.chgstm_status) { 295 + case CHGSTM_TRICKLE_CHARGE: 296 + case CHGSTM_PRE_CHARGE: 297 + case CHGSTM_FAST_CHARGE: 298 + case CHGSTM_TOP_OFF: 299 + val->intval = POWER_SUPPLY_STATUS_CHARGING; 300 + break; 301 + 302 + case CHGSTM_DONE: 303 + val->intval = POWER_SUPPLY_STATUS_FULL; 304 + break; 305 + 306 + case CHGSTM_SUSPEND: 307 + case CHGSTM_TEMPERATURE_ERROR_1: 308 + case CHGSTM_TEMPERATURE_ERROR_2: 309 + case CHGSTM_TEMPERATURE_ERROR_3: 310 + case CHGSTM_TEMPERATURE_ERROR_4: 311 + case CHGSTM_TEMPERATURE_ERROR_5: 312 + case CHGSTM_TEMPERATURE_ERROR_6: 313 + case CHGSTM_TEMPERATURE_ERROR_7: 314 + case CHGSTM_THERMAL_SHUT_DOWN_1: 315 + case CHGSTM_THERMAL_SHUT_DOWN_2: 316 + case CHGSTM_THERMAL_SHUT_DOWN_3: 317 + case CHGSTM_THERMAL_SHUT_DOWN_4: 318 + case CHGSTM_THERMAL_SHUT_DOWN_5: 319 + case CHGSTM_THERMAL_SHUT_DOWN_6: 320 + case CHGSTM_THERMAL_SHUT_DOWN_7: 321 + case CHGSTM_BATTERY_ERROR: 322 + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 323 + break; 324 + 325 + default: 326 + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; 327 + break; 328 + } 329 + break; 330 + 331 + case POWER_SUPPLY_PROP_MANUFACTURER: 332 + val->strval = BD9995X_MANUFACTURER; 333 + break; 334 + 335 + case POWER_SUPPLY_PROP_ONLINE: 336 + val->intval = state.online; 337 + break; 338 + 339 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 340 + ret = regmap_field_read(bd->rmap_fields[F_IBATP_VAL], &tmp); 341 + if (ret) 342 + return ret; 343 + val->intval = tmp * 1000; 344 + break; 345 + 346 + case POWER_SUPPLY_PROP_CHARGE_AVG: 347 + ret = regmap_field_read(bd->rmap_fields[F_IBATP_AVE_VAL], &tmp); 348 + if (ret) 349 + return ret; 350 + val->intval = tmp * 1000; 351 + break; 352 + 353 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 354 + /* 355 + * Currently the DT uses this property to give the 356 + * target current for fast-charging constant current phase. 357 + * I think it is correct in a sense. 358 + * 359 + * Yet, this prop we read and return here is the programmed 360 + * safety limit for combined input currents. This feels 361 + * also correct in a sense. 362 + * 363 + * However, this results a mismatch to DT value and value 364 + * read from sysfs. 365 + */ 366 + ret = regmap_field_read(bd->rmap_fields[F_SEL_ILIM_VAL], &tmp); 367 + if (ret) 368 + return ret; 369 + val->intval = tmp * 1000; 370 + break; 371 + 372 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 373 + if (!state.online) { 374 + val->intval = 0; 375 + break; 376 + } 377 + 378 + ret = regmap_field_read(bd->rmap_fields[F_VFASTCHG_REG_SET1], 379 + &tmp); 380 + if (ret) 381 + return ret; 382 + 383 + /* 384 + * The actual range : 2560 to 19200 mV. No matter what the 385 + * register says 386 + */ 387 + val->intval = clamp_val(tmp << 4, 2560, 19200); 388 + val->intval *= 1000; 389 + break; 390 + 391 + case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 392 + ret = regmap_field_read(bd->rmap_fields[F_ITERM_SET], &tmp); 393 + if (ret) 394 + return ret; 395 + /* Start step is 64 mA */ 396 + val->intval = tmp << 6; 397 + /* Maximum is 1024 mA - no matter what register says */ 398 + val->intval = min(val->intval, 1024); 399 + val->intval *= 1000; 400 + break; 401 + 402 + /* Battery properties which we access through charger */ 403 + case POWER_SUPPLY_PROP_PRESENT: 404 + val->intval = bd9995x_get_prop_batt_present(bd); 405 + break; 406 + 407 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 408 + val->intval = bd9995x_get_prop_batt_voltage(bd); 409 + break; 410 + 411 + case POWER_SUPPLY_PROP_CURRENT_NOW: 412 + val->intval = bd9995x_get_prop_batt_current(bd); 413 + break; 414 + 415 + case POWER_SUPPLY_PROP_CHARGE_TYPE: 416 + val->intval = bd9995x_get_prop_charge_type(bd); 417 + break; 418 + 419 + case POWER_SUPPLY_PROP_HEALTH: 420 + val->intval = bd9995x_get_prop_batt_health(bd); 421 + break; 422 + 423 + case POWER_SUPPLY_PROP_TEMP: 424 + val->intval = bd9995x_get_prop_batt_temp(bd); 425 + break; 426 + 427 + case POWER_SUPPLY_PROP_TECHNOLOGY: 428 + val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 429 + break; 430 + 431 + case POWER_SUPPLY_PROP_MODEL_NAME: 432 + val->strval = "bd99954"; 433 + break; 434 + 435 + default: 436 + return -EINVAL; 437 + 438 + } 439 + 440 + return 0; 441 + } 442 + 443 + static int bd9995x_get_chip_state(struct bd9995x_device *bd, 444 + struct bd9995x_state *state) 445 + { 446 + int i, ret, tmp; 447 + struct { 448 + struct regmap_field *id; 449 + u16 *data; 450 + } state_fields[] = { 451 + { 452 + bd->rmap_fields[F_CHGSTM_STATE], &state->chgstm_status, 453 + }, { 454 + bd->rmap_fields[F_VBAT_VSYS_STATUS], 455 + &state->vbat_vsys_status, 456 + }, { 457 + bd->rmap_fields[F_VBUS_VCC_STATUS], 458 + &state->vbus_vcc_status, 459 + }, 460 + }; 461 + 462 + 463 + for (i = 0; i < ARRAY_SIZE(state_fields); i++) { 464 + ret = regmap_field_read(state_fields[i].id, &tmp); 465 + if (ret) 466 + return ret; 467 + 468 + *state_fields[i].data = tmp; 469 + } 470 + 471 + if (state->vbus_vcc_status & STATUS_VCC_DET || 472 + state->vbus_vcc_status & STATUS_VBUS_DET) 473 + state->online = 1; 474 + else 475 + state->online = 0; 476 + 477 + return 0; 478 + } 479 + 480 + static irqreturn_t bd9995x_irq_handler_thread(int irq, void *private) 481 + { 482 + struct bd9995x_device *bd = private; 483 + int ret, status, mask, i; 484 + unsigned long tmp; 485 + struct bd9995x_state state; 486 + 487 + /* 488 + * The bd9995x does not seem to generate big amount of interrupts. 489 + * The logic regarding which interrupts can cause relevant 490 + * status changes seem to be pretty complex. 491 + * 492 + * So lets implement really simple and hopefully bullet-proof handler: 493 + * It does not really matter which IRQ we handle, we just go and 494 + * re-read all interesting statuses + give the framework a nudge. 495 + * 496 + * Other option would be building a _complex_ and error prone logic 497 + * trying to decide what could have been changed (resulting this IRQ 498 + * we are now handling). During the normal operation the BD99954 does 499 + * not seem to be generating much of interrupts so benefit from such 500 + * logic would probably be minimal. 501 + */ 502 + 503 + ret = regmap_read(bd->rmap, INT0_STATUS, &status); 504 + if (ret) { 505 + dev_err(bd->dev, "Failed to read IRQ status\n"); 506 + return IRQ_NONE; 507 + } 508 + 509 + ret = regmap_field_read(bd->rmap_fields[F_INT0_SET], &mask); 510 + if (ret) { 511 + dev_err(bd->dev, "Failed to read IRQ mask\n"); 512 + return IRQ_NONE; 513 + } 514 + 515 + /* Handle only IRQs that are not masked */ 516 + status &= mask; 517 + tmp = status; 518 + 519 + /* Lowest bit does not represent any sub-registers */ 520 + tmp >>= 1; 521 + 522 + /* 523 + * Mask and ack IRQs we will handle (+ the idiot bit) 524 + */ 525 + ret = regmap_field_write(bd->rmap_fields[F_INT0_SET], 0); 526 + if (ret) { 527 + dev_err(bd->dev, "Failed to mask F_INT0\n"); 528 + return IRQ_NONE; 529 + } 530 + 531 + ret = regmap_write(bd->rmap, INT0_STATUS, status); 532 + if (ret) { 533 + dev_err(bd->dev, "Failed to ack F_INT0\n"); 534 + goto err_umask; 535 + } 536 + 537 + for_each_set_bit(i, &tmp, 7) { 538 + int sub_status, sub_mask; 539 + int sub_status_reg[] = { 540 + INT1_STATUS, INT2_STATUS, INT3_STATUS, INT4_STATUS, 541 + INT5_STATUS, INT6_STATUS, INT7_STATUS, 542 + }; 543 + struct regmap_field *sub_mask_f[] = { 544 + bd->rmap_fields[F_INT1_SET], 545 + bd->rmap_fields[F_INT2_SET], 546 + bd->rmap_fields[F_INT3_SET], 547 + bd->rmap_fields[F_INT4_SET], 548 + bd->rmap_fields[F_INT5_SET], 549 + bd->rmap_fields[F_INT6_SET], 550 + bd->rmap_fields[F_INT7_SET], 551 + }; 552 + 553 + /* Clear sub IRQs */ 554 + ret = regmap_read(bd->rmap, sub_status_reg[i], &sub_status); 555 + if (ret) { 556 + dev_err(bd->dev, "Failed to read IRQ sub-status\n"); 557 + goto err_umask; 558 + } 559 + 560 + ret = regmap_field_read(sub_mask_f[i], &sub_mask); 561 + if (ret) { 562 + dev_err(bd->dev, "Failed to read IRQ sub-mask\n"); 563 + goto err_umask; 564 + } 565 + 566 + /* Ack active sub-statuses */ 567 + sub_status &= sub_mask; 568 + 569 + ret = regmap_write(bd->rmap, sub_status_reg[i], sub_status); 570 + if (ret) { 571 + dev_err(bd->dev, "Failed to ack sub-IRQ\n"); 572 + goto err_umask; 573 + } 574 + } 575 + 576 + ret = regmap_field_write(bd->rmap_fields[F_INT0_SET], mask); 577 + if (ret) 578 + /* May as well retry once */ 579 + goto err_umask; 580 + 581 + /* Read whole chip state */ 582 + ret = bd9995x_get_chip_state(bd, &state); 583 + if (ret < 0) { 584 + dev_err(bd->dev, "Failed to read chip state\n"); 585 + } else { 586 + mutex_lock(&bd->lock); 587 + bd->state = state; 588 + mutex_unlock(&bd->lock); 589 + 590 + power_supply_changed(bd->charger); 591 + } 592 + 593 + return IRQ_HANDLED; 594 + 595 + err_umask: 596 + ret = regmap_field_write(bd->rmap_fields[F_INT0_SET], mask); 597 + if (ret) 598 + dev_err(bd->dev, 599 + "Failed to un-mask F_INT0 - IRQ permanently disabled\n"); 600 + 601 + return IRQ_NONE; 602 + } 603 + 604 + static int __bd9995x_chip_reset(struct bd9995x_device *bd) 605 + { 606 + int ret, state; 607 + int rst_check_counter = 10; 608 + u16 tmp = ALLRST | OTPLD; 609 + 610 + ret = regmap_raw_write(bd->rmap, SYSTEM_CTRL_SET, &tmp, 2); 611 + if (ret < 0) 612 + return ret; 613 + 614 + do { 615 + ret = regmap_field_read(bd->rmap_fields[F_OTPLD_STATE], &state); 616 + if (ret) 617 + return ret; 618 + 619 + msleep(10); 620 + } while (state == 0 && --rst_check_counter); 621 + 622 + if (!rst_check_counter) { 623 + dev_err(bd->dev, "chip reset not completed\n"); 624 + return -ETIMEDOUT; 625 + } 626 + 627 + tmp = 0; 628 + ret = regmap_raw_write(bd->rmap, SYSTEM_CTRL_SET, &tmp, 2); 629 + 630 + return ret; 631 + } 632 + 633 + static int bd9995x_hw_init(struct bd9995x_device *bd) 634 + { 635 + int ret; 636 + int i; 637 + struct bd9995x_state state; 638 + struct bd9995x_init_data *id = &bd->init_data; 639 + 640 + const struct { 641 + enum bd9995x_fields id; 642 + u16 value; 643 + } init_data[] = { 644 + /* Enable the charging trigger after SDP charger attached */ 645 + {F_SDP_CHG_TRIG_EN, 1}, 646 + /* Enable charging trigger after SDP charger attached */ 647 + {F_SDP_CHG_TRIG, 1}, 648 + /* Disable charging trigger by BC1.2 detection */ 649 + {F_VBUS_BC_DISEN, 1}, 650 + /* Disable charging trigger by BC1.2 detection */ 651 + {F_VCC_BC_DISEN, 1}, 652 + /* Disable automatic limitation of the input current */ 653 + {F_ILIM_AUTO_DISEN, 1}, 654 + /* Select current limitation when SDP charger attached*/ 655 + {F_SDP_500_SEL, 1}, 656 + /* Select current limitation when DCP charger attached */ 657 + {F_DCP_2500_SEL, 1}, 658 + {F_VSYSREG_SET, id->vsysreg_set}, 659 + /* Activate USB charging and DC/DC converter */ 660 + {F_USB_SUS, 0}, 661 + /* DCDC clock: 1200 kHz*/ 662 + {F_DCDC_CLK_SEL, 3}, 663 + /* Enable charging */ 664 + {F_CHG_EN, 1}, 665 + /* Disable Input current Limit setting voltage measurement */ 666 + {F_EXTIADPEN, 0}, 667 + /* Disable input current limiting */ 668 + {F_VSYS_PRIORITY, 1}, 669 + {F_IBUS_LIM_SET, id->ibus_lim_set}, 670 + {F_ICC_LIM_SET, id->icc_lim_set}, 671 + /* Charge Termination Current Setting to 0*/ 672 + {F_ITERM_SET, id->iterm_set}, 673 + /* Trickle-charge Current Setting */ 674 + {F_ITRICH_SET, id->itrich_set}, 675 + /* Pre-charge Current setting */ 676 + {F_IPRECH_SET, id->iprech_set}, 677 + /* Fast Charge Current for constant current phase */ 678 + {F_ICHG_SET, id->ichg_set}, 679 + /* Fast Charge Voltage Regulation Setting */ 680 + {F_VFASTCHG_REG_SET1, id->vfastchg_reg_set1}, 681 + /* Set Pre-charge Voltage Threshold for trickle charging. */ 682 + {F_VPRECHG_TH_SET, id->vprechg_th_set}, 683 + {F_VRECHG_SET, id->vrechg_set}, 684 + {F_VBATOVP_SET, id->vbatovp_set}, 685 + /* Reverse buck boost voltage Setting */ 686 + {F_VRBOOST_SET, 0}, 687 + /* Disable fast-charging watchdog */ 688 + {F_WDT_FST, 0}, 689 + /* Disable pre-charging watchdog */ 690 + {F_WDT_PRE, 0}, 691 + /* Power save off */ 692 + {F_POWER_SAVE_MODE, 0}, 693 + {F_INT1_SET, INT1_ALL}, 694 + {F_INT2_SET, INT2_ALL}, 695 + {F_INT3_SET, INT3_ALL}, 696 + {F_INT4_SET, INT4_ALL}, 697 + {F_INT5_SET, INT5_ALL}, 698 + {F_INT6_SET, INT6_ALL}, 699 + {F_INT7_SET, INT7_ALL}, 700 + }; 701 + 702 + /* 703 + * Currently we initialize charger to a known state at startup. 704 + * If we want to allow for example the boot code to initialize 705 + * charger we should get rid of this. 706 + */ 707 + ret = __bd9995x_chip_reset(bd); 708 + if (ret < 0) 709 + return ret; 710 + 711 + /* Initialize currents/voltages and other parameters */ 712 + for (i = 0; i < ARRAY_SIZE(init_data); i++) { 713 + ret = regmap_field_write(bd->rmap_fields[init_data[i].id], 714 + init_data[i].value); 715 + if (ret) { 716 + dev_err(bd->dev, "failed to initialize charger (%d)\n", 717 + ret); 718 + return ret; 719 + } 720 + } 721 + 722 + ret = bd9995x_get_chip_state(bd, &state); 723 + if (ret < 0) 724 + return ret; 725 + 726 + mutex_lock(&bd->lock); 727 + bd->state = state; 728 + mutex_unlock(&bd->lock); 729 + 730 + return 0; 731 + } 732 + 733 + static enum power_supply_property bd9995x_power_supply_props[] = { 734 + POWER_SUPPLY_PROP_MANUFACTURER, 735 + POWER_SUPPLY_PROP_STATUS, 736 + POWER_SUPPLY_PROP_ONLINE, 737 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 738 + POWER_SUPPLY_PROP_CHARGE_AVG, 739 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 740 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, 741 + POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, 742 + /* Battery props we access through charger */ 743 + POWER_SUPPLY_PROP_PRESENT, 744 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 745 + POWER_SUPPLY_PROP_CURRENT_NOW, 746 + POWER_SUPPLY_PROP_CHARGE_TYPE, 747 + POWER_SUPPLY_PROP_HEALTH, 748 + POWER_SUPPLY_PROP_TEMP, 749 + POWER_SUPPLY_PROP_TECHNOLOGY, 750 + POWER_SUPPLY_PROP_MODEL_NAME, 751 + }; 752 + 753 + static const struct power_supply_desc bd9995x_power_supply_desc = { 754 + .name = "bd9995x-charger", 755 + .type = POWER_SUPPLY_TYPE_USB, 756 + .properties = bd9995x_power_supply_props, 757 + .num_properties = ARRAY_SIZE(bd9995x_power_supply_props), 758 + .get_property = bd9995x_power_supply_get_property, 759 + }; 760 + 761 + /* 762 + * Limit configurations for vbus-input-current and vcc-vacp-input-current 763 + * Minimum limit is 0 uA. Max is 511 * 32000 uA = 16352000 uA. This is 764 + * configured by writing a register so that each increment in register 765 + * value equals to 32000 uA limit increment. 766 + * 767 + * Eg, value 0x0 is limit 0, value 0x1 is limit 32000, ... 768 + * Describe the setting in linear_range table. 769 + */ 770 + static const struct linear_range input_current_limit_ranges[] = { 771 + { 772 + .min = 0, 773 + .step = 32000, 774 + .min_sel = 0x0, 775 + .max_sel = 0x1ff, 776 + }, 777 + }; 778 + 779 + /* Possible trickle, pre-charging and termination current values */ 780 + static const struct linear_range charging_current_ranges[] = { 781 + { 782 + .min = 0, 783 + .step = 64000, 784 + .min_sel = 0x0, 785 + .max_sel = 0x10, 786 + }, { 787 + .min = 1024000, 788 + .step = 0, 789 + .min_sel = 0x11, 790 + .max_sel = 0x1f, 791 + }, 792 + }; 793 + 794 + /* 795 + * Fast charging voltage regulation, starting re-charging limit 796 + * and battery over voltage protection have same possible values 797 + */ 798 + static const struct linear_range charge_voltage_regulation_ranges[] = { 799 + { 800 + .min = 2560000, 801 + .step = 0, 802 + .min_sel = 0, 803 + .max_sel = 0xA0, 804 + }, { 805 + .min = 2560000, 806 + .step = 16000, 807 + .min_sel = 0xA0, 808 + .max_sel = 0x4B0, 809 + }, { 810 + .min = 19200000, 811 + .step = 0, 812 + .min_sel = 0x4B0, 813 + .max_sel = 0x7FF, 814 + }, 815 + }; 816 + 817 + /* Possible VSYS voltage regulation values */ 818 + static const struct linear_range vsys_voltage_regulation_ranges[] = { 819 + { 820 + .min = 2560000, 821 + .step = 0, 822 + .min_sel = 0, 823 + .max_sel = 0x28, 824 + }, { 825 + .min = 2560000, 826 + .step = 64000, 827 + .min_sel = 0x28, 828 + .max_sel = 0x12C, 829 + }, { 830 + .min = 19200000, 831 + .step = 0, 832 + .min_sel = 0x12C, 833 + .max_sel = 0x1FF, 834 + }, 835 + }; 836 + 837 + /* Possible settings for switching from trickle to pre-charging limits */ 838 + static const struct linear_range trickle_to_pre_threshold_ranges[] = { 839 + { 840 + .min = 2048000, 841 + .step = 0, 842 + .min_sel = 0, 843 + .max_sel = 0x20, 844 + }, { 845 + .min = 2048000, 846 + .step = 64000, 847 + .min_sel = 0x20, 848 + .max_sel = 0x12C, 849 + }, { 850 + .min = 19200000, 851 + .step = 0, 852 + .min_sel = 0x12C, 853 + .max_sel = 0x1FF 854 + } 855 + }; 856 + 857 + /* Possible current values for fast-charging constant current phase */ 858 + static const struct linear_range fast_charge_current_ranges[] = { 859 + { 860 + .min = 0, 861 + .step = 64000, 862 + .min_sel = 0, 863 + .max_sel = 0xFF, 864 + } 865 + }; 866 + 867 + struct battery_init { 868 + const char *name; 869 + int *info_data; 870 + const struct linear_range *range; 871 + int ranges; 872 + u16 *data; 873 + }; 874 + 875 + struct dt_init { 876 + char *prop; 877 + const struct linear_range *range; 878 + int ranges; 879 + u16 *data; 880 + }; 881 + 882 + static int bd9995x_fw_probe(struct bd9995x_device *bd) 883 + { 884 + int ret; 885 + struct power_supply_battery_info info; 886 + u32 property; 887 + int i; 888 + int regval; 889 + bool found; 890 + struct bd9995x_init_data *init = &bd->init_data; 891 + struct battery_init battery_inits[] = { 892 + { 893 + .name = "trickle-charging current", 894 + .info_data = &info.tricklecharge_current_ua, 895 + .range = &charging_current_ranges[0], 896 + .ranges = 2, 897 + .data = &init->itrich_set, 898 + }, { 899 + .name = "pre-charging current", 900 + .info_data = &info.precharge_current_ua, 901 + .range = &charging_current_ranges[0], 902 + .ranges = 2, 903 + .data = &init->iprech_set, 904 + }, { 905 + .name = "pre-to-trickle charge voltage threshold", 906 + .info_data = &info.precharge_voltage_max_uv, 907 + .range = &trickle_to_pre_threshold_ranges[0], 908 + .ranges = 2, 909 + .data = &init->vprechg_th_set, 910 + }, { 911 + .name = "charging termination current", 912 + .info_data = &info.charge_term_current_ua, 913 + .range = &charging_current_ranges[0], 914 + .ranges = 2, 915 + .data = &init->iterm_set, 916 + }, { 917 + .name = "charging re-start voltage", 918 + .info_data = &info.charge_restart_voltage_uv, 919 + .range = &charge_voltage_regulation_ranges[0], 920 + .ranges = 2, 921 + .data = &init->vrechg_set, 922 + }, { 923 + .name = "battery overvoltage limit", 924 + .info_data = &info.overvoltage_limit_uv, 925 + .range = &charge_voltage_regulation_ranges[0], 926 + .ranges = 2, 927 + .data = &init->vbatovp_set, 928 + }, { 929 + .name = "fast-charging max current", 930 + .info_data = &info.constant_charge_current_max_ua, 931 + .range = &fast_charge_current_ranges[0], 932 + .ranges = 1, 933 + .data = &init->ichg_set, 934 + }, { 935 + .name = "fast-charging voltage", 936 + .info_data = &info.constant_charge_voltage_max_uv, 937 + .range = &charge_voltage_regulation_ranges[0], 938 + .ranges = 2, 939 + .data = &init->vfastchg_reg_set1, 940 + }, 941 + }; 942 + struct dt_init props[] = { 943 + { 944 + .prop = "rohm,vsys-regulation-microvolt", 945 + .range = &vsys_voltage_regulation_ranges[0], 946 + .ranges = 2, 947 + .data = &init->vsysreg_set, 948 + }, { 949 + .prop = "rohm,vbus-input-current-limit-microamp", 950 + .range = &input_current_limit_ranges[0], 951 + .ranges = 1, 952 + .data = &init->ibus_lim_set, 953 + }, { 954 + .prop = "rohm,vcc-input-current-limit-microamp", 955 + .range = &input_current_limit_ranges[0], 956 + .ranges = 1, 957 + .data = &init->icc_lim_set, 958 + }, 959 + }; 960 + 961 + /* 962 + * The power_supply_get_battery_info() does not support getting values 963 + * from ACPI. Let's fix it if ACPI is required here. 964 + */ 965 + ret = power_supply_get_battery_info(bd->charger, &info); 966 + if (ret < 0) 967 + return ret; 968 + 969 + for (i = 0; i < ARRAY_SIZE(battery_inits); i++) { 970 + int val = *battery_inits[i].info_data; 971 + const struct linear_range *range = battery_inits[i].range; 972 + int ranges = battery_inits[i].ranges; 973 + 974 + if (val == -EINVAL) 975 + continue; 976 + 977 + ret = linear_range_get_selector_low_array(range, ranges, val, 978 + &regval, &found); 979 + if (ret) { 980 + dev_err(bd->dev, "Unsupported value for %s\n", 981 + battery_inits[i].name); 982 + 983 + power_supply_put_battery_info(bd->charger, &info); 984 + return -EINVAL; 985 + } 986 + if (!found) { 987 + dev_warn(bd->dev, 988 + "Unsupported value for %s - using smaller\n", 989 + battery_inits[i].name); 990 + } 991 + *(battery_inits[i].data) = regval; 992 + } 993 + 994 + power_supply_put_battery_info(bd->charger, &info); 995 + 996 + for (i = 0; i < ARRAY_SIZE(props); i++) { 997 + ret = device_property_read_u32(bd->dev, props[i].prop, 998 + &property); 999 + if (ret < 0) { 1000 + dev_err(bd->dev, "failed to read %s", props[i].prop); 1001 + 1002 + return ret; 1003 + } 1004 + 1005 + ret = linear_range_get_selector_low_array(props[i].range, 1006 + props[i].ranges, 1007 + property, &regval, 1008 + &found); 1009 + if (ret) { 1010 + dev_err(bd->dev, "Unsupported value for '%s'\n", 1011 + props[i].prop); 1012 + 1013 + return -EINVAL; 1014 + } 1015 + 1016 + if (!found) { 1017 + dev_warn(bd->dev, 1018 + "Unsupported value for '%s' - using smaller\n", 1019 + props[i].prop); 1020 + } 1021 + 1022 + *(props[i].data) = regval; 1023 + } 1024 + 1025 + return 0; 1026 + } 1027 + 1028 + static void bd9995x_chip_reset(void *bd) 1029 + { 1030 + __bd9995x_chip_reset(bd); 1031 + } 1032 + 1033 + static int bd9995x_probe(struct i2c_client *client) 1034 + { 1035 + struct device *dev = &client->dev; 1036 + struct bd9995x_device *bd; 1037 + struct power_supply_config psy_cfg = {}; 1038 + int ret; 1039 + int i; 1040 + 1041 + bd = devm_kzalloc(dev, sizeof(*bd), GFP_KERNEL); 1042 + if (!bd) 1043 + return -ENOMEM; 1044 + 1045 + bd->client = client; 1046 + bd->dev = dev; 1047 + psy_cfg.drv_data = bd; 1048 + psy_cfg.of_node = dev->of_node; 1049 + 1050 + mutex_init(&bd->lock); 1051 + 1052 + bd->rmap = devm_regmap_init_i2c(client, &bd9995x_regmap_config); 1053 + if (IS_ERR(bd->rmap)) { 1054 + dev_err(dev, "Failed to setup register access via i2c\n"); 1055 + return PTR_ERR(bd->rmap); 1056 + } 1057 + 1058 + for (i = 0; i < ARRAY_SIZE(bd9995x_reg_fields); i++) { 1059 + const struct reg_field *reg_fields = bd9995x_reg_fields; 1060 + 1061 + bd->rmap_fields[i] = devm_regmap_field_alloc(dev, bd->rmap, 1062 + reg_fields[i]); 1063 + if (IS_ERR(bd->rmap_fields[i])) { 1064 + dev_err(dev, "cannot allocate regmap field\n"); 1065 + return PTR_ERR(bd->rmap_fields[i]); 1066 + } 1067 + } 1068 + 1069 + i2c_set_clientdata(client, bd); 1070 + 1071 + ret = regmap_field_read(bd->rmap_fields[F_CHIP_ID], &bd->chip_id); 1072 + if (ret) { 1073 + dev_err(dev, "Cannot read chip ID.\n"); 1074 + return ret; 1075 + } 1076 + 1077 + if (bd->chip_id != BD99954_ID) { 1078 + dev_err(dev, "Chip with ID=0x%x, not supported!\n", 1079 + bd->chip_id); 1080 + return -ENODEV; 1081 + } 1082 + 1083 + ret = regmap_field_read(bd->rmap_fields[F_CHIP_REV], &bd->chip_rev); 1084 + if (ret) { 1085 + dev_err(dev, "Cannot read revision.\n"); 1086 + return ret; 1087 + } 1088 + 1089 + dev_info(bd->dev, "Found BD99954 chip rev %d\n", bd->chip_rev); 1090 + 1091 + /* 1092 + * We need to init the psy before we can call 1093 + * power_supply_get_battery_info() for it 1094 + */ 1095 + bd->charger = devm_power_supply_register(bd->dev, 1096 + &bd9995x_power_supply_desc, 1097 + &psy_cfg); 1098 + if (IS_ERR(bd->charger)) { 1099 + dev_err(dev, "Failed to register power supply\n"); 1100 + return PTR_ERR(bd->charger); 1101 + } 1102 + 1103 + ret = bd9995x_fw_probe(bd); 1104 + if (ret < 0) { 1105 + dev_err(dev, "Cannot read device properties.\n"); 1106 + return ret; 1107 + } 1108 + 1109 + ret = bd9995x_hw_init(bd); 1110 + if (ret < 0) { 1111 + dev_err(dev, "Cannot initialize the chip.\n"); 1112 + return ret; 1113 + } 1114 + 1115 + ret = devm_add_action_or_reset(dev, bd9995x_chip_reset, bd); 1116 + if (ret) 1117 + return ret; 1118 + 1119 + return devm_request_threaded_irq(dev, client->irq, NULL, 1120 + bd9995x_irq_handler_thread, 1121 + IRQF_TRIGGER_LOW | IRQF_ONESHOT, 1122 + BD9995X_IRQ_PIN, bd); 1123 + } 1124 + 1125 + static const struct of_device_id bd9995x_of_match[] = { 1126 + { .compatible = "rohm,bd99954", }, 1127 + { } 1128 + }; 1129 + MODULE_DEVICE_TABLE(of, bd9995x_of_match); 1130 + 1131 + static struct i2c_driver bd9995x_driver = { 1132 + .driver = { 1133 + .name = "bd9995x-charger", 1134 + .of_match_table = bd9995x_of_match, 1135 + }, 1136 + .probe_new = bd9995x_probe, 1137 + }; 1138 + module_i2c_driver(bd9995x_driver); 1139 + 1140 + MODULE_AUTHOR("Laine Markus <markus.laine@fi.rohmeurope.com>"); 1141 + MODULE_DESCRIPTION("ROHM BD99954 charger driver"); 1142 + MODULE_LICENSE("GPL");
+1075
drivers/power/supply/bd99954-charger.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* Copyright (C) 2020 ROHM Semiconductors */ 3 + #ifndef BD99954_CHARGER_H 4 + #define BD99954_CHARGER_H 5 + 6 + #include <linux/regmap.h> 7 + 8 + #define BD9995X_MANUFACTURER "Rohm Semiconductor" 9 + #define BD9995X_IRQ_PIN "bd9995x_irq" 10 + 11 + #define BD9995X_VSYS_PRECHARGE_OFFSET_MV 200 12 + 13 + #define BD99954_ID 0x346 14 + #define BD99955_ID 0x221 15 + #define BD99956_ID 0x331 16 + 17 + /* Battery Charger Commands */ 18 + #define CHARGING_CURRENT 0x14 19 + #define CHARGING_VOLTAGE 0x15 20 + #define PROTECT_SET 0x3E 21 + #define MAP_SET 0x3F 22 + 23 + /* Extended commands */ 24 + #define CHGSTM_STATUS 0x100 25 + #define VBAT_VSYS_STATUS 0x101 26 + #define VBUS_VCC_STATUS 0x102 27 + #define CHGOP_STATUS 0x103 28 + #define WDT_STATUS 0x104 29 + #define CUR_ILIM_VAL 0x105 30 + #define SEL_ILIM_VAL 0x106 31 + #define IBUS_LIM_SET 0x107 32 + #define ICC_LIM_SET 0x108 33 + #define IOTG_LIM_SET 0x109 34 + #define VIN_CTRL_SET 0x10A 35 + #define CHGOP_SET1 0x10B 36 + #define CHGOP_SET2 0x10C 37 + #define VBUSCLPS_TH_SET 0x10D 38 + #define VCCCLPS_TH_SET 0x10E 39 + #define CHGWDT_SET 0x10F 40 + #define BATTWDT_SET 0x110 41 + #define VSYSREG_SET 0x111 42 + #define VSYSVAL_THH_SET 0x112 43 + #define VSYSVAL_THL_SET 0x113 44 + #define ITRICH_SET 0x114 45 + #define IPRECH_SET 0x115 46 + #define ICHG_SET 0x116 47 + #define ITERM_SET 0x117 48 + #define VPRECHG_TH_SET 0x118 49 + #define VRBOOST_SET 0x119 50 + #define VFASTCHG_REG_SET1 0x11A 51 + #define VFASTCHG_REG_SET2 0x11B 52 + #define VFASTCHG_REG_SET3 0x11C 53 + #define VRECHG_SET 0x11D 54 + #define VBATOVP_SET 0x11E 55 + #define IBATSHORT_SET 0x11F 56 + #define PROCHOT_CTRL_SET 0x120 57 + #define PROCHOT_ICRIT_SET 0x121 58 + #define PROCHOT_INORM_SET 0x122 59 + #define PROCHOT_IDCHG_SET 0x123 60 + #define PROCHOT_VSYS_SET 0x124 61 + #define PMON_IOUT_CTRL_SET 0x125 62 + #define PMON_DACIN_VAL 0x126 63 + #define IOUT_DACIN_VAL 0x127 64 + #define VCC_UCD_SET 0x128 65 + #define VCC_UCD_STATUS 0x129 66 + #define VCC_IDD_STATUS 0x12A 67 + #define VCC_UCD_FCTRL_SET 0x12B 68 + #define VCC_UCD_FCTRL_EN 0x12C 69 + #define VBUS_UCD_SET 0x130 70 + #define VBUS_UCD_STATUS 0x131 71 + #define VBUS_IDD_STATUS 0x132 72 + #define VBUS_UCD_FCTRL_SET 0x133 73 + #define VBUS_UCD_FCTRL_EN 0x134 74 + #define CHIP_ID 0x138 75 + #define CHIP_REV 0x139 76 + #define IC_SET1 0x13A 77 + #define IC_SET2 0x13B 78 + #define SYSTEM_STATUS 0x13C 79 + #define SYSTEM_CTRL_SET 0x13D 80 + #define VM_CTRL_SET 0x140 81 + #define THERM_WINDOW_SET1 0x141 82 + #define THERM_WINDOW_SET2 0x142 83 + #define THERM_WINDOW_SET3 0x143 84 + #define THERM_WINDOW_SET4 0x144 85 + #define THERM_WINDOW_SET5 0x145 86 + #define IBATP_TH_SET 0x146 87 + #define IBATM_TH_SET 0x147 88 + #define VBAT_TH_SET 0x148 89 + #define THERM_TH_SET 0x149 90 + #define IACP_TH_SET 0x14A 91 + #define VACP_TH_SET 0x14B 92 + #define VBUS_TH_SET 0x14C 93 + #define VCC_TH_SET 0x14D 94 + #define VSYS_TH_SET 0x14E 95 + #define EXTIADP_TH_SET 0x14F 96 + #define IBATP_VAL 0x150 97 + #define IBATP_AVE_VAL 0x151 98 + #define IBATM_VAL 0x152 99 + #define IBATM_AVE_VAL 0x153 100 + #define VBAT_VAL 0x154 101 + #define VBAT_AVE_VAL 0x155 102 + #define THERM_VAL 0x156 103 + #define VTH_VAL 0x157 104 + #define IACP_VAL 0x158 105 + #define IACP_AVE_VAL 0x159 106 + #define VACP_VAL 0x15A 107 + #define VACP_AVE_VAL 0x15B 108 + #define VBUS_VAL 0x15C 109 + #define VBUS_AVE_VAL 0x15D 110 + #define VCC_VAL 0x15E 111 + #define VCC_AVE_VAL 0x15F 112 + #define VSYS_VAL 0x160 113 + #define VSYS_AVE_VAL 0x161 114 + #define EXTIADP_VAL 0x162 115 + #define EXTIADP_AVE_VAL 0x163 116 + #define VACPCLPS_TH_SET 0x164 117 + #define INT0_SET 0x168 118 + #define INT1_SET 0x169 119 + #define INT2_SET 0x16A 120 + #define INT3_SET 0x16B 121 + #define INT4_SET 0x16C 122 + #define INT5_SET 0x16D 123 + #define INT6_SET 0x16E 124 + #define INT7_SET 0x16F 125 + #define INT0_STATUS 0x170 126 + #define INT1_STATUS 0x171 127 + #define INT2_STATUS 0x172 128 + #define INT3_STATUS 0x173 129 + #define INT4_STATUS 0x174 130 + #define INT5_STATUS 0x175 131 + #define INT6_STATUS 0x176 132 + #define INT7_STATUS 0x177 133 + #define OTPREG0 0x17A 134 + #define OTPREG1 0x17B 135 + #define SMBREG 0x17C 136 + #define DEBUG_MODE_SET 0x17F 137 + #define DEBUG0x14 0x214 138 + #define DEBUG0x1A 0x21A 139 + 140 + enum bd9995x_fields { 141 + F_PREV_CHGSTM_STATE, F_CHGSTM_STATE, 142 + F_VBAT_VSYS_STATUS, 143 + F_VBUS_VCC_STATUS, 144 + F_BATTEMP, F_VRECHG_DET, F_RBOOST_UV, F_RBOOSTS, 145 + F_THERMWDT_VAL, F_CHGWDT_VAL, 146 + F_CUR_ILIM_VAL, 147 + F_SEL_ILIM_VAL, 148 + F_IBUS_LIM_SET, 149 + F_ICC_LIM_SET, 150 + F_IOTG_LIM_SET, 151 + F_OTG_BOTH_EN, 152 + F_VRBOOST_TRIG, 153 + F_VRBOOST_EN, 154 + F_PP_BOTH_THRU, 155 + F_VIN_ORD, 156 + F_VBUS_EN, 157 + F_VCC_EN, 158 + F_VSYS_PRIORITY, 159 + F_PPC_SUB_CAP, 160 + F_PPC_CAP, 161 + F_DCP_2500_SEL, 162 + F_SDP_500_SEL, 163 + F_ILIM_AUTO_DISEN, 164 + F_VCC_BC_DISEN, 165 + F_VBUS_BC_DISEN, 166 + F_SDP_CHG_TRIG_EN, 167 + F_SDP_CHG_TRIG, 168 + F_AUTO_TOF, 169 + F_AUTO_FST, 170 + F_AUTO_RECH, 171 + F_ILIM_RESET_EN, 172 + F_DCDC_1MS_SEL, 173 + F_SEL_ILIM_DIV, 174 + F_BATT_LEARN, 175 + F_CHG_EN, 176 + F_USB_SUS, 177 + F_CHOP_SS_INIT, 178 + F_CHOP_ALL_INIT, 179 + F_DCDC_CLK_SEL, 180 + F_CHOP_SS, 181 + F_CHOP_ALL, 182 + F_VBUSCLPS_TH_SET, 183 + F_VCCCLPS_TH_SET, 184 + F_WDT_FST, 185 + F_WDT_PRE, 186 + F_WDT_IBAT_SHORT, 187 + F_WDT_THERM, 188 + F_VSYSREG_SET, 189 + F_VSYSVAL_THH_SET, 190 + F_VSYSVAL_THL_SET, 191 + F_ITRICH_SET, 192 + F_IPRECH_SET, 193 + F_ICHG_SET, 194 + F_ITERM_SET, 195 + F_VPRECHG_TH_SET, 196 + F_VRBOOST_SET, 197 + F_VFASTCHG_REG_SET1, 198 + F_VFASTCHG_REG_SET2, 199 + F_VFASTCHG_REG_SET3, 200 + F_VRECHG_SET, 201 + F_VBATOVP_SET, 202 + F_IBATM_SHORT_SET, 203 + F_PROCHOT_DG_SET, 204 + F_PROCHOT_ICRIT_DG_SET, 205 + F_PROCHOT_IDCHG_DG_SET, 206 + F_PROCHOT_EN, 207 + F_PROCHOT_ICRIT_SET, 208 + F_PROCHOT_INORM_SET, 209 + F_PROCHOT_IDCHG_SET, 210 + F_PROCHOT_VSYS_SET, 211 + F_IMON_INSEL, 212 + F_PMON_INSEL, 213 + F_IOUT_OUT_EN, 214 + F_IOUT_SOURCE_SEL, 215 + F_IOUT_GAIN_SET, 216 + F_PMON_OUT_EN, 217 + F_PMON_GAIN_SET, 218 + F_PMON_DACIN_VAL, 219 + F_IOUT_DACIN_VAL, 220 + F_VCC_BCSRETRY, 221 + F_VCC_ADCRTRY, 222 + F_VCC_USBDETEN, 223 + F_VCC_IDRDETEN, 224 + F_VCC_ENUMRDY, 225 + F_VCC_ADCPOLEN, 226 + F_VCC_DCDMODE, 227 + F_VCC_USB_SW_EN, 228 + F_VCC_USB_SW, 229 + F_VCC_DCDFAIL, 230 + F_VCC_CHGPORT, 231 + F_VCC_PUPDET, 232 + F_VCC_VBUS_VLD, 233 + F_VCC_CHGDET, 234 + F_VCC_OTGDET, 235 + F_VCC_VBINOP, 236 + F_VCC_EXTID, 237 + F_VCC_IDRDET, 238 + F_VCC_INDO, 239 + F_VCC_UCDSWEN, 240 + F_VCC_RREF_EN, 241 + F_VCC_DPPU_EN, 242 + F_VCC_DPREF_EN, 243 + F_VCC_DMREF_EN, 244 + F_VCC_DPDET_EN, 245 + F_VCC_DMDET_EN, 246 + F_VCC_DPSINK_EN, 247 + F_VCC_DMSINK_EN, 248 + F_VCC_DP_BUFF_EN, 249 + F_VCC_DM_BUFF_EN, 250 + F_VCC_EXTCLKENBL, 251 + F_VCC_PLSTESTEN, 252 + F_VCC_UCDSWEN_TSTENB, 253 + F_VCC_RREF_EN_TSTENB, 254 + F_VCC_DPPU_EN_TSTENB, 255 + F_VCC_DPREF_EN_TSTENB, 256 + F_VCC_DMREF_EN_TSTENB, 257 + F_VCC_DPDET_EN_TSTENB, 258 + F_VCC_DMDET_EN_TSTENB, 259 + F_VCC_DPSINK_EN_TSTENB, 260 + F_VCC_DMSINK_EN_TSTENB, 261 + F_VCC_DP_BUFF_EN_TSTENB, 262 + F_VCC_DM_BUFF_EN_TSTENB, 263 + F_VBUS_BCSRETRY, 264 + F_VBUS_ADCRTRY, 265 + F_VBUS_USBDETEN, 266 + F_VBUS_IDRDETEN, 267 + F_VBUS_ENUMRDY, 268 + F_VBUS_ADCPOLEN, 269 + F_VBUS_DCDMODE, 270 + F_VBUS_USB_SW_EN, 271 + F_VBUS_USB_SW, 272 + F_VBUS_DCDFAIL, 273 + F_VBUS_CHGPORT, 274 + F_VBUS_PUPDET, 275 + F_VBUS_VBUS_VLD, 276 + F_VBUS_CHGDET, 277 + F_VBUS_OTGDET, 278 + F_VBUS_VBINOP, 279 + F_VBUS_EXTID, 280 + F_VBUS_IDRDET, 281 + F_VBUS_INDO, 282 + F_VBUS_UCDSWEN, 283 + F_VBUS_RREF_EN, 284 + F_VBUS_DPPU_EN, 285 + F_VBUS_DPREF_EN, 286 + F_VBUS_DMREF_EN, 287 + F_VBUS_DPDET_EN, 288 + F_VBUS_DMDET_EN, 289 + F_VBUS_DPSINK_EN, 290 + F_VBUS_DMSINK_EN, 291 + F_VBUS_DP_BUFF_EN, 292 + F_VBUS_DM_BUFF_EN, 293 + F_VBUS_EXTCLKENBL, 294 + F_VBUS_PLSTESTEN, 295 + F_VBUS_UCDSWEN_TSTENB, 296 + F_VBUS_RREF_EN_TSTENB, 297 + F_VBUS_DPPU_EN_TSTENB, 298 + F_VBUS_DPREF_EN_TSTENB, 299 + F_VBUS_DMREF_EN_TSTENB, 300 + F_VBUS_DPDET_EN_TSTENB, 301 + F_VBUS_DMDET_EN_TSTENB, 302 + F_VBUS_DPSINK_EN_TSTENB, 303 + F_VBUS_DMSINK_EN_TSTENB, 304 + F_VBUS_DP_BUFF_EN_TSTENB, 305 + F_VBUS_DM_BUFF_EN_TSTENB, 306 + F_CHIP_ID, 307 + F_CHIP_REV, 308 + F_ONE_CELL_MODE, 309 + F_cell, 310 + F_VACP_AUTO_DISCHG, 311 + F_VACP_LOAD, 312 + F_ACOK_POL, 313 + F_ACOK_DISEN, 314 + F_DEBUG_SET1, 315 + F_DEBUG_SET0, 316 + F_MONRST_STATE, 317 + F_ALMRST_STATE, 318 + F_CHGRST_STATE, 319 + F_OTPLD_STATE, 320 + F_ALLRST_STATE, 321 + F_PROTECT_SET, 322 + F_MAP_SET, 323 + F_ADCINTERVAL, 324 + F_ADCMOD, 325 + F_ADCTMOD, 326 + F_EXTIADPEN, 327 + F_VSYSENB, 328 + F_VCCENB, 329 + F_VBUSENB, 330 + F_VACPENB, 331 + F_IACPENB, 332 + F_THERMENB, 333 + F_VBATENB, 334 + F_IBATMENB, 335 + F_IBATPENB, 336 + F_TMPTHR1B, 337 + F_TMPTHR1A, 338 + F_TMPTHR2B, 339 + F_TMPTHR2A, 340 + F_TMPTHR3B, 341 + F_TMPTHR3A, 342 + F_TMPTHR4B, 343 + F_TMPTHR4A, 344 + F_TMPTHR5B, 345 + F_TMPTHR5A, 346 + F_IBATP_TH_SET, 347 + F_IBATM_TH_SET, 348 + F_VBAT_TH_SET, 349 + F_THERM_TH_SET, 350 + F_IACP_TH_SET, 351 + F_VACP_TH_SET, 352 + F_VBUS_TH_SET, 353 + F_VCC_TH_SET, 354 + F_VSYS_TH_SET, 355 + F_EXTIADP_TH_SET, 356 + F_IBATP_VAL, 357 + F_IBATP_AVE_VAL, 358 + F_IBATM_VAL, 359 + F_IBATM_AVE_VAL, 360 + F_VBAT_VAL, 361 + F_VBAT_AVE_VAL, 362 + F_THERM_VAL, 363 + F_VTH_VAL, 364 + F_IACP_VAL, 365 + F_IACP_AVE_VAL, 366 + F_VACP_VAL, 367 + F_VACP_AVE_VAL, 368 + F_VBUS_VAL, 369 + F_VBUS_AVE_VAL, 370 + F_VCC_VAL, 371 + F_VCC_AVE_VAL, 372 + F_VSYS_VAL, 373 + F_VSYS_AVE_VAL, 374 + F_EXTIADP_VAL, 375 + F_EXTIADP_AVE_VAL, 376 + F_VACPCLPS_TH_SET, 377 + F_INT7_SET, 378 + F_INT6_SET, 379 + F_INT5_SET, 380 + F_INT4_SET, 381 + F_INT3_SET, 382 + F_INT2_SET, 383 + F_INT1_SET, 384 + F_INT0_SET, 385 + F_VBUS_RBUV_DET, 386 + F_VBUS_RBUV_RES, 387 + F_VBUS_TH_DET, 388 + F_VBUS_TH_RES, 389 + F_VBUS_IIN_MOD, 390 + F_VBUS_OV_DET, 391 + F_VBUS_OV_RES, 392 + F_VBUS_CLPS_DET, 393 + F_VBUS_CLPS, 394 + F_VBUS_DET, 395 + F_VBUS_RES, 396 + F_VCC_RBUV_DET, 397 + F_VCC_RBUV_RES, 398 + F_VCC_TH_DET, 399 + F_VCC_TH_RES, 400 + F_VCC_IIN_MOD, 401 + F_VCC_OVP_DET, 402 + F_VCC_OVP_RES, 403 + F_VCC_CLPS_DET, 404 + F_VCC_CLPS_RES, 405 + F_VCC_DET, 406 + F_VCC_RES, 407 + F_TH_DET, 408 + F_TH_RMV, 409 + F_TMP_OUT_DET, 410 + F_TMP_OUT_RES, 411 + F_VBAT_TH_DET, 412 + F_VBAT_TH_RES, 413 + F_IBAT_SHORT_DET, 414 + F_IBAT_SHORT_RES, 415 + F_VBAT_OV_DET, 416 + F_VBAT_OV_RES, 417 + F_BAT_ASSIST_DET, 418 + F_BAT_ASSIST_RES, 419 + F_VSYS_TH_DET, 420 + F_VSYS_TH_RES, 421 + F_VSYS_OV_DET, 422 + F_VSYS_OV_RES, 423 + F_VSYS_SHT_DET, 424 + F_VSYS_SHT_RES, 425 + F_VSYS_UV_DET, 426 + F_VSYS_UV_RES, 427 + F_OTP_LOAD_DONE, 428 + F_PWR_ON, 429 + F_EXTIADP_TRNS, 430 + F_EXTIADP_TH_DET, 431 + F_EXIADP_TH_RES, 432 + F_BAT_MNT_DET, 433 + F_BAT_MNT_RES, 434 + F_TSD_DET, 435 + F_TSD_RES, 436 + F_CHGWDT_EXP, 437 + F_THERMWDT_EXP, 438 + F_TMP_TRNS, 439 + F_CHG_TRNS, 440 + F_VBUS_UCD_PORT_DET, 441 + F_VBUS_UCD_UCHG_DET, 442 + F_VBUS_UCD_URID_RMV, 443 + F_VBUS_UCD_OTG_DET, 444 + F_VBUS_UCD_URID_MOD, 445 + F_VCC_UCD_PORT_DET, 446 + F_VCC_UCD_UCHG_DET, 447 + F_VCC_UCD_URID_RMV, 448 + F_VCC_UCD_OTG_DET, 449 + F_VCC_UCD_URID_MOD, 450 + F_PROCHOT_DET, 451 + F_PROCHOT_RES, 452 + F_VACP_DET, 453 + F_VACP_RES, 454 + F_VACP_TH_DET, 455 + F_VACP_TH_RES, 456 + F_IACP_TH_DET, 457 + F_IACP_THE_RES, 458 + F_THERM_TH_DET, 459 + F_THERM_TH_RES, 460 + F_IBATM_TH_DET, 461 + F_IBATM_TH_RES, 462 + F_IBATP_TH_DET, 463 + F_IBATP_TH_RES, 464 + F_INT7_STATUS, 465 + F_INT6_STATUS, 466 + F_INT5_STATUS, 467 + F_INT4_STATUS, 468 + F_INT3_STATUS, 469 + F_INT2_STATUS, 470 + F_INT1_STATUS, 471 + F_INT0_STATUS, 472 + F_ILIM_DECREASE, 473 + F_RESERVE_OTPREG1, 474 + F_POWER_SAVE_MODE, 475 + F_DEBUG_MODE_SET, 476 + F_DEBUG0x14, 477 + F_DEBUG0x1A, 478 + F_MAX_FIELDS 479 + }; 480 + 481 + static const struct reg_field bd9995x_reg_fields[] = { 482 + [F_PREV_CHGSTM_STATE] = REG_FIELD(CHGSTM_STATUS, 8, 14), 483 + [F_CHGSTM_STATE] = REG_FIELD(CHGSTM_STATUS, 0, 6), 484 + [F_VBAT_VSYS_STATUS] = REG_FIELD(VBAT_VSYS_STATUS, 0, 15), 485 + [F_VBUS_VCC_STATUS] = REG_FIELD(VBUS_VCC_STATUS, 0, 12), 486 + [F_BATTEMP] = REG_FIELD(CHGOP_STATUS, 8, 10), 487 + [F_VRECHG_DET] = REG_FIELD(CHGOP_STATUS, 6, 6), 488 + [F_RBOOST_UV] = REG_FIELD(CHGOP_STATUS, 1, 1), 489 + [F_RBOOSTS] = REG_FIELD(CHGOP_STATUS, 0, 0), 490 + [F_THERMWDT_VAL] = REG_FIELD(WDT_STATUS, 8, 15), 491 + [F_CHGWDT_VAL] = REG_FIELD(WDT_STATUS, 0, 7), 492 + [F_CUR_ILIM_VAL] = REG_FIELD(CUR_ILIM_VAL, 0, 13), 493 + [F_SEL_ILIM_VAL] = REG_FIELD(SEL_ILIM_VAL, 0, 13), 494 + [F_IBUS_LIM_SET] = REG_FIELD(IBUS_LIM_SET, 5, 13), 495 + [F_ICC_LIM_SET] = REG_FIELD(ICC_LIM_SET, 5, 13), 496 + [F_IOTG_LIM_SET] = REG_FIELD(IOTG_LIM_SET, 5, 13), 497 + [F_OTG_BOTH_EN] = REG_FIELD(VIN_CTRL_SET, 15, 15), 498 + [F_VRBOOST_TRIG] = REG_FIELD(VIN_CTRL_SET, 14, 14), 499 + [F_VRBOOST_EN] = REG_FIELD(VIN_CTRL_SET, 12, 13), 500 + [F_PP_BOTH_THRU] = REG_FIELD(VIN_CTRL_SET, 11, 11), 501 + [F_VIN_ORD] = REG_FIELD(VIN_CTRL_SET, 7, 7), 502 + [F_VBUS_EN] = REG_FIELD(VIN_CTRL_SET, 6, 6), 503 + [F_VCC_EN] = REG_FIELD(VIN_CTRL_SET, 5, 5), 504 + [F_VSYS_PRIORITY] = REG_FIELD(VIN_CTRL_SET, 4, 4), 505 + [F_PPC_SUB_CAP] = REG_FIELD(VIN_CTRL_SET, 2, 3), 506 + [F_PPC_CAP] = REG_FIELD(VIN_CTRL_SET, 0, 1), 507 + [F_DCP_2500_SEL] = REG_FIELD(CHGOP_SET1, 15, 15), 508 + [F_SDP_500_SEL] = REG_FIELD(CHGOP_SET1, 14, 14), 509 + [F_ILIM_AUTO_DISEN] = REG_FIELD(CHGOP_SET1, 13, 13), 510 + [F_VCC_BC_DISEN] = REG_FIELD(CHGOP_SET1, 11, 11), 511 + [F_VBUS_BC_DISEN] = REG_FIELD(CHGOP_SET1, 10, 10), 512 + [F_SDP_CHG_TRIG_EN] = REG_FIELD(CHGOP_SET1, 9, 9), 513 + [F_SDP_CHG_TRIG] = REG_FIELD(CHGOP_SET1, 8, 8), 514 + [F_AUTO_TOF] = REG_FIELD(CHGOP_SET1, 6, 6), 515 + [F_AUTO_FST] = REG_FIELD(CHGOP_SET1, 5, 5), 516 + [F_AUTO_RECH] = REG_FIELD(CHGOP_SET1, 3, 3), 517 + [F_ILIM_RESET_EN] = REG_FIELD(CHGOP_SET2, 14, 14), 518 + [F_DCDC_1MS_SEL] = REG_FIELD(CHGOP_SET2, 12, 13), 519 + [F_SEL_ILIM_DIV] = REG_FIELD(CHGOP_SET2, 10, 10), 520 + [F_BATT_LEARN] = REG_FIELD(CHGOP_SET2, 8, 8), 521 + [F_CHG_EN] = REG_FIELD(CHGOP_SET2, 7, 7), 522 + [F_USB_SUS] = REG_FIELD(CHGOP_SET2, 6, 6), 523 + [F_CHOP_SS_INIT] = REG_FIELD(CHGOP_SET2, 5, 5), 524 + [F_CHOP_ALL_INIT] = REG_FIELD(CHGOP_SET2, 4, 4), 525 + [F_DCDC_CLK_SEL] = REG_FIELD(CHGOP_SET2, 2, 3), 526 + [F_CHOP_SS] = REG_FIELD(CHGOP_SET2, 1, 1), 527 + [F_CHOP_ALL] = REG_FIELD(CHGOP_SET2, 0, 0), 528 + [F_VBUSCLPS_TH_SET] = REG_FIELD(VBUSCLPS_TH_SET, 7, 14), 529 + [F_VCCCLPS_TH_SET] = REG_FIELD(VCCCLPS_TH_SET, 7, 14), 530 + [F_WDT_FST] = REG_FIELD(CHGWDT_SET, 8, 15), 531 + [F_WDT_PRE] = REG_FIELD(CHGWDT_SET, 0, 7), 532 + [F_WDT_IBAT_SHORT] = REG_FIELD(BATTWDT_SET, 8, 15), 533 + [F_WDT_THERM] = REG_FIELD(BATTWDT_SET, 0, 7), 534 + [F_VSYSREG_SET] = REG_FIELD(VSYSREG_SET, 6, 14), 535 + [F_VSYSVAL_THH_SET] = REG_FIELD(VSYSVAL_THH_SET, 6, 14), 536 + [F_VSYSVAL_THL_SET] = REG_FIELD(VSYSVAL_THL_SET, 6, 14), 537 + [F_ITRICH_SET] = REG_FIELD(ITRICH_SET, 6, 10), 538 + [F_IPRECH_SET] = REG_FIELD(IPRECH_SET, 6, 10), 539 + [F_ICHG_SET] = REG_FIELD(ICHG_SET, 6, 13), 540 + [F_ITERM_SET] = REG_FIELD(ITERM_SET, 6, 10), 541 + [F_VPRECHG_TH_SET] = REG_FIELD(VPRECHG_TH_SET, 6, 14), 542 + [F_VRBOOST_SET] = REG_FIELD(VRBOOST_SET, 6, 14), 543 + [F_VFASTCHG_REG_SET1] = REG_FIELD(VFASTCHG_REG_SET1, 4, 14), 544 + [F_VFASTCHG_REG_SET2] = REG_FIELD(VFASTCHG_REG_SET2, 4, 14), 545 + [F_VFASTCHG_REG_SET3] = REG_FIELD(VFASTCHG_REG_SET3, 4, 14), 546 + [F_VRECHG_SET] = REG_FIELD(VRECHG_SET, 4, 14), 547 + [F_VBATOVP_SET] = REG_FIELD(VBATOVP_SET, 4, 14), 548 + [F_IBATM_SHORT_SET] = REG_FIELD(IBATSHORT_SET, 0, 14), 549 + [F_PROCHOT_DG_SET] = REG_FIELD(PROCHOT_CTRL_SET, 14, 15), 550 + [F_PROCHOT_ICRIT_DG_SET] = REG_FIELD(PROCHOT_CTRL_SET, 10, 11), 551 + [F_PROCHOT_IDCHG_DG_SET] = REG_FIELD(PROCHOT_CTRL_SET, 8, 9), 552 + [F_PROCHOT_EN] = REG_FIELD(PROCHOT_CTRL_SET, 0, 4), 553 + [F_PROCHOT_ICRIT_SET] = REG_FIELD(PROCHOT_ICRIT_SET, 0, 14), 554 + [F_PROCHOT_INORM_SET] = REG_FIELD(PROCHOT_INORM_SET, 0, 14), 555 + [F_PROCHOT_IDCHG_SET] = REG_FIELD(PROCHOT_IDCHG_SET, 0, 14), 556 + [F_PROCHOT_VSYS_SET] = REG_FIELD(PROCHOT_VSYS_SET, 0, 14), 557 + [F_IMON_INSEL] = REG_FIELD(PMON_IOUT_CTRL_SET, 9, 9), 558 + [F_PMON_INSEL] = REG_FIELD(PMON_IOUT_CTRL_SET, 8, 8), 559 + [F_IOUT_OUT_EN] = REG_FIELD(PMON_IOUT_CTRL_SET, 7, 7), 560 + [F_IOUT_SOURCE_SEL] = REG_FIELD(PMON_IOUT_CTRL_SET, 6, 6), 561 + [F_IOUT_GAIN_SET] = REG_FIELD(PMON_IOUT_CTRL_SET, 4, 5), 562 + [F_PMON_OUT_EN] = REG_FIELD(PMON_IOUT_CTRL_SET, 3, 3), 563 + [F_PMON_GAIN_SET] = REG_FIELD(PMON_IOUT_CTRL_SET, 0, 2), 564 + [F_PMON_DACIN_VAL] = REG_FIELD(PMON_DACIN_VAL, 0, 9), 565 + [F_IOUT_DACIN_VAL] = REG_FIELD(IOUT_DACIN_VAL, 0, 11), 566 + [F_VCC_BCSRETRY] = REG_FIELD(VCC_UCD_SET, 12, 12), 567 + [F_VCC_ADCRTRY] = REG_FIELD(VCC_UCD_SET, 8, 8), 568 + [F_VCC_USBDETEN] = REG_FIELD(VCC_UCD_SET, 7, 7), 569 + [F_VCC_IDRDETEN] = REG_FIELD(VCC_UCD_SET, 6, 6), 570 + [F_VCC_ENUMRDY] = REG_FIELD(VCC_UCD_SET, 5, 5), 571 + [F_VCC_ADCPOLEN] = REG_FIELD(VCC_UCD_SET, 4, 4), 572 + [F_VCC_DCDMODE] = REG_FIELD(VCC_UCD_SET, 3, 3), 573 + [F_VCC_USB_SW_EN] = REG_FIELD(VCC_UCD_SET, 1, 1), 574 + [F_VCC_USB_SW] = REG_FIELD(VCC_UCD_SET, 0, 0), 575 + [F_VCC_DCDFAIL] = REG_FIELD(VCC_UCD_STATUS, 15, 15), 576 + [F_VCC_CHGPORT] = REG_FIELD(VCC_UCD_STATUS, 12, 13), 577 + [F_VCC_PUPDET] = REG_FIELD(VCC_UCD_STATUS, 11, 11), 578 + [F_VCC_VBUS_VLD] = REG_FIELD(VCC_UCD_STATUS, 7, 7), 579 + [F_VCC_CHGDET] = REG_FIELD(VCC_UCD_STATUS, 6, 6), 580 + [F_VCC_OTGDET] = REG_FIELD(VCC_UCD_STATUS, 3, 3), 581 + [F_VCC_VBINOP] = REG_FIELD(VCC_IDD_STATUS, 6, 6), 582 + [F_VCC_EXTID] = REG_FIELD(VCC_IDD_STATUS, 5, 5), 583 + [F_VCC_IDRDET] = REG_FIELD(VCC_IDD_STATUS, 4, 4), 584 + [F_VCC_INDO] = REG_FIELD(VCC_IDD_STATUS, 0, 3), 585 + [F_VCC_UCDSWEN] = REG_FIELD(VCC_UCD_FCTRL_SET, 10, 10), 586 + [F_VCC_RREF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 9, 9), 587 + [F_VCC_DPPU_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 8, 8), 588 + [F_VCC_DPREF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 7, 7), 589 + [F_VCC_DMREF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 6, 6), 590 + [F_VCC_DPDET_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 5, 5), 591 + [F_VCC_DMDET_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 4, 4), 592 + [F_VCC_DPSINK_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 3, 3), 593 + [F_VCC_DMSINK_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 2, 2), 594 + [F_VCC_DP_BUFF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 1, 1), 595 + [F_VCC_DM_BUFF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 0, 0), 596 + [F_VCC_EXTCLKENBL] = REG_FIELD(VCC_UCD_FCTRL_EN, 15, 15), 597 + [F_VCC_PLSTESTEN] = REG_FIELD(VCC_UCD_FCTRL_EN, 14, 14), 598 + [F_VCC_UCDSWEN_TSTENB] = REG_FIELD(VCC_UCD_FCTRL_EN, 10, 10), 599 + [F_VCC_RREF_EN_TSTENB] = REG_FIELD(VCC_UCD_FCTRL_EN, 9, 9), 600 + [F_VCC_DPPU_EN_TSTENB] = REG_FIELD(VCC_UCD_FCTRL_EN, 8, 8), 601 + [F_VCC_DPREF_EN_TSTENB] = REG_FIELD(VCC_UCD_FCTRL_EN, 7, 7), 602 + [F_VCC_DMREF_EN_TSTENB] = REG_FIELD(VCC_UCD_FCTRL_EN, 6, 6), 603 + [F_VCC_DPDET_EN_TSTENB] = REG_FIELD(VCC_UCD_FCTRL_EN, 5, 5), 604 + [F_VCC_DMDET_EN_TSTENB] = REG_FIELD(VCC_UCD_FCTRL_EN, 4, 4), 605 + [F_VCC_DPSINK_EN_TSTENB] = REG_FIELD(VCC_UCD_FCTRL_EN, 3, 3), 606 + [F_VCC_DMSINK_EN_TSTENB] = REG_FIELD(VCC_UCD_FCTRL_EN, 2, 2), 607 + [F_VCC_DP_BUFF_EN_TSTENB] = REG_FIELD(VCC_UCD_FCTRL_EN, 1, 1), 608 + [F_VCC_DM_BUFF_EN_TSTENB] = REG_FIELD(VCC_UCD_FCTRL_EN, 0, 0), 609 + 610 + [F_VBUS_BCSRETRY] = REG_FIELD(VBUS_UCD_SET, 12, 12), 611 + [F_VBUS_ADCRTRY] = REG_FIELD(VBUS_UCD_SET, 8, 8), 612 + [F_VBUS_USBDETEN] = REG_FIELD(VBUS_UCD_SET, 7, 7), 613 + [F_VBUS_IDRDETEN] = REG_FIELD(VBUS_UCD_SET, 6, 6), 614 + [F_VBUS_ENUMRDY] = REG_FIELD(VBUS_UCD_SET, 5, 5), 615 + [F_VBUS_ADCPOLEN] = REG_FIELD(VBUS_UCD_SET, 4, 4), 616 + [F_VBUS_DCDMODE] = REG_FIELD(VBUS_UCD_SET, 3, 3), 617 + [F_VBUS_USB_SW_EN] = REG_FIELD(VBUS_UCD_SET, 1, 1), 618 + [F_VBUS_USB_SW] = REG_FIELD(VBUS_UCD_SET, 0, 0), 619 + [F_VBUS_DCDFAIL] = REG_FIELD(VBUS_UCD_STATUS, 15, 15), 620 + [F_VBUS_CHGPORT] = REG_FIELD(VBUS_UCD_STATUS, 12, 13), 621 + [F_VBUS_PUPDET] = REG_FIELD(VBUS_UCD_STATUS, 11, 11), 622 + [F_VBUS_VBUS_VLD] = REG_FIELD(VBUS_UCD_STATUS, 7, 7), 623 + [F_VBUS_CHGDET] = REG_FIELD(VBUS_UCD_STATUS, 6, 6), 624 + [F_VBUS_OTGDET] = REG_FIELD(VBUS_UCD_STATUS, 3, 3), 625 + [F_VBUS_VBINOP] = REG_FIELD(VBUS_IDD_STATUS, 6, 6), 626 + [F_VBUS_EXTID] = REG_FIELD(VBUS_IDD_STATUS, 5, 5), 627 + [F_VBUS_IDRDET] = REG_FIELD(VBUS_IDD_STATUS, 4, 4), 628 + [F_VBUS_INDO] = REG_FIELD(VBUS_IDD_STATUS, 0, 3), 629 + [F_VBUS_UCDSWEN] = REG_FIELD(VCC_UCD_FCTRL_SET, 10, 10), 630 + [F_VBUS_RREF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 9, 9), 631 + [F_VBUS_DPPU_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 8, 8), 632 + [F_VBUS_DPREF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 7, 7), 633 + [F_VBUS_DMREF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 6, 6), 634 + [F_VBUS_DPDET_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 5, 5), 635 + [F_VBUS_DMDET_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 4, 4), 636 + [F_VBUS_DPSINK_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 3, 3), 637 + [F_VBUS_DMSINK_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 2, 2), 638 + [F_VBUS_DP_BUFF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 1, 1), 639 + [F_VBUS_DM_BUFF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 0, 0), 640 + 641 + [F_VBUS_EXTCLKENBL] = REG_FIELD(VBUS_UCD_FCTRL_EN, 15, 15), 642 + [F_VBUS_PLSTESTEN] = REG_FIELD(VBUS_UCD_FCTRL_EN, 14, 14), 643 + [F_VBUS_UCDSWEN_TSTENB] = REG_FIELD(VBUS_UCD_FCTRL_EN, 10, 10), 644 + [F_VBUS_RREF_EN_TSTENB] = REG_FIELD(VBUS_UCD_FCTRL_EN, 9, 9), 645 + [F_VBUS_DPPU_EN_TSTENB] = REG_FIELD(VBUS_UCD_FCTRL_EN, 8, 8), 646 + [F_VBUS_DPREF_EN_TSTENB] = REG_FIELD(VBUS_UCD_FCTRL_EN, 7, 7), 647 + [F_VBUS_DMREF_EN_TSTENB] = REG_FIELD(VBUS_UCD_FCTRL_EN, 6, 6), 648 + [F_VBUS_DPDET_EN_TSTENB] = REG_FIELD(VBUS_UCD_FCTRL_EN, 5, 5), 649 + [F_VBUS_DMDET_EN_TSTENB] = REG_FIELD(VBUS_UCD_FCTRL_EN, 4, 4), 650 + [F_VBUS_DPSINK_EN_TSTENB] = REG_FIELD(VBUS_UCD_FCTRL_EN, 3, 3), 651 + [F_VBUS_DMSINK_EN_TSTENB] = REG_FIELD(VBUS_UCD_FCTRL_EN, 2, 2), 652 + [F_VBUS_DP_BUFF_EN_TSTENB] = REG_FIELD(VBUS_UCD_FCTRL_EN, 1, 1), 653 + [F_VBUS_DM_BUFF_EN_TSTENB] = REG_FIELD(VBUS_UCD_FCTRL_EN, 0, 0), 654 + 655 + [F_CHIP_ID] = REG_FIELD(CHIP_ID, 0, 15), 656 + [F_CHIP_REV] = REG_FIELD(CHIP_REV, 0, 15), 657 + [F_ONE_CELL_MODE] = REG_FIELD(IC_SET1, 11, 11), 658 + [F_cell] = REG_FIELD(IC_SET1, 1, 1), 659 + [F_VACP_AUTO_DISCHG] = REG_FIELD(IC_SET1, 9, 9), 660 + [F_VACP_LOAD] = REG_FIELD(IC_SET1, 8, 8), 661 + [F_ACOK_POL] = REG_FIELD(IC_SET1, 1, 1), 662 + [F_ACOK_DISEN] = REG_FIELD(IC_SET1, 0, 0), 663 + [F_DEBUG_SET1] = REG_FIELD(IC_SET2, 4, 8), 664 + [F_DEBUG_SET0] = REG_FIELD(IC_SET2, 0, 0), 665 + [F_MONRST_STATE] = REG_FIELD(SYSTEM_STATUS, 6, 6), 666 + [F_ALMRST_STATE] = REG_FIELD(SYSTEM_STATUS, 5, 5), 667 + [F_CHGRST_STATE] = REG_FIELD(SYSTEM_STATUS, 4, 4), 668 + [F_OTPLD_STATE] = REG_FIELD(SYSTEM_STATUS, 1, 1), 669 + [F_ALLRST_STATE] = REG_FIELD(SYSTEM_STATUS, 0, 0), 670 + [F_PROTECT_SET] = REG_FIELD(PROTECT_SET, 0, 15), 671 + [F_MAP_SET] = REG_FIELD(MAP_SET, 0, 15), 672 + [F_ADCINTERVAL] = REG_FIELD(VM_CTRL_SET, 14, 15), 673 + [F_ADCMOD] = REG_FIELD(VM_CTRL_SET, 12, 13), 674 + [F_ADCTMOD] = REG_FIELD(VM_CTRL_SET, 10, 11), 675 + [F_EXTIADPEN] = REG_FIELD(VM_CTRL_SET, 9, 9), 676 + [F_VSYSENB] = REG_FIELD(VM_CTRL_SET, 8, 8), 677 + [F_VCCENB] = REG_FIELD(VM_CTRL_SET, 7, 7), 678 + [F_VBUSENB] = REG_FIELD(VM_CTRL_SET, 6, 6), 679 + [F_VACPENB] = REG_FIELD(VM_CTRL_SET, 5, 5), 680 + [F_IACPENB] = REG_FIELD(VM_CTRL_SET, 4, 4), 681 + [F_THERMENB] = REG_FIELD(VM_CTRL_SET, 3, 3), 682 + [F_VBATENB] = REG_FIELD(VM_CTRL_SET, 2, 2), 683 + [F_IBATMENB] = REG_FIELD(VM_CTRL_SET, 1, 1), 684 + [F_IBATPENB] = REG_FIELD(VM_CTRL_SET, 0, 0), 685 + [F_TMPTHR1B] = REG_FIELD(THERM_WINDOW_SET1, 8, 15), 686 + [F_TMPTHR1A] = REG_FIELD(THERM_WINDOW_SET1, 0, 7), 687 + [F_TMPTHR2B] = REG_FIELD(THERM_WINDOW_SET2, 8, 15), 688 + [F_TMPTHR2A] = REG_FIELD(THERM_WINDOW_SET2, 0, 7), 689 + [F_TMPTHR3B] = REG_FIELD(THERM_WINDOW_SET3, 8, 15), 690 + [F_TMPTHR3A] = REG_FIELD(THERM_WINDOW_SET3, 0, 7), 691 + [F_TMPTHR4B] = REG_FIELD(THERM_WINDOW_SET4, 8, 15), 692 + [F_TMPTHR4A] = REG_FIELD(THERM_WINDOW_SET4, 0, 7), 693 + [F_TMPTHR5B] = REG_FIELD(THERM_WINDOW_SET5, 8, 15), 694 + [F_TMPTHR5A] = REG_FIELD(THERM_WINDOW_SET5, 0, 7), 695 + [F_IBATP_TH_SET] = REG_FIELD(IBATP_TH_SET, 0, 14), 696 + [F_IBATM_TH_SET] = REG_FIELD(IBATM_TH_SET, 0, 14), 697 + [F_VBAT_TH_SET] = REG_FIELD(VBAT_TH_SET, 0, 14), 698 + [F_THERM_TH_SET] = REG_FIELD(THERM_TH_SET, 0, 7), 699 + [F_IACP_TH_SET] = REG_FIELD(IACP_TH_SET, 0, 14), 700 + [F_VACP_TH_SET] = REG_FIELD(VACP_TH_SET, 0, 14), 701 + [F_VBUS_TH_SET] = REG_FIELD(VBUS_TH_SET, 0, 14), 702 + [F_VCC_TH_SET] = REG_FIELD(VCC_TH_SET, 0, 14), 703 + [F_VSYS_TH_SET] = REG_FIELD(VSYS_TH_SET, 0, 14), 704 + [F_EXTIADP_TH_SET] = REG_FIELD(EXTIADP_TH_SET, 0, 11), 705 + [F_IBATP_VAL] = REG_FIELD(IBATP_VAL, 0, 14), 706 + [F_IBATP_AVE_VAL] = REG_FIELD(IBATP_AVE_VAL, 0, 14), 707 + [F_IBATM_VAL] = REG_FIELD(IBATM_VAL, 0, 14), 708 + [F_IBATM_AVE_VAL] = REG_FIELD(IBATM_AVE_VAL, 0, 14), 709 + [F_VBAT_VAL] = REG_FIELD(VBAT_VAL, 0, 14), 710 + [F_VBAT_AVE_VAL] = REG_FIELD(VBAT_AVE_VAL, 0, 14), 711 + [F_THERM_VAL] = REG_FIELD(THERM_VAL, 0, 7), 712 + [F_VTH_VAL] = REG_FIELD(VTH_VAL, 0, 11), 713 + [F_IACP_VAL] = REG_FIELD(IACP_VAL, 0, 14), 714 + [F_IACP_AVE_VAL] = REG_FIELD(IACP_AVE_VAL, 0, 14), 715 + [F_VACP_VAL] = REG_FIELD(VACP_VAL, 0, 14), 716 + [F_VACP_AVE_VAL] = REG_FIELD(VACP_AVE_VAL, 0, 14), 717 + [F_VBUS_VAL] = REG_FIELD(VBUS_VAL, 0, 14), 718 + [F_VBUS_AVE_VAL] = REG_FIELD(VBUS_AVE_VAL, 0, 14), 719 + [F_VCC_VAL] = REG_FIELD(VCC_VAL, 0, 14), 720 + [F_VCC_AVE_VAL] = REG_FIELD(VCC_AVE_VAL, 0, 14), 721 + [F_VSYS_VAL] = REG_FIELD(VSYS_VAL, 0, 14), 722 + [F_VSYS_AVE_VAL] = REG_FIELD(VSYS_AVE_VAL, 0, 14), 723 + [F_EXTIADP_VAL] = REG_FIELD(EXTIADP_VAL, 0, 11), 724 + [F_EXTIADP_AVE_VAL] = REG_FIELD(EXTIADP_AVE_VAL, 0, 11), 725 + [F_VACPCLPS_TH_SET] = REG_FIELD(VACPCLPS_TH_SET, 7, 14), 726 + [F_INT7_SET] = REG_FIELD(INT7_SET, 0, 15), 727 + [F_INT6_SET] = REG_FIELD(INT6_SET, 0, 13), 728 + [F_INT5_SET] = REG_FIELD(INT5_SET, 0, 13), 729 + [F_INT4_SET] = REG_FIELD(INT4_SET, 0, 9), 730 + [F_INT3_SET] = REG_FIELD(INT3_SET, 0, 15), 731 + [F_INT2_SET] = REG_FIELD(INT2_SET, 0, 15), 732 + [F_INT1_SET] = REG_FIELD(INT1_SET, 0, 15), 733 + [F_INT0_SET] = REG_FIELD(INT0_SET, 0, 7), 734 + [F_VBUS_RBUV_DET] = REG_FIELD(INT1_SET, 15, 15), 735 + [F_VBUS_RBUV_RES] = REG_FIELD(INT1_SET, 14, 14), 736 + [F_VBUS_TH_DET] = REG_FIELD(INT1_SET, 9, 9), 737 + [F_VBUS_TH_RES] = REG_FIELD(INT1_SET, 8, 8), 738 + [F_VBUS_IIN_MOD] = REG_FIELD(INT1_SET, 6, 6), 739 + [F_VBUS_OV_DET] = REG_FIELD(INT1_SET, 5, 5), 740 + [F_VBUS_OV_RES] = REG_FIELD(INT1_SET, 4, 4), 741 + [F_VBUS_CLPS_DET] = REG_FIELD(INT1_SET, 3, 3), 742 + [F_VBUS_CLPS] = REG_FIELD(INT1_SET, 2, 2), 743 + [F_VBUS_DET] = REG_FIELD(INT1_SET, 1, 1), 744 + [F_VBUS_RES] = REG_FIELD(INT1_SET, 0, 0), 745 + [F_VCC_RBUV_DET] = REG_FIELD(INT2_SET, 15, 15), 746 + [F_VCC_RBUV_RES] = REG_FIELD(INT2_SET, 14, 14), 747 + [F_VCC_TH_DET] = REG_FIELD(INT2_SET, 9, 9), 748 + [F_VCC_TH_RES] = REG_FIELD(INT2_SET, 8, 8), 749 + [F_VCC_IIN_MOD] = REG_FIELD(INT2_SET, 6, 6), 750 + [F_VCC_OVP_DET] = REG_FIELD(INT2_SET, 5, 5), 751 + [F_VCC_OVP_RES] = REG_FIELD(INT2_SET, 4, 4), 752 + [F_VCC_CLPS_DET] = REG_FIELD(INT2_SET, 3, 3), 753 + [F_VCC_CLPS_RES] = REG_FIELD(INT2_SET, 2, 2), 754 + [F_VCC_DET] = REG_FIELD(INT2_SET, 1, 1), 755 + [F_VCC_RES] = REG_FIELD(INT2_SET, 0, 0), 756 + [F_TH_DET] = REG_FIELD(INT3_SET, 15, 15), 757 + [F_TH_RMV] = REG_FIELD(INT3_SET, 14, 14), 758 + [F_TMP_OUT_DET] = REG_FIELD(INT3_SET, 11, 11), 759 + [F_TMP_OUT_RES] = REG_FIELD(INT3_SET, 10, 10), 760 + [F_VBAT_TH_DET] = REG_FIELD(INT3_SET, 9, 9), 761 + [F_VBAT_TH_RES] = REG_FIELD(INT3_SET, 8, 8), 762 + [F_IBAT_SHORT_DET] = REG_FIELD(INT3_SET, 7, 7), 763 + [F_IBAT_SHORT_RES] = REG_FIELD(INT3_SET, 6, 6), 764 + [F_VBAT_OV_DET] = REG_FIELD(INT3_SET, 5, 5), 765 + [F_VBAT_OV_RES] = REG_FIELD(INT3_SET, 4, 4), 766 + [F_BAT_ASSIST_DET] = REG_FIELD(INT3_SET, 3, 3), 767 + [F_BAT_ASSIST_RES] = REG_FIELD(INT3_SET, 2, 2), 768 + [F_VSYS_TH_DET] = REG_FIELD(INT4_SET, 9, 9), 769 + [F_VSYS_TH_RES] = REG_FIELD(INT4_SET, 8, 8), 770 + [F_VSYS_OV_DET] = REG_FIELD(INT4_SET, 5, 5), 771 + [F_VSYS_OV_RES] = REG_FIELD(INT4_SET, 4, 4), 772 + [F_VSYS_SHT_DET] = REG_FIELD(INT4_SET, 3, 3), 773 + [F_VSYS_SHT_RES] = REG_FIELD(INT4_SET, 2, 2), 774 + [F_VSYS_UV_DET] = REG_FIELD(INT4_SET, 1, 1), 775 + [F_VSYS_UV_RES] = REG_FIELD(INT4_SET, 0, 0), 776 + [F_OTP_LOAD_DONE] = REG_FIELD(INT5_SET, 13, 13), 777 + [F_PWR_ON] = REG_FIELD(INT5_SET, 12, 12), 778 + [F_EXTIADP_TRNS] = REG_FIELD(INT5_SET, 11, 11), 779 + [F_EXTIADP_TH_DET] = REG_FIELD(INT5_SET, 9, 9), 780 + [F_EXIADP_TH_RES] = REG_FIELD(INT5_SET, 8, 8), 781 + [F_BAT_MNT_DET] = REG_FIELD(INT5_SET, 7, 7), 782 + [F_BAT_MNT_RES] = REG_FIELD(INT5_SET, 6, 6), 783 + [F_TSD_DET] = REG_FIELD(INT5_SET, 5, 5), 784 + [F_TSD_RES] = REG_FIELD(INT5_SET, 4, 4), 785 + [F_CHGWDT_EXP] = REG_FIELD(INT5_SET, 3, 3), 786 + [F_THERMWDT_EXP] = REG_FIELD(INT5_SET, 2, 2), 787 + [F_TMP_TRNS] = REG_FIELD(INT5_SET, 1, 1), 788 + [F_CHG_TRNS] = REG_FIELD(INT5_SET, 0, 0), 789 + [F_VBUS_UCD_PORT_DET] = REG_FIELD(INT6_SET, 13, 13), 790 + [F_VBUS_UCD_UCHG_DET] = REG_FIELD(INT6_SET, 12, 12), 791 + [F_VBUS_UCD_URID_RMV] = REG_FIELD(INT6_SET, 11, 11), 792 + [F_VBUS_UCD_OTG_DET] = REG_FIELD(INT6_SET, 10, 10), 793 + [F_VBUS_UCD_URID_MOD] = REG_FIELD(INT6_SET, 8, 8), 794 + [F_VCC_UCD_PORT_DET] = REG_FIELD(INT6_SET, 5, 5), 795 + [F_VCC_UCD_UCHG_DET] = REG_FIELD(INT6_SET, 4, 4), 796 + [F_VCC_UCD_URID_RMV] = REG_FIELD(INT6_SET, 3, 3), 797 + [F_VCC_UCD_OTG_DET] = REG_FIELD(INT6_SET, 2, 2), 798 + [F_VCC_UCD_URID_MOD] = REG_FIELD(INT6_SET, 0, 0), 799 + [F_PROCHOT_DET] = REG_FIELD(INT7_SET, 15, 15), 800 + [F_PROCHOT_RES] = REG_FIELD(INT7_SET, 14, 14), 801 + [F_VACP_DET] = REG_FIELD(INT7_SET, 11, 11), 802 + [F_VACP_RES] = REG_FIELD(INT7_SET, 10, 10), 803 + [F_VACP_TH_DET] = REG_FIELD(INT7_SET, 9, 9), 804 + [F_VACP_TH_RES] = REG_FIELD(INT7_SET, 8, 8), 805 + [F_IACP_TH_DET] = REG_FIELD(INT7_SET, 7, 7), 806 + [F_IACP_THE_RES] = REG_FIELD(INT7_SET, 6, 6), 807 + [F_THERM_TH_DET] = REG_FIELD(INT7_SET, 5, 5), 808 + [F_THERM_TH_RES] = REG_FIELD(INT7_SET, 4, 4), 809 + [F_IBATM_TH_DET] = REG_FIELD(INT7_SET, 3, 3), 810 + [F_IBATM_TH_RES] = REG_FIELD(INT7_SET, 2, 2), 811 + [F_IBATP_TH_DET] = REG_FIELD(INT7_SET, 1, 1), 812 + [F_IBATP_TH_RES] = REG_FIELD(INT7_SET, 0, 0), 813 + [F_INT7_STATUS] = REG_FIELD(INT7_STATUS, 0, 15), 814 + [F_INT6_STATUS] = REG_FIELD(INT6_STATUS, 0, 13), 815 + [F_INT5_STATUS] = REG_FIELD(INT5_STATUS, 0, 13), 816 + [F_INT4_STATUS] = REG_FIELD(INT4_STATUS, 0, 9), 817 + [F_INT3_STATUS] = REG_FIELD(INT3_STATUS, 0, 15), 818 + [F_INT2_STATUS] = REG_FIELD(INT2_STATUS, 0, 15), 819 + [F_INT1_STATUS] = REG_FIELD(INT1_STATUS, 0, 15), 820 + [F_INT0_STATUS] = REG_FIELD(INT0_STATUS, 0, 7), 821 + [F_ILIM_DECREASE] = REG_FIELD(OTPREG0, 0, 15), 822 + [F_RESERVE_OTPREG1] = REG_FIELD(OTPREG1, 0, 15), 823 + [F_POWER_SAVE_MODE] = REG_FIELD(SMBREG, 0, 15), 824 + [F_DEBUG_MODE_SET] = REG_FIELD(DEBUG_MODE_SET, 0, 15), 825 + [F_DEBUG0x14] = REG_FIELD(DEBUG0x14, 0, 15), 826 + [F_DEBUG0x1A] = REG_FIELD(DEBUG0x1A, 0, 15), 827 + }; 828 + 829 + /* CHGSTM_STATEs */ 830 + #define CHGSTM_SUSPEND 0x00 831 + #define CHGSTM_TRICKLE_CHARGE 0x01 832 + #define CHGSTM_PRE_CHARGE 0x02 833 + #define CHGSTM_FAST_CHARGE 0x03 834 + #define CHGSTM_TOP_OFF 0x04 835 + #define CHGSTM_DONE 0x05 836 + #define CHGSTM_OTG 0x08 837 + #define CHGSTM_OTG_DONE 0x09 838 + #define CHGSTM_TEMPERATURE_ERROR_1 0x10 839 + #define CHGSTM_TEMPERATURE_ERROR_2 0x11 840 + #define CHGSTM_TEMPERATURE_ERROR_3 0x12 841 + #define CHGSTM_TEMPERATURE_ERROR_4 0x13 842 + #define CHGSTM_TEMPERATURE_ERROR_5 0x14 843 + #define CHGSTM_TEMPERATURE_ERROR_6 0x15 844 + #define CHGSTM_TEMPERATURE_ERROR_7 0x18 845 + #define CHGSTM_THERMAL_SHUT_DOWN_1 0x20 846 + #define CHGSTM_THERMAL_SHUT_DOWN_2 0x21 847 + #define CHGSTM_THERMAL_SHUT_DOWN_3 0x22 848 + #define CHGSTM_THERMAL_SHUT_DOWN_4 0x23 849 + #define CHGSTM_THERMAL_SHUT_DOWN_5 0x24 850 + #define CHGSTM_THERMAL_SHUT_DOWN_6 0x25 851 + #define CHGSTM_THERMAL_SHUT_DOWN_7 0x28 852 + #define CHGSTM_BATTERY_ERROR 0x40 853 + 854 + /* VBAT_VSYS_STATUS */ 855 + #define STATUS_VSYS_OV BIT(15) 856 + #define STATUS_VSYS_SSD BIT(14) 857 + #define STATUS_VSYS_SCP BIT(13) 858 + #define STATUS_VSYS_UVN BIT(12) 859 + #define STATUS_IBAT_SHORT BIT(6) 860 + #define STATUS_VBAT_OV BIT(3) 861 + #define STATUS_DEAD_BAT BIT(0) 862 + 863 + /* VBUS_VCC_STATUS */ 864 + #define STATUS_VACP_DET BIT(12) 865 + #define STATUS_VCC_OVP BIT(11) 866 + #define STATUS_ILIM_VCC_MOD BIT(10) 867 + #define STATUS_VCC_CLPS BIT(9) 868 + #define STATUS_VCC_DET BIT(8) 869 + #define STATUS_VBUS_OVP BIT(3) 870 + #define STATUS_ILIM_VBUS_MOD BIT(2) 871 + #define STATUS_VBUS_CLPS BIT(1) 872 + #define STATUS_VBUS_DET BIT(0) 873 + 874 + /* Interrupt set/status definitions */ 875 + 876 + /* INT 0 */ 877 + #define INT0_INT7_STATUS BIT(7) 878 + #define INT0_INT6_STATUS BIT(6) 879 + #define INT0_INT5_STATUS BIT(5) 880 + #define INT0_INT4_STATUS BIT(4) 881 + #define INT0_INT3_STATUS BIT(3) 882 + #define INT0_INT2_STATUS BIT(2) 883 + #define INT0_INT1_STATUS BIT(1) 884 + #define INT0_INT0_STATUS BIT(0) 885 + #define INT0_ALL 0xff 886 + 887 + /* INT 1 */ 888 + #define VBUS_RBUV_DET BIT(15) 889 + #define VBUS_RBUV_RES BIT(14) 890 + #define VBUS_TH_DET BIT(9) 891 + #define VBUS_TH_RES BIT(8) 892 + #define VBUS_IIN_MOD BIT(6) 893 + #define VBUS_OV_DET BIT(5) 894 + #define VBUS_OV_RES BIT(4) 895 + #define VBUS_CLPS_DET BIT(3) 896 + #define VBUS_CLPS BIT(2) 897 + #define VBUS_DET BIT(1) 898 + #define VBUS_RES BIT(0) 899 + #define INT1_ALL (VBUS_RBUV_DET|\ 900 + VBUS_RBUV_RES|\ 901 + VBUS_TH_DET |\ 902 + VBUS_TH_RES |\ 903 + VBUS_IIN_MOD|\ 904 + VBUS_OV_DET |\ 905 + VBUS_OV_RES |\ 906 + VBUS_CLPS_DET |\ 907 + VBUS_CLPS |\ 908 + VBUS_DET |\ 909 + VBUS_RES) 910 + 911 + /* INT 2 */ 912 + #define VCC_RBUV_DET BIT(15) 913 + #define VCC_RBUV_RES BIT(14) 914 + #define VCC_TH_DET BIT(9) 915 + #define VCC_TH_RES BIT(8) 916 + #define VCC_IIN_MOD BIT(6) 917 + #define VCC_OVP_DET BIT(5) 918 + #define VCC_OVP_RES BIT(4) 919 + #define VCC_CLPS_DET BIT(3) 920 + #define VCC_CLPS_RES BIT(2) 921 + #define VCC_DET BIT(1) 922 + #define VCC_RES BIT(0) 923 + #define INT2_ALL (VCC_RBUV_DET |\ 924 + VCC_RBUV_RES |\ 925 + VCC_TH_DET |\ 926 + VCC_TH_RES |\ 927 + VCC_IIN_MOD |\ 928 + VCC_OVP_DET |\ 929 + VCC_OVP_RES |\ 930 + VCC_CLPS_DET |\ 931 + VCC_CLPS_RES |\ 932 + VCC_DET |\ 933 + VCC_RES) 934 + /* INT 3 */ 935 + #define TH_DET BIT(15) 936 + #define TH_RMV BIT(14) 937 + #define TMP_OUT_DET BIT(11) 938 + #define TMP_OUT_RES BIT(10) 939 + #define VBAT_TH_DET BIT(9) 940 + #define VBAT_TH_RES BIT(8) 941 + #define IBAT_SHORT_DET BIT(7) 942 + #define IBAT_SHORT_RES BIT(6) 943 + #define VBAT_OV_DET BIT(5) 944 + #define VBAT_OV_RES BIT(4) 945 + #define BAT_ASSIST_DET BIT(3) 946 + #define BAT_ASSIST_RES BIT(2) 947 + #define INT3_ALL (TH_DET |\ 948 + TH_RMV |\ 949 + TMP_OUT_DET |\ 950 + TMP_OUT_RES |\ 951 + VBAT_TH_DET |\ 952 + VBAT_TH_RES |\ 953 + IBAT_SHORT_DET |\ 954 + IBAT_SHORT_RES |\ 955 + VBAT_OV_DET |\ 956 + VBAT_OV_RES |\ 957 + BAT_ASSIST_DET |\ 958 + BAT_ASSIST_RES) 959 + 960 + /* INT 4 */ 961 + #define VSYS_TH_DET BIT(9) 962 + #define VSYS_TH_RES BIT(8) 963 + #define VSYS_OV_DET BIT(5) 964 + #define VSYS_OV_RES BIT(4) 965 + #define VSYS_SHT_DET BIT(3) 966 + #define VSYS_SHT_RES BIT(2) 967 + #define VSYS_UV_DET BIT(1) 968 + #define VSYS_UV_RES BIT(0) 969 + #define INT4_ALL (VSYS_TH_DET |\ 970 + VSYS_TH_RES |\ 971 + VSYS_OV_DET |\ 972 + VSYS_OV_RES |\ 973 + VSYS_SHT_DET |\ 974 + VSYS_SHT_RES |\ 975 + VSYS_UV_DET |\ 976 + VSYS_UV_RES) 977 + 978 + /* INT 5*/ 979 + #define OTP_LOAD_DONE BIT(13) 980 + #define PWR_ON BIT(12) 981 + #define EXTIADP_TRNS BIT(11) 982 + #define EXTIADP_TH_DET BIT(9) 983 + #define EXIADP_TH_RES BIT(8) 984 + #define BAT_MNT_DET BIT(7) 985 + #define BAT_MNT_RES BIT(6) 986 + #define TSD_DET BIT(5) 987 + #define TSD_RES BIT(4) 988 + #define CHGWDT_EXP BIT(3) 989 + #define THERMWDT_EXP BIT(2) 990 + #define TMP_TRNS BIT(1) 991 + #define CHG_TRNS BIT(0) 992 + #define INT5_ALL (OTP_LOAD_DONE |\ 993 + PWR_ON |\ 994 + EXTIADP_TRNS |\ 995 + EXTIADP_TH_DET |\ 996 + EXIADP_TH_RES |\ 997 + BAT_MNT_DET |\ 998 + BAT_MNT_RES |\ 999 + TSD_DET |\ 1000 + TSD_RES |\ 1001 + CHGWDT_EXP |\ 1002 + THERMWDT_EXP |\ 1003 + TMP_TRNS |\ 1004 + CHG_TRNS) 1005 + 1006 + /* INT 6*/ 1007 + #define VBUS_UCD_PORT_DET BIT(13) 1008 + #define VBUS_UCD_UCHG_DET BIT(12) 1009 + #define VBUS_UCD_URID_RMV BIT(11) 1010 + #define VBUS_UCD_OTG_DET BIT(10) 1011 + #define VBUS_UCD_URID_MOD BIT(8) 1012 + #define VCC_UCD_PORT_DET BIT(5) 1013 + #define VCC_UCD_UCHG_DET BIT(4) 1014 + #define VCC_UCD_URID_RMV BIT(3) 1015 + #define VCC_UCD_OTG_DET BIT(2) 1016 + #define VCC_UCD_URID_MOD BIT(0) 1017 + #define INT6_ALL (VBUS_UCD_PORT_DET |\ 1018 + VBUS_UCD_UCHG_DET |\ 1019 + VBUS_UCD_URID_RMV |\ 1020 + VBUS_UCD_OTG_DET |\ 1021 + VBUS_UCD_URID_MOD |\ 1022 + VCC_UCD_PORT_DET |\ 1023 + VCC_UCD_UCHG_DET |\ 1024 + VCC_UCD_URID_RMV |\ 1025 + VCC_UCD_OTG_DET |\ 1026 + VCC_UCD_URID_MOD) 1027 + 1028 + /* INT 7 */ 1029 + #define PROCHOT_DET BIT(15) 1030 + #define PROCHOT_RES BIT(14) 1031 + #define VACP_DET BIT(11) 1032 + #define VACP_RES BIT(10) 1033 + #define VACP_TH_DET BIT(9) 1034 + #define VACP_TH_RES BIT(8) 1035 + #define IACP_TH_DET BIT(7) 1036 + #define IACP_THE_RES BIT(6) 1037 + #define THERM_TH_DET BIT(5) 1038 + #define THERM_TH_RES BIT(4) 1039 + #define IBATM_TH_DET BIT(3) 1040 + #define IBATM_TH_RES BIT(2) 1041 + #define IBATP_TH_DET BIT(1) 1042 + #define IBATP_TH_RES BIT(0) 1043 + #define INT7_ALL (PROCHOT_DET |\ 1044 + PROCHOT_RES |\ 1045 + VACP_DET |\ 1046 + VACP_RES |\ 1047 + VACP_TH_DET |\ 1048 + VACP_TH_RES |\ 1049 + IACP_TH_DET |\ 1050 + IACP_THE_RES |\ 1051 + THERM_TH_DET |\ 1052 + THERM_TH_RES |\ 1053 + IBATM_TH_DET |\ 1054 + IBATM_TH_RES |\ 1055 + IBATP_TH_DET |\ 1056 + IBATP_TH_RES) 1057 + 1058 + /* SYSTEM_CTRL_SET*/ 1059 + #define MONRST BIT(6) 1060 + #define ALMRST BIT(5) 1061 + #define CHGRST BIT(4) 1062 + #define OTPLD BIT(1) 1063 + #define ALLRST BIT(0) 1064 + 1065 + /* F_BATTEMP */ 1066 + #define ROOM 0x0 1067 + #define HOT1 0x1 1068 + #define HOT2 0x2 1069 + #define HOT3 0x3 1070 + #define COLD1 0x4 1071 + #define COLD2 0x5 1072 + #define TEMP_DIS 0x6 1073 + #define BATT_OPEN 0x7 1074 + 1075 + #endif
+1 -1
drivers/power/supply/bq24190_charger.c
··· 673 673 * { .type = "bq24190", .addr = 0x6b, .properties = pe, .irq = irq }; 674 674 * struct i2c_adapter ad = { ... }; 675 675 * i2c_add_adapter(&ad); 676 - * i2c_new_device(&ad, &bi); 676 + * i2c_new_client_device(&ad, &bi); 677 677 */ 678 678 if (device_property_read_bool(bdi->dev, "disable-reset")) 679 679 return 0;
+108 -92
drivers/power/supply/bq25890_charger.c
··· 32 32 BQ25896, 33 33 }; 34 34 35 + static const char *const bq25890_chip_name[] = { 36 + "BQ25890", 37 + "BQ25892", 38 + "BQ25895", 39 + "BQ25896", 40 + }; 41 + 35 42 enum bq25890_fields { 36 43 F_EN_HIZ, F_EN_ILIM, F_IILIM, /* Reg00 */ 37 44 F_BHOT, F_BCOLD, F_VINDPM_OFS, /* Reg01 */ ··· 126 119 127 120 static const struct regmap_range bq25890_volatile_reg_ranges[] = { 128 121 regmap_reg_range(0x00, 0x00), 122 + regmap_reg_range(0x02, 0x02), 129 123 regmap_reg_range(0x09, 0x09), 130 124 regmap_reg_range(0x0b, 0x14), 131 125 }; ··· 254 246 /* range tables */ 255 247 TBL_ICHG, 256 248 TBL_ITERM, 249 + TBL_IILIM, 257 250 TBL_VREG, 258 251 TBL_BOOSTV, 259 252 TBL_SYSVMIN, ··· 295 286 /* TODO: BQ25896 has max ICHG 3008 mA */ 296 287 [TBL_ICHG] = { .rt = {0, 5056000, 64000} }, /* uA */ 297 288 [TBL_ITERM] = { .rt = {64000, 1024000, 64000} }, /* uA */ 289 + [TBL_IILIM] = { .rt = {50000, 3200000, 50000} }, /* uA */ 298 290 [TBL_VREG] = { .rt = {3840000, 4608000, 16000} }, /* uV */ 299 291 [TBL_BOOSTV] = { .rt = {4550000, 5510000, 64000} }, /* uV */ 300 292 [TBL_SYSVMIN] = { .rt = {3000000, 3700000, 100000} }, /* uV */ ··· 377 367 CHRG_FAULT_TIMER_EXPIRED, 378 368 }; 379 369 370 + static bool bq25890_is_adc_property(enum power_supply_property psp) 371 + { 372 + switch (psp) { 373 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 374 + case POWER_SUPPLY_PROP_CURRENT_NOW: 375 + return true; 376 + 377 + default: 378 + return false; 379 + } 380 + } 381 + 382 + static irqreturn_t __bq25890_handle_irq(struct bq25890_device *bq); 383 + 380 384 static int bq25890_power_supply_get_property(struct power_supply *psy, 381 385 enum power_supply_property psp, 382 386 union power_supply_propval *val) 383 387 { 384 - int ret; 385 388 struct bq25890_device *bq = power_supply_get_drvdata(psy); 386 389 struct bq25890_state state; 390 + bool do_adc_conv; 391 + int ret; 387 392 388 393 mutex_lock(&bq->lock); 394 + /* update state in case we lost an interrupt */ 395 + __bq25890_handle_irq(bq); 389 396 state = bq->state; 397 + do_adc_conv = !state.online && bq25890_is_adc_property(psp); 398 + if (do_adc_conv) 399 + bq25890_field_write(bq, F_CONV_START, 1); 390 400 mutex_unlock(&bq->lock); 401 + 402 + if (do_adc_conv) 403 + regmap_field_read_poll_timeout(bq->rmap_fields[F_CONV_START], 404 + ret, !ret, 25000, 1000000); 391 405 392 406 switch (psp) { 393 407 case POWER_SUPPLY_PROP_STATUS: ··· 429 395 430 396 break; 431 397 398 + case POWER_SUPPLY_PROP_CHARGE_TYPE: 399 + if (!state.online || state.chrg_status == STATUS_NOT_CHARGING || 400 + state.chrg_status == STATUS_TERMINATION_DONE) 401 + val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; 402 + else if (state.chrg_status == STATUS_PRE_CHARGING) 403 + val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD; 404 + else if (state.chrg_status == STATUS_FAST_CHARGING) 405 + val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; 406 + else /* unreachable */ 407 + val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; 408 + break; 409 + 432 410 case POWER_SUPPLY_PROP_MANUFACTURER: 433 411 val->strval = BQ25890_MANUFACTURER; 434 412 break; 435 413 436 414 case POWER_SUPPLY_PROP_MODEL_NAME: 437 - if (bq->chip_version == BQ25890) 438 - val->strval = "BQ25890"; 439 - else if (bq->chip_version == BQ25892) 440 - val->strval = "BQ25892"; 441 - else if (bq->chip_version == BQ25895) 442 - val->strval = "BQ25895"; 443 - else if (bq->chip_version == BQ25896) 444 - val->strval = "BQ25896"; 445 - else 446 - val->strval = "UNKNOWN"; 447 - 415 + val->strval = bq25890_chip_name[bq->chip_version]; 448 416 break; 449 417 450 418 case POWER_SUPPLY_PROP_ONLINE: ··· 464 428 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 465 429 else 466 430 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 467 - break; 468 - 469 - case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 470 - ret = bq25890_field_read(bq, F_ICHGR); /* read measured value */ 471 - if (ret < 0) 472 - return ret; 473 - 474 - /* converted_val = ADC_val * 50mA (table 10.3.19) */ 475 - val->intval = ret * 50000; 476 431 break; 477 432 478 433 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: ··· 488 461 val->intval = bq25890_find_val(bq->init_data.vreg, TBL_VREG); 489 462 break; 490 463 464 + case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: 465 + val->intval = bq25890_find_val(bq->init_data.iprechg, TBL_ITERM); 466 + break; 467 + 491 468 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 492 469 val->intval = bq25890_find_val(bq->init_data.iterm, TBL_ITERM); 470 + break; 471 + 472 + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 473 + ret = bq25890_field_read(bq, F_IILIM); 474 + if (ret < 0) 475 + return ret; 476 + 477 + val->intval = bq25890_find_val(ret, TBL_IILIM); 493 478 break; 494 479 495 480 case POWER_SUPPLY_PROP_VOLTAGE_NOW: ··· 511 472 512 473 /* converted_val = 2.304V + ADC_val * 20mV (table 10.3.15) */ 513 474 val->intval = 2304000 + ret * 20000; 475 + break; 476 + 477 + case POWER_SUPPLY_PROP_CURRENT_NOW: 478 + ret = bq25890_field_read(bq, F_ICHGR); /* read measured value */ 479 + if (ret < 0) 480 + return ret; 481 + 482 + /* converted_val = ADC_val * 50mA (table 10.3.19) */ 483 + val->intval = ret * -50000; 514 484 break; 515 485 516 486 default: ··· 561 513 return 0; 562 514 } 563 515 564 - static bool bq25890_state_changed(struct bq25890_device *bq, 565 - struct bq25890_state *new_state) 516 + static irqreturn_t __bq25890_handle_irq(struct bq25890_device *bq) 566 517 { 567 - struct bq25890_state old_state; 568 - 569 - mutex_lock(&bq->lock); 570 - old_state = bq->state; 571 - mutex_unlock(&bq->lock); 572 - 573 - return (old_state.chrg_status != new_state->chrg_status || 574 - old_state.chrg_fault != new_state->chrg_fault || 575 - old_state.online != new_state->online || 576 - old_state.bat_fault != new_state->bat_fault || 577 - old_state.boost_fault != new_state->boost_fault || 578 - old_state.vsys_status != new_state->vsys_status); 579 - } 580 - 581 - static void bq25890_handle_state_change(struct bq25890_device *bq, 582 - struct bq25890_state *new_state) 583 - { 518 + struct bq25890_state new_state; 584 519 int ret; 585 - struct bq25890_state old_state; 586 520 587 - mutex_lock(&bq->lock); 588 - old_state = bq->state; 589 - mutex_unlock(&bq->lock); 521 + ret = bq25890_get_chip_state(bq, &new_state); 522 + if (ret < 0) 523 + return IRQ_NONE; 590 524 591 - if (!new_state->online) { /* power removed */ 525 + if (!memcmp(&bq->state, &new_state, sizeof(new_state))) 526 + return IRQ_NONE; 527 + 528 + if (!new_state.online && bq->state.online) { /* power removed */ 592 529 /* disable ADC */ 593 530 ret = bq25890_field_write(bq, F_CONV_START, 0); 594 531 if (ret < 0) 595 532 goto error; 596 - } else if (!old_state.online) { /* power inserted */ 533 + } else if (new_state.online && !bq->state.online) { /* power inserted */ 597 534 /* enable ADC, to have control of charge current/voltage */ 598 535 ret = bq25890_field_write(bq, F_CONV_START, 1); 599 536 if (ret < 0) 600 537 goto error; 601 538 } 602 539 603 - return; 540 + bq->state = new_state; 541 + power_supply_changed(bq->charger); 604 542 543 + return IRQ_HANDLED; 605 544 error: 606 - dev_err(bq->dev, "Error communicating with the chip.\n"); 545 + dev_err(bq->dev, "Error communicating with the chip: %pe\n", 546 + ERR_PTR(ret)); 547 + return IRQ_HANDLED; 607 548 } 608 549 609 550 static irqreturn_t bq25890_irq_handler_thread(int irq, void *private) 610 551 { 611 552 struct bq25890_device *bq = private; 612 - int ret; 613 - struct bq25890_state state; 614 - 615 - ret = bq25890_get_chip_state(bq, &state); 616 - if (ret < 0) 617 - goto handled; 618 - 619 - if (!bq25890_state_changed(bq, &state)) 620 - goto handled; 621 - 622 - bq25890_handle_state_change(bq, &state); 553 + irqreturn_t ret; 623 554 624 555 mutex_lock(&bq->lock); 625 - bq->state = state; 556 + ret = __bq25890_handle_irq(bq); 626 557 mutex_unlock(&bq->lock); 627 558 628 - power_supply_changed(bq->charger); 629 - 630 - handled: 631 - return IRQ_HANDLED; 559 + return ret; 632 560 } 633 561 634 562 static int bq25890_chip_reset(struct bq25890_device *bq) ··· 634 610 { 635 611 int ret; 636 612 int i; 637 - struct bq25890_state state; 638 613 639 614 const struct { 640 615 enum bq25890_fields id; ··· 674 651 } 675 652 } 676 653 677 - /* Configure ADC for continuous conversions. This does not enable it. */ 678 - ret = bq25890_field_write(bq, F_CONV_RATE, 1); 654 + /* Configure ADC for continuous conversions when charging */ 655 + ret = bq25890_field_write(bq, F_CONV_RATE, !!bq->state.online); 679 656 if (ret < 0) { 680 657 dev_dbg(bq->dev, "Config ADC failed %d\n", ret); 681 658 return ret; 682 659 } 683 660 684 - ret = bq25890_get_chip_state(bq, &state); 661 + ret = bq25890_get_chip_state(bq, &bq->state); 685 662 if (ret < 0) { 686 663 dev_dbg(bq->dev, "Get state failed %d\n", ret); 687 664 return ret; 688 665 } 689 666 690 - mutex_lock(&bq->lock); 691 - bq->state = state; 692 - mutex_unlock(&bq->lock); 693 - 694 667 return 0; 695 668 } 696 669 697 - static enum power_supply_property bq25890_power_supply_props[] = { 670 + static const enum power_supply_property bq25890_power_supply_props[] = { 698 671 POWER_SUPPLY_PROP_MANUFACTURER, 699 672 POWER_SUPPLY_PROP_MODEL_NAME, 700 673 POWER_SUPPLY_PROP_STATUS, 674 + POWER_SUPPLY_PROP_CHARGE_TYPE, 701 675 POWER_SUPPLY_PROP_ONLINE, 702 676 POWER_SUPPLY_PROP_HEALTH, 703 - POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 704 677 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 705 678 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, 706 679 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 680 + POWER_SUPPLY_PROP_PRECHARGE_CURRENT, 707 681 POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, 682 + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 708 683 POWER_SUPPLY_PROP_VOLTAGE_NOW, 684 + POWER_SUPPLY_PROP_CURRENT_NOW, 709 685 }; 710 686 711 687 static char *bq25890_charger_supplied_to[] = { ··· 903 881 static int bq25890_probe(struct i2c_client *client, 904 882 const struct i2c_device_id *id) 905 883 { 906 - struct i2c_adapter *adapter = client->adapter; 907 884 struct device *dev = &client->dev; 908 885 struct bq25890_device *bq; 909 886 int ret; 910 887 int i; 911 - 912 - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 913 - dev_err(dev, "No support for SMBUS_BYTE_DATA\n"); 914 - return -ENODEV; 915 - } 916 888 917 889 bq = devm_kzalloc(dev, sizeof(*bq), GFP_KERNEL); 918 890 if (!bq) ··· 1020 1004 * If charger is removed, while in suspend, make sure ADC is diabled 1021 1005 * since it consumes slightly more power. 1022 1006 */ 1023 - return bq25890_field_write(bq, F_CONV_START, 0); 1007 + return bq25890_field_write(bq, F_CONV_RATE, 0); 1024 1008 } 1025 1009 1026 1010 static int bq25890_resume(struct device *dev) 1027 1011 { 1028 1012 int ret; 1029 - struct bq25890_state state; 1030 1013 struct bq25890_device *bq = dev_get_drvdata(dev); 1031 1014 1032 - ret = bq25890_get_chip_state(bq, &state); 1033 - if (ret < 0) 1034 - return ret; 1035 - 1036 1015 mutex_lock(&bq->lock); 1037 - bq->state = state; 1038 - mutex_unlock(&bq->lock); 1016 + 1017 + ret = bq25890_get_chip_state(bq, &bq->state); 1018 + if (ret < 0) 1019 + goto unlock; 1039 1020 1040 1021 /* Re-enable ADC only if charger is plugged in. */ 1041 - if (state.online) { 1042 - ret = bq25890_field_write(bq, F_CONV_START, 1); 1022 + if (bq->state.online) { 1023 + ret = bq25890_field_write(bq, F_CONV_RATE, 1); 1043 1024 if (ret < 0) 1044 - return ret; 1025 + goto unlock; 1045 1026 } 1046 1027 1047 1028 /* signal userspace, maybe state changed while suspended */ 1048 1029 power_supply_changed(bq->charger); 1049 1030 1050 - return 0; 1031 + unlock: 1032 + mutex_unlock(&bq->lock); 1033 + 1034 + return ret; 1051 1035 } 1052 1036 #endif 1053 1037
+22 -18
drivers/power/supply/charger-manager.c
··· 1422 1422 } 1423 1423 1424 1424 static int cm_init_thermal_data(struct charger_manager *cm, 1425 - struct power_supply *fuel_gauge) 1425 + struct power_supply *fuel_gauge, 1426 + enum power_supply_property *properties, 1427 + size_t *num_properties) 1426 1428 { 1427 1429 struct charger_desc *desc = cm->desc; 1428 1430 union power_supply_propval val; ··· 1435 1433 POWER_SUPPLY_PROP_TEMP, &val); 1436 1434 1437 1435 if (!ret) { 1438 - cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] = 1439 - POWER_SUPPLY_PROP_TEMP; 1440 - cm->charger_psy_desc.num_properties++; 1436 + properties[*num_properties] = POWER_SUPPLY_PROP_TEMP; 1437 + (*num_properties)++; 1441 1438 cm->desc->measure_battery_temp = true; 1442 1439 } 1443 1440 #ifdef CONFIG_THERMAL ··· 1447 1446 return PTR_ERR(cm->tzd_batt); 1448 1447 1449 1448 /* Use external thermometer */ 1450 - cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] = 1451 - POWER_SUPPLY_PROP_TEMP_AMBIENT; 1452 - cm->charger_psy_desc.num_properties++; 1449 + properties[*num_properties] = POWER_SUPPLY_PROP_TEMP_AMBIENT; 1450 + (*num_properties)++; 1453 1451 cm->desc->measure_battery_temp = true; 1454 1452 ret = 0; 1455 1453 } ··· 1621 1621 int j = 0; 1622 1622 union power_supply_propval val; 1623 1623 struct power_supply *fuel_gauge; 1624 + enum power_supply_property *properties; 1625 + size_t num_properties; 1624 1626 struct power_supply_config psy_cfg = {}; 1625 1627 1626 1628 if (IS_ERR(desc)) { ··· 1719 1717 cm->charger_psy_desc.name = cm->psy_name_buf; 1720 1718 1721 1719 /* Allocate for psy properties because they may vary */ 1722 - cm->charger_psy_desc.properties = 1723 - devm_kcalloc(&pdev->dev, 1720 + properties = devm_kcalloc(&pdev->dev, 1724 1721 ARRAY_SIZE(default_charger_props) + 1725 1722 NUM_CHARGER_PSY_OPTIONAL, 1726 - sizeof(enum power_supply_property), GFP_KERNEL); 1727 - if (!cm->charger_psy_desc.properties) 1723 + sizeof(*properties), GFP_KERNEL); 1724 + if (!properties) 1728 1725 return -ENOMEM; 1729 1726 1730 - memcpy(cm->charger_psy_desc.properties, default_charger_props, 1727 + memcpy(properties, default_charger_props, 1731 1728 sizeof(enum power_supply_property) * 1732 1729 ARRAY_SIZE(default_charger_props)); 1733 - cm->charger_psy_desc.num_properties = psy_default.num_properties; 1730 + num_properties = ARRAY_SIZE(default_charger_props); 1734 1731 1735 1732 /* Find which optional psy-properties are available */ 1736 1733 fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge); ··· 1740 1739 } 1741 1740 if (!power_supply_get_property(fuel_gauge, 1742 1741 POWER_SUPPLY_PROP_CHARGE_NOW, &val)) { 1743 - cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] = 1742 + properties[num_properties] = 1744 1743 POWER_SUPPLY_PROP_CHARGE_NOW; 1745 - cm->charger_psy_desc.num_properties++; 1744 + num_properties++; 1746 1745 } 1747 1746 if (!power_supply_get_property(fuel_gauge, 1748 1747 POWER_SUPPLY_PROP_CURRENT_NOW, 1749 1748 &val)) { 1750 - cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] = 1749 + properties[num_properties] = 1751 1750 POWER_SUPPLY_PROP_CURRENT_NOW; 1752 - cm->charger_psy_desc.num_properties++; 1751 + num_properties++; 1753 1752 } 1754 1753 1755 - ret = cm_init_thermal_data(cm, fuel_gauge); 1754 + ret = cm_init_thermal_data(cm, fuel_gauge, properties, &num_properties); 1756 1755 if (ret) { 1757 1756 dev_err(&pdev->dev, "Failed to initialize thermal data\n"); 1758 1757 cm->desc->measure_battery_temp = false; 1759 1758 } 1760 1759 power_supply_put(fuel_gauge); 1760 + 1761 + cm->charger_psy_desc.properties = properties; 1762 + cm->charger_psy_desc.num_properties = num_properties; 1761 1763 1762 1764 INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk); 1763 1765
+750
drivers/power/supply/cw2015_battery.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Fuel gauge driver for CellWise 2013 / 2015 4 + * 5 + * Copyright (C) 2012, RockChip 6 + * Copyright (C) 2020, Tobias Schramm 7 + * 8 + * Authors: xuhuicong <xhc@rock-chips.com> 9 + * Authors: Tobias Schramm <t.schramm@manjaro.org> 10 + */ 11 + 12 + #include <linux/bits.h> 13 + #include <linux/delay.h> 14 + #include <linux/i2c.h> 15 + #include <linux/gfp.h> 16 + #include <linux/gpio/consumer.h> 17 + #include <linux/kernel.h> 18 + #include <linux/module.h> 19 + #include <linux/power_supply.h> 20 + #include <linux/property.h> 21 + #include <linux/regmap.h> 22 + #include <linux/time.h> 23 + #include <linux/workqueue.h> 24 + 25 + #define CW2015_SIZE_BATINFO 64 26 + 27 + #define CW2015_RESET_TRIES 5 28 + 29 + #define CW2015_REG_VERSION 0x00 30 + #define CW2015_REG_VCELL 0x02 31 + #define CW2015_REG_SOC 0x04 32 + #define CW2015_REG_RRT_ALERT 0x06 33 + #define CW2015_REG_CONFIG 0x08 34 + #define CW2015_REG_MODE 0x0A 35 + #define CW2015_REG_BATINFO 0x10 36 + 37 + #define CW2015_MODE_SLEEP_MASK GENMASK(7, 6) 38 + #define CW2015_MODE_SLEEP (0x03 << 6) 39 + #define CW2015_MODE_NORMAL (0x00 << 6) 40 + #define CW2015_MODE_QUICK_START (0x03 << 4) 41 + #define CW2015_MODE_RESTART (0x0f << 0) 42 + 43 + #define CW2015_CONFIG_UPDATE_FLG (0x01 << 1) 44 + #define CW2015_ATHD(x) ((x) << 3) 45 + #define CW2015_MASK_ATHD GENMASK(7, 3) 46 + #define CW2015_MASK_SOC GENMASK(12, 0) 47 + 48 + /* reset gauge of no valid state of charge could be polled for 40s */ 49 + #define CW2015_BAT_SOC_ERROR_MS (40 * MSEC_PER_SEC) 50 + /* reset gauge if state of charge stuck for half an hour during charging */ 51 + #define CW2015_BAT_CHARGING_STUCK_MS (1800 * MSEC_PER_SEC) 52 + 53 + /* poll interval from CellWise GPL Android driver example */ 54 + #define CW2015_DEFAULT_POLL_INTERVAL_MS 8000 55 + 56 + #define CW2015_AVERAGING_SAMPLES 3 57 + 58 + struct cw_battery { 59 + struct device *dev; 60 + struct workqueue_struct *battery_workqueue; 61 + struct delayed_work battery_delay_work; 62 + struct regmap *regmap; 63 + struct power_supply *rk_bat; 64 + struct power_supply_battery_info battery; 65 + u8 *bat_profile; 66 + 67 + bool charger_attached; 68 + bool battery_changed; 69 + 70 + int soc; 71 + int voltage_mv; 72 + int status; 73 + int time_to_empty; 74 + int charge_count; 75 + 76 + u32 poll_interval_ms; 77 + u8 alert_level; 78 + 79 + unsigned int read_errors; 80 + unsigned int charge_stuck_cnt; 81 + }; 82 + 83 + static int cw_read_word(struct cw_battery *cw_bat, u8 reg, u16 *val) 84 + { 85 + __be16 value; 86 + int ret; 87 + 88 + ret = regmap_bulk_read(cw_bat->regmap, reg, &value, sizeof(value)); 89 + if (ret) 90 + return ret; 91 + 92 + *val = be16_to_cpu(value); 93 + return 0; 94 + } 95 + 96 + static int cw_update_profile(struct cw_battery *cw_bat) 97 + { 98 + int ret; 99 + unsigned int reg_val; 100 + u8 reset_val; 101 + 102 + /* make sure gauge is not in sleep mode */ 103 + ret = regmap_read(cw_bat->regmap, CW2015_REG_MODE, &reg_val); 104 + if (ret) 105 + return ret; 106 + 107 + reset_val = reg_val; 108 + if ((reg_val & CW2015_MODE_SLEEP_MASK) == CW2015_MODE_SLEEP) { 109 + dev_err(cw_bat->dev, 110 + "Gauge is in sleep mode, can't update battery info\n"); 111 + return -EINVAL; 112 + } 113 + 114 + /* write new battery info */ 115 + ret = regmap_raw_write(cw_bat->regmap, CW2015_REG_BATINFO, 116 + cw_bat->bat_profile, 117 + CW2015_SIZE_BATINFO); 118 + if (ret) 119 + return ret; 120 + 121 + /* set config update flag */ 122 + reg_val |= CW2015_CONFIG_UPDATE_FLG; 123 + reg_val &= ~CW2015_MASK_ATHD; 124 + reg_val |= CW2015_ATHD(cw_bat->alert_level); 125 + ret = regmap_write(cw_bat->regmap, CW2015_REG_CONFIG, reg_val); 126 + if (ret) 127 + return ret; 128 + 129 + /* reset gauge to apply new battery profile */ 130 + reset_val &= ~CW2015_MODE_RESTART; 131 + reg_val = reset_val | CW2015_MODE_RESTART; 132 + ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reg_val); 133 + if (ret) 134 + return ret; 135 + 136 + /* wait for gauge to reset */ 137 + msleep(20); 138 + 139 + /* clear reset flag */ 140 + ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reset_val); 141 + if (ret) 142 + return ret; 143 + 144 + /* wait for gauge to become ready */ 145 + ret = regmap_read_poll_timeout(cw_bat->regmap, CW2015_REG_SOC, 146 + reg_val, reg_val <= 100, 147 + 10 * USEC_PER_MSEC, 10 * USEC_PER_SEC); 148 + if (ret) 149 + dev_err(cw_bat->dev, 150 + "Gauge did not become ready after profile upload\n"); 151 + else 152 + dev_dbg(cw_bat->dev, "Battery profile updated\n"); 153 + 154 + return ret; 155 + } 156 + 157 + static int cw_init(struct cw_battery *cw_bat) 158 + { 159 + int ret; 160 + unsigned int reg_val = CW2015_MODE_SLEEP; 161 + 162 + if ((reg_val & CW2015_MODE_SLEEP_MASK) == CW2015_MODE_SLEEP) { 163 + reg_val = CW2015_MODE_NORMAL; 164 + ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reg_val); 165 + if (ret) 166 + return ret; 167 + } 168 + 169 + ret = regmap_read(cw_bat->regmap, CW2015_REG_CONFIG, &reg_val); 170 + if (ret) 171 + return ret; 172 + 173 + if ((reg_val & CW2015_MASK_ATHD) != CW2015_ATHD(cw_bat->alert_level)) { 174 + dev_dbg(cw_bat->dev, "Setting new alert level\n"); 175 + reg_val &= ~CW2015_MASK_ATHD; 176 + reg_val |= ~CW2015_ATHD(cw_bat->alert_level); 177 + ret = regmap_write(cw_bat->regmap, CW2015_REG_CONFIG, reg_val); 178 + if (ret) 179 + return ret; 180 + } 181 + 182 + ret = regmap_read(cw_bat->regmap, CW2015_REG_CONFIG, &reg_val); 183 + if (ret) 184 + return ret; 185 + 186 + if (!(reg_val & CW2015_CONFIG_UPDATE_FLG)) { 187 + dev_dbg(cw_bat->dev, 188 + "Battery profile not present, uploading battery profile\n"); 189 + if (cw_bat->bat_profile) { 190 + ret = cw_update_profile(cw_bat); 191 + if (ret) { 192 + dev_err(cw_bat->dev, 193 + "Failed to upload battery profile\n"); 194 + return ret; 195 + } 196 + } else { 197 + dev_warn(cw_bat->dev, 198 + "No profile specified, continuing without profile\n"); 199 + } 200 + } else if (cw_bat->bat_profile) { 201 + u8 bat_info[CW2015_SIZE_BATINFO]; 202 + 203 + ret = regmap_raw_read(cw_bat->regmap, CW2015_REG_BATINFO, 204 + bat_info, CW2015_SIZE_BATINFO); 205 + if (ret) { 206 + dev_err(cw_bat->dev, 207 + "Failed to read stored battery profile\n"); 208 + return ret; 209 + } 210 + 211 + if (memcmp(bat_info, cw_bat->bat_profile, CW2015_SIZE_BATINFO)) { 212 + dev_warn(cw_bat->dev, "Replacing stored battery profile\n"); 213 + ret = cw_update_profile(cw_bat); 214 + if (ret) 215 + return ret; 216 + } 217 + } else { 218 + dev_warn(cw_bat->dev, 219 + "Can't check current battery profile, no profile provided\n"); 220 + } 221 + 222 + dev_dbg(cw_bat->dev, "Battery profile configured\n"); 223 + return 0; 224 + } 225 + 226 + static int cw_power_on_reset(struct cw_battery *cw_bat) 227 + { 228 + int ret; 229 + unsigned char reset_val; 230 + 231 + reset_val = CW2015_MODE_SLEEP; 232 + ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reset_val); 233 + if (ret) 234 + return ret; 235 + 236 + /* wait for gauge to enter sleep */ 237 + msleep(20); 238 + 239 + reset_val = CW2015_MODE_NORMAL; 240 + ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reset_val); 241 + if (ret) 242 + return ret; 243 + 244 + ret = cw_init(cw_bat); 245 + if (ret) 246 + return ret; 247 + return 0; 248 + } 249 + 250 + #define HYSTERESIS(current, previous, up, down) \ 251 + (((current) < (previous) + (up)) && ((current) > (previous) - (down))) 252 + 253 + static int cw_get_soc(struct cw_battery *cw_bat) 254 + { 255 + unsigned int soc; 256 + int ret; 257 + 258 + ret = regmap_read(cw_bat->regmap, CW2015_REG_SOC, &soc); 259 + if (ret) 260 + return ret; 261 + 262 + if (soc > 100) { 263 + int max_error_cycles = 264 + CW2015_BAT_SOC_ERROR_MS / cw_bat->poll_interval_ms; 265 + 266 + dev_err(cw_bat->dev, "Invalid SoC %d%%\n", soc); 267 + cw_bat->read_errors++; 268 + if (cw_bat->read_errors > max_error_cycles) { 269 + dev_warn(cw_bat->dev, 270 + "Too many invalid SoC reports, resetting gauge\n"); 271 + cw_power_on_reset(cw_bat); 272 + cw_bat->read_errors = 0; 273 + } 274 + return cw_bat->soc; 275 + } 276 + cw_bat->read_errors = 0; 277 + 278 + /* Reset gauge if stuck while charging */ 279 + if (cw_bat->status == POWER_SUPPLY_STATUS_CHARGING && soc == cw_bat->soc) { 280 + int max_stuck_cycles = 281 + CW2015_BAT_CHARGING_STUCK_MS / cw_bat->poll_interval_ms; 282 + 283 + cw_bat->charge_stuck_cnt++; 284 + if (cw_bat->charge_stuck_cnt > max_stuck_cycles) { 285 + dev_warn(cw_bat->dev, 286 + "SoC stuck @%u%%, resetting gauge\n", soc); 287 + cw_power_on_reset(cw_bat); 288 + cw_bat->charge_stuck_cnt = 0; 289 + } 290 + } else { 291 + cw_bat->charge_stuck_cnt = 0; 292 + } 293 + 294 + /* Ignore voltage dips during charge */ 295 + if (cw_bat->charger_attached && HYSTERESIS(soc, cw_bat->soc, 0, 3)) 296 + soc = cw_bat->soc; 297 + 298 + /* Ignore voltage spikes during discharge */ 299 + if (!cw_bat->charger_attached && HYSTERESIS(soc, cw_bat->soc, 3, 0)) 300 + soc = cw_bat->soc; 301 + 302 + return soc; 303 + } 304 + 305 + static int cw_get_voltage(struct cw_battery *cw_bat) 306 + { 307 + int ret, i, voltage_mv; 308 + u16 reg_val; 309 + u32 avg = 0; 310 + 311 + for (i = 0; i < CW2015_AVERAGING_SAMPLES; i++) { 312 + ret = cw_read_word(cw_bat, CW2015_REG_VCELL, &reg_val); 313 + if (ret) 314 + return ret; 315 + 316 + avg += reg_val; 317 + } 318 + avg /= CW2015_AVERAGING_SAMPLES; 319 + 320 + /* 321 + * 305 uV per ADC step 322 + * Use 312 / 1024 as efficient approximation of 305 / 1000 323 + * Negligible error of 0.1% 324 + */ 325 + voltage_mv = avg * 312 / 1024; 326 + 327 + dev_dbg(cw_bat->dev, "Read voltage: %d mV, raw=0x%04x\n", 328 + voltage_mv, reg_val); 329 + return voltage_mv; 330 + } 331 + 332 + static int cw_get_time_to_empty(struct cw_battery *cw_bat) 333 + { 334 + int ret; 335 + u16 value16; 336 + 337 + ret = cw_read_word(cw_bat, CW2015_REG_RRT_ALERT, &value16); 338 + if (ret) 339 + return ret; 340 + 341 + return value16 & CW2015_MASK_SOC; 342 + } 343 + 344 + static void cw_update_charge_status(struct cw_battery *cw_bat) 345 + { 346 + int ret; 347 + 348 + ret = power_supply_am_i_supplied(cw_bat->rk_bat); 349 + if (ret < 0) { 350 + dev_warn(cw_bat->dev, "Failed to get supply state: %d\n", ret); 351 + } else { 352 + bool charger_attached; 353 + 354 + charger_attached = !!ret; 355 + if (cw_bat->charger_attached != charger_attached) { 356 + cw_bat->battery_changed = true; 357 + if (charger_attached) 358 + cw_bat->charge_count++; 359 + } 360 + cw_bat->charger_attached = charger_attached; 361 + } 362 + } 363 + 364 + static void cw_update_soc(struct cw_battery *cw_bat) 365 + { 366 + int soc; 367 + 368 + soc = cw_get_soc(cw_bat); 369 + if (soc < 0) 370 + dev_err(cw_bat->dev, "Failed to get SoC from gauge: %d\n", soc); 371 + else if (cw_bat->soc != soc) { 372 + cw_bat->soc = soc; 373 + cw_bat->battery_changed = true; 374 + } 375 + } 376 + 377 + static void cw_update_voltage(struct cw_battery *cw_bat) 378 + { 379 + int voltage_mv; 380 + 381 + voltage_mv = cw_get_voltage(cw_bat); 382 + if (voltage_mv < 0) 383 + dev_err(cw_bat->dev, "Failed to get voltage from gauge: %d\n", 384 + voltage_mv); 385 + else 386 + cw_bat->voltage_mv = voltage_mv; 387 + } 388 + 389 + static void cw_update_status(struct cw_battery *cw_bat) 390 + { 391 + int status = POWER_SUPPLY_STATUS_DISCHARGING; 392 + 393 + if (cw_bat->charger_attached) { 394 + if (cw_bat->soc >= 100) 395 + status = POWER_SUPPLY_STATUS_FULL; 396 + else 397 + status = POWER_SUPPLY_STATUS_CHARGING; 398 + } 399 + 400 + if (cw_bat->status != status) 401 + cw_bat->battery_changed = true; 402 + cw_bat->status = status; 403 + } 404 + 405 + static void cw_update_time_to_empty(struct cw_battery *cw_bat) 406 + { 407 + int time_to_empty; 408 + 409 + time_to_empty = cw_get_time_to_empty(cw_bat); 410 + if (time_to_empty < 0) 411 + dev_err(cw_bat->dev, "Failed to get time to empty from gauge: %d\n", 412 + time_to_empty); 413 + else if (cw_bat->time_to_empty != time_to_empty) { 414 + cw_bat->time_to_empty = time_to_empty; 415 + cw_bat->battery_changed = true; 416 + } 417 + } 418 + 419 + static void cw_bat_work(struct work_struct *work) 420 + { 421 + struct delayed_work *delay_work; 422 + struct cw_battery *cw_bat; 423 + int ret; 424 + unsigned int reg_val; 425 + 426 + delay_work = to_delayed_work(work); 427 + cw_bat = container_of(delay_work, struct cw_battery, battery_delay_work); 428 + ret = regmap_read(cw_bat->regmap, CW2015_REG_MODE, &reg_val); 429 + if (ret) { 430 + dev_err(cw_bat->dev, "Failed to read mode from gauge: %d\n", ret); 431 + } else { 432 + if ((reg_val & CW2015_MODE_SLEEP_MASK) == CW2015_MODE_SLEEP) { 433 + int i; 434 + 435 + for (i = 0; i < CW2015_RESET_TRIES; i++) { 436 + if (!cw_power_on_reset(cw_bat)) 437 + break; 438 + } 439 + } 440 + cw_update_soc(cw_bat); 441 + cw_update_voltage(cw_bat); 442 + cw_update_charge_status(cw_bat); 443 + cw_update_status(cw_bat); 444 + cw_update_time_to_empty(cw_bat); 445 + } 446 + dev_dbg(cw_bat->dev, "charger_attached = %d\n", cw_bat->charger_attached); 447 + dev_dbg(cw_bat->dev, "status = %d\n", cw_bat->status); 448 + dev_dbg(cw_bat->dev, "soc = %d%%\n", cw_bat->soc); 449 + dev_dbg(cw_bat->dev, "voltage = %dmV\n", cw_bat->voltage_mv); 450 + 451 + if (cw_bat->battery_changed) 452 + power_supply_changed(cw_bat->rk_bat); 453 + cw_bat->battery_changed = false; 454 + 455 + queue_delayed_work(cw_bat->battery_workqueue, 456 + &cw_bat->battery_delay_work, 457 + msecs_to_jiffies(cw_bat->poll_interval_ms)); 458 + } 459 + 460 + static bool cw_battery_valid_time_to_empty(struct cw_battery *cw_bat) 461 + { 462 + return cw_bat->time_to_empty > 0 && 463 + cw_bat->time_to_empty < CW2015_MASK_SOC && 464 + cw_bat->status == POWER_SUPPLY_STATUS_DISCHARGING; 465 + } 466 + 467 + static int cw_battery_get_property(struct power_supply *psy, 468 + enum power_supply_property psp, 469 + union power_supply_propval *val) 470 + { 471 + struct cw_battery *cw_bat; 472 + 473 + cw_bat = power_supply_get_drvdata(psy); 474 + switch (psp) { 475 + case POWER_SUPPLY_PROP_CAPACITY: 476 + val->intval = cw_bat->soc; 477 + break; 478 + 479 + case POWER_SUPPLY_PROP_STATUS: 480 + val->intval = cw_bat->status; 481 + break; 482 + 483 + case POWER_SUPPLY_PROP_PRESENT: 484 + val->intval = !!cw_bat->voltage_mv; 485 + break; 486 + 487 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 488 + val->intval = cw_bat->voltage_mv * 1000; 489 + break; 490 + 491 + case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: 492 + if (cw_battery_valid_time_to_empty(cw_bat)) 493 + val->intval = cw_bat->time_to_empty; 494 + else 495 + val->intval = 0; 496 + break; 497 + 498 + case POWER_SUPPLY_PROP_TECHNOLOGY: 499 + val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 500 + break; 501 + 502 + case POWER_SUPPLY_PROP_CHARGE_COUNTER: 503 + val->intval = cw_bat->charge_count; 504 + break; 505 + 506 + case POWER_SUPPLY_PROP_CHARGE_FULL: 507 + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 508 + if (cw_bat->battery.charge_full_design_uah > 0) 509 + val->intval = cw_bat->battery.charge_full_design_uah; 510 + else 511 + val->intval = 0; 512 + break; 513 + 514 + case POWER_SUPPLY_PROP_CURRENT_NOW: 515 + if (cw_battery_valid_time_to_empty(cw_bat) && 516 + cw_bat->battery.charge_full_design_uah > 0) { 517 + /* calculate remaining capacity */ 518 + val->intval = cw_bat->battery.charge_full_design_uah; 519 + val->intval = val->intval * cw_bat->soc / 100; 520 + 521 + /* estimate current based on time to empty */ 522 + val->intval = 60 * val->intval / cw_bat->time_to_empty; 523 + } else { 524 + val->intval = 0; 525 + } 526 + 527 + break; 528 + 529 + default: 530 + break; 531 + } 532 + return 0; 533 + } 534 + 535 + static enum power_supply_property cw_battery_properties[] = { 536 + POWER_SUPPLY_PROP_CAPACITY, 537 + POWER_SUPPLY_PROP_STATUS, 538 + POWER_SUPPLY_PROP_PRESENT, 539 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 540 + POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 541 + POWER_SUPPLY_PROP_TECHNOLOGY, 542 + POWER_SUPPLY_PROP_CHARGE_COUNTER, 543 + POWER_SUPPLY_PROP_CHARGE_FULL, 544 + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 545 + POWER_SUPPLY_PROP_CURRENT_NOW, 546 + }; 547 + 548 + static const struct power_supply_desc cw2015_bat_desc = { 549 + .name = "cw2015-battery", 550 + .type = POWER_SUPPLY_TYPE_BATTERY, 551 + .properties = cw_battery_properties, 552 + .num_properties = ARRAY_SIZE(cw_battery_properties), 553 + .get_property = cw_battery_get_property, 554 + }; 555 + 556 + static int cw2015_parse_properties(struct cw_battery *cw_bat) 557 + { 558 + struct device *dev = cw_bat->dev; 559 + int length; 560 + int ret; 561 + 562 + length = device_property_count_u8(dev, "cellwise,battery-profile"); 563 + if (length < 0) { 564 + dev_warn(cw_bat->dev, 565 + "No battery-profile found, using current flash contents\n"); 566 + } else if (length != CW2015_SIZE_BATINFO) { 567 + dev_err(cw_bat->dev, "battery-profile must be %d bytes\n", 568 + CW2015_SIZE_BATINFO); 569 + return -EINVAL; 570 + } else { 571 + cw_bat->bat_profile = devm_kzalloc(dev, length, GFP_KERNEL); 572 + if (!cw_bat->bat_profile) 573 + return -ENOMEM; 574 + 575 + ret = device_property_read_u8_array(dev, 576 + "cellwise,battery-profile", 577 + cw_bat->bat_profile, 578 + length); 579 + if (ret) 580 + return ret; 581 + } 582 + 583 + ret = device_property_read_u32(dev, "cellwise,monitor-interval-ms", 584 + &cw_bat->poll_interval_ms); 585 + if (ret) { 586 + dev_dbg(cw_bat->dev, "Using default poll interval\n"); 587 + cw_bat->poll_interval_ms = CW2015_DEFAULT_POLL_INTERVAL_MS; 588 + } 589 + 590 + return 0; 591 + } 592 + 593 + static const struct regmap_range regmap_ranges_rd_yes[] = { 594 + regmap_reg_range(CW2015_REG_VERSION, CW2015_REG_VERSION), 595 + regmap_reg_range(CW2015_REG_VCELL, CW2015_REG_CONFIG), 596 + regmap_reg_range(CW2015_REG_MODE, CW2015_REG_MODE), 597 + regmap_reg_range(CW2015_REG_BATINFO, 598 + CW2015_REG_BATINFO + CW2015_SIZE_BATINFO - 1), 599 + }; 600 + 601 + static const struct regmap_access_table regmap_rd_table = { 602 + .yes_ranges = regmap_ranges_rd_yes, 603 + .n_yes_ranges = 4, 604 + }; 605 + 606 + static const struct regmap_range regmap_ranges_wr_yes[] = { 607 + regmap_reg_range(CW2015_REG_RRT_ALERT, CW2015_REG_CONFIG), 608 + regmap_reg_range(CW2015_REG_MODE, CW2015_REG_MODE), 609 + regmap_reg_range(CW2015_REG_BATINFO, 610 + CW2015_REG_BATINFO + CW2015_SIZE_BATINFO - 1), 611 + }; 612 + 613 + static const struct regmap_access_table regmap_wr_table = { 614 + .yes_ranges = regmap_ranges_wr_yes, 615 + .n_yes_ranges = 3, 616 + }; 617 + 618 + static const struct regmap_range regmap_ranges_vol_yes[] = { 619 + regmap_reg_range(CW2015_REG_VCELL, CW2015_REG_SOC + 1), 620 + }; 621 + 622 + static const struct regmap_access_table regmap_vol_table = { 623 + .yes_ranges = regmap_ranges_vol_yes, 624 + .n_yes_ranges = 1, 625 + }; 626 + 627 + static const struct regmap_config cw2015_regmap_config = { 628 + .reg_bits = 8, 629 + .val_bits = 8, 630 + .rd_table = &regmap_rd_table, 631 + .wr_table = &regmap_wr_table, 632 + .volatile_table = &regmap_vol_table, 633 + .max_register = CW2015_REG_BATINFO + CW2015_SIZE_BATINFO - 1, 634 + }; 635 + 636 + static int cw_bat_probe(struct i2c_client *client) 637 + { 638 + int ret; 639 + struct cw_battery *cw_bat; 640 + struct power_supply_config psy_cfg = { 0 }; 641 + 642 + cw_bat = devm_kzalloc(&client->dev, sizeof(*cw_bat), GFP_KERNEL); 643 + if (!cw_bat) 644 + return -ENOMEM; 645 + 646 + i2c_set_clientdata(client, cw_bat); 647 + cw_bat->dev = &client->dev; 648 + cw_bat->soc = 1; 649 + 650 + ret = cw2015_parse_properties(cw_bat); 651 + if (ret) { 652 + dev_err(cw_bat->dev, "Failed to parse cw2015 properties\n"); 653 + return ret; 654 + } 655 + 656 + cw_bat->regmap = devm_regmap_init_i2c(client, &cw2015_regmap_config); 657 + if (IS_ERR(cw_bat->regmap)) { 658 + dev_err(cw_bat->dev, "Failed to allocate regmap: %ld\n", 659 + PTR_ERR(cw_bat->regmap)); 660 + return PTR_ERR(cw_bat->regmap); 661 + } 662 + 663 + ret = cw_init(cw_bat); 664 + if (ret) { 665 + dev_err(cw_bat->dev, "Init failed: %d\n", ret); 666 + return ret; 667 + } 668 + 669 + psy_cfg.drv_data = cw_bat; 670 + psy_cfg.fwnode = dev_fwnode(cw_bat->dev); 671 + 672 + cw_bat->rk_bat = devm_power_supply_register(&client->dev, 673 + &cw2015_bat_desc, 674 + &psy_cfg); 675 + if (IS_ERR(cw_bat->rk_bat)) { 676 + dev_err(cw_bat->dev, "Failed to register power supply\n"); 677 + return PTR_ERR(cw_bat->rk_bat); 678 + } 679 + 680 + ret = power_supply_get_battery_info(cw_bat->rk_bat, &cw_bat->battery); 681 + if (ret) { 682 + dev_warn(cw_bat->dev, 683 + "No monitored battery, some properties will be missing\n"); 684 + } 685 + 686 + cw_bat->battery_workqueue = create_singlethread_workqueue("rk_battery"); 687 + INIT_DELAYED_WORK(&cw_bat->battery_delay_work, cw_bat_work); 688 + queue_delayed_work(cw_bat->battery_workqueue, 689 + &cw_bat->battery_delay_work, msecs_to_jiffies(10)); 690 + return 0; 691 + } 692 + 693 + static int __maybe_unused cw_bat_suspend(struct device *dev) 694 + { 695 + struct i2c_client *client = to_i2c_client(dev); 696 + struct cw_battery *cw_bat = i2c_get_clientdata(client); 697 + 698 + cancel_delayed_work_sync(&cw_bat->battery_delay_work); 699 + return 0; 700 + } 701 + 702 + static int __maybe_unused cw_bat_resume(struct device *dev) 703 + { 704 + struct i2c_client *client = to_i2c_client(dev); 705 + struct cw_battery *cw_bat = i2c_get_clientdata(client); 706 + 707 + queue_delayed_work(cw_bat->battery_workqueue, 708 + &cw_bat->battery_delay_work, 0); 709 + return 0; 710 + } 711 + 712 + static SIMPLE_DEV_PM_OPS(cw_bat_pm_ops, cw_bat_suspend, cw_bat_resume); 713 + 714 + static int cw_bat_remove(struct i2c_client *client) 715 + { 716 + struct cw_battery *cw_bat = i2c_get_clientdata(client); 717 + 718 + cancel_delayed_work_sync(&cw_bat->battery_delay_work); 719 + power_supply_put_battery_info(cw_bat->rk_bat, &cw_bat->battery); 720 + return 0; 721 + } 722 + 723 + static const struct i2c_device_id cw_bat_id_table[] = { 724 + { "cw2015", 0 }, 725 + { } 726 + }; 727 + 728 + static const struct of_device_id cw2015_of_match[] = { 729 + { .compatible = "cellwise,cw2015" }, 730 + { } 731 + }; 732 + MODULE_DEVICE_TABLE(of, cw2015_of_match); 733 + 734 + static struct i2c_driver cw_bat_driver = { 735 + .driver = { 736 + .name = "cw2015", 737 + .of_match_table = cw2015_of_match, 738 + .pm = &cw_bat_pm_ops, 739 + }, 740 + .probe_new = cw_bat_probe, 741 + .remove = cw_bat_remove, 742 + .id_table = cw_bat_id_table, 743 + }; 744 + 745 + module_i2c_driver(cw_bat_driver); 746 + 747 + MODULE_AUTHOR("xhc<xhc@rock-chips.com>"); 748 + MODULE_AUTHOR("Tobias Schramm <t.schramm@manjaro.org>"); 749 + MODULE_DESCRIPTION("cw2015/cw2013 battery driver"); 750 + MODULE_LICENSE("GPL");
+11 -11
drivers/power/supply/generic-adc-battery.c
··· 241 241 struct power_supply_desc *psy_desc; 242 242 struct power_supply_config psy_cfg = {}; 243 243 struct gab_platform_data *pdata = pdev->dev.platform_data; 244 + enum power_supply_property *properties; 244 245 int ret = 0; 245 246 int chan; 246 247 int index = ARRAY_SIZE(gab_props); ··· 269 268 * copying the static properties and allocating extra memory for holding 270 269 * the extra configurable properties received from platform data. 271 270 */ 272 - psy_desc->properties = kcalloc(ARRAY_SIZE(gab_props) + 273 - ARRAY_SIZE(gab_chan_name), 274 - sizeof(*psy_desc->properties), 275 - GFP_KERNEL); 276 - if (!psy_desc->properties) { 271 + properties = kcalloc(ARRAY_SIZE(gab_props) + 272 + ARRAY_SIZE(gab_chan_name), 273 + sizeof(*properties), 274 + GFP_KERNEL); 275 + if (!properties) { 277 276 ret = -ENOMEM; 278 277 goto first_mem_fail; 279 278 } 280 279 281 - memcpy(psy_desc->properties, gab_props, sizeof(gab_props)); 280 + memcpy(properties, gab_props, sizeof(gab_props)); 282 281 283 282 /* 284 283 * getting channel from iio and copying the battery properties ··· 295 294 int index2; 296 295 297 296 for (index2 = 0; index2 < index; index2++) { 298 - if (psy_desc->properties[index2] == 299 - gab_dyn_props[chan]) 297 + if (properties[index2] == gab_dyn_props[chan]) 300 298 break; /* already known */ 301 299 } 302 300 if (index2 == index) /* really new */ 303 - psy_desc->properties[index++] = 304 - gab_dyn_props[chan]; 301 + properties[index++] = gab_dyn_props[chan]; 305 302 any = true; 306 303 } 307 304 } ··· 316 317 * as come channels may be not be supported by the device.So 317 318 * we need to take care of that. 318 319 */ 320 + psy_desc->properties = properties; 319 321 psy_desc->num_properties = index; 320 322 321 323 adc_bat->psy = power_supply_register(&pdev->dev, psy_desc, &psy_cfg); ··· 358 358 iio_channel_release(adc_bat->channel[chan]); 359 359 } 360 360 second_mem_fail: 361 - kfree(psy_desc->properties); 361 + kfree(properties); 362 362 first_mem_fail: 363 363 return ret; 364 364 }
+2 -16
drivers/power/supply/lp8788-charger.c
··· 572 572 return; 573 573 574 574 /* ADC channel for battery voltage */ 575 - chan = iio_channel_get(dev, pdata->adc_vbatt); 575 + chan = devm_iio_channel_get(dev, pdata->adc_vbatt); 576 576 pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan; 577 577 578 578 /* ADC channel for battery temperature */ 579 - chan = iio_channel_get(dev, pdata->adc_batt_temp); 579 + chan = devm_iio_channel_get(dev, pdata->adc_batt_temp); 580 580 pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan; 581 - } 582 - 583 - static void lp8788_release_adc_channel(struct lp8788_charger *pchg) 584 - { 585 - int i; 586 - 587 - for (i = 0; i < LP8788_NUM_CHG_ADC; i++) { 588 - if (!pchg->chan[i]) 589 - continue; 590 - 591 - iio_channel_release(pchg->chan[i]); 592 - pchg->chan[i] = NULL; 593 - } 594 581 } 595 582 596 583 static ssize_t lp8788_show_charger_status(struct device *dev, ··· 722 735 flush_work(&pchg->charger_work); 723 736 lp8788_irq_unregister(pdev, pchg); 724 737 lp8788_psy_unregister(pchg); 725 - lp8788_release_adc_channel(pchg); 726 738 727 739 return 0; 728 740 }
+10
drivers/power/supply/max14577_charger.c
··· 623 623 }; 624 624 MODULE_DEVICE_TABLE(platform, max14577_charger_id); 625 625 626 + static const struct of_device_id of_max14577_charger_dt_match[] = { 627 + { .compatible = "maxim,max14577-charger", 628 + .data = (void *)MAXIM_DEVICE_TYPE_MAX14577, }, 629 + { .compatible = "maxim,max77836-charger", 630 + .data = (void *)MAXIM_DEVICE_TYPE_MAX77836, }, 631 + { }, 632 + }; 633 + MODULE_DEVICE_TABLE(of, of_max14577_charger_dt_match); 634 + 626 635 static struct platform_driver max14577_charger_driver = { 627 636 .driver = { 628 637 .name = "max14577-charger", 638 + .of_match_table = of_max14577_charger_dt_match, 629 639 }, 630 640 .probe = max14577_charger_probe, 631 641 .remove = max14577_charger_remove,
+2 -3
drivers/power/supply/max14656_charger_detector.c
··· 139 139 140 140 u8 buf[REG_TOTAL_NUM]; 141 141 u8 chg_type; 142 - int ret = 0; 143 142 144 - ret = max14656_read_block_reg(chip->client, MAX14656_DEVICE_ID, 145 - REG_TOTAL_NUM, buf); 143 + max14656_read_block_reg(chip->client, MAX14656_DEVICE_ID, 144 + REG_TOTAL_NUM, buf); 146 145 147 146 if ((buf[MAX14656_STATUS_1] & STATUS1_VB_VALID_MASK) && 148 147 (buf[MAX14656_STATUS_1] & STATUS1_CHG_TYPE_MASK)) {
+1 -1
drivers/power/supply/max17040_battery.c
··· 126 126 127 127 vcell = max17040_read_reg(client, MAX17040_VCELL); 128 128 129 - chip->vcell = vcell; 129 + chip->vcell = (vcell >> 4) * 1250; 130 130 } 131 131 132 132 static void max17040_get_soc(struct i2c_client *client)
+8
drivers/power/supply/max17042_battery.c
··· 87 87 POWER_SUPPLY_PROP_SCOPE, 88 88 POWER_SUPPLY_PROP_CURRENT_NOW, 89 89 POWER_SUPPLY_PROP_CURRENT_AVG, 90 + POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 90 91 }; 91 92 92 93 static int max17042_get_temperature(struct max17042_chip *chip, int *temp) ··· 411 410 } else { 412 411 return -EINVAL; 413 412 } 413 + break; 414 + case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: 415 + ret = regmap_read(map, MAX17042_TTE, &data); 416 + if (ret < 0) 417 + return ret; 418 + 419 + val->intval = data * 5625 / 1000; 414 420 break; 415 421 default: 416 422 return -EINVAL;
+2 -2
drivers/power/supply/olpc_battery.c
··· 88 88 }; 89 89 90 90 static const struct power_supply_desc olpc_ac_desc = { 91 - .name = "olpc-ac", 91 + .name = "olpc_ac", 92 92 .type = POWER_SUPPLY_TYPE_MAINS, 93 93 .properties = olpc_ac_props, 94 94 .num_properties = ARRAY_SIZE(olpc_ac_props), ··· 605 605 *********************************************************************/ 606 606 607 607 static struct power_supply_desc olpc_bat_desc = { 608 - .name = "olpc-battery", 608 + .name = "olpc_battery", 609 609 .get_property = olpc_bat_get_property, 610 610 .use_for_apm = 1, 611 611 };
+8
drivers/power/supply/power_supply_core.c
··· 620 620 &info->voltage_min_design_uv); 621 621 of_property_read_u32(battery_np, "voltage-max-design-microvolt", 622 622 &info->voltage_max_design_uv); 623 + of_property_read_u32(battery_np, "trickle-charge-current-microamp", 624 + &info->tricklecharge_current_ua); 623 625 of_property_read_u32(battery_np, "precharge-current-microamp", 624 626 &info->precharge_current_ua); 627 + of_property_read_u32(battery_np, "precharge-upper-limit-microvolt", 628 + &info->precharge_voltage_max_uv); 625 629 of_property_read_u32(battery_np, "charge-term-current-microamp", 626 630 &info->charge_term_current_ua); 631 + of_property_read_u32(battery_np, "re-charge-voltage-microvolt", 632 + &info->charge_restart_voltage_uv); 633 + of_property_read_u32(battery_np, "over-voltage-threshold-microvolt", 634 + &info->overvoltage_limit_uv); 627 635 of_property_read_u32(battery_np, "constant-charge-current-max-microamp", 628 636 &info->constant_charge_current_max_ua); 629 637 of_property_read_u32(battery_np, "constant-charge-voltage-max-microvolt",
+59 -5
drivers/power/supply/power_supply_hwmon.c
··· 13 13 unsigned long *props; 14 14 }; 15 15 16 + static const char *const ps_temp_label[] = { 17 + "temp", 18 + "ambient temp", 19 + }; 20 + 16 21 static int power_supply_hwmon_in_to_property(u32 attr) 17 22 { 18 23 switch (attr) { ··· 103 98 return type == hwmon_temp && attr == hwmon_temp_label; 104 99 } 105 100 101 + struct hwmon_type_attr_list { 102 + const u32 *attrs; 103 + size_t n_attrs; 104 + }; 105 + 106 + static const u32 ps_temp_attrs[] = { 107 + hwmon_temp_input, 108 + hwmon_temp_min, hwmon_temp_max, 109 + hwmon_temp_min_alarm, hwmon_temp_max_alarm, 110 + }; 111 + 112 + static const struct hwmon_type_attr_list ps_type_attrs[hwmon_max] = { 113 + [hwmon_temp] = { ps_temp_attrs, ARRAY_SIZE(ps_temp_attrs) }, 114 + }; 115 + 116 + static bool power_supply_hwmon_has_input( 117 + const struct power_supply_hwmon *psyhw, 118 + enum hwmon_sensor_types type, int channel) 119 + { 120 + const struct hwmon_type_attr_list *attr_list = &ps_type_attrs[type]; 121 + size_t i; 122 + 123 + for (i = 0; i < attr_list->n_attrs; ++i) { 124 + int prop = power_supply_hwmon_to_property(type, 125 + attr_list->attrs[i], channel); 126 + 127 + if (prop >= 0 && test_bit(prop, psyhw->props)) 128 + return true; 129 + } 130 + 131 + return false; 132 + } 133 + 106 134 static bool power_supply_hwmon_is_writable(enum hwmon_sensor_types type, 107 135 u32 attr) 108 136 { ··· 162 124 const struct power_supply_hwmon *psyhw = data; 163 125 int prop; 164 126 165 - 166 - if (power_supply_hwmon_is_a_label(type, attr)) 167 - return 0444; 127 + if (power_supply_hwmon_is_a_label(type, attr)) { 128 + if (power_supply_hwmon_has_input(psyhw, type, channel)) 129 + return 0444; 130 + else 131 + return 0; 132 + } 168 133 169 134 prop = power_supply_hwmon_to_property(type, attr, channel); 170 135 if (prop < 0 || !test_bit(prop, psyhw->props)) ··· 185 144 u32 attr, int channel, 186 145 const char **str) 187 146 { 188 - *str = channel ? "temp" : "temp ambient"; 147 + switch (type) { 148 + case hwmon_temp: 149 + *str = ps_temp_label[channel]; 150 + break; 151 + default: 152 + /* unreachable, but see: 153 + * gcc bug #51513 [1] and clang bug #978 [2] 154 + * 155 + * [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51513 156 + * [2] https://github.com/ClangBuiltLinux/linux/issues/978 157 + */ 158 + break; 159 + } 160 + 189 161 return 0; 190 162 } 191 163 ··· 358 304 goto error; 359 305 } 360 306 361 - ret = devm_add_action(dev, power_supply_hwmon_bitmap_free, 307 + ret = devm_add_action_or_reset(dev, power_supply_hwmon_bitmap_free, 362 308 psyhw->props); 363 309 if (ret) 364 310 goto error;
+261 -219
drivers/power/supply/power_supply_sysfs.c
··· 18 18 19 19 #include "power_supply.h" 20 20 21 - /* 22 - * This is because the name "current" breaks the device attr macro. 23 - * The "current" word resolves to "(get_current())" so instead of 24 - * "current" "(get_current())" appears in the sysfs. 25 - * 26 - * The source of this definition is the device.h which calls __ATTR 27 - * macro in sysfs.h which calls the __stringify macro. 28 - * 29 - * Only modification that the name is not tried to be resolved 30 - * (as a macro let's say). 31 - */ 21 + #define MAX_PROP_NAME_LEN 30 32 22 33 - #define POWER_SUPPLY_ATTR(_name) \ 34 - { \ 35 - .attr = { .name = #_name }, \ 36 - .show = power_supply_show_property, \ 37 - .store = power_supply_store_property, \ 23 + struct power_supply_attr { 24 + const char *prop_name; 25 + char attr_name[MAX_PROP_NAME_LEN + 1]; 26 + struct device_attribute dev_attr; 27 + const char * const *text_values; 28 + int text_values_len; 29 + }; 30 + 31 + #define _POWER_SUPPLY_ATTR(_name, _text, _len) \ 32 + [POWER_SUPPLY_PROP_ ## _name] = \ 33 + { \ 34 + .prop_name = #_name, \ 35 + .attr_name = #_name "\0", \ 36 + .text_values = _text, \ 37 + .text_values_len = _len, \ 38 38 } 39 39 40 - static struct device_attribute power_supply_attrs[]; 40 + #define POWER_SUPPLY_ATTR(_name) _POWER_SUPPLY_ATTR(_name, NULL, 0) 41 + #define _POWER_SUPPLY_ENUM_ATTR(_name, _text) \ 42 + _POWER_SUPPLY_ATTR(_name, _text, ARRAY_SIZE(_text)) 43 + #define POWER_SUPPLY_ENUM_ATTR(_name) \ 44 + _POWER_SUPPLY_ENUM_ATTR(_name, POWER_SUPPLY_ ## _name ## _TEXT) 41 45 42 - static const char * const power_supply_type_text[] = { 43 - "Unknown", "Battery", "UPS", "Mains", "USB", 44 - "USB_DCP", "USB_CDP", "USB_ACA", "USB_C", 45 - "USB_PD", "USB_PD_DRP", "BrickID" 46 + static const char * const POWER_SUPPLY_TYPE_TEXT[] = { 47 + [POWER_SUPPLY_TYPE_UNKNOWN] = "Unknown", 48 + [POWER_SUPPLY_TYPE_BATTERY] = "Battery", 49 + [POWER_SUPPLY_TYPE_UPS] = "UPS", 50 + [POWER_SUPPLY_TYPE_MAINS] = "Mains", 51 + [POWER_SUPPLY_TYPE_USB] = "USB", 52 + [POWER_SUPPLY_TYPE_USB_DCP] = "USB_DCP", 53 + [POWER_SUPPLY_TYPE_USB_CDP] = "USB_CDP", 54 + [POWER_SUPPLY_TYPE_USB_ACA] = "USB_ACA", 55 + [POWER_SUPPLY_TYPE_USB_TYPE_C] = "USB_C", 56 + [POWER_SUPPLY_TYPE_USB_PD] = "USB_PD", 57 + [POWER_SUPPLY_TYPE_USB_PD_DRP] = "USB_PD_DRP", 58 + [POWER_SUPPLY_TYPE_APPLE_BRICK_ID] = "BrickID", 46 59 }; 47 60 48 - static const char * const power_supply_usb_type_text[] = { 49 - "Unknown", "SDP", "DCP", "CDP", "ACA", "C", 50 - "PD", "PD_DRP", "PD_PPS", "BrickID" 61 + static const char * const POWER_SUPPLY_USB_TYPE_TEXT[] = { 62 + [POWER_SUPPLY_USB_TYPE_UNKNOWN] = "Unknown", 63 + [POWER_SUPPLY_USB_TYPE_SDP] = "SDP", 64 + [POWER_SUPPLY_USB_TYPE_DCP] = "DCP", 65 + [POWER_SUPPLY_USB_TYPE_CDP] = "CDP", 66 + [POWER_SUPPLY_USB_TYPE_ACA] = "ACA", 67 + [POWER_SUPPLY_USB_TYPE_C] = "C", 68 + [POWER_SUPPLY_USB_TYPE_PD] = "PD", 69 + [POWER_SUPPLY_USB_TYPE_PD_DRP] = "PD_DRP", 70 + [POWER_SUPPLY_USB_TYPE_PD_PPS] = "PD_PPS", 71 + [POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID] = "BrickID", 51 72 }; 52 73 53 - static const char * const power_supply_status_text[] = { 54 - "Unknown", "Charging", "Discharging", "Not charging", "Full" 74 + static const char * const POWER_SUPPLY_STATUS_TEXT[] = { 75 + [POWER_SUPPLY_STATUS_UNKNOWN] = "Unknown", 76 + [POWER_SUPPLY_STATUS_CHARGING] = "Charging", 77 + [POWER_SUPPLY_STATUS_DISCHARGING] = "Discharging", 78 + [POWER_SUPPLY_STATUS_NOT_CHARGING] = "Not charging", 79 + [POWER_SUPPLY_STATUS_FULL] = "Full", 55 80 }; 56 81 57 - static const char * const power_supply_charge_type_text[] = { 58 - "Unknown", "N/A", "Trickle", "Fast", "Standard", "Adaptive", "Custom" 82 + static const char * const POWER_SUPPLY_CHARGE_TYPE_TEXT[] = { 83 + [POWER_SUPPLY_CHARGE_TYPE_UNKNOWN] = "Unknown", 84 + [POWER_SUPPLY_CHARGE_TYPE_NONE] = "N/A", 85 + [POWER_SUPPLY_CHARGE_TYPE_TRICKLE] = "Trickle", 86 + [POWER_SUPPLY_CHARGE_TYPE_FAST] = "Fast", 87 + [POWER_SUPPLY_CHARGE_TYPE_STANDARD] = "Standard", 88 + [POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE] = "Adaptive", 89 + [POWER_SUPPLY_CHARGE_TYPE_CUSTOM] = "Custom", 59 90 }; 60 91 61 - static const char * const power_supply_health_text[] = { 62 - "Unknown", "Good", "Overheat", "Dead", "Over voltage", 63 - "Unspecified failure", "Cold", "Watchdog timer expire", 64 - "Safety timer expire", "Over current" 92 + static const char * const POWER_SUPPLY_HEALTH_TEXT[] = { 93 + [POWER_SUPPLY_HEALTH_UNKNOWN] = "Unknown", 94 + [POWER_SUPPLY_HEALTH_GOOD] = "Good", 95 + [POWER_SUPPLY_HEALTH_OVERHEAT] = "Overheat", 96 + [POWER_SUPPLY_HEALTH_DEAD] = "Dead", 97 + [POWER_SUPPLY_HEALTH_OVERVOLTAGE] = "Over voltage", 98 + [POWER_SUPPLY_HEALTH_UNSPEC_FAILURE] = "Unspecified failure", 99 + [POWER_SUPPLY_HEALTH_COLD] = "Cold", 100 + [POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE] = "Watchdog timer expire", 101 + [POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE] = "Safety timer expire", 102 + [POWER_SUPPLY_HEALTH_OVERCURRENT] = "Over current", 103 + [POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED] = "Calibration required", 65 104 }; 66 105 67 - static const char * const power_supply_technology_text[] = { 68 - "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd", 69 - "LiMn" 106 + static const char * const POWER_SUPPLY_TECHNOLOGY_TEXT[] = { 107 + [POWER_SUPPLY_TECHNOLOGY_UNKNOWN] = "Unknown", 108 + [POWER_SUPPLY_TECHNOLOGY_NiMH] = "NiMH", 109 + [POWER_SUPPLY_TECHNOLOGY_LION] = "Li-ion", 110 + [POWER_SUPPLY_TECHNOLOGY_LIPO] = "Li-poly", 111 + [POWER_SUPPLY_TECHNOLOGY_LiFe] = "LiFe", 112 + [POWER_SUPPLY_TECHNOLOGY_NiCd] = "NiCd", 113 + [POWER_SUPPLY_TECHNOLOGY_LiMn] = "LiMn", 70 114 }; 71 115 72 - static const char * const power_supply_capacity_level_text[] = { 73 - "Unknown", "Critical", "Low", "Normal", "High", "Full" 116 + static const char * const POWER_SUPPLY_CAPACITY_LEVEL_TEXT[] = { 117 + [POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN] = "Unknown", 118 + [POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL] = "Critical", 119 + [POWER_SUPPLY_CAPACITY_LEVEL_LOW] = "Low", 120 + [POWER_SUPPLY_CAPACITY_LEVEL_NORMAL] = "Normal", 121 + [POWER_SUPPLY_CAPACITY_LEVEL_HIGH] = "High", 122 + [POWER_SUPPLY_CAPACITY_LEVEL_FULL] = "Full", 74 123 }; 75 124 76 - static const char * const power_supply_scope_text[] = { 77 - "Unknown", "System", "Device" 125 + static const char * const POWER_SUPPLY_SCOPE_TEXT[] = { 126 + [POWER_SUPPLY_SCOPE_UNKNOWN] = "Unknown", 127 + [POWER_SUPPLY_SCOPE_SYSTEM] = "System", 128 + [POWER_SUPPLY_SCOPE_DEVICE] = "Device", 78 129 }; 130 + 131 + static struct power_supply_attr power_supply_attrs[] = { 132 + /* Properties of type `int' */ 133 + POWER_SUPPLY_ENUM_ATTR(STATUS), 134 + POWER_SUPPLY_ENUM_ATTR(CHARGE_TYPE), 135 + POWER_SUPPLY_ENUM_ATTR(HEALTH), 136 + POWER_SUPPLY_ATTR(PRESENT), 137 + POWER_SUPPLY_ATTR(ONLINE), 138 + POWER_SUPPLY_ATTR(AUTHENTIC), 139 + POWER_SUPPLY_ENUM_ATTR(TECHNOLOGY), 140 + POWER_SUPPLY_ATTR(CYCLE_COUNT), 141 + POWER_SUPPLY_ATTR(VOLTAGE_MAX), 142 + POWER_SUPPLY_ATTR(VOLTAGE_MIN), 143 + POWER_SUPPLY_ATTR(VOLTAGE_MAX_DESIGN), 144 + POWER_SUPPLY_ATTR(VOLTAGE_MIN_DESIGN), 145 + POWER_SUPPLY_ATTR(VOLTAGE_NOW), 146 + POWER_SUPPLY_ATTR(VOLTAGE_AVG), 147 + POWER_SUPPLY_ATTR(VOLTAGE_OCV), 148 + POWER_SUPPLY_ATTR(VOLTAGE_BOOT), 149 + POWER_SUPPLY_ATTR(CURRENT_MAX), 150 + POWER_SUPPLY_ATTR(CURRENT_NOW), 151 + POWER_SUPPLY_ATTR(CURRENT_AVG), 152 + POWER_SUPPLY_ATTR(CURRENT_BOOT), 153 + POWER_SUPPLY_ATTR(POWER_NOW), 154 + POWER_SUPPLY_ATTR(POWER_AVG), 155 + POWER_SUPPLY_ATTR(CHARGE_FULL_DESIGN), 156 + POWER_SUPPLY_ATTR(CHARGE_EMPTY_DESIGN), 157 + POWER_SUPPLY_ATTR(CHARGE_FULL), 158 + POWER_SUPPLY_ATTR(CHARGE_EMPTY), 159 + POWER_SUPPLY_ATTR(CHARGE_NOW), 160 + POWER_SUPPLY_ATTR(CHARGE_AVG), 161 + POWER_SUPPLY_ATTR(CHARGE_COUNTER), 162 + POWER_SUPPLY_ATTR(CONSTANT_CHARGE_CURRENT), 163 + POWER_SUPPLY_ATTR(CONSTANT_CHARGE_CURRENT_MAX), 164 + POWER_SUPPLY_ATTR(CONSTANT_CHARGE_VOLTAGE), 165 + POWER_SUPPLY_ATTR(CONSTANT_CHARGE_VOLTAGE_MAX), 166 + POWER_SUPPLY_ATTR(CHARGE_CONTROL_LIMIT), 167 + POWER_SUPPLY_ATTR(CHARGE_CONTROL_LIMIT_MAX), 168 + POWER_SUPPLY_ATTR(CHARGE_CONTROL_START_THRESHOLD), 169 + POWER_SUPPLY_ATTR(CHARGE_CONTROL_END_THRESHOLD), 170 + POWER_SUPPLY_ATTR(INPUT_CURRENT_LIMIT), 171 + POWER_SUPPLY_ATTR(INPUT_VOLTAGE_LIMIT), 172 + POWER_SUPPLY_ATTR(INPUT_POWER_LIMIT), 173 + POWER_SUPPLY_ATTR(ENERGY_FULL_DESIGN), 174 + POWER_SUPPLY_ATTR(ENERGY_EMPTY_DESIGN), 175 + POWER_SUPPLY_ATTR(ENERGY_FULL), 176 + POWER_SUPPLY_ATTR(ENERGY_EMPTY), 177 + POWER_SUPPLY_ATTR(ENERGY_NOW), 178 + POWER_SUPPLY_ATTR(ENERGY_AVG), 179 + POWER_SUPPLY_ATTR(CAPACITY), 180 + POWER_SUPPLY_ATTR(CAPACITY_ALERT_MIN), 181 + POWER_SUPPLY_ATTR(CAPACITY_ALERT_MAX), 182 + POWER_SUPPLY_ATTR(CAPACITY_ERROR_MARGIN), 183 + POWER_SUPPLY_ENUM_ATTR(CAPACITY_LEVEL), 184 + POWER_SUPPLY_ATTR(TEMP), 185 + POWER_SUPPLY_ATTR(TEMP_MAX), 186 + POWER_SUPPLY_ATTR(TEMP_MIN), 187 + POWER_SUPPLY_ATTR(TEMP_ALERT_MIN), 188 + POWER_SUPPLY_ATTR(TEMP_ALERT_MAX), 189 + POWER_SUPPLY_ATTR(TEMP_AMBIENT), 190 + POWER_SUPPLY_ATTR(TEMP_AMBIENT_ALERT_MIN), 191 + POWER_SUPPLY_ATTR(TEMP_AMBIENT_ALERT_MAX), 192 + POWER_SUPPLY_ATTR(TIME_TO_EMPTY_NOW), 193 + POWER_SUPPLY_ATTR(TIME_TO_EMPTY_AVG), 194 + POWER_SUPPLY_ATTR(TIME_TO_FULL_NOW), 195 + POWER_SUPPLY_ATTR(TIME_TO_FULL_AVG), 196 + POWER_SUPPLY_ENUM_ATTR(TYPE), 197 + POWER_SUPPLY_ATTR(USB_TYPE), 198 + POWER_SUPPLY_ENUM_ATTR(SCOPE), 199 + POWER_SUPPLY_ATTR(PRECHARGE_CURRENT), 200 + POWER_SUPPLY_ATTR(CHARGE_TERM_CURRENT), 201 + POWER_SUPPLY_ATTR(CALIBRATE), 202 + POWER_SUPPLY_ATTR(MANUFACTURE_YEAR), 203 + POWER_SUPPLY_ATTR(MANUFACTURE_MONTH), 204 + POWER_SUPPLY_ATTR(MANUFACTURE_DAY), 205 + /* Properties of type `const char *' */ 206 + POWER_SUPPLY_ATTR(MODEL_NAME), 207 + POWER_SUPPLY_ATTR(MANUFACTURER), 208 + POWER_SUPPLY_ATTR(SERIAL_NUMBER), 209 + }; 210 + 211 + static struct attribute * 212 + __power_supply_attrs[ARRAY_SIZE(power_supply_attrs) + 1]; 213 + 214 + static struct power_supply_attr *to_ps_attr(struct device_attribute *attr) 215 + { 216 + return container_of(attr, struct power_supply_attr, dev_attr); 217 + } 218 + 219 + static enum power_supply_property dev_attr_psp(struct device_attribute *attr) 220 + { 221 + return to_ps_attr(attr) - power_supply_attrs; 222 + } 79 223 80 224 static ssize_t power_supply_show_usb_type(struct device *dev, 81 - enum power_supply_usb_type *usb_types, 82 - ssize_t num_usb_types, 225 + const struct power_supply_desc *desc, 83 226 union power_supply_propval *value, 84 227 char *buf) 85 228 { ··· 231 88 bool match = false; 232 89 int i; 233 90 234 - for (i = 0; i < num_usb_types; ++i) { 235 - usb_type = usb_types[i]; 91 + for (i = 0; i < desc->num_usb_types; ++i) { 92 + usb_type = desc->usb_types[i]; 236 93 237 94 if (value->intval == usb_type) { 238 95 count += sprintf(buf + count, "[%s] ", 239 - power_supply_usb_type_text[usb_type]); 96 + POWER_SUPPLY_USB_TYPE_TEXT[usb_type]); 240 97 match = true; 241 98 } else { 242 99 count += sprintf(buf + count, "%s ", 243 - power_supply_usb_type_text[usb_type]); 100 + POWER_SUPPLY_USB_TYPE_TEXT[usb_type]); 244 101 } 245 102 } 246 103 ··· 260 117 char *buf) { 261 118 ssize_t ret; 262 119 struct power_supply *psy = dev_get_drvdata(dev); 263 - enum power_supply_property psp = attr - power_supply_attrs; 120 + struct power_supply_attr *ps_attr = to_ps_attr(attr); 121 + enum power_supply_property psp = dev_attr_psp(attr); 264 122 union power_supply_propval value; 265 123 266 124 if (psp == POWER_SUPPLY_PROP_TYPE) { ··· 281 137 } 282 138 } 283 139 140 + if (ps_attr->text_values_len > 0 && 141 + value.intval < ps_attr->text_values_len && value.intval >= 0) { 142 + return sprintf(buf, "%s\n", ps_attr->text_values[value.intval]); 143 + } 144 + 284 145 switch (psp) { 285 - case POWER_SUPPLY_PROP_STATUS: 286 - ret = sprintf(buf, "%s\n", 287 - power_supply_status_text[value.intval]); 288 - break; 289 - case POWER_SUPPLY_PROP_CHARGE_TYPE: 290 - ret = sprintf(buf, "%s\n", 291 - power_supply_charge_type_text[value.intval]); 292 - break; 293 - case POWER_SUPPLY_PROP_HEALTH: 294 - ret = sprintf(buf, "%s\n", 295 - power_supply_health_text[value.intval]); 296 - break; 297 - case POWER_SUPPLY_PROP_TECHNOLOGY: 298 - ret = sprintf(buf, "%s\n", 299 - power_supply_technology_text[value.intval]); 300 - break; 301 - case POWER_SUPPLY_PROP_CAPACITY_LEVEL: 302 - ret = sprintf(buf, "%s\n", 303 - power_supply_capacity_level_text[value.intval]); 304 - break; 305 - case POWER_SUPPLY_PROP_TYPE: 306 - ret = sprintf(buf, "%s\n", 307 - power_supply_type_text[value.intval]); 308 - break; 309 146 case POWER_SUPPLY_PROP_USB_TYPE: 310 - ret = power_supply_show_usb_type(dev, psy->desc->usb_types, 311 - psy->desc->num_usb_types, 312 - &value, buf); 313 - break; 314 - case POWER_SUPPLY_PROP_SCOPE: 315 - ret = sprintf(buf, "%s\n", 316 - power_supply_scope_text[value.intval]); 147 + ret = power_supply_show_usb_type(dev, psy->desc, 148 + &value, buf); 317 149 break; 318 150 case POWER_SUPPLY_PROP_MODEL_NAME ... POWER_SUPPLY_PROP_SERIAL_NUMBER: 319 151 ret = sprintf(buf, "%s\n", value.strval); ··· 306 186 const char *buf, size_t count) { 307 187 ssize_t ret; 308 188 struct power_supply *psy = dev_get_drvdata(dev); 309 - enum power_supply_property psp = attr - power_supply_attrs; 189 + struct power_supply_attr *ps_attr = to_ps_attr(attr); 190 + enum power_supply_property psp = dev_attr_psp(attr); 310 191 union power_supply_propval value; 311 192 312 - switch (psp) { 313 - case POWER_SUPPLY_PROP_STATUS: 314 - ret = sysfs_match_string(power_supply_status_text, buf); 315 - break; 316 - case POWER_SUPPLY_PROP_CHARGE_TYPE: 317 - ret = sysfs_match_string(power_supply_charge_type_text, buf); 318 - break; 319 - case POWER_SUPPLY_PROP_HEALTH: 320 - ret = sysfs_match_string(power_supply_health_text, buf); 321 - break; 322 - case POWER_SUPPLY_PROP_TECHNOLOGY: 323 - ret = sysfs_match_string(power_supply_technology_text, buf); 324 - break; 325 - case POWER_SUPPLY_PROP_CAPACITY_LEVEL: 326 - ret = sysfs_match_string(power_supply_capacity_level_text, buf); 327 - break; 328 - case POWER_SUPPLY_PROP_SCOPE: 329 - ret = sysfs_match_string(power_supply_scope_text, buf); 330 - break; 331 - default: 332 - ret = -EINVAL; 193 + ret = -EINVAL; 194 + if (ps_attr->text_values_len > 0) { 195 + ret = __sysfs_match_string(ps_attr->text_values, 196 + ps_attr->text_values_len, buf); 333 197 } 334 198 335 199 /* ··· 339 235 return count; 340 236 } 341 237 342 - /* Must be in the same order as POWER_SUPPLY_PROP_* */ 343 - static struct device_attribute power_supply_attrs[] = { 344 - /* Properties of type `int' */ 345 - POWER_SUPPLY_ATTR(status), 346 - POWER_SUPPLY_ATTR(charge_type), 347 - POWER_SUPPLY_ATTR(health), 348 - POWER_SUPPLY_ATTR(present), 349 - POWER_SUPPLY_ATTR(online), 350 - POWER_SUPPLY_ATTR(authentic), 351 - POWER_SUPPLY_ATTR(technology), 352 - POWER_SUPPLY_ATTR(cycle_count), 353 - POWER_SUPPLY_ATTR(voltage_max), 354 - POWER_SUPPLY_ATTR(voltage_min), 355 - POWER_SUPPLY_ATTR(voltage_max_design), 356 - POWER_SUPPLY_ATTR(voltage_min_design), 357 - POWER_SUPPLY_ATTR(voltage_now), 358 - POWER_SUPPLY_ATTR(voltage_avg), 359 - POWER_SUPPLY_ATTR(voltage_ocv), 360 - POWER_SUPPLY_ATTR(voltage_boot), 361 - POWER_SUPPLY_ATTR(current_max), 362 - POWER_SUPPLY_ATTR(current_now), 363 - POWER_SUPPLY_ATTR(current_avg), 364 - POWER_SUPPLY_ATTR(current_boot), 365 - POWER_SUPPLY_ATTR(power_now), 366 - POWER_SUPPLY_ATTR(power_avg), 367 - POWER_SUPPLY_ATTR(charge_full_design), 368 - POWER_SUPPLY_ATTR(charge_empty_design), 369 - POWER_SUPPLY_ATTR(charge_full), 370 - POWER_SUPPLY_ATTR(charge_empty), 371 - POWER_SUPPLY_ATTR(charge_now), 372 - POWER_SUPPLY_ATTR(charge_avg), 373 - POWER_SUPPLY_ATTR(charge_counter), 374 - POWER_SUPPLY_ATTR(constant_charge_current), 375 - POWER_SUPPLY_ATTR(constant_charge_current_max), 376 - POWER_SUPPLY_ATTR(constant_charge_voltage), 377 - POWER_SUPPLY_ATTR(constant_charge_voltage_max), 378 - POWER_SUPPLY_ATTR(charge_control_limit), 379 - POWER_SUPPLY_ATTR(charge_control_limit_max), 380 - POWER_SUPPLY_ATTR(charge_control_start_threshold), 381 - POWER_SUPPLY_ATTR(charge_control_end_threshold), 382 - POWER_SUPPLY_ATTR(input_current_limit), 383 - POWER_SUPPLY_ATTR(input_voltage_limit), 384 - POWER_SUPPLY_ATTR(input_power_limit), 385 - POWER_SUPPLY_ATTR(energy_full_design), 386 - POWER_SUPPLY_ATTR(energy_empty_design), 387 - POWER_SUPPLY_ATTR(energy_full), 388 - POWER_SUPPLY_ATTR(energy_empty), 389 - POWER_SUPPLY_ATTR(energy_now), 390 - POWER_SUPPLY_ATTR(energy_avg), 391 - POWER_SUPPLY_ATTR(capacity), 392 - POWER_SUPPLY_ATTR(capacity_alert_min), 393 - POWER_SUPPLY_ATTR(capacity_alert_max), 394 - POWER_SUPPLY_ATTR(capacity_level), 395 - POWER_SUPPLY_ATTR(temp), 396 - POWER_SUPPLY_ATTR(temp_max), 397 - POWER_SUPPLY_ATTR(temp_min), 398 - POWER_SUPPLY_ATTR(temp_alert_min), 399 - POWER_SUPPLY_ATTR(temp_alert_max), 400 - POWER_SUPPLY_ATTR(temp_ambient), 401 - POWER_SUPPLY_ATTR(temp_ambient_alert_min), 402 - POWER_SUPPLY_ATTR(temp_ambient_alert_max), 403 - POWER_SUPPLY_ATTR(time_to_empty_now), 404 - POWER_SUPPLY_ATTR(time_to_empty_avg), 405 - POWER_SUPPLY_ATTR(time_to_full_now), 406 - POWER_SUPPLY_ATTR(time_to_full_avg), 407 - POWER_SUPPLY_ATTR(type), 408 - POWER_SUPPLY_ATTR(usb_type), 409 - POWER_SUPPLY_ATTR(scope), 410 - POWER_SUPPLY_ATTR(precharge_current), 411 - POWER_SUPPLY_ATTR(charge_term_current), 412 - POWER_SUPPLY_ATTR(calibrate), 413 - /* Properties of type `const char *' */ 414 - POWER_SUPPLY_ATTR(model_name), 415 - POWER_SUPPLY_ATTR(manufacturer), 416 - POWER_SUPPLY_ATTR(serial_number), 417 - }; 418 - 419 - static struct attribute * 420 - __power_supply_attrs[ARRAY_SIZE(power_supply_attrs) + 1]; 421 - 422 238 static umode_t power_supply_attr_is_visible(struct kobject *kobj, 423 239 struct attribute *attr, 424 240 int attrno) ··· 347 323 struct power_supply *psy = dev_get_drvdata(dev); 348 324 umode_t mode = S_IRUSR | S_IRGRP | S_IROTH; 349 325 int i; 326 + 327 + if (!power_supply_attrs[attrno].prop_name) 328 + return 0; 350 329 351 330 if (attrno == POWER_SUPPLY_PROP_TYPE) 352 331 return mode; ··· 379 352 NULL, 380 353 }; 381 354 355 + static void str_to_lower(char *str) 356 + { 357 + while (*str) { 358 + *str = tolower(*str); 359 + str++; 360 + } 361 + } 362 + 382 363 void power_supply_init_attrs(struct device_type *dev_type) 383 364 { 384 365 int i; 385 366 386 367 dev_type->groups = power_supply_attr_groups; 387 368 388 - for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++) 389 - __power_supply_attrs[i] = &power_supply_attrs[i].attr; 369 + for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++) { 370 + struct device_attribute *attr; 371 + 372 + if (!power_supply_attrs[i].prop_name) { 373 + pr_warn("%s: Property %d skipped because is is missing from power_supply_attrs\n", 374 + __func__, i); 375 + sprintf(power_supply_attrs[i].attr_name, "_err_%d", i); 376 + } else { 377 + str_to_lower(power_supply_attrs[i].attr_name); 378 + } 379 + 380 + attr = &power_supply_attrs[i].dev_attr; 381 + 382 + attr->attr.name = power_supply_attrs[i].attr_name; 383 + attr->show = power_supply_show_property; 384 + attr->store = power_supply_store_property; 385 + __power_supply_attrs[i] = &attr->attr; 386 + } 390 387 } 391 388 392 - static char *kstruprdup(const char *str, gfp_t gfp) 389 + static int add_prop_uevent(struct device *dev, struct kobj_uevent_env *env, 390 + enum power_supply_property prop, char *prop_buf) 393 391 { 394 - char *ret, *ustr; 392 + int ret = 0; 393 + struct power_supply_attr *pwr_attr; 394 + struct device_attribute *dev_attr; 395 + char *line; 395 396 396 - ustr = ret = kmalloc(strlen(str) + 1, gfp); 397 + pwr_attr = &power_supply_attrs[prop]; 398 + dev_attr = &pwr_attr->dev_attr; 397 399 398 - if (!ret) 399 - return NULL; 400 + ret = power_supply_show_property(dev, dev_attr, prop_buf); 401 + if (ret == -ENODEV || ret == -ENODATA) { 402 + /* 403 + * When a battery is absent, we expect -ENODEV. Don't abort; 404 + * send the uevent with at least the the PRESENT=0 property 405 + */ 406 + return 0; 407 + } 400 408 401 - while (*str) 402 - *ustr++ = toupper(*str++); 409 + if (ret < 0) 410 + return ret; 403 411 404 - *ustr = 0; 412 + line = strchr(prop_buf, '\n'); 413 + if (line) 414 + *line = 0; 405 415 406 - return ret; 416 + return add_uevent_var(env, "POWER_SUPPLY_%s=%s", 417 + pwr_attr->prop_name, prop_buf); 407 418 } 408 419 409 420 int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env) ··· 449 384 struct power_supply *psy = dev_get_drvdata(dev); 450 385 int ret = 0, j; 451 386 char *prop_buf; 452 - char *attrname; 453 387 454 388 if (!psy || !psy->desc) { 455 389 dev_dbg(dev, "No power supply yet\n"); ··· 463 399 if (!prop_buf) 464 400 return -ENOMEM; 465 401 402 + ret = add_prop_uevent(dev, env, POWER_SUPPLY_PROP_TYPE, prop_buf); 403 + if (ret) 404 + goto out; 405 + 466 406 for (j = 0; j < psy->desc->num_properties; j++) { 467 - struct device_attribute *attr; 468 - char *line; 469 - 470 - attr = &power_supply_attrs[psy->desc->properties[j]]; 471 - 472 - ret = power_supply_show_property(dev, attr, prop_buf); 473 - if (ret == -ENODEV || ret == -ENODATA) { 474 - /* When a battery is absent, we expect -ENODEV. Don't abort; 475 - send the uevent with at least the the PRESENT=0 property */ 476 - ret = 0; 477 - continue; 478 - } 479 - 480 - if (ret < 0) 481 - goto out; 482 - 483 - line = strchr(prop_buf, '\n'); 484 - if (line) 485 - *line = 0; 486 - 487 - attrname = kstruprdup(attr->attr.name, GFP_KERNEL); 488 - if (!attrname) { 489 - ret = -ENOMEM; 490 - goto out; 491 - } 492 - 493 - ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf); 494 - kfree(attrname); 407 + ret = add_prop_uevent(dev, env, psy->desc->properties[j], 408 + prop_buf); 495 409 if (ret) 496 410 goto out; 497 411 }
+203 -29
drivers/power/supply/sbs-battery.c
··· 14 14 #include <linux/interrupt.h> 15 15 #include <linux/kernel.h> 16 16 #include <linux/module.h> 17 - #include <linux/of.h> 17 + #include <linux/property.h> 18 18 #include <linux/of_device.h> 19 19 #include <linux/power/sbs-battery.h> 20 20 #include <linux/power_supply.h> ··· 23 23 24 24 enum { 25 25 REG_MANUFACTURER_DATA, 26 + REG_BATTERY_MODE, 26 27 REG_TEMPERATURE, 27 28 REG_VOLTAGE, 28 - REG_CURRENT, 29 + REG_CURRENT_NOW, 30 + REG_CURRENT_AVG, 31 + REG_MAX_ERR, 29 32 REG_CAPACITY, 30 33 REG_TIME_TO_EMPTY, 31 34 REG_TIME_TO_FULL, ··· 44 41 REG_DESIGN_CAPACITY_CHARGE, 45 42 REG_DESIGN_VOLTAGE_MIN, 46 43 REG_DESIGN_VOLTAGE_MAX, 44 + REG_CHEMISTRY, 47 45 REG_MANUFACTURER, 48 46 REG_MODEL_NAME, 47 + REG_CHARGE_CURRENT, 48 + REG_CHARGE_VOLTAGE, 49 49 }; 50 + 51 + #define REG_ADDR_MANUFACTURE_DATE 0x1B 50 52 51 53 /* Battery Mode defines */ 52 54 #define BATTERY_MODE_OFFSET 0x03 ··· 60 52 CAPACITY_MODE_AMPS = 0, 61 53 CAPACITY_MODE_WATTS = BATTERY_MODE_CAPACITY_MASK 62 54 }; 55 + #define BATTERY_MODE_CHARGER_MASK (1<<14) 63 56 64 57 /* manufacturer access defines */ 65 58 #define MANUFACTURER_ACCESS_STATUS 0x0006 ··· 88 79 } sbs_data[] = { 89 80 [REG_MANUFACTURER_DATA] = 90 81 SBS_DATA(POWER_SUPPLY_PROP_PRESENT, 0x00, 0, 65535), 82 + [REG_BATTERY_MODE] = 83 + SBS_DATA(-1, 0x03, 0, 65535), 91 84 [REG_TEMPERATURE] = 92 85 SBS_DATA(POWER_SUPPLY_PROP_TEMP, 0x08, 0, 65535), 93 86 [REG_VOLTAGE] = 94 87 SBS_DATA(POWER_SUPPLY_PROP_VOLTAGE_NOW, 0x09, 0, 20000), 95 - [REG_CURRENT] = 88 + [REG_CURRENT_NOW] = 96 89 SBS_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768, 32767), 90 + [REG_CURRENT_AVG] = 91 + SBS_DATA(POWER_SUPPLY_PROP_CURRENT_AVG, 0x0B, -32768, 32767), 92 + [REG_MAX_ERR] = 93 + SBS_DATA(POWER_SUPPLY_PROP_CAPACITY_ERROR_MARGIN, 0x0c, 0, 100), 97 94 [REG_CAPACITY] = 98 95 SBS_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0D, 0, 100), 99 96 [REG_REMAINING_CAPACITY] = ··· 114 99 SBS_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0, 65535), 115 100 [REG_TIME_TO_FULL] = 116 101 SBS_DATA(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 0x13, 0, 65535), 102 + [REG_CHARGE_CURRENT] = 103 + SBS_DATA(POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 0x14, 0, 65535), 104 + [REG_CHARGE_VOLTAGE] = 105 + SBS_DATA(POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 0x15, 0, 65535), 117 106 [REG_STATUS] = 118 107 SBS_DATA(POWER_SUPPLY_PROP_STATUS, 0x16, 0, 65535), 119 108 [REG_CAPACITY_LEVEL] = ··· 138 119 [REG_MANUFACTURER] = 139 120 SBS_DATA(POWER_SUPPLY_PROP_MANUFACTURER, 0x20, 0, 65535), 140 121 [REG_MODEL_NAME] = 141 - SBS_DATA(POWER_SUPPLY_PROP_MODEL_NAME, 0x21, 0, 65535) 122 + SBS_DATA(POWER_SUPPLY_PROP_MODEL_NAME, 0x21, 0, 65535), 123 + [REG_CHEMISTRY] = 124 + SBS_DATA(POWER_SUPPLY_PROP_TECHNOLOGY, 0x22, 0, 65535) 142 125 }; 143 126 144 - static enum power_supply_property sbs_properties[] = { 127 + static const enum power_supply_property sbs_properties[] = { 145 128 POWER_SUPPLY_PROP_STATUS, 146 129 POWER_SUPPLY_PROP_CAPACITY_LEVEL, 147 130 POWER_SUPPLY_PROP_HEALTH, ··· 152 131 POWER_SUPPLY_PROP_CYCLE_COUNT, 153 132 POWER_SUPPLY_PROP_VOLTAGE_NOW, 154 133 POWER_SUPPLY_PROP_CURRENT_NOW, 134 + POWER_SUPPLY_PROP_CURRENT_AVG, 155 135 POWER_SUPPLY_PROP_CAPACITY, 136 + POWER_SUPPLY_PROP_CAPACITY_ERROR_MARGIN, 156 137 POWER_SUPPLY_PROP_TEMP, 157 138 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 158 139 POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, ··· 167 144 POWER_SUPPLY_PROP_CHARGE_NOW, 168 145 POWER_SUPPLY_PROP_CHARGE_FULL, 169 146 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 147 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 148 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 149 + POWER_SUPPLY_PROP_MANUFACTURE_YEAR, 150 + POWER_SUPPLY_PROP_MANUFACTURE_MONTH, 151 + POWER_SUPPLY_PROP_MANUFACTURE_DAY, 170 152 /* Properties of type `const char *' */ 171 153 POWER_SUPPLY_PROP_MANUFACTURER, 172 154 POWER_SUPPLY_PROP_MODEL_NAME 173 155 }; 174 156 175 - /* Supports special manufacturer commands from TI BQ20Z75 IC. */ 176 - #define SBS_FLAGS_TI_BQ20Z75 BIT(0) 157 + /* Supports special manufacturer commands from TI BQ20Z65 and BQ20Z75 IC. */ 158 + #define SBS_FLAGS_TI_BQ20ZX5 BIT(0) 177 159 178 160 struct sbs_info { 179 161 struct i2c_client *client; ··· 186 158 bool is_present; 187 159 struct gpio_desc *gpio_detect; 188 160 bool enable_detection; 161 + bool charger_broadcasts; 189 162 int last_state; 190 163 int poll_time; 191 164 u32 i2c_retry_count; ··· 198 169 199 170 static char model_name[I2C_SMBUS_BLOCK_MAX + 1]; 200 171 static char manufacturer[I2C_SMBUS_BLOCK_MAX + 1]; 172 + static char chemistry[I2C_SMBUS_BLOCK_MAX + 1]; 201 173 static bool force_load; 174 + 175 + static int sbs_read_word_data(struct i2c_client *client, u8 address); 176 + static int sbs_write_word_data(struct i2c_client *client, u8 address, u16 value); 177 + 178 + static void sbs_disable_charger_broadcasts(struct sbs_info *chip) 179 + { 180 + int val = sbs_read_word_data(chip->client, BATTERY_MODE_OFFSET); 181 + if (val < 0) 182 + goto exit; 183 + 184 + val |= BATTERY_MODE_CHARGER_MASK; 185 + 186 + val = sbs_write_word_data(chip->client, BATTERY_MODE_OFFSET, val); 187 + 188 + exit: 189 + if (val < 0) 190 + dev_err(&chip->client->dev, 191 + "Failed to disable charger broadcasting: %d\n", val); 192 + else 193 + dev_dbg(&chip->client->dev, "%s\n", __func__); 194 + } 195 + 196 + static int sbs_update_presence(struct sbs_info *chip, bool is_present) 197 + { 198 + if (chip->is_present == is_present) 199 + return 0; 200 + 201 + if (!is_present) { 202 + chip->is_present = false; 203 + return 0; 204 + } 205 + 206 + if (!chip->is_present && is_present && !chip->charger_broadcasts) 207 + sbs_disable_charger_broadcasts(chip); 208 + 209 + chip->is_present = true; 210 + 211 + return 0; 212 + } 202 213 203 214 static int sbs_read_word_data(struct i2c_client *client, u8 address) 204 215 { ··· 357 288 { 358 289 int ret; 359 290 360 - ret = sbs_read_word_data(client, sbs_data[REG_CURRENT].addr); 291 + ret = sbs_read_word_data(client, sbs_data[REG_CURRENT_NOW].addr); 361 292 if (ret < 0) 362 293 return ret; 363 294 364 295 ret = (s16)ret; 365 296 366 - /* Not drawing current means full (cannot be not charging) */ 367 - if (ret == 0) 368 - *intval = POWER_SUPPLY_STATUS_FULL; 297 + /* Not drawing current -> not charging (i.e. idle) */ 298 + if (*intval != POWER_SUPPLY_STATUS_FULL && ret == 0) 299 + *intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 369 300 370 301 if (*intval == POWER_SUPPLY_STATUS_FULL) { 371 302 /* Drawing or providing current when full */ ··· 376 307 } 377 308 378 309 return 0; 310 + } 311 + 312 + static bool sbs_bat_needs_calibration(struct i2c_client *client) 313 + { 314 + int ret; 315 + 316 + ret = sbs_read_word_data(client, sbs_data[REG_BATTERY_MODE].addr); 317 + if (ret < 0) 318 + return false; 319 + 320 + return !!(ret & BIT(7)); 379 321 } 380 322 381 323 static int sbs_get_battery_presence_and_health( ··· 408 328 409 329 if (psp == POWER_SUPPLY_PROP_PRESENT) 410 330 val->intval = 1; /* battery present */ 411 - else /* POWER_SUPPLY_PROP_HEALTH */ 412 - /* SBS spec doesn't have a general health command. */ 413 - val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; 331 + else { /* POWER_SUPPLY_PROP_HEALTH */ 332 + if (sbs_bat_needs_calibration(client)) { 333 + val->intval = POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED; 334 + } else { 335 + /* SBS spec doesn't have a general health command. */ 336 + val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; 337 + } 338 + } 414 339 415 340 return 0; 416 341 } ··· 469 384 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 470 385 else if (ret == 0x0C) 471 386 val->intval = POWER_SUPPLY_HEALTH_DEAD; 387 + else if (sbs_bat_needs_calibration(client)) 388 + val->intval = POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED; 472 389 else 473 390 val->intval = POWER_SUPPLY_HEALTH_GOOD; 474 391 } ··· 579 492 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 580 493 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 581 494 case POWER_SUPPLY_PROP_CURRENT_NOW: 495 + case POWER_SUPPLY_PROP_CURRENT_AVG: 582 496 case POWER_SUPPLY_PROP_CHARGE_NOW: 497 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 498 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 583 499 case POWER_SUPPLY_PROP_CHARGE_FULL: 584 500 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 585 501 val->intval *= BASE_UNIT_CONVERSION; ··· 692 602 return -EINVAL; 693 603 } 694 604 605 + static int sbs_get_chemistry(struct i2c_client *client, 606 + union power_supply_propval *val) 607 + { 608 + enum power_supply_property psp = POWER_SUPPLY_PROP_TECHNOLOGY; 609 + int ret; 610 + 611 + ret = sbs_get_property_index(client, psp); 612 + if (ret < 0) 613 + return ret; 614 + 615 + ret = sbs_get_battery_string_property(client, ret, psp, 616 + chemistry); 617 + if (ret < 0) 618 + return ret; 619 + 620 + if (!strncasecmp(chemistry, "LION", 4)) 621 + val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 622 + else if (!strncasecmp(chemistry, "LiP", 3)) 623 + val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO; 624 + else if (!strncasecmp(chemistry, "NiCd", 4)) 625 + val->intval = POWER_SUPPLY_TECHNOLOGY_NiCd; 626 + else if (!strncasecmp(chemistry, "NiMH", 4)) 627 + val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH; 628 + else 629 + val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; 630 + 631 + if (val->intval == POWER_SUPPLY_TECHNOLOGY_UNKNOWN) 632 + dev_warn(&client->dev, "Unknown chemistry: %s\n", chemistry); 633 + 634 + return 0; 635 + } 636 + 637 + static int sbs_get_battery_manufacture_date(struct i2c_client *client, 638 + enum power_supply_property psp, 639 + union power_supply_propval *val) 640 + { 641 + int ret; 642 + u16 day, month, year; 643 + 644 + ret = sbs_read_word_data(client, REG_ADDR_MANUFACTURE_DATE); 645 + if (ret < 0) 646 + return ret; 647 + 648 + day = ret & GENMASK(4, 0); 649 + month = (ret & GENMASK(8, 5)) >> 5; 650 + year = ((ret & GENMASK(15, 9)) >> 9) + 1980; 651 + 652 + switch (psp) { 653 + case POWER_SUPPLY_PROP_MANUFACTURE_YEAR: 654 + val->intval = year; 655 + break; 656 + case POWER_SUPPLY_PROP_MANUFACTURE_MONTH: 657 + val->intval = month; 658 + break; 659 + case POWER_SUPPLY_PROP_MANUFACTURE_DAY: 660 + val->intval = day; 661 + break; 662 + default: 663 + return -EINVAL; 664 + } 665 + 666 + return 0; 667 + } 668 + 695 669 static int sbs_get_property(struct power_supply *psy, 696 670 enum power_supply_property psp, 697 671 union power_supply_propval *val) ··· 770 616 return ret; 771 617 if (psp == POWER_SUPPLY_PROP_PRESENT) { 772 618 val->intval = ret; 773 - chip->is_present = val->intval; 619 + sbs_update_presence(chip, ret); 774 620 return 0; 775 621 } 776 622 if (ret == 0) ··· 780 626 switch (psp) { 781 627 case POWER_SUPPLY_PROP_PRESENT: 782 628 case POWER_SUPPLY_PROP_HEALTH: 783 - if (chip->flags & SBS_FLAGS_TI_BQ20Z75) 629 + if (chip->flags & SBS_FLAGS_TI_BQ20ZX5) 784 630 ret = sbs_get_ti_battery_presence_and_health(client, 785 631 psp, val); 786 632 else ··· 793 639 break; 794 640 795 641 case POWER_SUPPLY_PROP_TECHNOLOGY: 796 - val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 642 + ret = sbs_get_chemistry(client, val); 643 + if (ret < 0) 644 + break; 645 + 797 646 goto done; /* don't trigger power_supply_changed()! */ 798 647 799 648 case POWER_SUPPLY_PROP_ENERGY_NOW: ··· 827 670 case POWER_SUPPLY_PROP_CYCLE_COUNT: 828 671 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 829 672 case POWER_SUPPLY_PROP_CURRENT_NOW: 673 + case POWER_SUPPLY_PROP_CURRENT_AVG: 830 674 case POWER_SUPPLY_PROP_TEMP: 831 675 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: 832 676 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: 833 677 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 834 678 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 679 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 680 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 835 681 case POWER_SUPPLY_PROP_CAPACITY: 682 + case POWER_SUPPLY_PROP_CAPACITY_ERROR_MARGIN: 836 683 ret = sbs_get_property_index(client, psp); 837 684 if (ret < 0) 838 685 break; ··· 864 703 val->strval = manufacturer; 865 704 break; 866 705 706 + case POWER_SUPPLY_PROP_MANUFACTURE_YEAR: 707 + case POWER_SUPPLY_PROP_MANUFACTURE_MONTH: 708 + case POWER_SUPPLY_PROP_MANUFACTURE_DAY: 709 + ret = sbs_get_battery_manufacture_date(client, psp, val); 710 + break; 711 + 867 712 default: 868 713 dev_err(&client->dev, 869 714 "%s: INVALID property\n", __func__); ··· 881 714 882 715 if (!chip->gpio_detect && 883 716 chip->is_present != (ret >= 0)) { 884 - chip->is_present = (ret >= 0); 717 + sbs_update_presence(chip, (ret >= 0)); 885 718 power_supply_changed(chip->power_supply); 886 719 } 887 720 ··· 912 745 ret = gpiod_get_value_cansleep(chip->gpio_detect); 913 746 if (ret < 0) 914 747 return; 915 - chip->is_present = ret; 748 + sbs_update_presence(chip, ret); 916 749 power_supply_changed(battery); 917 750 } 918 751 ··· 982 815 .external_power_changed = sbs_external_power_changed, 983 816 }; 984 817 985 - static int sbs_probe(struct i2c_client *client, 986 - const struct i2c_device_id *id) 818 + static int sbs_probe(struct i2c_client *client) 987 819 { 988 820 struct sbs_info *chip; 989 821 struct power_supply_desc *sbs_desc; ··· 1005 839 if (!chip) 1006 840 return -ENOMEM; 1007 841 1008 - chip->flags = (u32)(uintptr_t)of_device_get_match_data(&client->dev); 842 + chip->flags = (u32)(uintptr_t)device_get_match_data(&client->dev); 1009 843 chip->client = client; 1010 844 chip->enable_detection = false; 1011 845 psy_cfg.of_node = client->dev.of_node; ··· 1016 850 /* use pdata if available, fall back to DT properties, 1017 851 * or hardcoded defaults if not 1018 852 */ 1019 - rc = of_property_read_u32(client->dev.of_node, "sbs,i2c-retry-count", 1020 - &chip->i2c_retry_count); 853 + rc = device_property_read_u32(&client->dev, "sbs,i2c-retry-count", 854 + &chip->i2c_retry_count); 1021 855 if (rc) 1022 856 chip->i2c_retry_count = 0; 1023 857 1024 - rc = of_property_read_u32(client->dev.of_node, "sbs,poll-retry-count", 1025 - &chip->poll_retry_count); 858 + rc = device_property_read_u32(&client->dev, "sbs,poll-retry-count", 859 + &chip->poll_retry_count); 1026 860 if (rc) 1027 861 chip->poll_retry_count = 0; 1028 862 ··· 1031 865 chip->i2c_retry_count = pdata->i2c_retry_count; 1032 866 } 1033 867 chip->i2c_retry_count = chip->i2c_retry_count + 1; 868 + 869 + chip->charger_broadcasts = !device_property_read_bool(&client->dev, 870 + "sbs,disable-charger-broadcasts"); 1034 871 1035 872 chip->gpio_detect = devm_gpiod_get_optional(&client->dev, 1036 873 "sbs,battery-detect", GPIOD_IN); ··· 1119 950 if (chip->poll_time > 0) 1120 951 cancel_delayed_work_sync(&chip->work); 1121 952 1122 - if (chip->flags & SBS_FLAGS_TI_BQ20Z75) { 953 + if (chip->flags & SBS_FLAGS_TI_BQ20ZX5) { 1123 954 /* Write to manufacturer access with sleep command. */ 1124 955 ret = sbs_write_word_data(client, 1125 956 sbs_data[REG_MANUFACTURER_DATA].addr, ··· 1139 970 #endif 1140 971 1141 972 static const struct i2c_device_id sbs_id[] = { 973 + { "bq20z65", 0 }, 1142 974 { "bq20z75", 0 }, 1143 975 { "sbs-battery", 1 }, 1144 976 {} ··· 1149 979 static const struct of_device_id sbs_dt_ids[] = { 1150 980 { .compatible = "sbs,sbs-battery" }, 1151 981 { 982 + .compatible = "ti,bq20z65", 983 + .data = (void *)SBS_FLAGS_TI_BQ20ZX5, 984 + }, 985 + { 1152 986 .compatible = "ti,bq20z75", 1153 - .data = (void *)SBS_FLAGS_TI_BQ20Z75, 987 + .data = (void *)SBS_FLAGS_TI_BQ20ZX5, 1154 988 }, 1155 989 { } 1156 990 }; 1157 991 MODULE_DEVICE_TABLE(of, sbs_dt_ids); 1158 992 1159 993 static struct i2c_driver sbs_battery_driver = { 1160 - .probe = sbs_probe, 994 + .probe_new = sbs_probe, 1161 995 .remove = sbs_remove, 1162 996 .alert = sbs_alert, 1163 997 .id_table = sbs_id,
+74 -3
drivers/power/supply/sc27xx_fuel_gauge.c
··· 42 42 #define SC27XX_FGU_USER_AREA_SET 0xa0 43 43 #define SC27XX_FGU_USER_AREA_CLEAR 0xa4 44 44 #define SC27XX_FGU_USER_AREA_STATUS 0xa8 45 + #define SC27XX_FGU_VOLTAGE_BUF 0xd0 46 + #define SC27XX_FGU_CURRENT_BUF 0xf0 45 47 46 48 #define SC27XX_WRITE_SELCLB_EN BIT(0) 47 49 #define SC27XX_FGU_CLBCNT_MASK GENMASK(15, 0) ··· 84 82 * @init_clbcnt: the initial coulomb counter 85 83 * @max_volt: the maximum constant input voltage in millivolt 86 84 * @min_volt: the minimum drained battery voltage in microvolt 85 + * @boot_volt: the voltage measured during boot in microvolt 87 86 * @table_len: the capacity table length 88 87 * @resist_table_len: the resistance table length 89 88 * @cur_1000ma_adc: ADC value corresponding to 1000 mA ··· 110 107 int init_clbcnt; 111 108 int max_volt; 112 109 int min_volt; 110 + int boot_volt; 113 111 int table_len; 114 112 int resist_table_len; 115 113 int cur_1000ma_adc; ··· 323 319 324 320 volt = sc27xx_fgu_adc_to_voltage(data, volt); 325 321 ocv = volt * 1000 - oci * data->internal_resist; 322 + data->boot_volt = ocv; 326 323 327 324 /* 328 325 * Parse the capacity table to look up the correct capacity percent ··· 377 372 378 373 *clb_cnt = ccl & SC27XX_FGU_CLBCNT_MASK; 379 374 *clb_cnt |= (cch & SC27XX_FGU_CLBCNT_MASK) << SC27XX_FGU_CLBCNT_SHIFT; 375 + 376 + return 0; 377 + } 378 + 379 + static int sc27xx_fgu_get_vol_now(struct sc27xx_fgu_data *data, int *val) 380 + { 381 + int ret; 382 + u32 vol; 383 + 384 + ret = regmap_read(data->regmap, data->base + SC27XX_FGU_VOLTAGE_BUF, 385 + &vol); 386 + if (ret) 387 + return ret; 388 + 389 + /* 390 + * It is ADC values reading from registers which need to convert to 391 + * corresponding voltage values. 392 + */ 393 + *val = sc27xx_fgu_adc_to_voltage(data, vol); 394 + 395 + return 0; 396 + } 397 + 398 + static int sc27xx_fgu_get_cur_now(struct sc27xx_fgu_data *data, int *val) 399 + { 400 + int ret; 401 + u32 cur; 402 + 403 + ret = regmap_read(data->regmap, data->base + SC27XX_FGU_CURRENT_BUF, 404 + &cur); 405 + if (ret) 406 + return ret; 407 + 408 + /* 409 + * It is ADC values reading from registers which need to convert to 410 + * corresponding current values. 411 + */ 412 + *val = sc27xx_fgu_adc_to_current(data, cur - SC27XX_FGU_CUR_BASIC_ADC); 380 413 381 414 return 0; 382 415 } ··· 620 577 val->intval = value; 621 578 break; 622 579 623 - case POWER_SUPPLY_PROP_VOLTAGE_NOW: 580 + case POWER_SUPPLY_PROP_VOLTAGE_AVG: 624 581 ret = sc27xx_fgu_get_vbat_vol(data, &value); 625 582 if (ret) 626 583 goto error; ··· 644 601 val->intval = value; 645 602 break; 646 603 647 - case POWER_SUPPLY_PROP_CURRENT_NOW: 648 604 case POWER_SUPPLY_PROP_CURRENT_AVG: 649 605 ret = sc27xx_fgu_get_current(data, &value); 650 606 if (ret) ··· 665 623 36 * SC27XX_FGU_SAMPLE_HZ); 666 624 val->intval = sc27xx_fgu_adc_to_current(data, value); 667 625 626 + break; 627 + 628 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 629 + ret = sc27xx_fgu_get_vol_now(data, &value); 630 + if (ret) 631 + goto error; 632 + 633 + val->intval = value * 1000; 634 + break; 635 + 636 + case POWER_SUPPLY_PROP_CURRENT_NOW: 637 + ret = sc27xx_fgu_get_cur_now(data, &value); 638 + if (ret) 639 + goto error; 640 + 641 + val->intval = value * 1000; 642 + break; 643 + 644 + case POWER_SUPPLY_PROP_VOLTAGE_BOOT: 645 + val->intval = data->boot_volt; 668 646 break; 669 647 670 648 default: ··· 718 656 ret = 0; 719 657 break; 720 658 659 + case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: 660 + data->total_cap = val->intval / 1000; 661 + ret = 0; 662 + break; 663 + 721 664 default: 722 665 ret = -EINVAL; 723 666 } ··· 743 676 enum power_supply_property psp) 744 677 { 745 678 return psp == POWER_SUPPLY_PROP_CAPACITY || 746 - psp == POWER_SUPPLY_PROP_CALIBRATE; 679 + psp == POWER_SUPPLY_PROP_CALIBRATE || 680 + psp == POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; 747 681 } 748 682 749 683 static enum power_supply_property sc27xx_fgu_props[] = { ··· 756 688 POWER_SUPPLY_PROP_CAPACITY, 757 689 POWER_SUPPLY_PROP_VOLTAGE_NOW, 758 690 POWER_SUPPLY_PROP_VOLTAGE_OCV, 691 + POWER_SUPPLY_PROP_VOLTAGE_AVG, 692 + POWER_SUPPLY_PROP_VOLTAGE_BOOT, 759 693 POWER_SUPPLY_PROP_CURRENT_NOW, 760 694 POWER_SUPPLY_PROP_CURRENT_AVG, 761 695 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, ··· 775 705 .set_property = sc27xx_fgu_set_property, 776 706 .external_power_changed = sc27xx_fgu_external_power_changed, 777 707 .property_is_writeable = sc27xx_fgu_property_is_writeable, 708 + .no_thermal = true, 778 709 }; 779 710 780 711 static void sc27xx_fgu_adjust_cap(struct sc27xx_fgu_data *data, int cap)
+5
drivers/power/supply/smb347-charger.c
··· 8 8 * Mika Westerberg <mika.westerberg@linux.intel.com> 9 9 */ 10 10 11 + #include <linux/delay.h> 11 12 #include <linux/err.h> 12 13 #include <linux/gpio.h> 13 14 #include <linux/kernel.h> ··· 709 708 bool handled = false; 710 709 int ret; 711 710 711 + /* SMB347 it needs at least 20ms for setting IRQSTAT_E_*IN_UV_IRQ */ 712 + usleep_range(25000, 35000); 713 + 712 714 ret = regmap_read(smb->regmap, STAT_C, &stat_c); 713 715 if (ret < 0) { 714 716 dev_warn(smb->dev, "reading STAT_C failed\n"); ··· 1142 1138 switch (reg) { 1143 1139 case IRQSTAT_A: 1144 1140 case IRQSTAT_C: 1141 + case IRQSTAT_D: 1145 1142 case IRQSTAT_E: 1146 1143 case IRQSTAT_F: 1147 1144 case STAT_A:
+1 -1
include/linux/kobject.h
··· 29 29 #include <linux/uidgid.h> 30 30 31 31 #define UEVENT_HELPER_PATH_LEN 256 32 - #define UEVENT_NUM_ENVP 32 /* number of env pointers */ 32 + #define UEVENT_NUM_ENVP 64 /* number of env pointers */ 33 33 #define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */ 34 34 35 35 #ifdef CONFIG_UEVENT_HELPER
+11 -2
include/linux/power_supply.h
··· 61 61 POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE, 62 62 POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE, 63 63 POWER_SUPPLY_HEALTH_OVERCURRENT, 64 + POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED, 64 65 }; 65 66 66 67 enum { ··· 140 139 POWER_SUPPLY_PROP_CAPACITY, /* in percents! */ 141 140 POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN, /* in percents! */ 142 141 POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX, /* in percents! */ 142 + POWER_SUPPLY_PROP_CAPACITY_ERROR_MARGIN, /* in percents! */ 143 143 POWER_SUPPLY_PROP_CAPACITY_LEVEL, 144 144 POWER_SUPPLY_PROP_TEMP, 145 145 POWER_SUPPLY_PROP_TEMP_MAX, ··· 160 158 POWER_SUPPLY_PROP_PRECHARGE_CURRENT, 161 159 POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, 162 160 POWER_SUPPLY_PROP_CALIBRATE, 161 + POWER_SUPPLY_PROP_MANUFACTURE_YEAR, 162 + POWER_SUPPLY_PROP_MANUFACTURE_MONTH, 163 + POWER_SUPPLY_PROP_MANUFACTURE_DAY, 163 164 /* Properties of type `const char *' */ 164 165 POWER_SUPPLY_PROP_MODEL_NAME, 165 166 POWER_SUPPLY_PROP_MANUFACTURER, ··· 228 223 struct power_supply_desc { 229 224 const char *name; 230 225 enum power_supply_type type; 231 - enum power_supply_usb_type *usb_types; 226 + const enum power_supply_usb_type *usb_types; 232 227 size_t num_usb_types; 233 - enum power_supply_property *properties; 228 + const enum power_supply_property *properties; 234 229 size_t num_properties; 235 230 236 231 /* ··· 351 346 int charge_full_design_uah; /* microAmp-hours */ 352 347 int voltage_min_design_uv; /* microVolts */ 353 348 int voltage_max_design_uv; /* microVolts */ 349 + int tricklecharge_current_ua; /* microAmps */ 354 350 int precharge_current_ua; /* microAmps */ 351 + int precharge_voltage_max_uv; /* microVolts */ 355 352 int charge_term_current_ua; /* microAmps */ 353 + int charge_restart_voltage_uv; /* microVolts */ 354 + int overvoltage_limit_uv; /* microVolts */ 356 355 int constant_charge_current_max_ua; /* microAmps */ 357 356 int constant_charge_voltage_max_uv; /* microVolts */ 358 357 int factory_internal_resistance_uohm; /* microOhms */