* [PATCH v1 0/2] power: supply: Add support for Maxim MAX8971 charger @ 2025-02-21 9:59 Svyatoslav Ryhel 2025-02-21 9:59 ` [PATCH v1 1/2] dt-bindings: power: supply: Document " Svyatoslav Ryhel 2025-02-21 9:59 ` [PATCH v1 2/2] power: supply: Add support for " Svyatoslav Ryhel 0 siblings, 2 replies; 9+ messages in thread From: Svyatoslav Ryhel @ 2025-02-21 9:59 UTC (permalink / raw) To: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Svyatoslav Ryhel Cc: linux-pm, devicetree, linux-kernel The MAX8971 is a compact, high-frequency, high-efficiency switch-mode charger for a one-cell lithium-ion (Li+) battery. Svyatoslav Ryhel (2): dt-bindings: power: supply: Document Maxim MAX8971 charger power: supply: Add support for Maxim MAX8971 charger .../bindings/power/supply/maxim,max8971.yaml | 133 ++++ drivers/power/supply/Kconfig | 14 + drivers/power/supply/Makefile | 1 + drivers/power/supply/max8971_charger.c | 685 ++++++++++++++++++ 4 files changed, 833 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml create mode 100644 drivers/power/supply/max8971_charger.c -- 2.43.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v1 1/2] dt-bindings: power: supply: Document Maxim MAX8971 charger 2025-02-21 9:59 [PATCH v1 0/2] power: supply: Add support for Maxim MAX8971 charger Svyatoslav Ryhel @ 2025-02-21 9:59 ` Svyatoslav Ryhel 2025-02-23 11:43 ` Krzysztof Kozlowski 2025-02-21 9:59 ` [PATCH v1 2/2] power: supply: Add support for " Svyatoslav Ryhel 1 sibling, 1 reply; 9+ messages in thread From: Svyatoslav Ryhel @ 2025-02-21 9:59 UTC (permalink / raw) To: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Svyatoslav Ryhel Cc: linux-pm, devicetree, linux-kernel Add bindings for Maxim MAX8971 charger. Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com> --- .../bindings/power/supply/maxim,max8971.yaml | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml diff --git a/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml b/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml new file mode 100644 index 000000000000..26b37e6f662f --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml @@ -0,0 +1,133 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/supply/maxim,max8971.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX8971 IC charger + +maintainers: + - Svyatoslav Ryhel <clamor95@gmail.com> + +description: + The MAX8971 is a compact, high-frequency, high-efficiency switch-mode + charger for a one-cell lithium-ion (Li+) battery. + +properties: + compatible: + const: maxim,max8971 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + extcon: + description: + Special device used to detect type of plug. + $ref: /schemas/types.yaml#/definitions/phandle + + maxim,fcharge-current-limit-microamp: + description: + Fast-Charge current limit + minimum: 250000 + default: 500000 + maximum: 1550000 + + maxim,fcharge-timer-hours: + description: | + Fast-Charge timer in hours. Setting this value 3 and lower or 11 and + higher will disable Fast-Charge timer. + $ref: /schemas/types.yaml#/definitions/uint32 + default: 5 + + maxim,fcharge-rst-threshold-high: + description: + Set Fast-Charge reset threshold to -100 mV + type: boolean + + maxim,in-current-limit-microamp: + description: + Input current limit + minimum: 100000 + default: 500000 + maximum: 1500000 + + maxim,topoff-timer-minutes: + description: + Top-Off timer minutes + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 10, 20, 30, 40, 50, 60, 70] + default: 30 + + maxim,topoff-current-threshold-microamp: + description: + Top-Off current threshold + enum: [50000, 100000, 150000, 200000] + default: 50000 + + maxim,fcharge-usb-current-limit-microamp: + description: + Fast-Charge USB current limit + minimum: 100000 + default: 500000 + maximum: 1500000 + + maxim,fcharge-ac-current-limit-microamp: + description: + Fast-Charge AC current limit + minimum: 100000 + default: 500000 + maximum: 1500000 + + maxim,usb-in-current-limit-microamp: + description: + USB Input current limit + minimum: 100000 + default: 500000 + maximum: 1500000 + + maxim,ac-in-current-limit-microamp: + description: + AC Input current limit + minimum: 100000 + default: 500000 + maximum: 1500000 + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + charger@35 { + compatible = "maxim,max8971"; + reg = <0x35>; + + interrupt-parent = <&gpio>; + interrupts = <74 IRQ_TYPE_LEVEL_LOW>; + + maxim,fcharge-ac-current-limit-microamp = <900000>; + maxim,fcharge-timer-hours = <0>; + + maxim,fcharge-rst-threshold-high; + maxim,ac-in-current-limit-microamp = <1200000>; + + maxim,topoff-timer-minutes = <0>; + maxim,topoff-current-threshold-microamp = <200000>; + + extcon = <&extcon>; + }; + }; +... -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v1 1/2] dt-bindings: power: supply: Document Maxim MAX8971 charger 2025-02-21 9:59 ` [PATCH v1 1/2] dt-bindings: power: supply: Document " Svyatoslav Ryhel @ 2025-02-23 11:43 ` Krzysztof Kozlowski 2025-02-23 11:56 ` Svyatoslav Ryhel 0 siblings, 1 reply; 9+ messages in thread From: Krzysztof Kozlowski @ 2025-02-23 11:43 UTC (permalink / raw) To: Svyatoslav Ryhel Cc: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-pm, devicetree, linux-kernel On Fri, Feb 21, 2025 at 11:59:42AM +0200, Svyatoslav Ryhel wrote: > Add bindings for Maxim MAX8971 charger. > > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com> > --- > .../bindings/power/supply/maxim,max8971.yaml | 133 ++++++++++++++++++ > 1 file changed, 133 insertions(+) > create mode 100644 Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml > > diff --git a/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml b/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml > new file mode 100644 > index 000000000000..26b37e6f662f > --- /dev/null > +++ b/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml > @@ -0,0 +1,133 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/power/supply/maxim,max8971.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Maxim MAX8971 IC charger > + > +maintainers: > + - Svyatoslav Ryhel <clamor95@gmail.com> > + > +description: > + The MAX8971 is a compact, high-frequency, high-efficiency switch-mode > + charger for a one-cell lithium-ion (Li+) battery. > + > +properties: > + compatible: > + const: maxim,max8971 > + > + reg: > + maxItems: 1 > + > + interrupts: > + maxItems: 1 > + > + extcon: > + description: > + Special device used to detect type of plug. > + $ref: /schemas/types.yaml#/definitions/phandle You rather miss proper connector or ports. Which device pins are describbed here? > + > + maxim,fcharge-current-limit-microamp: > + description: > + Fast-Charge current limit > + minimum: 250000 > + default: 500000 > + maximum: 1550000 > + > + maxim,fcharge-timer-hours: > + description: | > + Fast-Charge timer in hours. Setting this value 3 and lower or 11 and > + higher will disable Fast-Charge timer. > + $ref: /schemas/types.yaml#/definitions/uint32 > + default: 5 > + > + maxim,fcharge-rst-threshold-high: > + description: > + Set Fast-Charge reset threshold to -100 mV > + type: boolean > + > + maxim,in-current-limit-microamp: > + description: > + Input current limit > + minimum: 100000 > + default: 500000 > + maximum: 1500000 > + > + maxim,topoff-timer-minutes: > + description: > + Top-Off timer minutes > + $ref: /schemas/types.yaml#/definitions/uint32 > + enum: [0, 10, 20, 30, 40, 50, 60, 70] > + default: 30 > + > + maxim,topoff-current-threshold-microamp: > + description: > + Top-Off current threshold > + enum: [50000, 100000, 150000, 200000] > + default: 50000 > + > + maxim,fcharge-usb-current-limit-microamp: > + description: > + Fast-Charge USB current limit > + minimum: 100000 > + default: 500000 > + maximum: 1500000 > + > + maxim,fcharge-ac-current-limit-microamp: > + description: > + Fast-Charge AC current limit > + minimum: 100000 > + default: 500000 > + maximum: 1500000 > + > + maxim,usb-in-current-limit-microamp: > + description: > + USB Input current limit > + minimum: 100000 > + default: 500000 > + maximum: 1500000 > + > + maxim,ac-in-current-limit-microamp: > + description: > + AC Input current limit > + minimum: 100000 > + default: 500000 > + maximum: 1500000 For all or most of these you miss monitored batter. > + > +required: > + - compatible > + - reg > + - interrupts > + Missing allOf with ref to power supply. > +additionalProperties: false unevaluatedProperties instead, see other bindings. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 1/2] dt-bindings: power: supply: Document Maxim MAX8971 charger 2025-02-23 11:43 ` Krzysztof Kozlowski @ 2025-02-23 11:56 ` Svyatoslav Ryhel 2025-02-23 14:14 ` Krzysztof Kozlowski 0 siblings, 1 reply; 9+ messages in thread From: Svyatoslav Ryhel @ 2025-02-23 11:56 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-pm, devicetree, linux-kernel нд, 23 лют. 2025 р. о 13:43 Krzysztof Kozlowski <krzk@kernel.org> пише: > > On Fri, Feb 21, 2025 at 11:59:42AM +0200, Svyatoslav Ryhel wrote: > > Add bindings for Maxim MAX8971 charger. > > > > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com> > > --- > > .../bindings/power/supply/maxim,max8971.yaml | 133 ++++++++++++++++++ > > 1 file changed, 133 insertions(+) > > create mode 100644 Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml > > > > diff --git a/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml b/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml > > new file mode 100644 > > index 000000000000..26b37e6f662f > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml > > @@ -0,0 +1,133 @@ > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > > +%YAML 1.2 > > +--- > > +$id: http://devicetree.org/schemas/power/supply/maxim,max8971.yaml# > > +$schema: http://devicetree.org/meta-schemas/core.yaml# > > + > > +title: Maxim MAX8971 IC charger > > + > > +maintainers: > > + - Svyatoslav Ryhel <clamor95@gmail.com> > > + > > +description: > > + The MAX8971 is a compact, high-frequency, high-efficiency switch-mode > > + charger for a one-cell lithium-ion (Li+) battery. > > + > > +properties: > > + compatible: > > + const: maxim,max8971 > > + > > + reg: > > + maxItems: 1 > > + > > + interrupts: > > + maxItems: 1 > > + > > + extcon: > > + description: > > + Special device used to detect type of plug. > > + $ref: /schemas/types.yaml#/definitions/phandle > > You rather miss proper connector or ports. Which device pins are > describbed here? > This is an optional phandle to extcon, which can detect plug type. If extcon is provided, charger then can change its setup to better provide supply to the battery. If no extcon is provided, device itself can detect only the fact of charger without details about type. > > > + > > + maxim,fcharge-current-limit-microamp: > > + description: > > + Fast-Charge current limit > > + minimum: 250000 > > + default: 500000 > > + maximum: 1550000 > > + > > + maxim,fcharge-timer-hours: > > + description: | > > + Fast-Charge timer in hours. Setting this value 3 and lower or 11 and > > + higher will disable Fast-Charge timer. > > + $ref: /schemas/types.yaml#/definitions/uint32 > > + default: 5 > > + > > + maxim,fcharge-rst-threshold-high: > > + description: > > + Set Fast-Charge reset threshold to -100 mV > > + type: boolean > > + > > + maxim,in-current-limit-microamp: > > + description: > > + Input current limit > > + minimum: 100000 > > + default: 500000 > > + maximum: 1500000 > > + > > + maxim,topoff-timer-minutes: > > + description: > > + Top-Off timer minutes > > + $ref: /schemas/types.yaml#/definitions/uint32 > > + enum: [0, 10, 20, 30, 40, 50, 60, 70] > > + default: 30 > > + > > + maxim,topoff-current-threshold-microamp: > > + description: > > + Top-Off current threshold > > + enum: [50000, 100000, 150000, 200000] > > + default: 50000 > > + > > + maxim,fcharge-usb-current-limit-microamp: > > + description: > > + Fast-Charge USB current limit > > + minimum: 100000 > > + default: 500000 > > + maximum: 1500000 > > + > > + maxim,fcharge-ac-current-limit-microamp: > > + description: > > + Fast-Charge AC current limit > > + minimum: 100000 > > + default: 500000 > > + maximum: 1500000 > > + > > + maxim,usb-in-current-limit-microamp: > > + description: > > + USB Input current limit > > + minimum: 100000 > > + default: 500000 > > + maximum: 1500000 > > + > > + maxim,ac-in-current-limit-microamp: > > + description: > > + AC Input current limit > > + minimum: 100000 > > + default: 500000 > > + maximum: 1500000 > > For all or most of these you miss monitored batter. > This is a charger, it does not monitor battery. There is a fuel gauge for that or a battery monitor. > > + > > +required: > > + - compatible > > + - reg > > + - interrupts > > + > > Missing allOf with ref to power supply. > > > +additionalProperties: false > > unevaluatedProperties instead, see other bindings. > > Best regards, > Krzysztof > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 1/2] dt-bindings: power: supply: Document Maxim MAX8971 charger 2025-02-23 11:56 ` Svyatoslav Ryhel @ 2025-02-23 14:14 ` Krzysztof Kozlowski 2025-02-23 14:28 ` Svyatoslav Ryhel 0 siblings, 1 reply; 9+ messages in thread From: Krzysztof Kozlowski @ 2025-02-23 14:14 UTC (permalink / raw) To: Svyatoslav Ryhel Cc: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-pm, devicetree, linux-kernel On 23/02/2025 12:56, Svyatoslav Ryhel wrote: > нд, 23 лют. 2025 р. о 13:43 Krzysztof Kozlowski <krzk@kernel.org> пише: >> >> On Fri, Feb 21, 2025 at 11:59:42AM +0200, Svyatoslav Ryhel wrote: >>> Add bindings for Maxim MAX8971 charger. >>> >>> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com> >>> --- >>> .../bindings/power/supply/maxim,max8971.yaml | 133 ++++++++++++++++++ >>> 1 file changed, 133 insertions(+) >>> create mode 100644 Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml >>> >>> diff --git a/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml b/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml >>> new file mode 100644 >>> index 000000000000..26b37e6f662f >>> --- /dev/null >>> +++ b/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml >>> @@ -0,0 +1,133 @@ >>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) >>> +%YAML 1.2 >>> +--- >>> +$id: http://devicetree.org/schemas/power/supply/maxim,max8971.yaml# >>> +$schema: http://devicetree.org/meta-schemas/core.yaml# >>> + >>> +title: Maxim MAX8971 IC charger >>> + >>> +maintainers: >>> + - Svyatoslav Ryhel <clamor95@gmail.com> >>> + >>> +description: >>> + The MAX8971 is a compact, high-frequency, high-efficiency switch-mode >>> + charger for a one-cell lithium-ion (Li+) battery. >>> + >>> +properties: >>> + compatible: >>> + const: maxim,max8971 >>> + >>> + reg: >>> + maxItems: 1 >>> + >>> + interrupts: >>> + maxItems: 1 >>> + >>> + extcon: >>> + description: >>> + Special device used to detect type of plug. >>> + $ref: /schemas/types.yaml#/definitions/phandle >> >> You rather miss proper connector or ports. Which device pins are >> describbed here? >> > > This is an optional phandle to extcon, which can detect plug type. If I know what is this, you just wrote. extcon property is not allowed anymore. > extcon is provided, charger then can change its setup to better > provide supply to the battery. If no extcon is provided, device itself > can detect only the fact of charger without details about type. > >> >>> + >>> + maxim,fcharge-current-limit-microamp: >>> + description: >>> + Fast-Charge current limit >>> + minimum: 250000 >>> + default: 500000 >>> + maximum: 1550000 >>> + >>> + maxim,fcharge-timer-hours: >>> + description: | >>> + Fast-Charge timer in hours. Setting this value 3 and lower or 11 and >>> + higher will disable Fast-Charge timer. >>> + $ref: /schemas/types.yaml#/definitions/uint32 >>> + default: 5 >>> + >>> + maxim,fcharge-rst-threshold-high: >>> + description: >>> + Set Fast-Charge reset threshold to -100 mV >>> + type: boolean >>> + >>> + maxim,in-current-limit-microamp: >>> + description: >>> + Input current limit >>> + minimum: 100000 >>> + default: 500000 >>> + maximum: 1500000 >>> + >>> + maxim,topoff-timer-minutes: >>> + description: >>> + Top-Off timer minutes >>> + $ref: /schemas/types.yaml#/definitions/uint32 >>> + enum: [0, 10, 20, 30, 40, 50, 60, 70] >>> + default: 30 >>> + >>> + maxim,topoff-current-threshold-microamp: >>> + description: >>> + Top-Off current threshold >>> + enum: [50000, 100000, 150000, 200000] >>> + default: 50000 >>> + >>> + maxim,fcharge-usb-current-limit-microamp: >>> + description: >>> + Fast-Charge USB current limit >>> + minimum: 100000 >>> + default: 500000 >>> + maximum: 1500000 >>> + >>> + maxim,fcharge-ac-current-limit-microamp: >>> + description: >>> + Fast-Charge AC current limit >>> + minimum: 100000 >>> + default: 500000 >>> + maximum: 1500000 >>> + >>> + maxim,usb-in-current-limit-microamp: >>> + description: >>> + USB Input current limit >>> + minimum: 100000 >>> + default: 500000 >>> + maximum: 1500000 >>> + >>> + maxim,ac-in-current-limit-microamp: >>> + description: >>> + AC Input current limit >>> + minimum: 100000 >>> + default: 500000 >>> + maximum: 1500000 >> >> For all or most of these you miss monitored batter. >> > > This is a charger, it does not monitor battery. There is a fuel gauge > for that or a battery monitor. > What does charger charge? Battery or something else? Best regards, Krzysztof ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 1/2] dt-bindings: power: supply: Document Maxim MAX8971 charger 2025-02-23 14:14 ` Krzysztof Kozlowski @ 2025-02-23 14:28 ` Svyatoslav Ryhel 2025-02-24 8:23 ` Krzysztof Kozlowski 0 siblings, 1 reply; 9+ messages in thread From: Svyatoslav Ryhel @ 2025-02-23 14:28 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-pm, devicetree, linux-kernel нд, 23 лют. 2025 р. о 16:14 Krzysztof Kozlowski <krzk@kernel.org> пише: > > On 23/02/2025 12:56, Svyatoslav Ryhel wrote: > > нд, 23 лют. 2025 р. о 13:43 Krzysztof Kozlowski <krzk@kernel.org> пише: > >> > >> On Fri, Feb 21, 2025 at 11:59:42AM +0200, Svyatoslav Ryhel wrote: > >>> Add bindings for Maxim MAX8971 charger. > >>> > >>> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com> > >>> --- > >>> .../bindings/power/supply/maxim,max8971.yaml | 133 ++++++++++++++++++ > >>> 1 file changed, 133 insertions(+) > >>> create mode 100644 Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml > >>> > >>> diff --git a/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml b/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml > >>> new file mode 100644 > >>> index 000000000000..26b37e6f662f > >>> --- /dev/null > >>> +++ b/Documentation/devicetree/bindings/power/supply/maxim,max8971.yaml > >>> @@ -0,0 +1,133 @@ > >>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > >>> +%YAML 1.2 > >>> +--- > >>> +$id: http://devicetree.org/schemas/power/supply/maxim,max8971.yaml# > >>> +$schema: http://devicetree.org/meta-schemas/core.yaml# > >>> + > >>> +title: Maxim MAX8971 IC charger > >>> + > >>> +maintainers: > >>> + - Svyatoslav Ryhel <clamor95@gmail.com> > >>> + > >>> +description: > >>> + The MAX8971 is a compact, high-frequency, high-efficiency switch-mode > >>> + charger for a one-cell lithium-ion (Li+) battery. > >>> + > >>> +properties: > >>> + compatible: > >>> + const: maxim,max8971 > >>> + > >>> + reg: > >>> + maxItems: 1 > >>> + > >>> + interrupts: > >>> + maxItems: 1 > >>> + > >>> + extcon: > >>> + description: > >>> + Special device used to detect type of plug. > >>> + $ref: /schemas/types.yaml#/definitions/phandle > >> > >> You rather miss proper connector or ports. Which device pins are > >> describbed here? > >> > > > > This is an optional phandle to extcon, which can detect plug type. If > > I know what is this, you just wrote. extcon property is not allowed anymore. > There is no helper for obtaining extcon via graph endpoint I am aware of. Can you provide an example of graph parsing extcon helper? > > extcon is provided, charger then can change its setup to better > > provide supply to the battery. If no extcon is provided, device itself > > can detect only the fact of charger without details about type. > > > > > >> > >>> + > >>> + maxim,fcharge-current-limit-microamp: > >>> + description: > >>> + Fast-Charge current limit > >>> + minimum: 250000 > >>> + default: 500000 > >>> + maximum: 1550000 > >>> + > >>> + maxim,fcharge-timer-hours: > >>> + description: | > >>> + Fast-Charge timer in hours. Setting this value 3 and lower or 11 and > >>> + higher will disable Fast-Charge timer. > >>> + $ref: /schemas/types.yaml#/definitions/uint32 > >>> + default: 5 > >>> + > >>> + maxim,fcharge-rst-threshold-high: > >>> + description: > >>> + Set Fast-Charge reset threshold to -100 mV > >>> + type: boolean > >>> + > >>> + maxim,in-current-limit-microamp: > >>> + description: > >>> + Input current limit > >>> + minimum: 100000 > >>> + default: 500000 > >>> + maximum: 1500000 > >>> + > >>> + maxim,topoff-timer-minutes: > >>> + description: > >>> + Top-Off timer minutes > >>> + $ref: /schemas/types.yaml#/definitions/uint32 > >>> + enum: [0, 10, 20, 30, 40, 50, 60, 70] > >>> + default: 30 > >>> + > >>> + maxim,topoff-current-threshold-microamp: > >>> + description: > >>> + Top-Off current threshold > >>> + enum: [50000, 100000, 150000, 200000] > >>> + default: 50000 > >>> + > >>> + maxim,fcharge-usb-current-limit-microamp: > >>> + description: > >>> + Fast-Charge USB current limit > >>> + minimum: 100000 > >>> + default: 500000 > >>> + maximum: 1500000 > >>> + > >>> + maxim,fcharge-ac-current-limit-microamp: > >>> + description: > >>> + Fast-Charge AC current limit > >>> + minimum: 100000 > >>> + default: 500000 > >>> + maximum: 1500000 > >>> + > >>> + maxim,usb-in-current-limit-microamp: > >>> + description: > >>> + USB Input current limit > >>> + minimum: 100000 > >>> + default: 500000 > >>> + maximum: 1500000 > >>> + > >>> + maxim,ac-in-current-limit-microamp: > >>> + description: > >>> + AC Input current limit > >>> + minimum: 100000 > >>> + default: 500000 > >>> + maximum: 1500000 > >> > >> For all or most of these you miss monitored batter. > >> > > > > This is a charger, it does not monitor battery. There is a fuel gauge > > for that or a battery monitor. > > > What does charger charge? Battery or something else? > Anything it is linked to. Moreover ref to power supply is not needed since properties from there are not relevant to this driver. monitored-battery refers to a simple battery cell, which has nothing to do with charger and power-supplies is irrelevant since this device is on its own a power-supplies for battery/fuel gauge. > Best regards, > Krzysztof ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 1/2] dt-bindings: power: supply: Document Maxim MAX8971 charger 2025-02-23 14:28 ` Svyatoslav Ryhel @ 2025-02-24 8:23 ` Krzysztof Kozlowski 2025-02-24 8:28 ` Svyatoslav Ryhel 0 siblings, 1 reply; 9+ messages in thread From: Krzysztof Kozlowski @ 2025-02-24 8:23 UTC (permalink / raw) To: Svyatoslav Ryhel Cc: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-pm, devicetree, linux-kernel On 23/02/2025 15:28, Svyatoslav Ryhel wrote: >>>>> + extcon: >>>>> + description: >>>>> + Special device used to detect type of plug. >>>>> + $ref: /schemas/types.yaml#/definitions/phandle >>>> >>>> You rather miss proper connector or ports. Which device pins are >>>> describbed here? >>>> >>> >>> This is an optional phandle to extcon, which can detect plug type. If >> >> I know what is this, you just wrote. extcon property is not allowed anymore. >> > > There is no helper for obtaining extcon via graph endpoint I am aware > of. Can you provide an example of graph parsing extcon helper? Most of recent drivers have the same problem and they solved it somehow without introducing 'extcon' property. > >>> extcon is provided, charger then can change its setup to better >>> provide supply to the battery. If no extcon is provided, device itself >>> can detect only the fact of charger without details about type. >> >> >>> >>>> >>>>> + >>>>> + maxim,fcharge-current-limit-microamp: >>>>> + description: >>>>> + Fast-Charge current limit >>>>> + minimum: 250000 >>>>> + default: 500000 >>>>> + maximum: 1550000 >>>>> + >>>>> + maxim,fcharge-timer-hours: >>>>> + description: | >>>>> + Fast-Charge timer in hours. Setting this value 3 and lower or 11 and >>>>> + higher will disable Fast-Charge timer. >>>>> + $ref: /schemas/types.yaml#/definitions/uint32 >>>>> + default: 5 >>>>> + >>>>> + maxim,fcharge-rst-threshold-high: >>>>> + description: >>>>> + Set Fast-Charge reset threshold to -100 mV >>>>> + type: boolean >>>>> + >>>>> + maxim,in-current-limit-microamp: >>>>> + description: >>>>> + Input current limit >>>>> + minimum: 100000 >>>>> + default: 500000 >>>>> + maximum: 1500000 >>>>> + >>>>> + maxim,topoff-timer-minutes: >>>>> + description: >>>>> + Top-Off timer minutes >>>>> + $ref: /schemas/types.yaml#/definitions/uint32 >>>>> + enum: [0, 10, 20, 30, 40, 50, 60, 70] >>>>> + default: 30 >>>>> + >>>>> + maxim,topoff-current-threshold-microamp: >>>>> + description: >>>>> + Top-Off current threshold >>>>> + enum: [50000, 100000, 150000, 200000] >>>>> + default: 50000 >>>>> + >>>>> + maxim,fcharge-usb-current-limit-microamp: >>>>> + description: >>>>> + Fast-Charge USB current limit >>>>> + minimum: 100000 >>>>> + default: 500000 >>>>> + maximum: 1500000 >>>>> + >>>>> + maxim,fcharge-ac-current-limit-microamp: >>>>> + description: >>>>> + Fast-Charge AC current limit >>>>> + minimum: 100000 >>>>> + default: 500000 >>>>> + maximum: 1500000 >>>>> + >>>>> + maxim,usb-in-current-limit-microamp: >>>>> + description: >>>>> + USB Input current limit >>>>> + minimum: 100000 >>>>> + default: 500000 >>>>> + maximum: 1500000 >>>>> + >>>>> + maxim,ac-in-current-limit-microamp: >>>>> + description: >>>>> + AC Input current limit >>>>> + minimum: 100000 >>>>> + default: 500000 >>>>> + maximum: 1500000 >>>> >>>> For all or most of these you miss monitored batter. >>>> >>> >>> This is a charger, it does not monitor battery. There is a fuel gauge >>> for that or a battery monitor. >>> >> What does charger charge? Battery or something else? >> > > Anything it is linked to. Moreover ref to power supply is not needed Not true. I opened datasheet and it clearly says: "1-Cell Li+ charger". It cannot charge other things properly, so it cannot charge "anything". It only charges batteries. "The MAX8971 is a compact, high-frequency, high-effi- ciency switch-mode charger for a one-cell lithium-ion (Li+) battery. " > since properties from there are not relevant to this driver. We talk about hardware here. > monitored-battery refers to a simple battery cell, which has nothing > to do with charger and power-supplies is irrelevant since this device battery cell has everything to do with charger because it describes the characteristic of what device you are charging: e.g. maximum input current or top-off currents, which you define here as well. You are duplicating some properties and adding some which are not DT at all (all timers). Look how other devices do it. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 1/2] dt-bindings: power: supply: Document Maxim MAX8971 charger 2025-02-24 8:23 ` Krzysztof Kozlowski @ 2025-02-24 8:28 ` Svyatoslav Ryhel 0 siblings, 0 replies; 9+ messages in thread From: Svyatoslav Ryhel @ 2025-02-24 8:28 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-pm, devicetree, linux-kernel пн, 24 лют. 2025 р. о 10:23 Krzysztof Kozlowski <krzk@kernel.org> пише: > > On 23/02/2025 15:28, Svyatoslav Ryhel wrote: > >>>>> + extcon: > >>>>> + description: > >>>>> + Special device used to detect type of plug. > >>>>> + $ref: /schemas/types.yaml#/definitions/phandle > >>>> > >>>> You rather miss proper connector or ports. Which device pins are > >>>> describbed here? > >>>> > >>> > >>> This is an optional phandle to extcon, which can detect plug type. If > >> > >> I know what is this, you just wrote. extcon property is not allowed anymore. > >> > > > > There is no helper for obtaining extcon via graph endpoint I am aware > > of. Can you provide an example of graph parsing extcon helper? > > Most of recent drivers have the same problem and they solved it somehow > without introducing 'extcon' property. > > > > >>> extcon is provided, charger then can change its setup to better > >>> provide supply to the battery. If no extcon is provided, device itself > >>> can detect only the fact of charger without details about type. > >> > >> > >>> > >>>> > >>>>> + > >>>>> + maxim,fcharge-current-limit-microamp: > >>>>> + description: > >>>>> + Fast-Charge current limit > >>>>> + minimum: 250000 > >>>>> + default: 500000 > >>>>> + maximum: 1550000 > >>>>> + > >>>>> + maxim,fcharge-timer-hours: > >>>>> + description: | > >>>>> + Fast-Charge timer in hours. Setting this value 3 and lower or 11 and > >>>>> + higher will disable Fast-Charge timer. > >>>>> + $ref: /schemas/types.yaml#/definitions/uint32 > >>>>> + default: 5 > >>>>> + > >>>>> + maxim,fcharge-rst-threshold-high: > >>>>> + description: > >>>>> + Set Fast-Charge reset threshold to -100 mV > >>>>> + type: boolean > >>>>> + > >>>>> + maxim,in-current-limit-microamp: > >>>>> + description: > >>>>> + Input current limit > >>>>> + minimum: 100000 > >>>>> + default: 500000 > >>>>> + maximum: 1500000 > >>>>> + > >>>>> + maxim,topoff-timer-minutes: > >>>>> + description: > >>>>> + Top-Off timer minutes > >>>>> + $ref: /schemas/types.yaml#/definitions/uint32 > >>>>> + enum: [0, 10, 20, 30, 40, 50, 60, 70] > >>>>> + default: 30 > >>>>> + > >>>>> + maxim,topoff-current-threshold-microamp: > >>>>> + description: > >>>>> + Top-Off current threshold > >>>>> + enum: [50000, 100000, 150000, 200000] > >>>>> + default: 50000 > >>>>> + > >>>>> + maxim,fcharge-usb-current-limit-microamp: > >>>>> + description: > >>>>> + Fast-Charge USB current limit > >>>>> + minimum: 100000 > >>>>> + default: 500000 > >>>>> + maximum: 1500000 > >>>>> + > >>>>> + maxim,fcharge-ac-current-limit-microamp: > >>>>> + description: > >>>>> + Fast-Charge AC current limit > >>>>> + minimum: 100000 > >>>>> + default: 500000 > >>>>> + maximum: 1500000 > >>>>> + > >>>>> + maxim,usb-in-current-limit-microamp: > >>>>> + description: > >>>>> + USB Input current limit > >>>>> + minimum: 100000 > >>>>> + default: 500000 > >>>>> + maximum: 1500000 > >>>>> + > >>>>> + maxim,ac-in-current-limit-microamp: > >>>>> + description: > >>>>> + AC Input current limit > >>>>> + minimum: 100000 > >>>>> + default: 500000 > >>>>> + maximum: 1500000 > >>>> > >>>> For all or most of these you miss monitored batter. > >>>> > >>> > >>> This is a charger, it does not monitor battery. There is a fuel gauge > >>> for that or a battery monitor. > >>> > >> What does charger charge? Battery or something else? > >> > > > > Anything it is linked to. Moreover ref to power supply is not needed > > Not true. I opened datasheet and it clearly says: > "1-Cell Li+ charger". > > It cannot charge other things properly, so it cannot charge "anything". > It only charges batteries. > > "The MAX8971 is a compact, high-frequency, high-effi- > ciency switch-mode charger for a one-cell lithium-ion (Li+) > battery. " > > > since properties from there are not relevant to this driver. > > We talk about hardware here. > > > monitored-battery refers to a simple battery cell, which has nothing > > to do with charger and power-supplies is irrelevant since this device > > battery cell has everything to do with charger because it describes the > characteristic of what device you are charging: e.g. maximum input > current or top-off currents, which you define here as well. > > You are duplicating some properties and adding some which are not DT at > all (all timers). Look how other devices do it. > OK > > Best regards, > Krzysztof ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v1 2/2] power: supply: Add support for Maxim MAX8971 charger 2025-02-21 9:59 [PATCH v1 0/2] power: supply: Add support for Maxim MAX8971 charger Svyatoslav Ryhel 2025-02-21 9:59 ` [PATCH v1 1/2] dt-bindings: power: supply: Document " Svyatoslav Ryhel @ 2025-02-21 9:59 ` Svyatoslav Ryhel 1 sibling, 0 replies; 9+ messages in thread From: Svyatoslav Ryhel @ 2025-02-21 9:59 UTC (permalink / raw) To: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Svyatoslav Ryhel Cc: linux-pm, devicetree, linux-kernel The MAX8971 is a compact, high-frequency, high-efficiency switch-mode charger for a one-cell lithium-ion (Li+) battery. Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com> --- drivers/power/supply/Kconfig | 14 + drivers/power/supply/Makefile | 1 + drivers/power/supply/max8971_charger.c | 685 +++++++++++++++++++++++++ 3 files changed, 700 insertions(+) create mode 100644 drivers/power/supply/max8971_charger.c diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 9f2eef6787f7..7c86116c2947 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -595,6 +595,20 @@ config CHARGER_MAX77976 This driver can also be built as a module. If so, the module will be called max77976_charger. +config CHARGER_MAX8971 + tristate "Maxim MAX8971 battery charger driver" + depends on I2C + select REGMAP_I2C + help + The MAX8971 is a compact, high-frequency, high-efficiency switch-mode + charger for a one-cell lithium-ion (Li+) battery. It delivers up to + 1.55A of current to the battery from inputs up to 7.5V and withstands + transient inputs up to 22V. + + Say Y to enable support for the Maxim MAX8971 battery charger. + This driver can also be built as a module. If so, the module will be + called max8971_charger. + config CHARGER_MAX8997 tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver" depends on MFD_MAX8997 && REGULATOR_MAX8997 diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index 59c4a9f40d28..8fa051ff87ff 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -81,6 +81,7 @@ obj-$(CONFIG_CHARGER_DETECTOR_MAX14656) += max14656_charger_detector.o obj-$(CONFIG_CHARGER_MAX77650) += max77650-charger.o obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o obj-$(CONFIG_CHARGER_MAX77976) += max77976_charger.o +obj-$(CONFIG_CHARGER_MAX8971) += max8971_charger.o obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o obj-$(CONFIG_CHARGER_MP2629) += mp2629_charger.o diff --git a/drivers/power/supply/max8971_charger.c b/drivers/power/supply/max8971_charger.c new file mode 100644 index 000000000000..946467875989 --- /dev/null +++ b/drivers/power/supply/max8971_charger.c @@ -0,0 +1,685 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include <linux/devm-helpers.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/extcon.h> +#include <linux/i2c.h> +#include <linux/mod_devicetable.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/pm.h> +#include <linux/power_supply.h> +#include <linux/regmap.h> +#include <linux/types.h> + +#define MAX8971_REG_CHGINT 0x0f +#define MAX8971_REG_CHG_RST BIT(0) +#define MAX8971_REG_CHGINT_MASK 0x01 +#define MAX8971_AICL_MASK BIT(7) +#define MAX8971_REG_CHG_STAT 0x02 +#define MAX8971_CHG_MASK BIT(3) +#define MAX8971_REG_DETAILS1 0x03 +#define MAX8971_REG_DETAILS2 0x04 +#define MAX8971_REG_CHGCNTL1 0x05 +#define MAX8971_REG_FCHGCRNT 0x06 +#define MAX8971_REG_DCCRNT 0x07 +#define MAX8971_CHGRSTRT_MASK BIT(6) +#define MAX8971_CHGRSTRT_SHIFT 6 +#define MAX8971_REG_TOPOFF 0x08 +#define MAX8971_REG_TEMPREG 0x09 +#define MAX8971_REG_PROTCMD 0x0a +#define MAX8971_CHGPROT_LOCKED 0x00 +#define MAX8971_CHGPROT_UNLOCKED 0x03 + +#define MAX8971_CHGCC_DCILMT_DEFAULT 500 +#define MAX8971_FCHGT_DEFAULT 2 +#define MAX8971_TOPOFFT_DEFAULT 3 + +static const char *max8971_manufacturer = "Maxim Integrated"; +static const char *max8971_model = "MAX8971"; + +enum max8971_charging_state { + MAX8971_CHARGING_DEAD_BATTERY, + MAX8971_CHARGING_PREQUALIFICATION, + MAX8971_CHARGING_FAST_CONST_CURRENT, + MAX8971_CHARGING_FAST_CONST_VOLTAGE, + MAX8971_CHARGING_TOP_OFF, + MAX8971_CHARGING_DONE, + MAX8971_CHARGING_TIMER_FAULT, + MAX8971_CHARGING_SUSPENDED_THERMAL, + MAX8971_CHARGING_OFF, + MAX8971_CHARGING_THERMAL_LOOP, +}; + +enum max8971_health_state { + MAX8971_HEALTH_UNKNOWN, + MAX8971_HEALTH_COLD, + MAX8971_HEALTH_COOL, + MAX8971_HEALTH_WARM, + MAX8971_HEALTH_HOT, + MAX8971_HEALTH_OVERHEAT, +}; + +/* Fast-Charge current limit, 250..1550 mA, 50 mA steps */ +#define MAX8971_CHG_CC_STEP 50000U +#define MAX8971_CHG_CC_MIN 250000U +#define MAX8971_CHG_CC_MAX 1550000U + +/* Input current limit, 250..1500 mA, 25 mA steps */ +#define MAX8971_DCILMT_STEP 25000U +#define MAX8971_DCILMT_MIN 250000U +#define MAX8971_DCILMT_MAX 1500000U + +enum max8971_field_idx { + THM_DTLS, /* DETAILS1 */ + BAT_DTLS, CHG_DTLS, /* DETAILS2 */ + CHG_CC, FCHG_T, /* FCHGCRNT */ + DCI_LMT, /* DCCRNT */ + TOPOFF_T, CHG_CV, /* TOPOFF */ + CPROT, /* PROTCMD */ + MAX8971_N_REGMAP_FIELDS +}; + +static const struct reg_field max8971_reg_field[MAX8971_N_REGMAP_FIELDS] = { + [THM_DTLS] = REG_FIELD(MAX8971_REG_DETAILS1, 0, 2), + [BAT_DTLS] = REG_FIELD(MAX8971_REG_DETAILS2, 4, 5), + [CHG_DTLS] = REG_FIELD(MAX8971_REG_DETAILS2, 0, 3), + [CHG_CC] = REG_FIELD(MAX8971_REG_FCHGCRNT, 0, 4), + [FCHG_T] = REG_FIELD(MAX8971_REG_FCHGCRNT, 5, 7), + [DCI_LMT] = REG_FIELD(MAX8971_REG_DCCRNT, 0, 5), + [TOPOFF_T] = REG_FIELD(MAX8971_REG_TOPOFF, 5, 7), + [CHG_CV] = REG_FIELD(MAX8971_REG_TOPOFF, 2, 3), + [CPROT] = REG_FIELD(MAX8971_REG_PROTCMD, 2, 3), +}; + +static const struct regmap_config max8971_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX8971_REG_CHGINT, +}; + +struct max8971_config { + u32 chgcc; + u32 fchgt; + u32 chgrstrt; + u32 dcilmt; + u32 tofft; + u32 toffs; +}; + +struct max8971_data { + struct i2c_client *client; + struct device *dev; + struct power_supply *psy_mains; + + struct extcon_dev *edev; + struct notifier_block extcon_nb; + struct delayed_work extcon_work; + + struct regmap *regmap; + struct regmap_field *rfield[MAX8971_N_REGMAP_FIELDS]; + + struct max8971_config config; + enum power_supply_usb_type usb_type; + + u32 chgcc_usb; + u32 chgcc_ac; + u32 dcilmt_usb; + u32 dcilmt_ac; + + bool present; +}; + +static int max8971_get_status(struct max8971_data *priv, int *val) +{ + u32 regval; + int err; + + err = regmap_field_read(priv->rfield[CHG_DTLS], ®val); + if (err) + return err; + + switch (regval) { + case MAX8971_CHARGING_DEAD_BATTERY: + case MAX8971_CHARGING_PREQUALIFICATION: + case MAX8971_CHARGING_FAST_CONST_CURRENT: + case MAX8971_CHARGING_FAST_CONST_VOLTAGE: + case MAX8971_CHARGING_TOP_OFF: + case MAX8971_CHARGING_THERMAL_LOOP: + *val = POWER_SUPPLY_STATUS_CHARGING; + break; + case MAX8971_CHARGING_DONE: + *val = POWER_SUPPLY_STATUS_FULL; + break; + case MAX8971_CHARGING_TIMER_FAULT: + *val = POWER_SUPPLY_STATUS_NOT_CHARGING; + break; + case MAX8971_CHARGING_OFF: + case MAX8971_CHARGING_SUSPENDED_THERMAL: + *val = POWER_SUPPLY_STATUS_DISCHARGING; + break; + default: + *val = POWER_SUPPLY_STATUS_UNKNOWN; + } + + return 0; +} + +static int max8971_get_charge_type(struct max8971_data *priv, int *val) +{ + u32 regval; + int err; + + err = regmap_field_read(priv->rfield[CHG_DTLS], ®val); + if (err) + return err; + + switch (regval) { + case MAX8971_CHARGING_DEAD_BATTERY: + case MAX8971_CHARGING_PREQUALIFICATION: + *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; + break; + case MAX8971_CHARGING_FAST_CONST_CURRENT: + case MAX8971_CHARGING_FAST_CONST_VOLTAGE: + *val = POWER_SUPPLY_CHARGE_TYPE_FAST; + break; + case MAX8971_CHARGING_TOP_OFF: + case MAX8971_CHARGING_THERMAL_LOOP: + *val = POWER_SUPPLY_CHARGE_TYPE_STANDARD; + break; + case MAX8971_CHARGING_DONE: + case MAX8971_CHARGING_TIMER_FAULT: + case MAX8971_CHARGING_SUSPENDED_THERMAL: + case MAX8971_CHARGING_OFF: + *val = POWER_SUPPLY_CHARGE_TYPE_NONE; + break; + default: + *val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; + } + + return 0; +} + +static int max8971_get_health(struct max8971_data *priv, int *val) +{ + u32 regval; + int err; + + err = regmap_field_read(priv->rfield[THM_DTLS], ®val); + if (err) + return err; + + switch (regval) { + case MAX8971_HEALTH_COLD: + *val = POWER_SUPPLY_HEALTH_COLD; + break; + case MAX8971_HEALTH_COOL: + *val = POWER_SUPPLY_HEALTH_COOL; + break; + case MAX8971_HEALTH_WARM: + *val = POWER_SUPPLY_HEALTH_GOOD; + break; + case MAX8971_HEALTH_HOT: + *val = POWER_SUPPLY_HEALTH_HOT; + break; + case MAX8971_HEALTH_OVERHEAT: + *val = POWER_SUPPLY_HEALTH_OVERHEAT; + break; + case MAX8971_HEALTH_UNKNOWN: + default: + *val = POWER_SUPPLY_HEALTH_UNKNOWN; + } + + return 0; +} + +static int max8971_get_online(struct max8971_data *priv, int *val) +{ + u32 regval; + int err; + + err = regmap_read(priv->regmap, MAX8971_REG_CHG_STAT, ®val); + if (err) + return err; + + if (priv->present) + /* CHG_OK bit is 0 when charger is online */ + *val = !(regval & MAX8971_CHG_MASK); + else + *val = priv->present; + + return 0; +} + +static int max8971_get_integer(struct max8971_data *priv, enum max8971_field_idx fidx, + u32 clamp_min, u32 clamp_max, u32 mult, int *val) +{ + u32 regval; + int err; + + err = regmap_field_read(priv->rfield[fidx], ®val); + if (err) + return err; + + *val = clamp_val(regval * mult, clamp_min, clamp_max); + + return 0; +} + +static int max8971_set_integer(struct max8971_data *priv, enum max8971_field_idx fidx, + u32 clamp_min, u32 clamp_max, u32 div, int val) +{ + u32 regval; + + regval = clamp_val(val, clamp_min, clamp_max) / div; + + return regmap_field_write(priv->rfield[fidx], regval); +} + +static int max8971_get_property(struct power_supply *psy, enum power_supply_property psp, + union power_supply_propval *val) +{ + struct max8971_data *priv = power_supply_get_drvdata(psy); + int ret = 0; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + ret = max8971_get_status(priv, &val->intval); + break; + case POWER_SUPPLY_PROP_CHARGE_TYPE: + ret = max8971_get_charge_type(priv, &val->intval); + break; + case POWER_SUPPLY_PROP_USB_TYPE: + val->intval = priv->usb_type; + break; + case POWER_SUPPLY_PROP_HEALTH: + ret = max8971_get_health(priv, &val->intval); + break; + case POWER_SUPPLY_PROP_ONLINE: + ret = max8971_get_online(priv, &val->intval); + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = priv->present; + break; + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX: + val->intval = MAX8971_CHG_CC_MAX; + break; + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + ret = max8971_get_integer(priv, CHG_CC, MAX8971_CHG_CC_MIN, MAX8971_CHG_CC_MAX, + MAX8971_CHG_CC_STEP, &val->intval); + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + ret = max8971_get_integer(priv, DCI_LMT, MAX8971_DCILMT_MIN, MAX8971_DCILMT_MAX, + MAX8971_DCILMT_STEP, &val->intval); + break; + case POWER_SUPPLY_PROP_MODEL_NAME: + val->strval = max8971_model; + break; + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = max8971_manufacturer; + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int max8971_set_property(struct power_supply *psy, enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct max8971_data *priv = power_supply_get_drvdata(psy); + int ret = 0; + + switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + ret = max8971_set_integer(priv, CHG_CC, MAX8971_CHG_CC_MIN, MAX8971_CHG_CC_MAX, + MAX8971_CHG_CC_STEP, val->intval); + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + ret = max8971_set_integer(priv, DCI_LMT, MAX8971_DCILMT_MIN, MAX8971_DCILMT_MAX, + MAX8971_DCILMT_STEP, val->intval); + break; + default: + ret = -EINVAL; + } + + return ret; +}; + +static int max8971_property_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + return true; + default: + return false; + } +} + +static enum power_supply_property max8971_properties[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_CHARGE_TYPE, + POWER_SUPPLY_PROP_USB_TYPE, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, + POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, + POWER_SUPPLY_PROP_MODEL_NAME, + POWER_SUPPLY_PROP_MANUFACTURER, +}; + +static const struct power_supply_desc max8971_charger_desc = { + .name = "charger", + .type = POWER_SUPPLY_TYPE_USB, + .usb_types = BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) | + BIT(POWER_SUPPLY_USB_TYPE_SDP) | + BIT(POWER_SUPPLY_USB_TYPE_DCP) | + BIT(POWER_SUPPLY_USB_TYPE_CDP) | + BIT(POWER_SUPPLY_USB_TYPE_ACA), + .properties = max8971_properties, + .num_properties = ARRAY_SIZE(max8971_properties), + .get_property = max8971_get_property, + .set_property = max8971_set_property, + .property_is_writeable = max8971_property_is_writeable, +}; + +static void max8971_extcon_evt_worker(struct work_struct *work) +{ + struct max8971_data *priv = + container_of(work, struct max8971_data, extcon_work.work); + struct device *dev = priv->dev; + struct extcon_dev *edev = priv->edev; + u32 chgcc, dcilmt; + + if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) { + dev_dbg(dev, "USB SDP charger is connected\n"); + priv->usb_type = POWER_SUPPLY_USB_TYPE_SDP; + chgcc = priv->chgcc_usb; + dcilmt = priv->dcilmt_usb; + } else if (extcon_get_state(edev, EXTCON_USB) > 0) { + dev_dbg(dev, "USB charger is connected\n"); + priv->usb_type = POWER_SUPPLY_USB_TYPE_SDP; + chgcc = priv->chgcc_usb; + dcilmt = priv->dcilmt_usb; + } else if (extcon_get_state(edev, EXTCON_DISP_MHL) > 0) { + dev_dbg(dev, "MHL plug is connected\n"); + priv->usb_type = POWER_SUPPLY_USB_TYPE_SDP; + chgcc = priv->chgcc_usb; + dcilmt = priv->dcilmt_usb; + } else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) { + dev_dbg(dev, "USB DCP charger is connected\n"); + priv->usb_type = POWER_SUPPLY_USB_TYPE_DCP; + chgcc = priv->chgcc_ac; + dcilmt = priv->dcilmt_ac; + } else if (extcon_get_state(edev, EXTCON_CHG_USB_FAST) > 0) { + dev_dbg(dev, "USB FAST charger is connected\n"); + priv->usb_type = POWER_SUPPLY_USB_TYPE_ACA; + chgcc = priv->chgcc_ac; + dcilmt = priv->dcilmt_ac; + } else if (extcon_get_state(edev, EXTCON_CHG_USB_SLOW) > 0) { + dev_dbg(dev, "USB SLOW charger is connected\n"); + priv->usb_type = POWER_SUPPLY_USB_TYPE_ACA; + chgcc = priv->chgcc_ac; + dcilmt = priv->dcilmt_ac; + } else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) { + dev_dbg(dev, "USB CDP charger is connected\n"); + priv->usb_type = POWER_SUPPLY_USB_TYPE_CDP; + chgcc = priv->chgcc_ac; + dcilmt = priv->dcilmt_ac; + } else { + dev_dbg(dev, "USB state is unknown\n"); + priv->usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN; + return; + } + + regmap_field_write(priv->rfield[CPROT], MAX8971_CHGPROT_UNLOCKED); + + max8971_set_integer(priv, CHG_CC, MAX8971_CHG_CC_MIN, MAX8971_CHG_CC_MAX, + MAX8971_CHG_CC_STEP, chgcc); + max8971_set_integer(priv, DCI_LMT, MAX8971_DCILMT_MIN, MAX8971_DCILMT_MAX, + MAX8971_DCILMT_STEP, dcilmt); + + regmap_field_write(priv->rfield[CPROT], MAX8971_CHGPROT_LOCKED); +} + +static int extcon_get_charger_type(struct notifier_block *nb, + unsigned long state, void *data) +{ + struct max8971_data *priv = + container_of(nb, struct max8971_data, extcon_nb); + schedule_delayed_work(&priv->extcon_work, 0); + return NOTIFY_OK; +} + +static void max8971_update_config(struct max8971_data *priv) +{ + struct max8971_config *config = &priv->config; + + regmap_field_write(priv->rfield[CPROT], MAX8971_CHGPROT_UNLOCKED); + + /* Construct Fast-Charge Current and Timer Control register */ + if (config->chgcc != MAX8971_CHGCC_DCILMT_DEFAULT) + max8971_set_integer(priv, CHG_CC, MAX8971_CHG_CC_MIN, MAX8971_CHG_CC_MAX, + MAX8971_CHG_CC_STEP, config->chgcc); + + if (config->fchgt != MAX8971_FCHGT_DEFAULT) + regmap_field_write(priv->rfield[FCHG_T], config->fchgt); + + /* Construct Input-Current Limit and Charger Restart Threshold register */ + if (config->chgrstrt) + regmap_write_bits(priv->regmap, MAX8971_REG_DCCRNT, MAX8971_CHGRSTRT_MASK, + config->chgrstrt << MAX8971_CHGRSTRT_SHIFT); + + if (config->dcilmt != MAX8971_CHGCC_DCILMT_DEFAULT) + max8971_set_integer(priv, DCI_LMT, MAX8971_DCILMT_MIN, MAX8971_DCILMT_MAX, + MAX8971_DCILMT_STEP, config->dcilmt); + + /* Construct Done Current, Timer, and Battery Regulation Voltage register */ + if (config->tofft != MAX8971_TOPOFFT_DEFAULT) + regmap_field_write(priv->rfield[TOPOFF_T], config->tofft); + + if (config->toffs) + regmap_field_write(priv->rfield[CHG_CV], config->toffs); + + regmap_field_write(priv->rfield[CPROT], MAX8971_CHGPROT_LOCKED); +} + +static irqreturn_t max8971_interrupt(int irq, void *dev_id) +{ + struct max8971_data *priv = dev_id; + struct device *dev = priv->dev; + int ret, state; + + ret = regmap_read(priv->regmap, MAX8971_REG_CHGINT, &state); + if (ret) + dev_err(dev, "interrupt reg read failed %d\n", ret); + + ret = regmap_write_bits(priv->regmap, MAX8971_REG_CHGINT_MASK, + MAX8971_AICL_MASK, MAX8971_AICL_MASK); + if (ret) + dev_err(dev, "failed to mask IRQ\n"); + + /* set presence prop */ + priv->present = state & MAX8971_REG_CHG_RST; + + /* on every plug chip resets to default */ + if (priv->present) + max8971_update_config(priv); + + /* update supply status */ + power_supply_changed(priv->psy_mains); + + return IRQ_HANDLED; +} + +static void max8971_dt_init(struct max8971_data *priv) +{ + struct device *dev = priv->dev; + struct max8971_config *config = &priv->config; + + /* Construct Fast-Charge Current and Timer Control register */ + config->chgcc = 500 * 1000; + device_property_read_u32(dev, "maxim,fcharge-current-limit-microamp", &config->chgcc); + + config->fchgt = 5; + device_property_read_u32(dev, "maxim,fcharge-timer-hours", &config->fchgt); + config->fchgt -= 3; + if (config->fchgt < 0 || config->fchgt > 7) + config->fchgt = 0; + + /* Construct Input-Current Limit and Charger Restart Threshold register */ + config->chgrstrt = device_property_read_bool(dev, "maxim,fcharge-rst-threshold-high"); + + config->dcilmt = 500 * 1000; + device_property_read_u32(dev, "maxim,in-current-limit-microamp", &config->dcilmt); + + /* Construct Done Current, Timer, and Battery Regulation Voltage register */ + config->tofft = 30; + device_property_read_u32(dev, "maxim,topoff-timer-minutes", &config->tofft); + config->tofft /= 10; + if (config->tofft > 7) + config->tofft = 7; + + config->toffs = 50 * 1000; + device_property_read_u32(dev, "maxim,topoff-current-threshold-microamp", &config->toffs); + config->toffs = (config->toffs / 1000 - 50) / 50; + + /* Perform initial setup */ + max8971_update_config(priv); + + /* Get additional variables */ + priv->chgcc_usb = 500 * 1000; + device_property_read_u32(dev, "maxim,fcharge-usb-current-limit-microamp", &priv->chgcc_usb); + + priv->chgcc_ac = 500 * 1000; + device_property_read_u32(dev, "maxim,fcharge-ac-current-limit-microamp", &priv->chgcc_ac); + + priv->dcilmt_usb = 500 * 1000; + device_property_read_u32(dev, "maxim,usb-in-current-limit-microamp", &priv->dcilmt_usb); + + priv->dcilmt_ac = 500 * 1000; + device_property_read_u32(dev, "maxim,ac-in-current-limit-microamp", &priv->dcilmt_ac); +} + +static char *max8971_supplied_to[] = { + "battery", +}; + +static int max8971_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct max8971_data *priv; + struct power_supply_config cfg = { }; + int ret, i; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->client = client; + priv->dev = dev; + priv->usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN; + + i2c_set_clientdata(client, priv); + + priv->regmap = devm_regmap_init_i2c(client, &max8971_regmap_config); + if (IS_ERR(priv->regmap)) + return dev_err_probe(dev, PTR_ERR(priv->regmap), "cannot allocate regmap\n"); + + for (i = 0; i < MAX8971_N_REGMAP_FIELDS; i++) { + priv->rfield[i] = devm_regmap_field_alloc(dev, priv->regmap, max8971_reg_field[i]); + if (IS_ERR(priv->rfield[i])) + return dev_err_probe(dev, PTR_ERR(priv->rfield[i]), + "cannot allocate regmap field\n"); + } + + max8971_dt_init(priv); + + cfg.of_node = dev->of_node; + cfg.drv_data = priv; + cfg.supplied_to = max8971_supplied_to; + cfg.num_supplicants = ARRAY_SIZE(max8971_supplied_to); + + priv->psy_mains = devm_power_supply_register(dev, &max8971_charger_desc, &cfg); + if (IS_ERR(priv->psy_mains)) + return dev_err_probe(dev, PTR_ERR(priv->psy_mains), + "failed to register mains supply\n"); + + ret = regmap_write_bits(priv->regmap, MAX8971_REG_CHGINT_MASK, MAX8971_AICL_MASK, + MAX8971_AICL_MASK); + if (ret) + return dev_err_probe(dev, ret, "failed to mask IRQ\n"); + + ret = devm_request_threaded_irq(dev, client->irq, NULL, &max8971_interrupt, + IRQF_ONESHOT | IRQF_SHARED, client->name, priv); + if (ret) + return dev_err_probe(dev, ret, "failed to register IRQ %d\n", client->irq); + + if (device_property_present(dev, "extcon")) { + priv->edev = extcon_get_edev_by_phandle(dev, 0); + if (IS_ERR(priv->edev)) + return dev_err_probe(dev, PTR_ERR(priv->edev), + "failed to register extcon\n"); + + ret = devm_delayed_work_autocancel(dev, &priv->extcon_work, + max8971_extcon_evt_worker); + if (ret) + return dev_err_probe(dev, ret, "failed to add extcon evt stop action\n"); + + priv->extcon_nb.notifier_call = extcon_get_charger_type; + + ret = devm_extcon_register_notifier_all(dev, priv->edev, &priv->extcon_nb); + if (ret) + return dev_err_probe(dev, ret, "failed to register notifier\n"); + + /* Initial configuration work with 1 sec delay */ + schedule_delayed_work(&priv->extcon_work, msecs_to_jiffies(1000)); + } + + return 0; +} + +static int max8971_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct max8971_data *priv = i2c_get_clientdata(client); + + irq_wake_thread(client->irq, priv); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(max8971_pm_ops, NULL, max8971_resume); + +static const struct of_device_id max8971_match_ids[] = { + { .compatible = "maxim,max8971" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, max8971_match_ids); + +static const struct i2c_device_id max8971_i2c_id[] = { + { "max8971" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max8971_i2c_id); + +static struct i2c_driver max8971_driver = { + .driver = { + .name = "max8971-charger", + .of_match_table = max8971_match_ids, + .pm = &max8971_pm_ops, + }, + .probe = max8971_probe, + .id_table = max8971_i2c_id, +}; +module_i2c_driver(max8971_driver); + +MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>"); +MODULE_DESCRIPTION("MAX8971 Charger Driver"); +MODULE_LICENSE("GPL"); -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-02-24 8:28 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-02-21 9:59 [PATCH v1 0/2] power: supply: Add support for Maxim MAX8971 charger Svyatoslav Ryhel 2025-02-21 9:59 ` [PATCH v1 1/2] dt-bindings: power: supply: Document " Svyatoslav Ryhel 2025-02-23 11:43 ` Krzysztof Kozlowski 2025-02-23 11:56 ` Svyatoslav Ryhel 2025-02-23 14:14 ` Krzysztof Kozlowski 2025-02-23 14:28 ` Svyatoslav Ryhel 2025-02-24 8:23 ` Krzysztof Kozlowski 2025-02-24 8:28 ` Svyatoslav Ryhel 2025-02-21 9:59 ` [PATCH v1 2/2] power: supply: Add support for " Svyatoslav Ryhel
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox