linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers
@ 2025-11-03 19:14 André Draszik
  2025-11-03 19:14 ` [PATCH v3 01/20] dt-bindings: firmware: google,gs101-acpm-ipc: convert regulators to lowercase André Draszik
                   ` (19 more replies)
  0 siblings, 20 replies; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

This series extends the existing S2MPG10 PMIC driver to add support for
the regulators, and adds new S2MPG11 core and regulator drivers.

This series must be applied in-order, due to the regulator drivers
depending on headers & definitions added by the bindings and core
drivers. I would expect them all to go via the MFD tree.

The patches are kept together in one series, due to S2MPG11 and its
regulators being very similar to S2MPG10.

The Samsung S2MPG11 PMIC is a Power Management IC for mobile
applications with buck converters, various LDOs, power meters, and
additional GPIO interfaces. It typically complements an S2MPG10 PMIC in
a main/sub configuration as the sub-PMIC and both are used on the
Google Pixel 6 and 6 Pro (oriole / raven).

A DT update for Oriole / Raven to enable these is required which I will
send out separately.

Cheers,
Andre'

Signed-off-by: André Draszik <andre.draszik@linaro.org>
---
Changes in v3:
- Krzysztof:
  - split s2mpg10 core binding into separate file
  - drop PCTRLSEL values that can be described using standard
    properties, and update remaining macro names (self)
  - drop maxItems:1 where not needed (Krzysztof)
  - samsung,ext-control-gpios -> enable-gpios
- fix LDO20M_EN pin name -> VLDO20M_EN
- move all binding patternProperties to top-level
- one (driver) instance per actual rail, not per rail type (LDO or
  buck)
- new macro REGULATOR_LINEAR_VRANGE() (patch 10)
- address some (pre-existing) checkpatch warnings)
- various updates to regulator driver (patch 16 & 19).See footer there
- more descriptive commit messages
- Link to v2: https://lore.kernel.org/r/20250606-s2mpg1x-regulators-v2-0-b03feffd2621@linaro.org

Changes in v2:
- s2mpg11 also exposes additional GPIOs, update all relevant commit
  messages (nevertheless, GPIOs are out of scope in this series)
- fix some commit message typos: s2mp1 -> s2mpg1
- patch2: drop | (literal style mark) from samsung,ext-control-gpios
- patch5: add | to vinb*-supply description for better formatting
- patch13: update ::of_parse_cb assignment
- patch15: drop duplicated ::of_parse_cb assignment
- Link to v1: https://lore.kernel.org/r/20250604-s2mpg1x-regulators-v1-0-6038740f49ae@linaro.org

---
André Draszik (20):
      dt-bindings: firmware: google,gs101-acpm-ipc: convert regulators to lowercase
      dt-bindings: mfd: samsung,s2mps11: split s2mpg10 into separate file
      regulator: dt-bindings: add s2mpg10-pmic regulators
      regulator: dt-bindings: add s2mpg11-pmic regulators
      dt-bindings: mfd: samsung,s2mpg10: Link s2mpg10-pmic to its regulators
      dt-bindings: mfd: samsung,s2mpg10: Add s2mpg11-pmic
      dt-bindings: firmware: google,gs101-acpm-ipc: update PMIC examples
      mfd: sec-common: Instantiate s2mpg10 bucks and ldos separately
      mfd: sec: Add support for S2MPG11 PMIC via ACPM
      regulator: add REGULATOR_LINEAR_VRANGE macro
      regulator: s2mps11: drop two needless variable initialisations
      regulator: s2mps11: use dev_err_probe() where appropriate
      regulator: s2mps11: place constants on right side of comparison tests
      regulator: s2mps11: update node parsing (allow -supply properties)
      regulator: s2mps11: refactor handling of external rail control
      regulator: s2mps11: add S2MPG10 regulator
      regulator: s2mps11: refactor S2MPG10  ::set_voltage_time() for S2MPG11 reuse
      regulator: s2mps11: refactor S2MPG10 regulator macros for S2MPG11 reuse
      regulator: s2mps11: add S2MPG11 regulator
      regulator: s2mps11: more descriptive gpio consumer name

 .../bindings/firmware/google,gs101-acpm-ipc.yaml   |   44 +-
 .../devicetree/bindings/mfd/samsung,s2mpg10.yaml   |  124 ++
 .../devicetree/bindings/mfd/samsung,s2mps11.yaml   |   29 +-
 .../regulator/samsung,s2mpg10-regulator.yaml       |  158 +++
 .../regulator/samsung,s2mpg11-regulator.yaml       |  136 +++
 MAINTAINERS                                        |    1 +
 drivers/mfd/sec-acpm.c                             |  213 +++-
 drivers/mfd/sec-common.c                           |   88 +-
 drivers/mfd/sec-irq.c                              |   67 +-
 drivers/regulator/s2mps11.c                        | 1193 ++++++++++++++++++--
 .../regulator/samsung,s2mpg10-regulator.h          |   53 +
 include/linux/mfd/samsung/core.h                   |    1 +
 include/linux/mfd/samsung/irq.h                    |   99 ++
 include/linux/mfd/samsung/s2mpg10.h                |   24 +
 include/linux/mfd/samsung/s2mpg11.h                |  434 +++++++
 include/linux/regulator/driver.h                   |    5 +
 16 files changed, 2510 insertions(+), 159 deletions(-)
---
base-commit: 131f3d9446a6075192cdd91f197989d98302faa6
change-id: 20250603-s2mpg1x-regulators-7a41c8399abf

Best regards,
-- 
André Draszik <andre.draszik@linaro.org>


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v3 01/20] dt-bindings: firmware: google,gs101-acpm-ipc: convert regulators to lowercase
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-03 19:14 ` [PATCH v3 02/20] dt-bindings: mfd: samsung,s2mps11: split s2mpg10 into separate file André Draszik
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

Using lowercase for the buck and ldo nodenames is preferred, as
evidenced e.g. in [1].

Convert the example here to lowercase before we add any bindings
describing the s2mpg1x regulators that will enforce the spelling.

Link: https://lore.kernel.org/all/20250223-mysterious-infrared-civet-e5bcbf@krzk-bin/ [1]
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: André Draszik <andre.draszik@linaro.org>
---
 Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
index d3bca6088d128485618bb2b538ed8596b4ba14f0..4a1e3e3c0505aad6669cadf9b7b58aa4c7f284cb 100644
--- a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
+++ b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
@@ -75,7 +75,7 @@ examples:
             interrupts-extended = <&gpa0 6 IRQ_TYPE_LEVEL_LOW>;
 
             regulators {
-                LDO1 {
+                ldo1m {
                     regulator-name = "vdd_ldo1";
                     regulator-min-microvolt = <700000>;
                     regulator-max-microvolt = <1300000>;
@@ -84,7 +84,7 @@ examples:
 
                 // ...
 
-                BUCK1 {
+                buck8m {
                     regulator-name = "vdd_mif";
                     regulator-min-microvolt = <450000>;
                     regulator-max-microvolt = <1300000>;

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 02/20] dt-bindings: mfd: samsung,s2mps11: split s2mpg10 into separate file
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
  2025-11-03 19:14 ` [PATCH v3 01/20] dt-bindings: firmware: google,gs101-acpm-ipc: convert regulators to lowercase André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-04  8:26   ` Krzysztof Kozlowski
  2025-11-03 19:14 ` [PATCH v3 03/20] regulator: dt-bindings: add s2mpg10-pmic regulators André Draszik
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

The s2mpg10 binding is going to acquire various additional properties.
To avoid making the common samsung,s2mps11 binding file too complicated
due to additional nesting, split s2mpg10 out into its own file.

As a side-effect, the oneOf for the interrupts is not required anymore,
as the required: node is at the top-level now.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
Note: checkpatch suggests to update MAINTAINERS, but the new file is
covered already due to using a wildcard.

v3:
- new patch (Krzysztof)
---
 .../devicetree/bindings/mfd/samsung,s2mpg10.yaml   | 46 ++++++++++++++++++++++
 .../devicetree/bindings/mfd/samsung,s2mps11.yaml   | 29 +-------------
 2 files changed, 47 insertions(+), 28 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/samsung,s2mpg10.yaml b/Documentation/devicetree/bindings/mfd/samsung,s2mpg10.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..841b7c8ab556bc6a3d4cc8d5a0c811814d4176be
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/samsung,s2mpg10.yaml
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/samsung,s2mpg10.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S2MPG10 Power Management IC
+
+maintainers:
+  - André Draszik <andre.draszik@linaro.org>
+
+description: |
+  This is part of the device tree bindings for the S2MPG family of Power
+  Management IC (PMIC).
+
+  The Samsung S2MPG10 is a Power Management IC for mobile applications with buck
+  converters, various LDOs, power meters, RTC, clock outputs, and additional
+  GPIO interfaces.
+
+properties:
+  compatible:
+    const: samsung,s2mpg10-pmic
+
+  clocks:
+    $ref: /schemas/clock/samsung,s2mps11.yaml
+    description:
+      Child node describing clock provider.
+
+  interrupts:
+    maxItems: 1
+
+  regulators:
+    type: object
+    description:
+      List of child nodes that specify the regulators.
+
+  system-power-controller: true
+
+  wakeup-source: true
+
+required:
+  - compatible
+  - interrupts
+  - regulators
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
index 31d544a9c05cad878d10a0ae9b99631f08eb04a8..ac5d0c149796b6a4034b5d4245bfa8be0433cfab 100644
--- a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
+++ b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
@@ -20,7 +20,6 @@ description: |
 properties:
   compatible:
     enum:
-      - samsung,s2mpg10-pmic
       - samsung,s2mps11-pmic
       - samsung,s2mps13-pmic
       - samsung,s2mps14-pmic
@@ -59,42 +58,16 @@ properties:
       reset (setting buck voltages to default values).
     type: boolean
 
-  system-power-controller: true
-
   wakeup-source: true
 
 required:
   - compatible
+  - reg
   - regulators
 
 additionalProperties: false
 
 allOf:
-  - if:
-      properties:
-        compatible:
-          contains:
-            const: samsung,s2mpg10-pmic
-    then:
-      properties:
-        reg: false
-        samsung,s2mps11-acokb-ground: false
-        samsung,s2mps11-wrstbi-ground: false
-
-      # oneOf is required, because dtschema's fixups.py doesn't handle this
-      # nesting here. Its special treatment to allow either interrupt property
-      # when only one is specified in the binding works at the top level only.
-      oneOf:
-        - required: [interrupts]
-        - required: [interrupts-extended]
-
-    else:
-      properties:
-        system-power-controller: false
-
-      required:
-        - reg
-
   - if:
       properties:
         compatible:

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 03/20] regulator: dt-bindings: add s2mpg10-pmic regulators
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
  2025-11-03 19:14 ` [PATCH v3 01/20] dt-bindings: firmware: google,gs101-acpm-ipc: convert regulators to lowercase André Draszik
  2025-11-03 19:14 ` [PATCH v3 02/20] dt-bindings: mfd: samsung,s2mps11: split s2mpg10 into separate file André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-03 19:14 ` [PATCH v3 04/20] regulator: dt-bindings: add s2mpg11-pmic regulators André Draszik
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

The S2MPG10 PMIC is a Power Management IC for mobile applications with
buck converters, various LDOs, power meters, RTC, clock outputs, and
additional GPIO interfaces.

It has 10 buck and 31 LDO rails. Several of these can either be
controlled via software (register writes) or via external signals, in
particular by:
    * one out of several input pins connected to a main processor's:
        *  GPIO pins
        * other pins that are e.g. firmware- or power-domain-controlled
          without explicit driver intervention
    * a combination of input pins and register writes.

Control via input pins allows PMIC rails to be controlled by firmware,
e.g. during standby/suspend, or as part of power domain handling where
otherwise that would not be possible. Additionally toggling a pin is
faster than register writes, and it also allows the PMIC to ensure that
any necessary timing requirements between rails are respected
automatically if multiple rails are to be enabled or disabled quasi
simultaneously.

While external control via input pins appears to exist on other
versions of this PMIC, there is more flexibility in this version, in
particular there is a selection of input pins to choose from for each
rail (which must therefore be configured accordingly if in use),
whereas other versions don't have this flexibility.

Add documentation related to the regulator (buck & ldo) parts like
devicetree definitions, regulator naming patterns, and additional
properties.

S2MPG10 is typically used as the main-PMIC together with an S2MPG11
PMIC in a main/sub configuration, hence the datasheet and the binding
both suffix the rails with an 'm'.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
v3:
- drop PCTRLSEL values that can be described using standard properties
  (Krzysztof), drop useless ones, rename the remaining ones
- drop maxItems:1 where not needed (Krzysztof)
- samsung,ext-control-gpios -> enable-gpios (Krzysztof)
- fix LDO20M_EN pin name -> VLDO20M_EN

v2:
- drop | (literal style mark) from samsung,ext-control-gpios
  description
---
 .../regulator/samsung,s2mpg10-regulator.yaml       | 158 +++++++++++++++++++++
 MAINTAINERS                                        |   1 +
 .../regulator/samsung,s2mpg10-regulator.h          |  39 +++++
 3 files changed, 198 insertions(+)

diff --git a/Documentation/devicetree/bindings/regulator/samsung,s2mpg10-regulator.yaml b/Documentation/devicetree/bindings/regulator/samsung,s2mpg10-regulator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..da8963bb270212f24d8844de4355e1410c170c0d
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/samsung,s2mpg10-regulator.yaml
@@ -0,0 +1,158 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/samsung,s2mpg10-regulator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S2MPG10 Power Management IC regulators
+
+maintainers:
+  - André Draszik <andre.draszik@linaro.org>
+
+description: |
+  This is part of the device tree bindings for the S2MG10 Power Management IC
+  (PMIC).
+
+  The S2MPG10 PMIC provides 10 buck and 31 LDO regulators.
+
+  See also Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml for
+  additional information and example.
+
+definitions:
+  s2mpg10-ext-control:
+    properties:
+      samsung,ext-control:
+        description: |
+          These rails can be controlled via one of several possible external
+          (hardware) signals. If so, this property configures the signal the PMIC
+          should monitor. For S2MPG10 rails where external control is possible other
+          than ldo20m, the following values generally corresponding to the
+          respective on-chip pin are valid:
+            - 0 # S2MPG10_EXTCTRL_PWREN - PWREN pin
+            - 1 # S2MPG10_EXTCTRL_PWREN_MIF - PWREN_MIF pin
+            - 2 # S2MPG10_EXTCTRL_AP_ACTIVE_N - ~AP_ACTIVE_N pin
+            - 3 # S2MPG10_EXTCTRL_CPUCL1_EN - CPUCL1_EN pin
+            - 4 # S2MPG10_EXTCTRL_CPUCL1_EN2 - CPUCL1_EN & PWREN pins
+            - 5 # S2MPG10_EXTCTRL_CPUCL2_EN - CPUCL2_EN pin
+            - 6 # S2MPG10_EXTCTRL_CPUCL2_EN2 - CPUCL2_E2 & PWREN pins
+            - 7 # S2MPG10_EXTCTRL_TPU_EN - TPU_EN pin
+            - 8 # S2MPG10_EXTCTRL_TPU_EN2 - TPU_EN & ~AP_ACTIVE_N pins
+            - 9 # S2MPG10_EXTCTRL_TCXO_ON - TCXO_ON pin
+            - 10 # S2MPG10_EXTCTRL_TCXO_ON2 - TCXO_ON & ~AP_ACTIVE_N pins
+
+          For S2MPG10 ldo20m, the following values are valid
+            - 11 # S2MPG10_EXTCTRL_LDO20M_EN2 - VLDO20M_EN & LDO20M_SFR
+            - 12 # S2MPG10_EXTCTRL_LDO20M_EN - VLDO20M_EN pin
+
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 12
+
+      enable-gpios:
+        description:
+          For rails where external control is done via a GPIO, this optional
+          property describes the GPIO line used.
+
+    dependentRequired:
+      enable-gpios: [ "samsung,ext-control" ]
+
+properties:
+  # 1 LDO with possible (but limited) external control
+  ldo20m:
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      Properties for a single LDO regulator.
+
+    allOf:
+      - $ref: "#/definitions/s2mpg10-ext-control"
+
+    properties:
+      regulator-ramp-delay: false
+
+      samsung,ext-control:
+        minimum: 11
+
+patternProperties:
+  # 10 bucks
+  "^buck([1-9]|10)m$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      Properties for a single buck regulator.
+
+    allOf:
+      - $ref: "#/definitions/s2mpg10-ext-control"
+
+    properties:
+      regulator-ramp-delay:
+        enum: [6250, 12500, 25000]
+        default: 6250
+
+      samsung,ext-control:
+        maximum: 10
+
+  # 12 standard LDOs
+  "^ldo(2[1-9]?|3[0-1])m$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      Properties for single LDO regulator.
+
+    properties:
+      regulator-ramp-delay: false
+
+  # 12 LDOs with possible external control
+  "^ldo([3-689]|1[046-9])m$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      Properties for a single LDO regulator.
+
+    allOf:
+      - $ref: "#/definitions/s2mpg10-ext-control"
+
+    properties:
+      regulator-ramp-delay: false
+
+      samsung,ext-control:
+        maximum: 10
+
+  # 6 LDOs with ramp support, 5 out of those with possible external control
+  "^ldo(1[1235]?|7)m$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      Properties for a single LDO regulator.
+
+    allOf:
+      - $ref: "#/definitions/s2mpg10-ext-control"
+
+    properties:
+      regulator-ramp-delay:
+        enum: [6250, 12500]
+        default: 6250
+
+      samsung,ext-control:
+        maximum: 10
+
+additionalProperties: false
+
+allOf:
+  # Bucks 8, 9, and LDO 1 can not be controlled externally - above definition
+  # allows it and we deny it here. This approach reduces repetition.
+  - if:
+      anyOf:
+        - required: [buck8m]
+        - required: [buck9m]
+        - required: [ldo1m]
+    then:
+      patternProperties:
+        "^(buck[8-9]|ldo1)m$":
+          properties:
+            samsung,ext-control: false
diff --git a/MAINTAINERS b/MAINTAINERS
index 5f7aa6a8a9a17c0212d122860ba1a93fcdec9e7f..6da407f12dd2c2b3f4ed8f30bfc995c497684c86 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22977,6 +22977,7 @@ F:	drivers/mfd/sec*.[ch]
 F:	drivers/regulator/s2*.c
 F:	drivers/regulator/s5m*.c
 F:	drivers/rtc/rtc-s5m.c
+F:	include/dt-bindings/regulator/samsung,s2m*.h
 F:	include/linux/mfd/samsung/
 
 SAMSUNG S3C24XX/S3C64XX SOC SERIES CAMIF DRIVER
diff --git a/include/dt-bindings/regulator/samsung,s2mpg10-regulator.h b/include/dt-bindings/regulator/samsung,s2mpg10-regulator.h
new file mode 100644
index 0000000000000000000000000000000000000000..4a6bf13442f50bb1c475728722eaebd0ec3dcbfa
--- /dev/null
+++ b/include/dt-bindings/regulator/samsung,s2mpg10-regulator.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright 2021 Google LLC
+ * Copyright 2025 Linaro Ltd.
+ *
+ * Device Tree binding constants for the Samsung S2MPG1x PMIC regulators
+ */
+
+#ifndef _DT_BINDINGS_REGULATOR_SAMSUNG_S2MPG10_H
+#define _DT_BINDINGS_REGULATOR_SAMSUNG_S2MPG10_H
+
+/*
+ * Several regulators may be controlled via external signals instead of via
+ * software. These constants describe the possible signals for such regulators
+ * and generally correspond to the respecitve on-chip pins.
+ *
+ * S2MPG10 regulators supporting these are:
+ * - buck1m .. buck7m buck10m
+ * - ldo3m .. ldo19m
+ *
+ * ldo20m supports external control, but using a different set of control
+ * signals.
+ */
+#define S2MPG10_EXTCTRL_PWREN       0 /* PWREN pin */
+#define S2MPG10_EXTCTRL_PWREN_MIF   1 /* PWREN_MIF pin */
+#define S2MPG10_EXTCTRL_AP_ACTIVE_N 2 /* ~AP_ACTIVE_N pin */
+#define S2MPG10_EXTCTRL_CPUCL1_EN   3 /* CPUCL1_EN pin */
+#define S2MPG10_EXTCTRL_CPUCL1_EN2  4 /* CPUCL1_EN & PWREN pins */
+#define S2MPG10_EXTCTRL_CPUCL2_EN   5 /* CPUCL2_EN pin */
+#define S2MPG10_EXTCTRL_CPUCL2_EN2  6 /* CPUCL2_E2 & PWREN pins */
+#define S2MPG10_EXTCTRL_TPU_EN      7 /* TPU_EN pin */
+#define S2MPG10_EXTCTRL_TPU_EN2     8 /* TPU_EN & ~AP_ACTIVE_N pins */
+#define S2MPG10_EXTCTRL_TCXO_ON     9 /* TCXO_ON pin */
+#define S2MPG10_EXTCTRL_TCXO_ON2    10 /* TCXO_ON & ~AP_ACTIVE_N pins */
+
+#define S2MPG10_EXTCTRL_LDO20M_EN2  11 /* VLDO20M_EN & LDO20M_SFR */
+#define S2MPG10_EXTCTRL_LDO20M_EN   12 /* VLDO20M_EN pin */
+
+#endif /* _DT_BINDINGS_REGULATOR_SAMSUNG_S2MPG10_H */

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 04/20] regulator: dt-bindings: add s2mpg11-pmic regulators
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (2 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 03/20] regulator: dt-bindings: add s2mpg10-pmic regulators André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-04  9:39   ` Krzysztof Kozlowski
  2025-11-03 19:14 ` [PATCH v3 05/20] dt-bindings: mfd: samsung,s2mpg10: Link s2mpg10-pmic to its regulators André Draszik
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

The S2MPG11 PMIC is a Power Management IC for mobile applications with
buck converters, various LDOs, power meters, NTC thermistor inputs, and
additional GPIO interfaces. It typically complements an S2MPG10 PMIC in
a main/sub configuration as the sub-PMIC.

S2MPG11 has 12 buck, 1 buck-boost, and 15 LDO rails. Several of these
can either be controlled via software (register writes) or via external
signals, in particular by:
    * one out of several input pins connected to a main processor's:
        *  GPIO pins
        * other pins that are e.g. firmware- or power-domain-controlled
          without explicit driver intervention
    * a combination of input pins and register writes.

Control via input pins allows PMIC rails to be controlled by firmware,
e.g. during standby/suspend, or as part of power domain handling where
otherwise that would not be possible. Additionally toggling a pin is
faster than register writes, and it also allows the PMIC to ensure that
any necessary timing requirements between rails are respected
automatically if multiple rails are to be enabled or disabled quasi
simultaneously.

While external control via input pins appears to exist on other
versions of this PMIC, there is more flexibility in this version, in
particular there is a selection of input pins to choose from for each
rail (which must therefore be configured accordingly if in use),
whereas other versions don't have this flexibility.

Add documentation related to the regulator (buck & ldo) parts like
devicetree definitions, regulator naming patterns, and additional
properties.

Since S2MPG11 is typically used as the sub-PMIC together with an
S2MPG10 as the main-PMIC, the datasheet and the binding both suffix the
rails with an 's'.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
Note: checkpatch suggests to update MAINTAINERS, but the new file is
covered already due to using a wildcard.

v3:
- mention NTC thermistor inputs in commit message
- drop PCTRLSEL values that can be described using standard properties
  (Krzysztof), drop useless ones, rename the remaining ones
- drop maxItems:1 where not needed (Krzysztof)
- samsung,ext-control-gpios -> enable-gpios (Krzysztof)
- drop buckboost from 'allOf' limitation - not needed as it has its own
  specific description

v2:
- fix commit message typos: s2mp1 -> s2mpg1
- mention GPIOs in commit message
---
 .../regulator/samsung,s2mpg11-regulator.yaml       | 136 +++++++++++++++++++++
 .../regulator/samsung,s2mpg10-regulator.h          |  14 +++
 2 files changed, 150 insertions(+)

diff --git a/Documentation/devicetree/bindings/regulator/samsung,s2mpg11-regulator.yaml b/Documentation/devicetree/bindings/regulator/samsung,s2mpg11-regulator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0080ac23b6c926cdc632903e2b2716c12e8a4991
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/samsung,s2mpg11-regulator.yaml
@@ -0,0 +1,136 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/samsung,s2mpg11-regulator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S2MPG11 Power Management IC regulators
+
+maintainers:
+  - André Draszik <andre.draszik@linaro.org>
+
+description: |
+  This is part of the device tree bindings for the S2MG11 Power Management IC
+  (PMIC).
+
+  The S2MPG11 PMIC provides 12 buck, 1 buck-boost, and 15 LDO regulators.
+
+  See also Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml for
+  additional information and example.
+
+definitions:
+  s2mpg11-ext-control:
+    properties:
+      samsung,ext-control:
+        description: |
+          These rails can be controlled via one of several possible external
+          (hardware) signals. If so, this property configures the signal the PMIC
+          should monitor. The following values generally corresponding to the
+          respective on-chip pin are valid:
+            - 0 # S2MPG11_PCTRLSEL_PWREN - PWREN pin
+            - 1 # S2MPG11_PCTRLSEL_PWREN_MIF - PWREN_MIF pin
+            - 2 # S2MPG11_PCTRLSEL_AP_ACTIVE_N - ~AP_ACTIVE_N pin
+            - 3 # S2MPG11_PCTRLSEL_G3D_EN - G3D_EN pin
+            - 4 # S2MPG11_PCTRLSEL_G3D_EN2 - G3D_EN & ~AP_ACTIVE_N pins
+            - 5 # S2MPG11_PCTRLSEL_AOC_VDD - AOC_VDD pin
+            - 6 # S2MPG11_PCTRLSEL_AOC_RET - AOC_RET pin
+            - 7 # S2MPG11_PCTRLSEL_UFS_EN - UFS_EN pin
+            - 8 # S2MPG11_PCTRLSEL_LDO13S_EN - VLDO13S_EN pin
+
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 8
+
+      enable-gpios:
+        description:
+          For rails where external control is done via a GPIO, this optional
+          property describes the GPIO line used.
+
+    dependentRequired:
+      enable-gpios: [ "samsung,ext-control" ]
+
+properties:
+  buckboost:
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      Properties for the buck-boost regulator.
+
+    properties:
+      regulator-ramp-delay: false
+
+patternProperties:
+  # 12 bucks
+  "^buck(([1-9]|10)s|[ad])$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      Properties for a single buck regulator.
+
+    allOf:
+      - $ref: "#/definitions/s2mpg11-ext-control"
+
+    properties:
+      regulator-ramp-delay:
+        enum: [6250, 12500, 25000]
+        default: 6250
+
+  # 11 standard LDOs
+  "^ldo([3-79]|1[01245])s$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      Properties for a single LDO regulator.
+
+    properties:
+      regulator-ramp-delay: false
+
+  # 2 LDOs with possible external control
+  "^ldo(8|13)s$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      Properties for single LDO regulator.
+
+    allOf:
+      - $ref: "#/definitions/s2mpg11-ext-control"
+
+    properties:
+      regulator-ramp-delay: false
+
+  # 2 LDOs with ramp support and possible external control
+  "^ldo[12]s$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      Properties for a single LDO regulator.
+
+    allOf:
+      - $ref: "#/definitions/s2mpg11-ext-control"
+
+    properties:
+      regulator-ramp-delay:
+        enum: [6250, 12500]
+        default: 6250
+
+additionalProperties: false
+
+allOf:
+  # Bucks 4, 6, 7 and 10 can not be controlled externally - above definition
+  # allows it and we deny it here. This approach reduces repetition.
+  - if:
+      anyOf:
+        - required: [buck4s]
+        - required: [buck6s]
+        - required: [buck7s]
+        - required: [buck10s]
+    then:
+      patternProperties:
+        "^buck([467]|10)s$":
+          properties:
+            samsung,ext-control: false
diff --git a/include/dt-bindings/regulator/samsung,s2mpg10-regulator.h b/include/dt-bindings/regulator/samsung,s2mpg10-regulator.h
index 4a6bf13442f50bb1c475728722eaebd0ec3dcbfa..d9c16bba4d85809df99c2887b8dc61ea1bea5ad1 100644
--- a/include/dt-bindings/regulator/samsung,s2mpg10-regulator.h
+++ b/include/dt-bindings/regulator/samsung,s2mpg10-regulator.h
@@ -20,6 +20,10 @@
  *
  * ldo20m supports external control, but using a different set of control
  * signals.
+ *
+ * S2MPG11 regulators supporting these are:
+ * - buck1s .. buck3s buck5s buck8s buck9s bucka buckd
+ * - ldo1s ldo2s ldo8s ldo13s
  */
 #define S2MPG10_EXTCTRL_PWREN       0 /* PWREN pin */
 #define S2MPG10_EXTCTRL_PWREN_MIF   1 /* PWREN_MIF pin */
@@ -36,4 +40,14 @@
 #define S2MPG10_EXTCTRL_LDO20M_EN2  11 /* VLDO20M_EN & LDO20M_SFR */
 #define S2MPG10_EXTCTRL_LDO20M_EN   12 /* VLDO20M_EN pin */
 
+#define S2MPG11_EXTCTRL_PWREN       0 /* PWREN pin */
+#define S2MPG11_EXTCTRL_PWREN_MIF   1 /* PWREN_MIF pin */
+#define S2MPG11_EXTCTRL_AP_ACTIVE_N 2 /* ~AP_ACTIVE_N pin */
+#define S2MPG11_EXTCTRL_G3D_EN      3 /* G3D_EN pin */
+#define S2MPG11_EXTCTRL_G3D_EN2     4 /* G3D_EN & ~AP_ACTIVE_N pins */
+#define S2MPG11_EXTCTRL_AOC_VDD     5 /* AOC_VDD pin */
+#define S2MPG11_EXTCTRL_AOC_RET     6 /* AOC_RET pin */
+#define S2MPG11_EXTCTRL_UFS_EN      7 /* UFS_EN pin */
+#define S2MPG11_EXTCTRL_LDO13S_EN   8 /* VLDO13S_EN pin */
+
 #endif /* _DT_BINDINGS_REGULATOR_SAMSUNG_S2MPG10_H */

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 05/20] dt-bindings: mfd: samsung,s2mpg10: Link s2mpg10-pmic to its regulators
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (3 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 04/20] regulator: dt-bindings: add s2mpg11-pmic regulators André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-04  8:28   ` Krzysztof Kozlowski
  2025-11-03 19:14 ` [PATCH v3 06/20] dt-bindings: mfd: samsung,s2mpg10: Add s2mpg11-pmic André Draszik
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

Update the regulators node to link to the correct and expected
samsung,s2mpg10-pmic regulators binding, in order to describe the
regulators available on this PMIC.

Additionally, describe the supply inputs of the regulator rails, with
the supply names matching the datasheet.

Note 1: S2MPG10 is typically used as the main-PMIC together with an
S2MPG11 PMIC in a main/sub configuration, hence the datasheet and the
binding both suffix the supplies with an 'm'.

Note 2: The changes are done within an allOf: / if: match, because the
intention is to add the S2MPG11 PMIC to this binding as well, and doing
it this way avoids additional churn in those follow-up patches.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
v3:
- move to new samsung,s2mpg10.yaml file
- move all patternProperties to top-level
---
 .../devicetree/bindings/mfd/samsung,s2mpg10.yaml   | 37 ++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/samsung,s2mpg10.yaml b/Documentation/devicetree/bindings/mfd/samsung,s2mpg10.yaml
index 841b7c8ab556bc6a3d4cc8d5a0c811814d4176be..dc06333a4050af69297ac3cae0628a0fffc3fcc9 100644
--- a/Documentation/devicetree/bindings/mfd/samsung,s2mpg10.yaml
+++ b/Documentation/devicetree/bindings/mfd/samsung,s2mpg10.yaml
@@ -38,9 +38,46 @@ properties:
 
   wakeup-source: true
 
+patternProperties:
+  "^vinb([1-9]|10)m-supply$":
+    description:
+      Phandle to the power supply for each buck rail of this PMIC. There is a
+      1:1 mapping of supply to rail, e.g. vinb1m-supply supplies buck1m.
+
+  "^vinl([1-9]|1[0-5])m-supply$":
+    description: |
+      Phandle to the power supply for one or multiple LDO rails of this PMIC.
+      The mapping of supply to rail(s) is as follows:
+        vinl1m - ldo13m
+        vinl2m - ldo15m
+        vinl3m - ldo1m, ldo5m, ldo7m
+        vinl4m - ldo3m, ldo8m
+        vinl5m - ldo16m
+        vinl6m - ldo17m
+        vinl7m - ldo6m, ldo11m, ldo24m, ldo28m
+        vinl8m - ldo12m
+        vinl9m - ldo2m, ldo4m
+        vinl10m - ldo9m, ldo14m, ldo18m, 19m, ldo20m, ldo25m
+        vinl11m - ldo23m, ldo31m
+        vinl12m - ldo29m
+        vinl13m - ldo30m
+        vinl14m - ldo21m
+        vinl15m - ldo10m, ldo22m, ldo26m, ldo27m
+
 required:
   - compatible
   - interrupts
   - regulators
 
 additionalProperties: false
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,s2mpg10-pmic
+    then:
+      properties:
+        regulators:
+          $ref: /schemas/regulator/samsung,s2mpg10-regulator.yaml

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 06/20] dt-bindings: mfd: samsung,s2mpg10: Add s2mpg11-pmic
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (4 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 05/20] dt-bindings: mfd: samsung,s2mpg10: Link s2mpg10-pmic to its regulators André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-04  8:37   ` Krzysztof Kozlowski
  2025-11-03 19:14 ` [PATCH v3 07/20] dt-bindings: firmware: google,gs101-acpm-ipc: update PMIC examples André Draszik
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

The Samsung S2MPG11 PMIC is similar to the existing S2MPG10 PMIC
supported by this binding.

It is a Power Management IC for mobile applications with buck
converters, various LDOs, power meters, NTC thermistor inputs, and
additional GPIO interfaces and typically complements an S2MPG10 PMIC in
a main/sub configuration as the sub-PMIC.

Like S2MPG10, communication is via the Samsung ACPM firmware and it
therefore needs to be a child of the ACPM firmware node.

Add the PMIC, the regulators node, and the supply inputs of the
regulator rails, with the supply names matching the datasheet.

Note: S2MPG11 is typically used as the sub-PMIC together with an
S2MPG10 PMIC in a main/sub configuration, hence the datasheet and the
binding both suffix the supplies with an 's'.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
v3:
- move to new samsung,s2mpg10.yaml file
- deny 'clocks' property
- mention NTC thermistor inputs in commit message
- move all patternProperties to top-level

v2:
- add | to vinb*-supply description for better formatting to mark as
  literal style
- mention GPIOs in commit message
---
 .../devicetree/bindings/mfd/samsung,s2mpg10.yaml   | 49 ++++++++++++++++++++--
 1 file changed, 45 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/samsung,s2mpg10.yaml b/Documentation/devicetree/bindings/mfd/samsung,s2mpg10.yaml
index dc06333a4050af69297ac3cae0628a0fffc3fcc9..6f0912989f2eff12d04dea03b3a067529327e8d3 100644
--- a/Documentation/devicetree/bindings/mfd/samsung,s2mpg10.yaml
+++ b/Documentation/devicetree/bindings/mfd/samsung,s2mpg10.yaml
@@ -19,7 +19,9 @@ description: |
 
 properties:
   compatible:
-    const: samsung,s2mpg10-pmic
+    enum:
+      - samsung,s2mpg10-pmic
+      - samsung,s2mpg11-pmic
 
   clocks:
     $ref: /schemas/clock/samsung,s2mps11.yaml
@@ -39,15 +41,15 @@ properties:
   wakeup-source: true
 
 patternProperties:
-  "^vinb([1-9]|10)m-supply$":
+  "^vinb([1-9]|10)[ms]-supply$":
     description:
       Phandle to the power supply for each buck rail of this PMIC. There is a
       1:1 mapping of supply to rail, e.g. vinb1m-supply supplies buck1m.
 
   "^vinl([1-9]|1[0-5])m-supply$":
     description: |
-      Phandle to the power supply for one or multiple LDO rails of this PMIC.
-      The mapping of supply to rail(s) is as follows:
+      Phandle to the power supply for one or multiple LDO rails of the S2MPG10
+      PMIC. The mapping of supply to rail(s) is as follows:
         vinl1m - ldo13m
         vinl2m - ldo15m
         vinl3m - ldo1m, ldo5m, ldo7m
@@ -64,6 +66,25 @@ patternProperties:
         vinl14m - ldo21m
         vinl15m - ldo10m, ldo22m, ldo26m, ldo27m
 
+  "^vinb[abd]-supply$":
+    description: |
+      Phandle to the power supply for the additional buck rails of the S2MPG11
+      PMIC. The mapping of supply to rail is as follows::
+        vinba - bucka
+        vinbb - buck boost
+        vinbd - buckd
+
+  "^vinl[1-6]s-supply$":
+    description: |
+      Phandle to the power supply for one or multiple LDO rails of the S2MPG11
+      PMIC. The mapping of supply to rail(s) is as follows:
+        vinl1s - ldo1s, ldo2s
+        vinl2s - ldo8s, ldo9s
+        vinl3s - ldo3s, ldo5s, ldo7s, ldo15s
+        vinl4s - ldo10s, ldo11s, ldo12s, ldo14s
+        vinl5s - ldo4s, ldo6s
+        vinl6s - ldo13s
+
 required:
   - compatible
   - interrupts
@@ -81,3 +102,23 @@ allOf:
       properties:
         regulators:
           $ref: /schemas/regulator/samsung,s2mpg10-regulator.yaml
+
+      patternProperties:
+        "[^m]-supply$": false
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,s2mpg11-pmic
+    then:
+      properties:
+        clocks: false
+
+        regulators:
+          $ref: /schemas/regulator/samsung,s2mpg11-regulator.yaml
+
+        system-power-controller: false
+
+      patternProperties:
+        "m-supply$": false

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 07/20] dt-bindings: firmware: google,gs101-acpm-ipc: update PMIC examples
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (5 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 06/20] dt-bindings: mfd: samsung,s2mpg10: Add s2mpg11-pmic André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-04  8:31   ` Krzysztof Kozlowski
  2025-11-04  9:46   ` Krzysztof Kozlowski
  2025-11-03 19:14 ` [PATCH v3 08/20] mfd: sec-common: Instantiate s2mpg10 bucks and ldos separately André Draszik
                   ` (12 subsequent siblings)
  19 siblings, 2 replies; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

In a typical system using the Samsung S2MPG10 PMIC, an S2MPG11 is used
as a sub-PMIC.

The interface for both is the ACPM firmware protocol, so update the
example here to describe the connection for both.

Signed-off-by: André Draszik <andre.draszik@linaro.org>
---
 .../bindings/firmware/google,gs101-acpm-ipc.yaml   | 40 ++++++++++++++++++++--
 1 file changed, 37 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
index 4a1e3e3c0505aad6669cadf9b7b58aa4c7f284cb..c25e155926e5f44bd74f195cdbff3672c7499f8e 100644
--- a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
+++ b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
@@ -45,6 +45,15 @@ properties:
       compatible:
         const: samsung,s2mpg10-pmic
 
+  pmic2:
+    description: Child node describing the sub PMIC.
+    type: object
+    additionalProperties: true
+
+    properties:
+      compatible:
+        const: samsung,s2mpg11-pmic
+
   shmem:
     description:
       List of phandle pointing to the shared memory (SHM) area. The memory
@@ -62,7 +71,9 @@ additionalProperties: false
 
 examples:
   - |
+    #include <dt-bindings/gpio/gpio.h>
     #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/regulator/samsung,s2mpg10-regulator.h>
 
     power-management {
         compatible = "google,gs101-acpm-ipc";
@@ -74,12 +85,20 @@ examples:
             compatible = "samsung,s2mpg10-pmic";
             interrupts-extended = <&gpa0 6 IRQ_TYPE_LEVEL_LOW>;
 
+            vinl3m-supply = <&buck8m>;
+
             regulators {
                 ldo1m {
                     regulator-name = "vdd_ldo1";
                     regulator-min-microvolt = <700000>;
                     regulator-max-microvolt = <1300000>;
-                    regulator-always-on;
+                };
+
+                ldo20m {
+                    regulator-name = "vdd_dmic";
+                    regulator-min-microvolt = <700000>;
+                    regulator-max-microvolt = <1300000>;
+                    samsung,ext-control = <S2MPG10_EXTCTRL_LDO20M_EN>;
                 };
 
                 // ...
@@ -88,8 +107,23 @@ examples:
                     regulator-name = "vdd_mif";
                     regulator-min-microvolt = <450000>;
                     regulator-max-microvolt = <1300000>;
-                    regulator-always-on;
-                    regulator-boot-on;
+                    regulator-ramp-delay = <6250>;
+                };
+            };
+        };
+
+        pmic2 {
+            compatible = "samsung,s2mpg11-pmic";
+            interrupts-extended = <&gpa0 7 IRQ_TYPE_LEVEL_LOW>;
+
+            vinl1s-supply = <&buck8m>;
+            vinl2s-supply = <&buck6s>;
+
+            regulators {
+                buckd {
+                    regulator-ramp-delay = <6250>;
+                    enable-gpios = <&gpp0 1 GPIO_ACTIVE_HIGH>;
+                    samsung,ext-control = <S2MPG11_EXTCTRL_UFS_EN>;
                 };
             };
         };

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 08/20] mfd: sec-common: Instantiate s2mpg10 bucks and ldos separately
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (6 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 07/20] dt-bindings: firmware: google,gs101-acpm-ipc: update PMIC examples André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-03 19:14 ` [PATCH v3 09/20] mfd: sec: Add support for S2MPG11 PMIC via ACPM André Draszik
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

Bucks can conceivably be used as supplies for LDOs, but currently it
can be impossible to mark BUCKs as LDO supplies. This becomes
particularly an issue with the upcoming support for the S2MPG11 PMIC.

The typical use of the S2MPG10 PMIC is in combination with an S2MPG11
PMIC in a main/sub configuration. Bucks of one are usually used as
supplies for LDOs of either itself or of the other: several S2MPG10
LDOs are consumers of various S2MPG10 bucks & S2MPG11 bucks, and
several S2MPG11 LDOs are supplied by various S2MPG10 bucks & S2MPG11
bucks.

So we have a circular dependency here - LDOs (and potentially also
bucks) of one PMIC depend on bucks of the other.

This means that if all S2MPG10 rails are handled by the same instance
of the S2MPG10 regulator driver, probe of all rails will defer, because
the supplies to the LDOs can not be resolved during probe. The same
goes for S2MPG11.

The result is that neither driver can probe successfully and probe will
ultimately fail. In other words it's currently impossible to mark BUCKs
as LDO supplies.

Additionally, multiple (LDO-) rails may share the same (buck) supply
rail and some of these LDOs might supply important consumers, e.g. RAM.
To stay with RAM, if one of those consumers needs to defer probe before
the rail supplying RAM has probed, the shared (buck) supply gets
disabled and the whole system comes to a halt, since Linux hasn't seen
the DDR-supplying rail yet, and hasn't had a chance to mark the buck
rail as having another consumer.

By splitting all rails into separate driver instances, the circular
dependency is gone, each individual instance can probe when its supplies
are ready. This approach also solves the multiple-consumers-on-one-rail
issue during probe.

The mfd_cell's ::id field is used to inform the regulator driver which
regulator to instantiate.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
v3:
- one instance per actual rail, not per rail type (LDO or buck)
- more descriptive commit message

v2:
- fix commit message typos: s2mp1 -> s2mpg1
---
 drivers/mfd/sec-common.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
index 42d55e70e34c8d7cd68cddaecc88017e259365b4..b722481594801e545d24014af6afd5e1e39d7522 100644
--- a/drivers/mfd/sec-common.c
+++ b/drivers/mfd/sec-common.c
@@ -14,6 +14,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/irq.h>
+#include <linux/mfd/samsung/s2mpg10.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps13.h>
 #include <linux/module.h>
@@ -35,7 +36,47 @@ static const struct mfd_cell s2dos05_devs[] = {
 
 static const struct mfd_cell s2mpg10_devs[] = {
 	MFD_CELL_NAME("s2mpg10-meter"),
-	MFD_CELL_NAME("s2mpg10-regulator"),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_BUCK1),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_BUCK2),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_BUCK3),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_BUCK4),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_BUCK5),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_BUCK6),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_BUCK7),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_BUCK8),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_BUCK9),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_BUCK10),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO1),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO2),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO3),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO4),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO5),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO6),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO7),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO8),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO9),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO10),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO11),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO12),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO13),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO14),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO15),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO16),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO17),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO18),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO19),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO20),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO21),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO22),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO23),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO24),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO25),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO26),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO27),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO28),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO29),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO30),
+	MFD_CELL_BASIC("s2mpg10-regulator", NULL, NULL, 0, S2MPG10_LDO31),
 	MFD_CELL_NAME("s2mpg10-rtc"),
 	MFD_CELL_OF("s2mpg10-clk", NULL, NULL, 0, 0, "samsung,s2mpg10-clk"),
 	MFD_CELL_OF("s2mpg10-gpio", NULL, NULL, 0, 0, "samsung,s2mpg10-gpio"),

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 09/20] mfd: sec: Add support for S2MPG11 PMIC via ACPM
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (7 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 08/20] mfd: sec-common: Instantiate s2mpg10 bucks and ldos separately André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-13 16:25   ` Lee Jones
  2025-11-03 19:14 ` [PATCH v3 10/20] regulator: add REGULATOR_LINEAR_VRANGE macro André Draszik
                   ` (10 subsequent siblings)
  19 siblings, 1 reply; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

Add support for Samsung's S2MPG11 PMIC, which is a Power Management IC
for mobile applications with buck converters, various LDOs, power
meters, NTC thermistor inputs, and additional GPIO interfaces. It
typically complements an S2MPG10 PMIC in a main/sub configuration as
the sub-PMIC.

Like S2MPG10, communication is not via I2C, but via the Samsung ACPM
firmware.

Also like S2MPG10, the regulator rails will need to be instantiated
individually to allow probe to succeed due to rails being used as
supplies for S2MPG10, and to avoid supply rails from being disabled
unexpectedly due to probe deferral.

Note: The firmware uses the ACPM channel ID and the Speedy channel ID
to select the PMIC address. Since these are firmware properties, they
can not be retrieved from DT, but instead are deducted from the
compatible for now.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
Note: checkpatch suggests to update MAINTAINERS, but the new file is
covered already due to using a wildcard.

v3:
- mention NTC thermistor inputs in commit message
- one instance per actual rail, not per rail type (LDO or buck)

v2:
- mention GPIOs in commit message
---
 drivers/mfd/sec-acpm.c              | 213 +++++++++++++++++-
 drivers/mfd/sec-common.c            |  45 +++-
 drivers/mfd/sec-irq.c               |  67 +++++-
 include/linux/mfd/samsung/core.h    |   1 +
 include/linux/mfd/samsung/irq.h     |  99 ++++++++
 include/linux/mfd/samsung/s2mpg11.h | 434 ++++++++++++++++++++++++++++++++++++
 6 files changed, 848 insertions(+), 11 deletions(-)

diff --git a/drivers/mfd/sec-acpm.c b/drivers/mfd/sec-acpm.c
index 8b31c816d65b86c54a108fa994384abfac0e7da4..b44af6f8b1cdfcb75cf9d4c55c9d973a88fd510c 100644
--- a/drivers/mfd/sec-acpm.c
+++ b/drivers/mfd/sec-acpm.c
@@ -13,6 +13,7 @@
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/rtc.h>
 #include <linux/mfd/samsung/s2mpg10.h>
+#include <linux/mfd/samsung/s2mpg11.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/of.h>
@@ -216,6 +217,155 @@ static const struct regmap_config s2mpg10_regmap_config_meter = {
 	.cache_type = REGCACHE_FLAT,
 };
 
+static const struct regmap_range s2mpg11_common_registers[] = {
+	regmap_reg_range(0x00, 0x02), /* CHIP_ID_S, INT, INT_MASK */
+	regmap_reg_range(0x0a, 0x0c), /* Speedy control */
+	regmap_reg_range(0x1a, 0x27), /* Debug */
+};
+
+static const struct regmap_range s2mpg11_common_ro_registers[] = {
+	regmap_reg_range(0x00, 0x01), /* CHIP_ID_S, INT */
+	regmap_reg_range(0x25, 0x27), /* Debug */
+};
+
+static const struct regmap_range s2mpg11_common_nonvolatile_registers[] = {
+	regmap_reg_range(0x00, 0x00), /* CHIP_ID_S */
+	regmap_reg_range(0x02, 0x02), /* INT_MASK */
+	regmap_reg_range(0x0a, 0x0c), /* Speedy control */
+};
+
+static const struct regmap_range s2mpg11_common_precious_registers[] = {
+	regmap_reg_range(0x01, 0x01), /* INT */
+};
+
+static const struct regmap_access_table s2mpg11_common_wr_table = {
+	.yes_ranges = s2mpg11_common_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg11_common_registers),
+	.no_ranges = s2mpg11_common_ro_registers,
+	.n_no_ranges = ARRAY_SIZE(s2mpg11_common_ro_registers),
+};
+
+static const struct regmap_access_table s2mpg11_common_rd_table = {
+	.yes_ranges = s2mpg11_common_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg11_common_registers),
+};
+
+static const struct regmap_access_table s2mpg11_common_volatile_table = {
+	.no_ranges = s2mpg11_common_nonvolatile_registers,
+	.n_no_ranges = ARRAY_SIZE(s2mpg11_common_nonvolatile_registers),
+};
+
+static const struct regmap_access_table s2mpg11_common_precious_table = {
+	.yes_ranges = s2mpg11_common_precious_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg11_common_precious_registers),
+};
+
+static const struct regmap_config s2mpg11_regmap_config_common = {
+	.name = "common",
+	.reg_bits = ACPM_ADDR_BITS,
+	.val_bits = 8,
+	.max_register = S2MPG11_COMMON_SPD_DEBUG4,
+	.wr_table = &s2mpg11_common_wr_table,
+	.rd_table = &s2mpg11_common_rd_table,
+	.volatile_table = &s2mpg11_common_volatile_table,
+	.precious_table = &s2mpg11_common_precious_table,
+	.num_reg_defaults_raw = S2MPG11_COMMON_SPD_DEBUG4 + 1,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static const struct regmap_range s2mpg11_pmic_registers[] = {
+	regmap_reg_range(0x00, 0x5a), /* All PMIC registers */
+	regmap_reg_range(0x5c, 0xb7), /* All PMIC registers */
+};
+
+static const struct regmap_range s2mpg11_pmic_ro_registers[] = {
+	regmap_reg_range(0x00, 0x05), /* INTx */
+	regmap_reg_range(0x0c, 0x0d), /* STATUS OFFSRC */
+	regmap_reg_range(0x98, 0x98), /* GPIO input */
+};
+
+static const struct regmap_range s2mpg11_pmic_nonvolatile_registers[] = {
+	regmap_reg_range(0x06, 0x0b), /* INTxM */
+};
+
+static const struct regmap_range s2mpg11_pmic_precious_registers[] = {
+	regmap_reg_range(0x00, 0x05), /* INTx */
+};
+
+static const struct regmap_access_table s2mpg11_pmic_wr_table = {
+	.yes_ranges = s2mpg11_pmic_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg11_pmic_registers),
+	.no_ranges = s2mpg11_pmic_ro_registers,
+	.n_no_ranges = ARRAY_SIZE(s2mpg11_pmic_ro_registers),
+};
+
+static const struct regmap_access_table s2mpg11_pmic_rd_table = {
+	.yes_ranges = s2mpg11_pmic_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg11_pmic_registers),
+};
+
+static const struct regmap_access_table s2mpg11_pmic_volatile_table = {
+	.no_ranges = s2mpg11_pmic_nonvolatile_registers,
+	.n_no_ranges = ARRAY_SIZE(s2mpg11_pmic_nonvolatile_registers),
+};
+
+static const struct regmap_access_table s2mpg11_pmic_precious_table = {
+	.yes_ranges = s2mpg11_pmic_precious_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg11_pmic_precious_registers),
+};
+
+static const struct regmap_config s2mpg11_regmap_config_pmic = {
+	.name = "pmic",
+	.reg_bits = ACPM_ADDR_BITS,
+	.val_bits = 8,
+	.max_register = S2MPG11_PMIC_LDO_SENSE2,
+	.wr_table = &s2mpg11_pmic_wr_table,
+	.rd_table = &s2mpg11_pmic_rd_table,
+	.volatile_table = &s2mpg11_pmic_volatile_table,
+	.precious_table = &s2mpg11_pmic_precious_table,
+	.num_reg_defaults_raw = S2MPG11_PMIC_LDO_SENSE2 + 1,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static const struct regmap_range s2mpg11_meter_registers[] = {
+	regmap_reg_range(0x00, 0x3e), /* Meter config */
+	regmap_reg_range(0x40, 0x8a), /* Meter data */
+	regmap_reg_range(0x8d, 0x9c), /* Meter data */
+};
+
+static const struct regmap_range s2mpg11_meter_ro_registers[] = {
+	regmap_reg_range(0x40, 0x9c), /* Meter data */
+};
+
+static const struct regmap_access_table s2mpg11_meter_wr_table = {
+	.yes_ranges = s2mpg11_meter_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg11_meter_registers),
+	.no_ranges = s2mpg11_meter_ro_registers,
+	.n_no_ranges = ARRAY_SIZE(s2mpg11_meter_ro_registers),
+};
+
+static const struct regmap_access_table s2mpg11_meter_rd_table = {
+	.yes_ranges = s2mpg11_meter_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg11_meter_registers),
+};
+
+static const struct regmap_access_table s2mpg11_meter_volatile_table = {
+	.yes_ranges = s2mpg11_meter_ro_registers,
+	.n_yes_ranges = ARRAY_SIZE(s2mpg11_meter_ro_registers),
+};
+
+static const struct regmap_config s2mpg11_regmap_config_meter = {
+	.name = "meter",
+	.reg_bits = ACPM_ADDR_BITS,
+	.val_bits = 8,
+	.max_register = S2MPG11_METER_LPF_DATA_NTC7_2,
+	.wr_table = &s2mpg11_meter_wr_table,
+	.rd_table = &s2mpg11_meter_rd_table,
+	.volatile_table = &s2mpg11_meter_volatile_table,
+	.num_reg_defaults_raw = S2MPG11_METER_LPF_DATA_NTC7_2 + 1,
+	.cache_type = REGCACHE_FLAT,
+};
+
 struct sec_pmic_acpm_shared_bus_context {
 	const struct acpm_handle *acpm;
 	unsigned int acpm_chan_id;
@@ -325,16 +475,22 @@ static struct regmap *sec_pmic_acpm_regmap_init(struct device *dev,
 	return regmap;
 }
 
-static void sec_pmic_acpm_mask_common_irqs(void *regmap_common)
+static void sec_pmic_acpm_mask_common_s2mpg10_irqs(void *regmap_common)
 {
 	regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
 }
 
+static void sec_pmic_acpm_mask_common_s2mpg11_irqs(void *regmap_common)
+{
+	regmap_write(regmap_common, S2MPG11_COMMON_INT_MASK, S2MPG11_COMMON_INT_SRC);
+}
+
 static int sec_pmic_acpm_probe(struct platform_device *pdev)
 {
 	struct regmap *regmap_common, *regmap_pmic, *regmap;
 	const struct sec_pmic_acpm_platform_data *pdata;
 	struct sec_pmic_acpm_shared_bus_context *shared_ctx;
+	void (*masq_irqs_handler)(void *data);
 	const struct acpm_handle *acpm;
 	struct device *dev = &pdev->dev;
 	int ret, irq;
@@ -365,7 +521,19 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev)
 		return PTR_ERR(regmap_common);
 
 	/* Mask all interrupts from 'common' block, until successful init */
-	ret = regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
+	switch (pdata->device_type) {
+	case S2MPG10:
+		ret = regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
+		break;
+
+	case S2MPG11:
+		ret = regmap_write(regmap_common, S2MPG11_COMMON_INT_MASK, S2MPG11_COMMON_INT_SRC);
+		break;
+
+	default:
+		return dev_err_probe(dev, -EINVAL, "Unsupported device type %d\n",
+				     pdata->device_type);
+	}
 	if (ret)
 		return dev_err_probe(dev, ret, "failed to mask common block interrupts\n");
 
@@ -374,10 +542,12 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev)
 	if (IS_ERR(regmap_pmic))
 		return PTR_ERR(regmap_pmic);
 
-	regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_RTC,
-					   pdata->regmap_cfg_rtc, true);
-	if (IS_ERR(regmap))
-		return PTR_ERR(regmap);
+	if (pdata->regmap_cfg_rtc) {
+		regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_RTC,
+						   pdata->regmap_cfg_rtc, true);
+		if (IS_ERR(regmap))
+			return PTR_ERR(regmap);
+	}
 
 	regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_METER,
 					   pdata->regmap_cfg_meter, true);
@@ -392,13 +562,28 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev)
 		devm_device_init_wakeup(dev);
 
 	/* Unmask PMIC interrupt from 'common' block, now that everything is in place. */
-	ret = regmap_clear_bits(regmap_common, S2MPG10_COMMON_INT_MASK,
-				S2MPG10_COMMON_INT_SRC_PMIC);
+	switch (pdata->device_type) {
+	case S2MPG10:
+		ret = regmap_clear_bits(regmap_common, S2MPG10_COMMON_INT_MASK,
+					S2MPG10_COMMON_INT_SRC_PMIC);
+		masq_irqs_handler = sec_pmic_acpm_mask_common_s2mpg10_irqs;
+		break;
+
+	case S2MPG11:
+		ret = regmap_clear_bits(regmap_common, S2MPG11_COMMON_INT_MASK,
+					S2MPG11_COMMON_INT_SRC_PMIC);
+		masq_irqs_handler = sec_pmic_acpm_mask_common_s2mpg11_irqs;
+		break;
+
+	default:
+		return dev_err_probe(dev, -EINVAL, "Unsupported device type %d\n",
+				     pdata->device_type);
+	}
 	if (ret)
 		return dev_err_probe(dev, ret, "failed to unmask PMIC interrupt\n");
 
 	/* Mask all interrupts from 'common' block on shutdown */
-	ret = devm_add_action_or_reset(dev, sec_pmic_acpm_mask_common_irqs, regmap_common);
+	ret = devm_add_action_or_reset(dev, masq_irqs_handler, regmap_common);
 	if (ret)
 		return ret;
 
@@ -420,8 +605,18 @@ static const struct sec_pmic_acpm_platform_data s2mpg10_data = {
 	.regmap_cfg_meter = &s2mpg10_regmap_config_meter,
 };
 
+static const struct sec_pmic_acpm_platform_data s2mpg11_data = {
+	.device_type = S2MPG11,
+	.acpm_chan_id = 2,
+	.speedy_channel = 1,
+	.regmap_cfg_common = &s2mpg11_regmap_config_common,
+	.regmap_cfg_pmic = &s2mpg11_regmap_config_pmic,
+	.regmap_cfg_meter = &s2mpg11_regmap_config_meter,
+};
+
 static const struct of_device_id sec_pmic_acpm_of_match[] = {
 	{ .compatible = "samsung,s2mpg10-pmic", .data = &s2mpg10_data, },
+	{ .compatible = "samsung,s2mpg11-pmic", .data = &s2mpg11_data, },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, sec_pmic_acpm_of_match);
diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
index b722481594801e545d24014af6afd5e1e39d7522..4daa0ece91dc783560dfad499f11193b689c2fd1 100644
--- a/drivers/mfd/sec-common.c
+++ b/drivers/mfd/sec-common.c
@@ -15,6 +15,7 @@
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/irq.h>
 #include <linux/mfd/samsung/s2mpg10.h>
+#include <linux/mfd/samsung/s2mpg11.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps13.h>
 #include <linux/module.h>
@@ -82,6 +83,39 @@ static const struct mfd_cell s2mpg10_devs[] = {
 	MFD_CELL_OF("s2mpg10-gpio", NULL, NULL, 0, 0, "samsung,s2mpg10-gpio"),
 };
 
+static const struct mfd_cell s2mpg11_devs[] = {
+	MFD_CELL_NAME("s2mpg11-meter"),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCKBOOST),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK1),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK2),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK3),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK4),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK5),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK6),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK7),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK8),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK9),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK10),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCKD),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCKA),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO1),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO2),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO3),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO4),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO5),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO6),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO7),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO8),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO9),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO10),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO11),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO12),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO13),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO14),
+	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO15),
+	MFD_CELL_OF("s2mpg11-gpio", NULL, NULL, 0, 0, "samsung,s2mpg11-gpio"),
+};
+
 static const struct mfd_cell s2mps11_devs[] = {
 	MFD_CELL_NAME("s2mps11-regulator"),
 	MFD_CELL_NAME("s2mps14-rtc"),
@@ -125,8 +159,13 @@ static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)
 	unsigned int val;
 
 	/* For s2mpg1x, the revision is in a different regmap */
-	if (sec_pmic->device_type == S2MPG10)
+	switch (sec_pmic->device_type) {
+	case S2MPG10:
+	case S2MPG11:
 		return;
+	default:
+		break;
+	}
 
 	/* For each device type, the REG_ID is always the first register */
 	if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val))
@@ -231,6 +270,10 @@ int sec_pmic_probe(struct device *dev, int device_type, unsigned int irq,
 		sec_devs = s2mpg10_devs;
 		num_sec_devs = ARRAY_SIZE(s2mpg10_devs);
 		break;
+	case S2MPG11:
+		sec_devs = s2mpg11_devs;
+		num_sec_devs = ARRAY_SIZE(s2mpg11_devs);
+		break;
 	case S2MPS11X:
 		sec_devs = s2mps11_devs;
 		num_sec_devs = ARRAY_SIZE(s2mps11_devs);
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index c5c80b1ba104e6c5a55b442d2f10a8554201a961..a04e46144baae6a195a84df56c53e399e3875e3d 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -11,6 +11,7 @@
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/irq.h>
 #include <linux/mfd/samsung/s2mpg10.h>
+#include <linux/mfd/samsung/s2mpg11.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps14.h>
 #include <linux/mfd/samsung/s2mpu02.h>
@@ -73,6 +74,58 @@ static const struct regmap_irq s2mpg10_irqs[] = {
 	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH7, 5, S2MPG10_IRQ_PWR_WARN_CH7_MASK),
 };
 
+static const struct regmap_irq s2mpg11_irqs[] = {
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PWRONF, 0, S2MPG11_IRQ_PWRONF_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PWRONR, 0, S2MPG11_IRQ_PWRONR_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PIF_TIMEOUT_MIF, 0, S2MPG11_IRQ_PIF_TIMEOUT_MIF_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PIF_TIMEOUTS, 0, S2MPG11_IRQ_PIF_TIMEOUTS_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_WTSR, 0, S2MPG11_IRQ_WTSR_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_SPD_ABNORMAL_STOP, 0, S2MPG11_IRQ_SPD_ABNORMAL_STOP_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_SPD_PARITY_ERR, 0, S2MPG11_IRQ_SPD_PARITY_ERR_MASK),
+
+	REGMAP_IRQ_REG(S2MPG11_IRQ_140C, 1, S2MPG11_IRQ_INT140C_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_120C, 1, S2MPG11_IRQ_INT120C_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_TSD, 1, S2MPG11_IRQ_TSD_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_WRST, 1, S2MPG11_IRQ_WRST_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_CYCLE_DONE, 1, S2MPG11_IRQ_NTC_CYCLE_DONE_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PMETER_OVERF, 1, S2MPG11_IRQ_PMETER_OVERF_MASK),
+
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B1S, 2, S2MPG11_IRQ_OCP_B1S_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B2S, 2, S2MPG11_IRQ_OCP_B2S_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B3S, 2, S2MPG11_IRQ_OCP_B3S_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B4S, 2, S2MPG11_IRQ_OCP_B4S_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B5S, 2, S2MPG11_IRQ_OCP_B5S_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B6S, 2, S2MPG11_IRQ_OCP_B6S_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B7S, 2, S2MPG11_IRQ_OCP_B7S_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B8S, 2, S2MPG11_IRQ_OCP_B8S_MASK),
+
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B9S, 3, S2MPG11_IRQ_OCP_B9S_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B10S, 3, S2MPG11_IRQ_OCP_B10S_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_BDS, 3, S2MPG11_IRQ_OCP_BDS_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_BAS, 3, S2MPG11_IRQ_OCP_BAS_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_BBS, 3, S2MPG11_IRQ_OCP_BBS_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_WLWP_ACC, 3, S2MPG11_IRQ_WLWP_ACC_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_SPD_SRP_PKT_RST, 3, S2MPG11_IRQ_SPD_SRP_PKT_RST_MASK),
+
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH0, 4, S2MPG11_IRQ_PWR_WARN_CH0_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH1, 4, S2MPG11_IRQ_PWR_WARN_CH1_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH2, 4, S2MPG11_IRQ_PWR_WARN_CH2_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH3, 4, S2MPG11_IRQ_PWR_WARN_CH3_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH4, 4, S2MPG11_IRQ_PWR_WARN_CH4_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH5, 4, S2MPG11_IRQ_PWR_WARN_CH5_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH6, 4, S2MPG11_IRQ_PWR_WARN_CH6_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH7, 4, S2MPG11_IRQ_PWR_WARN_CH7_MASK),
+
+	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH0, 5, S2MPG11_IRQ_NTC_WARN_CH0_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH1, 5, S2MPG11_IRQ_NTC_WARN_CH1_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH2, 5, S2MPG11_IRQ_NTC_WARN_CH2_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH3, 5, S2MPG11_IRQ_NTC_WARN_CH3_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH4, 5, S2MPG11_IRQ_NTC_WARN_CH4_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH5, 5, S2MPG11_IRQ_NTC_WARN_CH5_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH6, 5, S2MPG11_IRQ_NTC_WARN_CH6_MASK),
+	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH7, 5, S2MPG11_IRQ_NTC_WARN_CH7_MASK),
+};
+
 static const struct regmap_irq s2mps11_irqs[] = {
 	REGMAP_IRQ_REG(S2MPS11_IRQ_PWRONF, 0, S2MPS11_IRQ_PWRONF_MASK),
 	REGMAP_IRQ_REG(S2MPS11_IRQ_PWRONR, 0, S2MPS11_IRQ_PWRONR_MASK),
@@ -180,7 +233,7 @@ static const struct regmap_irq s5m8767_irqs[] = {
 	REGMAP_IRQ_REG(S5M8767_IRQ_WTSR, 2, S5M8767_IRQ_WTSR_MASK),
 };
 
-/* All S2MPG10 interrupt sources are read-only and don't require clearing */
+/* All S2MPG1x interrupt sources are read-only and don't require clearing */
 static const struct regmap_irq_chip s2mpg10_irq_chip = {
 	.name = "s2mpg10",
 	.irqs = s2mpg10_irqs,
@@ -190,6 +243,15 @@ static const struct regmap_irq_chip s2mpg10_irq_chip = {
 	.mask_base = S2MPG10_PMIC_INT1M,
 };
 
+static const struct regmap_irq_chip s2mpg11_irq_chip = {
+	.name = "s2mpg11",
+	.irqs = s2mpg11_irqs,
+	.num_irqs = ARRAY_SIZE(s2mpg11_irqs),
+	.num_regs = 6,
+	.status_base = S2MPG11_PMIC_INT1,
+	.mask_base = S2MPG11_PMIC_INT1M,
+};
+
 static const struct regmap_irq_chip s2mps11_irq_chip = {
 	.name = "s2mps11",
 	.irqs = s2mps11_irqs,
@@ -270,6 +332,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 	case S2MPG10:
 		sec_irq_chip = &s2mpg10_irq_chip;
 		break;
+	case S2MPG11:
+		sec_irq_chip = &s2mpg11_irq_chip;
+		break;
 	case S2MPS11X:
 		sec_irq_chip = &s2mps11_irq_chip;
 		break;
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index d785e101fe795a5d8f9cccf4ccc4232437e89416..f5fba117bea61b3e3fb308759dc2748f6dd01dfb 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -40,6 +40,7 @@ enum sec_device_type {
 	S2DOS05,
 	S2MPA01,
 	S2MPG10,
+	S2MPG11,
 	S2MPS11X,
 	S2MPS13X,
 	S2MPS14X,
diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h
index b4805cbd949bd605004bd88cf361109d1cbbc3bf..08b1ab33bad48194491fef88d48d5d0027e06a7c 100644
--- a/include/linux/mfd/samsung/irq.h
+++ b/include/linux/mfd/samsung/irq.h
@@ -160,6 +160,105 @@ enum s2mpg10_irq {
 	S2MPG10_IRQ_NR,
 };
 
+enum s2mpg11_irq {
+	/* PMIC */
+	S2MPG11_IRQ_PWRONF,
+	S2MPG11_IRQ_PWRONR,
+	S2MPG11_IRQ_PIF_TIMEOUT_MIF,
+	S2MPG11_IRQ_PIF_TIMEOUTS,
+	S2MPG11_IRQ_WTSR,
+	S2MPG11_IRQ_SPD_ABNORMAL_STOP,
+	S2MPG11_IRQ_SPD_PARITY_ERR,
+#define S2MPG11_IRQ_PWRONF_MASK			BIT(0)
+#define S2MPG11_IRQ_PWRONR_MASK			BIT(1)
+#define S2MPG11_IRQ_PIF_TIMEOUT_MIF_MASK	BIT(3)
+#define S2MPG11_IRQ_PIF_TIMEOUTS_MASK		BIT(4)
+#define S2MPG11_IRQ_WTSR_MASK			BIT(5)
+#define S2MPG11_IRQ_SPD_ABNORMAL_STOP_MASK	BIT(6)
+#define S2MPG11_IRQ_SPD_PARITY_ERR_MASK		BIT(7)
+
+	S2MPG11_IRQ_140C,
+	S2MPG11_IRQ_120C,
+	S2MPG11_IRQ_TSD,
+	S2MPG11_IRQ_WRST,
+	S2MPG11_IRQ_NTC_CYCLE_DONE,
+	S2MPG11_IRQ_PMETER_OVERF,
+#define S2MPG11_IRQ_INT140C_MASK	BIT(0)
+#define S2MPG11_IRQ_INT120C_MASK	BIT(1)
+#define S2MPG11_IRQ_TSD_MASK		BIT(2)
+#define S2MPG11_IRQ_WRST_MASK		BIT(5)
+#define S2MPG11_IRQ_NTC_CYCLE_DONE_MASK	BIT(6)
+#define S2MPG11_IRQ_PMETER_OVERF_MASK	BIT(7)
+
+	S2MPG11_IRQ_OCP_B1S,
+	S2MPG11_IRQ_OCP_B2S,
+	S2MPG11_IRQ_OCP_B3S,
+	S2MPG11_IRQ_OCP_B4S,
+	S2MPG11_IRQ_OCP_B5S,
+	S2MPG11_IRQ_OCP_B6S,
+	S2MPG11_IRQ_OCP_B7S,
+	S2MPG11_IRQ_OCP_B8S,
+#define S2MPG11_IRQ_OCP_B1S_MASK	BIT(0)
+#define S2MPG11_IRQ_OCP_B2S_MASK	BIT(1)
+#define S2MPG11_IRQ_OCP_B3S_MASK	BIT(2)
+#define S2MPG11_IRQ_OCP_B4S_MASK	BIT(3)
+#define S2MPG11_IRQ_OCP_B5S_MASK	BIT(4)
+#define S2MPG11_IRQ_OCP_B6S_MASK	BIT(5)
+#define S2MPG11_IRQ_OCP_B7S_MASK	BIT(6)
+#define S2MPG11_IRQ_OCP_B8S_MASK	BIT(7)
+
+	S2MPG11_IRQ_OCP_B9S,
+	S2MPG11_IRQ_OCP_B10S,
+	S2MPG11_IRQ_OCP_BDS,
+	S2MPG11_IRQ_OCP_BAS,
+	S2MPG11_IRQ_OCP_BBS,
+	S2MPG11_IRQ_WLWP_ACC,
+	S2MPG11_IRQ_SPD_SRP_PKT_RST,
+#define S2MPG11_IRQ_OCP_B9S_MASK		BIT(0)
+#define S2MPG11_IRQ_OCP_B10S_MASK		BIT(1)
+#define S2MPG11_IRQ_OCP_BDS_MASK		BIT(2)
+#define S2MPG11_IRQ_OCP_BAS_MASK		BIT(3)
+#define S2MPG11_IRQ_OCP_BBS_MASK		BIT(4)
+#define S2MPG11_IRQ_WLWP_ACC_MASK		BIT(5)
+#define S2MPG11_IRQ_SPD_SRP_PKT_RST_MASK	BIT(7)
+
+	S2MPG11_IRQ_PWR_WARN_CH0,
+	S2MPG11_IRQ_PWR_WARN_CH1,
+	S2MPG11_IRQ_PWR_WARN_CH2,
+	S2MPG11_IRQ_PWR_WARN_CH3,
+	S2MPG11_IRQ_PWR_WARN_CH4,
+	S2MPG11_IRQ_PWR_WARN_CH5,
+	S2MPG11_IRQ_PWR_WARN_CH6,
+	S2MPG11_IRQ_PWR_WARN_CH7,
+#define S2MPG11_IRQ_PWR_WARN_CH0_MASK	BIT(0)
+#define S2MPG11_IRQ_PWR_WARN_CH1_MASK	BIT(1)
+#define S2MPG11_IRQ_PWR_WARN_CH2_MASK	BIT(2)
+#define S2MPG11_IRQ_PWR_WARN_CH3_MASK	BIT(3)
+#define S2MPG11_IRQ_PWR_WARN_CH4_MASK	BIT(4)
+#define S2MPG11_IRQ_PWR_WARN_CH5_MASK	BIT(5)
+#define S2MPG11_IRQ_PWR_WARN_CH6_MASK	BIT(6)
+#define S2MPG11_IRQ_PWR_WARN_CH7_MASK	BIT(7)
+
+	S2MPG11_IRQ_NTC_WARN_CH0,
+	S2MPG11_IRQ_NTC_WARN_CH1,
+	S2MPG11_IRQ_NTC_WARN_CH2,
+	S2MPG11_IRQ_NTC_WARN_CH3,
+	S2MPG11_IRQ_NTC_WARN_CH4,
+	S2MPG11_IRQ_NTC_WARN_CH5,
+	S2MPG11_IRQ_NTC_WARN_CH6,
+	S2MPG11_IRQ_NTC_WARN_CH7,
+#define S2MPG11_IRQ_NTC_WARN_CH0_MASK	BIT(0)
+#define S2MPG11_IRQ_NTC_WARN_CH1_MASK	BIT(1)
+#define S2MPG11_IRQ_NTC_WARN_CH2_MASK	BIT(2)
+#define S2MPG11_IRQ_NTC_WARN_CH3_MASK	BIT(3)
+#define S2MPG11_IRQ_NTC_WARN_CH4_MASK	BIT(4)
+#define S2MPG11_IRQ_NTC_WARN_CH5_MASK	BIT(5)
+#define S2MPG11_IRQ_NTC_WARN_CH6_MASK	BIT(6)
+#define S2MPG11_IRQ_NTC_WARN_CH7_MASK	BIT(7)
+
+	S2MPG11_IRQ_NR,
+};
+
 enum s2mps11_irq {
 	S2MPS11_IRQ_PWRONF,
 	S2MPS11_IRQ_PWRONR,
diff --git a/include/linux/mfd/samsung/s2mpg11.h b/include/linux/mfd/samsung/s2mpg11.h
new file mode 100644
index 0000000000000000000000000000000000000000..db300cb3bcef1b5b8630e189c58dbb92df8e6cb4
--- /dev/null
+++ b/include/linux/mfd/samsung/s2mpg11.h
@@ -0,0 +1,434 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2015 Samsung Electronics
+ * Copyright 2020 Google Inc
+ * Copyright 2025 Linaro Ltd.
+ */
+
+#ifndef __LINUX_MFD_S2MPG11_H
+#define __LINUX_MFD_S2MPG11_H
+
+/* Common registers (type 0x000) */
+enum s2mpg11_common_reg {
+	S2MPG11_COMMON_CHIPID,
+	S2MPG11_COMMON_INT,
+	S2MPG11_COMMON_INT_MASK,
+	S2MPG11_COMMON_SPD_CTRL1 = 0x0a,
+	S2MPG11_COMMON_SPD_CTRL2,
+	S2MPG11_COMMON_SPD_CTRL3,
+	S2MPG11_COMMON_MON1SEL = 0x1a,
+	S2MPG11_COMMON_MON2SEL,
+	S2MPG11_COMMON_MONR,
+	S2MPG11_COMMON_DEBUG_CTRL1,
+	S2MPG11_COMMON_DEBUG_CTRL2,
+	S2MPG11_COMMON_DEBUG_CTRL3,
+	S2MPG11_COMMON_DEBUG_CTRL4,
+	S2MPG11_COMMON_DEBUG_CTRL5,
+	S2MPG11_COMMON_DEBUG_CTRL6,
+	S2MPG11_COMMON_TEST_MODE1,
+	S2MPG11_COMMON_SPD_DEBUG1,
+	S2MPG11_COMMON_SPD_DEBUG2,
+	S2MPG11_COMMON_SPD_DEBUG3,
+	S2MPG11_COMMON_SPD_DEBUG4,
+};
+
+/* For S2MPG11_COMMON_INT and S2MPG11_COMMON_INT_MASK */
+#define S2MPG11_COMMON_INT_SRC       GENMASK(2, 0)
+#define S2MPG11_COMMON_INT_SRC_PMIC  BIT(0)
+
+/* PMIC registers (type 0x100) */
+enum s2mpg11_pmic_reg {
+	S2MPG11_PMIC_INT1,
+	S2MPG11_PMIC_INT2,
+	S2MPG11_PMIC_INT3,
+	S2MPG11_PMIC_INT4,
+	S2MPG11_PMIC_INT5,
+	S2MPG11_PMIC_INT6,
+	S2MPG11_PMIC_INT1M,
+	S2MPG11_PMIC_INT2M,
+	S2MPG11_PMIC_INT3M,
+	S2MPG11_PMIC_INT4M,
+	S2MPG11_PMIC_INT5M,
+	S2MPG11_PMIC_INT6M,
+	S2MPG11_PMIC_STATUS1,
+	S2MPG11_PMIC_OFFSRC,
+	S2MPG11_PMIC_COMMON_CTRL1,
+	S2MPG11_PMIC_COMMON_CTRL2,
+	S2MPG11_PMIC_COMMON_CTRL3,
+	S2MPG11_PMIC_MIMICKING_CTRL,
+	S2MPG11_PMIC_B1S_CTRL,
+	S2MPG11_PMIC_B1S_OUT1,
+	S2MPG11_PMIC_B1S_OUT2,
+	S2MPG11_PMIC_B2S_CTRL,
+	S2MPG11_PMIC_B2S_OUT1,
+	S2MPG11_PMIC_B2S_OUT2,
+	S2MPG11_PMIC_B3S_CTRL,
+	S2MPG11_PMIC_B3S_OUT1,
+	S2MPG11_PMIC_B3S_OUT2,
+	S2MPG11_PMIC_B4S_CTRL,
+	S2MPG11_PMIC_B4S_OUT,
+	S2MPG11_PMIC_B5S_CTRL,
+	S2MPG11_PMIC_B5S_OUT,
+	S2MPG11_PMIC_B6S_CTRL,
+	S2MPG11_PMIC_B6S_OUT1,
+	S2MPG11_PMIC_B6S_OUT2,
+	S2MPG11_PMIC_B7S_CTRL,
+	S2MPG11_PMIC_B7S_OUT1,
+	S2MPG11_PMIC_B7S_OUT2,
+	S2MPG11_PMIC_B8S_CTRL,
+	S2MPG11_PMIC_B8S_OUT1,
+	S2MPG11_PMIC_B8S_OUT2,
+	S2MPG11_PMIC_B9S_CTRL,
+	S2MPG11_PMIC_B9S_OUT1,
+	S2MPG11_PMIC_B9S_OUT2,
+	S2MPG11_PMIC_B10S_CTRL,
+	S2MPG11_PMIC_B10S_OUT,
+	S2MPG11_PMIC_BUCKD_CTRL,
+	S2MPG11_PMIC_BUCKD_OUT,
+	S2MPG11_PMIC_BUCKA_CTRL,
+	S2MPG11_PMIC_BUCKA_OUT,
+	S2MPG11_PMIC_BB_CTRL,
+	S2MPG11_PMIC_BB_OUT1,
+	S2MPG11_PMIC_BB_OUT2,
+	S2MPG11_PMIC_BUCK1S_USONIC,
+	S2MPG11_PMIC_BUCK2S_USONIC,
+	S2MPG11_PMIC_BUCK3S_USONIC,
+	S2MPG11_PMIC_BUCK4S_USONIC,
+	S2MPG11_PMIC_BUCK5S_USONIC,
+	S2MPG11_PMIC_BUCK6S_USONIC,
+	S2MPG11_PMIC_BUCK7S_USONIC,
+	S2MPG11_PMIC_BUCK8S_USONIC,
+	S2MPG11_PMIC_BUCK9S_USONIC,
+	S2MPG11_PMIC_BUCK10S_USONIC,
+	S2MPG11_PMIC_BUCKD_USONIC,
+	S2MPG11_PMIC_BUCKA_USONIC,
+	S2MPG11_PMIC_BB_USONIC,
+	S2MPG11_PMIC_L1S_CTRL1,
+	S2MPG11_PMIC_L1S_CTRL2,
+	S2MPG11_PMIC_L2S_CTRL1,
+	S2MPG11_PMIC_L2S_CTRL2,
+	S2MPG11_PMIC_L3S_CTRL,
+	S2MPG11_PMIC_L4S_CTRL,
+	S2MPG11_PMIC_L5S_CTRL,
+	S2MPG11_PMIC_L6S_CTRL,
+	S2MPG11_PMIC_L7S_CTRL,
+	S2MPG11_PMIC_L8S_CTRL,
+	S2MPG11_PMIC_L9S_CTRL,
+	S2MPG11_PMIC_L10S_CTRL,
+	S2MPG11_PMIC_L11S_CTRL,
+	S2MPG11_PMIC_L12S_CTRL,
+	S2MPG11_PMIC_L13S_CTRL,
+	S2MPG11_PMIC_L14S_CTRL,
+	S2MPG11_PMIC_L15S_CTRL,
+	S2MPG11_PMIC_LDO_CTRL1,
+	S2MPG11_PMIC_LDO_DSCH1,
+	S2MPG11_PMIC_LDO_DSCH2,
+	S2MPG11_PMIC_DVS_RAMP1,
+	S2MPG11_PMIC_DVS_RAMP2,
+	S2MPG11_PMIC_DVS_RAMP3,
+	S2MPG11_PMIC_DVS_RAMP4,
+	S2MPG11_PMIC_DVS_RAMP5,
+	S2MPG11_PMIC_DVS_RAMP6,
+	/* Nothing @ 0x5a */
+	S2MPG11_PMIC_DVS_SYNC_CTRL1 = 0x5c,
+	S2MPG11_PMIC_DVS_SYNC_CTRL2,
+	S2MPG11_PMIC_OFF_CTRL1,
+	S2MPG11_PMIC_OFF_CTRL2,
+	S2MPG11_PMIC_OFF_CTRL3,
+	S2MPG11_PMIC_SEQ_CTRL1,
+	S2MPG11_PMIC_SEQ_CTRL2,
+	S2MPG11_PMIC_SEQ_CTRL3,
+	S2MPG11_PMIC_SEQ_CTRL4,
+	S2MPG11_PMIC_SEQ_CTRL5,
+	S2MPG11_PMIC_SEQ_CTRL6,
+	S2MPG11_PMIC_SEQ_CTRL7,
+	S2MPG11_PMIC_SEQ_CTRL8,
+	S2MPG11_PMIC_SEQ_CTRL9,
+	S2MPG11_PMIC_SEQ_CTRL10,
+	S2MPG11_PMIC_SEQ_CTRL11,
+	S2MPG11_PMIC_SEQ_CTRL12,
+	S2MPG11_PMIC_SEQ_CTRL13,
+	S2MPG11_PMIC_SEQ_CTRL14,
+	S2MPG11_PMIC_SEQ_CTRL15,
+	S2MPG11_PMIC_SEQ_CTRL16,
+	S2MPG11_PMIC_SEQ_CTRL17,
+	S2MPG11_PMIC_SEQ_CTRL18,
+	S2MPG11_PMIC_SEQ_CTRL19,
+	S2MPG11_PMIC_SEQ_CTRL20,
+	S2MPG11_PMIC_SEQ_CTRL21,
+	S2MPG11_PMIC_SEQ_CTRL22,
+	S2MPG11_PMIC_SEQ_CTRL23,
+	S2MPG11_PMIC_SEQ_CTRL24,
+	S2MPG11_PMIC_SEQ_CTRL25,
+	S2MPG11_PMIC_SEQ_CTRL26,
+	S2MPG11_PMIC_SEQ_CTRL27,
+	S2MPG11_PMIC_OFF_SEQ_CTRL1,
+	S2MPG11_PMIC_OFF_SEQ_CTRL2,
+	S2MPG11_PMIC_OFF_SEQ_CTRL3,
+	S2MPG11_PMIC_OFF_SEQ_CTRL4,
+	S2MPG11_PMIC_OFF_SEQ_CTRL5,
+	S2MPG11_PMIC_OFF_SEQ_CTRL6,
+	S2MPG11_PMIC_OFF_SEQ_CTRL7,
+	S2MPG11_PMIC_OFF_SEQ_CTRL8,
+	S2MPG11_PMIC_OFF_SEQ_CTRL9,
+	S2MPG11_PMIC_OFF_SEQ_CTRL10,
+	S2MPG11_PMIC_OFF_SEQ_CTRL11,
+	S2MPG11_PMIC_OFF_SEQ_CTRL12,
+	S2MPG11_PMIC_OFF_SEQ_CTRL13,
+	S2MPG11_PMIC_OFF_SEQ_CTRL14,
+	S2MPG11_PMIC_OFF_SEQ_CTRL15,
+	S2MPG11_PMIC_OFF_SEQ_CTRL16,
+	S2MPG11_PMIC_OFF_SEQ_CTRL17,
+	S2MPG11_PMIC_PCTRLSEL1,
+	S2MPG11_PMIC_PCTRLSEL2,
+	S2MPG11_PMIC_PCTRLSEL3,
+	S2MPG11_PMIC_PCTRLSEL4,
+	S2MPG11_PMIC_PCTRLSEL5,
+	S2MPG11_PMIC_PCTRLSEL6,
+	S2MPG11_PMIC_DCTRLSEL1,
+	S2MPG11_PMIC_DCTRLSEL2,
+	S2MPG11_PMIC_DCTRLSEL3,
+	S2MPG11_PMIC_DCTRLSEL4,
+	S2MPG11_PMIC_DCTRLSEL5,
+	S2MPG11_PMIC_GPIO_CTRL1,
+	S2MPG11_PMIC_GPIO_CTRL2,
+	S2MPG11_PMIC_GPIO_CTRL3,
+	S2MPG11_PMIC_GPIO_CTRL4,
+	S2MPG11_PMIC_GPIO_CTRL5,
+	S2MPG11_PMIC_GPIO_CTRL6,
+	S2MPG11_PMIC_GPIO_CTRL7,
+	S2MPG11_PMIC_B2S_OCP_WARN,
+	S2MPG11_PMIC_B2S_OCP_WARN_X,
+	S2MPG11_PMIC_B2S_OCP_WARN_Y,
+	S2MPG11_PMIC_B2S_OCP_WARN_Z,
+	S2MPG11_PMIC_B2S_SOFT_OCP_WARN,
+	S2MPG11_PMIC_B2S_SOFT_OCP_WARN_X,
+	S2MPG11_PMIC_B2S_SOFT_OCP_WARN_Y,
+	S2MPG11_PMIC_B2S_SOFT_OCP_WARN_Z,
+	S2MPG11_PMIC_BUCK_OCP_EN1,
+	S2MPG11_PMIC_BUCK_OCP_EN2,
+	S2MPG11_PMIC_BUCK_OCP_PD_EN1,
+	S2MPG11_PMIC_BUCK_OCP_PD_EN2,
+	S2MPG11_PMIC_BUCK_OCP_CTRL1,
+	S2MPG11_PMIC_BUCK_OCP_CTRL2,
+	S2MPG11_PMIC_BUCK_OCP_CTRL3,
+	S2MPG11_PMIC_BUCK_OCP_CTRL4,
+	S2MPG11_PMIC_BUCK_OCP_CTRL5,
+	S2MPG11_PMIC_BUCK_OCP_CTRL6,
+	S2MPG11_PMIC_BUCK_OCP_CTRL7,
+	S2MPG11_PMIC_PIF_CTRL,
+	S2MPG11_PMIC_BUCK_HR_MODE1,
+	S2MPG11_PMIC_BUCK_HR_MODE2,
+	S2MPG11_PMIC_FAULTOUT_CTRL,
+	S2MPG11_PMIC_LDO_SENSE1,
+	S2MPG11_PMIC_LDO_SENSE2,
+};
+
+/* For S2MPG11_PMIC_PCTRLSELx */
+#define S2MPG11_PCTRLSEL_PWREN           0x1 /* PWREN pin */
+#define S2MPG11_PCTRLSEL_PWREN_TRG       0x2 /* PWREN_TRG bit in MIMICKING_CTRL */
+#define S2MPG11_PCTRLSEL_PWREN_MIF       0x3 /* PWREN_MIF pin */
+#define S2MPG11_PCTRLSEL_PWREN_MIF_TRG   0x4 /* PWREN_MIF_TRG bit in MIMICKING_CTRL */
+#define S2MPG11_PCTRLSEL_AP_ACTIVE_N     0x5 /* ~AP_ACTIVE_N pin */
+#define S2MPG11_PCTRLSEL_AP_ACTIVE_N_TRG 0x6 /* ~AP_ACTIVE_N_TRG bit in MIMICKING_CTRL */
+#define S2MPG11_PCTRLSEL_G3D_EN          0x7 /* G3D_EN pin */
+#define S2MPG11_PCTRLSEL_G3D_EN2         0x8 /* G3D_EN & ~AP_ACTIVE_N pins */
+#define S2MPG11_PCTRLSEL_AOC_VDD         0x9 /* AOC_VDD pin */
+#define S2MPG11_PCTRLSEL_AOC_RET         0xa /* AOC_RET pin */
+#define S2MPG11_PCTRLSEL_UFS_EN          0xb /* UFS_EN pin */
+#define S2MPG11_PCTRLSEL_LDO13S_EN       0xc /* VLDO13S_EN pin */
+
+/* Meter registers (type 0xa00) */
+enum s2mpg11_meter_reg {
+	S2MPG11_METER_CTRL1,
+	S2MPG11_METER_CTRL2,
+	S2MPG11_METER_CTRL3,
+	S2MPG11_METER_CTRL4,
+	S2MPG11_METER_CTRL5,
+	S2MPG11_METER_BUCKEN1,
+	S2MPG11_METER_BUCKEN2,
+	S2MPG11_METER_MUXSEL0,
+	S2MPG11_METER_MUXSEL1,
+	S2MPG11_METER_MUXSEL2,
+	S2MPG11_METER_MUXSEL3,
+	S2MPG11_METER_MUXSEL4,
+	S2MPG11_METER_MUXSEL5,
+	S2MPG11_METER_MUXSEL6,
+	S2MPG11_METER_MUXSEL7,
+	S2MPG11_METER_LPF_C0_0,
+	S2MPG11_METER_LPF_C0_1,
+	S2MPG11_METER_LPF_C0_2,
+	S2MPG11_METER_LPF_C0_3,
+	S2MPG11_METER_LPF_C0_4,
+	S2MPG11_METER_LPF_C0_5,
+	S2MPG11_METER_LPF_C0_6,
+	S2MPG11_METER_LPF_C0_7,
+	S2MPG11_METER_NTC_LPF_C0_0,
+	S2MPG11_METER_NTC_LPF_C0_1,
+	S2MPG11_METER_NTC_LPF_C0_2,
+	S2MPG11_METER_NTC_LPF_C0_3,
+	S2MPG11_METER_NTC_LPF_C0_4,
+	S2MPG11_METER_NTC_LPF_C0_5,
+	S2MPG11_METER_NTC_LPF_C0_6,
+	S2MPG11_METER_NTC_LPF_C0_7,
+	S2MPG11_METER_PWR_WARN0,
+	S2MPG11_METER_PWR_WARN1,
+	S2MPG11_METER_PWR_WARN2,
+	S2MPG11_METER_PWR_WARN3,
+	S2MPG11_METER_PWR_WARN4,
+	S2MPG11_METER_PWR_WARN5,
+	S2MPG11_METER_PWR_WARN6,
+	S2MPG11_METER_PWR_WARN7,
+	S2MPG11_METER_NTC_L_WARN0,
+	S2MPG11_METER_NTC_L_WARN1,
+	S2MPG11_METER_NTC_L_WARN2,
+	S2MPG11_METER_NTC_L_WARN3,
+	S2MPG11_METER_NTC_L_WARN4,
+	S2MPG11_METER_NTC_L_WARN5,
+	S2MPG11_METER_NTC_L_WARN6,
+	S2MPG11_METER_NTC_L_WARN7,
+	S2MPG11_METER_NTC_H_WARN0,
+	S2MPG11_METER_NTC_H_WARN1,
+	S2MPG11_METER_NTC_H_WARN2,
+	S2MPG11_METER_NTC_H_WARN3,
+	S2MPG11_METER_NTC_H_WARN4,
+	S2MPG11_METER_NTC_H_WARN5,
+	S2MPG11_METER_NTC_H_WARN6,
+	S2MPG11_METER_NTC_H_WARN7,
+	S2MPG11_METER_PWR_HYS1,
+	S2MPG11_METER_PWR_HYS2,
+	S2MPG11_METER_PWR_HYS3,
+	S2MPG11_METER_PWR_HYS4,
+	S2MPG11_METER_NTC_HYS1,
+	S2MPG11_METER_NTC_HYS2,
+	S2MPG11_METER_NTC_HYS3,
+	S2MPG11_METER_NTC_HYS4,
+	/* Nothing @ 0x3f */
+	S2MPG11_METER_ACC_DATA_CH0_1 = 0x40,
+	S2MPG11_METER_ACC_DATA_CH0_2,
+	S2MPG11_METER_ACC_DATA_CH0_3,
+	S2MPG11_METER_ACC_DATA_CH0_4,
+	S2MPG11_METER_ACC_DATA_CH0_5,
+	S2MPG11_METER_ACC_DATA_CH0_6,
+	S2MPG11_METER_ACC_DATA_CH1_1,
+	S2MPG11_METER_ACC_DATA_CH1_2,
+	S2MPG11_METER_ACC_DATA_CH1_3,
+	S2MPG11_METER_ACC_DATA_CH1_4,
+	S2MPG11_METER_ACC_DATA_CH1_5,
+	S2MPG11_METER_ACC_DATA_CH1_6,
+	S2MPG11_METER_ACC_DATA_CH2_1,
+	S2MPG11_METER_ACC_DATA_CH2_2,
+	S2MPG11_METER_ACC_DATA_CH2_3,
+	S2MPG11_METER_ACC_DATA_CH2_4,
+	S2MPG11_METER_ACC_DATA_CH2_5,
+	S2MPG11_METER_ACC_DATA_CH2_6,
+	S2MPG11_METER_ACC_DATA_CH3_1,
+	S2MPG11_METER_ACC_DATA_CH3_2,
+	S2MPG11_METER_ACC_DATA_CH3_3,
+	S2MPG11_METER_ACC_DATA_CH3_4,
+	S2MPG11_METER_ACC_DATA_CH3_5,
+	S2MPG11_METER_ACC_DATA_CH3_6,
+	S2MPG11_METER_ACC_DATA_CH4_1,
+	S2MPG11_METER_ACC_DATA_CH4_2,
+	S2MPG11_METER_ACC_DATA_CH4_3,
+	S2MPG11_METER_ACC_DATA_CH4_4,
+	S2MPG11_METER_ACC_DATA_CH4_5,
+	S2MPG11_METER_ACC_DATA_CH4_6,
+	S2MPG11_METER_ACC_DATA_CH5_1,
+	S2MPG11_METER_ACC_DATA_CH5_2,
+	S2MPG11_METER_ACC_DATA_CH5_3,
+	S2MPG11_METER_ACC_DATA_CH5_4,
+	S2MPG11_METER_ACC_DATA_CH5_5,
+	S2MPG11_METER_ACC_DATA_CH5_6,
+	S2MPG11_METER_ACC_DATA_CH6_1,
+	S2MPG11_METER_ACC_DATA_CH6_2,
+	S2MPG11_METER_ACC_DATA_CH6_3,
+	S2MPG11_METER_ACC_DATA_CH6_4,
+	S2MPG11_METER_ACC_DATA_CH6_5,
+	S2MPG11_METER_ACC_DATA_CH6_6,
+	S2MPG11_METER_ACC_DATA_CH7_1,
+	S2MPG11_METER_ACC_DATA_CH7_2,
+	S2MPG11_METER_ACC_DATA_CH7_3,
+	S2MPG11_METER_ACC_DATA_CH7_4,
+	S2MPG11_METER_ACC_DATA_CH7_5,
+	S2MPG11_METER_ACC_DATA_CH7_6,
+	S2MPG11_METER_ACC_COUNT_1,
+	S2MPG11_METER_ACC_COUNT_2,
+	S2MPG11_METER_ACC_COUNT_3,
+	S2MPG11_METER_LPF_DATA_CH0_1,
+	S2MPG11_METER_LPF_DATA_CH0_2,
+	S2MPG11_METER_LPF_DATA_CH0_3,
+	S2MPG11_METER_LPF_DATA_CH1_1,
+	S2MPG11_METER_LPF_DATA_CH1_2,
+	S2MPG11_METER_LPF_DATA_CH1_3,
+	S2MPG11_METER_LPF_DATA_CH2_1,
+	S2MPG11_METER_LPF_DATA_CH2_2,
+	S2MPG11_METER_LPF_DATA_CH2_3,
+	S2MPG11_METER_LPF_DATA_CH3_1,
+	S2MPG11_METER_LPF_DATA_CH3_2,
+	S2MPG11_METER_LPF_DATA_CH3_3,
+	S2MPG11_METER_LPF_DATA_CH4_1,
+	S2MPG11_METER_LPF_DATA_CH4_2,
+	S2MPG11_METER_LPF_DATA_CH4_3,
+	S2MPG11_METER_LPF_DATA_CH5_1,
+	S2MPG11_METER_LPF_DATA_CH5_2,
+	S2MPG11_METER_LPF_DATA_CH5_3,
+	S2MPG11_METER_LPF_DATA_CH6_1,
+	S2MPG11_METER_LPF_DATA_CH6_2,
+	S2MPG11_METER_LPF_DATA_CH6_3,
+	S2MPG11_METER_LPF_DATA_CH7_1,
+	S2MPG11_METER_LPF_DATA_CH7_2,
+	S2MPG11_METER_LPF_DATA_CH7_3,
+	/* Nothing @ 0x8b 0x8c */
+	S2MPG11_METER_LPF_DATA_NTC0_1 = 0x8d,
+	S2MPG11_METER_LPF_DATA_NTC0_2,
+	S2MPG11_METER_LPF_DATA_NTC1_1,
+	S2MPG11_METER_LPF_DATA_NTC1_2,
+	S2MPG11_METER_LPF_DATA_NTC2_1,
+	S2MPG11_METER_LPF_DATA_NTC2_2,
+	S2MPG11_METER_LPF_DATA_NTC3_1,
+	S2MPG11_METER_LPF_DATA_NTC3_2,
+	S2MPG11_METER_LPF_DATA_NTC4_1,
+	S2MPG11_METER_LPF_DATA_NTC4_2,
+	S2MPG11_METER_LPF_DATA_NTC5_1,
+	S2MPG11_METER_LPF_DATA_NTC5_2,
+	S2MPG11_METER_LPF_DATA_NTC6_1,
+	S2MPG11_METER_LPF_DATA_NTC6_2,
+	S2MPG11_METER_LPF_DATA_NTC7_1,
+	S2MPG11_METER_LPF_DATA_NTC7_2,
+};
+
+/* S2MPG11 regulator IDs */
+enum s2mpg11_regulators {
+	S2MPG11_LDO1,
+	S2MPG11_LDO2,
+	S2MPG11_LDO3,
+	S2MPG11_LDO4,
+	S2MPG11_LDO5,
+	S2MPG11_LDO6,
+	S2MPG11_LDO7,
+	S2MPG11_LDO8,
+	S2MPG11_LDO9,
+	S2MPG11_LDO10,
+	S2MPG11_LDO11,
+	S2MPG11_LDO12,
+	S2MPG11_LDO13,
+	S2MPG11_LDO14,
+	S2MPG11_LDO15,
+	S2MPG11_BUCK1,
+	S2MPG11_BUCK2,
+	S2MPG11_BUCK3,
+	S2MPG11_BUCK4,
+	S2MPG11_BUCK5,
+	S2MPG11_BUCK6,
+	S2MPG11_BUCK7,
+	S2MPG11_BUCK8,
+	S2MPG11_BUCK9,
+	S2MPG11_BUCK10,
+	S2MPG11_BUCKD,
+	S2MPG11_BUCKA,
+	S2MPG11_BUCKBOOST,
+	S2MPG11_REGULATOR_MAX,
+};
+
+#endif /* __LINUX_MFD_S2MPG11_H */

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 10/20] regulator: add REGULATOR_LINEAR_VRANGE macro
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (8 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 09/20] mfd: sec: Add support for S2MPG11 PMIC via ACPM André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-04 14:27   ` Mark Brown
  2025-11-03 19:14 ` [PATCH v3 11/20] regulator: s2mps11: drop two needless variable initialisations André Draszik
                   ` (9 subsequent siblings)
  19 siblings, 1 reply; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

REGULATOR_LINEAR_VRANGE is similar to REGULATOR_LINEAR_RANGE, but
allows a more natural declaration of a voltage range for a regulator,
in that it expects the minimum and maximum values as voltages rather
than as selectors.

Using voltages arguably makes this macro easier to use by drivers and
code using it can become easier to read compared to
REGULATOR_LINEAR_RANGE.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
While this commit doesn't introduce any users, the upcoming s2mpg10 and
s2mpg11 drivers are using it.

v3:
- new patch
---
 include/linux/regulator/driver.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 978cf593b6624228fe1fd9c2a3e186b53ef172f8..977755db64c6dfaea7246067eab0d9a2971caa01 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -53,6 +53,11 @@ enum regulator_detection_severity {
 #define REGULATOR_LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV)	\
 	LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV)
 
+/* Initialize struct linear_range using voltages, not selectors */
+#define REGULATOR_LINEAR_VRANGE(_offs_uV, _min_uV, _max_uV, _step_uV)	\
+	LINEAR_RANGE(_min_uV, ((_min_uV) - (_offs_uV)) / (_step_uV),	\
+		     ((_max_uV) - (_offs_uV)) / (_step_uV), _step_uV)
+
 /**
  * struct regulator_ops - regulator operations.
  *

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 11/20] regulator: s2mps11: drop two needless variable initialisations
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (9 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 10/20] regulator: add REGULATOR_LINEAR_VRANGE macro André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-04  8:41   ` Krzysztof Kozlowski
  2025-11-03 19:14 ` [PATCH v3 12/20] regulator: s2mps11: use dev_err_probe() where appropriate André Draszik
                   ` (8 subsequent siblings)
  19 siblings, 1 reply; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

The initialisations being removed are needless, as both variables are
being assigned values unconditionally further down. Additionally, doing
this eager init here might lead to preventing the compiler from issuing
a warning if a future code change actually forgets to assign a useful
value in some code path.

Signed-off-by: André Draszik <andre.draszik@linaro.org>
---
 drivers/regulator/s2mps11.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 04ae9c6150bd5ae9dba47b9b3cfcfb62e4698b6d..1f51fbc6c7b6e158f9707c04d9f030b9eee5e842 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -1207,8 +1207,8 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	struct regulator_config config = { };
 	struct s2mps11_info *s2mps11;
-	unsigned int rdev_num = 0;
-	int i, ret = 0;
+	unsigned int rdev_num;
+	int i, ret;
 	const struct regulator_desc *regulators;
 
 	s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 12/20] regulator: s2mps11: use dev_err_probe() where appropriate
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (10 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 11/20] regulator: s2mps11: drop two needless variable initialisations André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-04  8:41   ` Krzysztof Kozlowski
  2025-11-03 19:14 ` [PATCH v3 13/20] regulator: s2mps11: place constants on right side of comparison tests André Draszik
                   ` (7 subsequent siblings)
  19 siblings, 1 reply; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

dev_err_probe() exists to simplify code and harmonise error messages,
there's no reason not to use it here.

While at it, harmonise some error messages to add regulator name and ID
like in other messages in this driver, and update messages to be more
similar to other child-drivers of this PMIC (e.g. RTC).

Signed-off-by: André Draszik <andre.draszik@linaro.org>
---
 drivers/regulator/s2mps11.c | 29 ++++++++++++++---------------
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 1f51fbc6c7b6e158f9707c04d9f030b9eee5e842..30586e9884bfb998ff07e3148813344b307506c0 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -1249,9 +1249,9 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 		BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mpu05_regulators));
 		break;
 	default:
-		dev_err(&pdev->dev, "Invalid device type: %u\n",
-				    s2mps11->dev_type);
-		return -EINVAL;
+		return dev_err_probe(&pdev->dev, -ENODEV,
+				     "Unsupported device type %d\n",
+				     s2mps11->dev_type);
 	}
 
 	s2mps11->ext_control_gpiod = devm_kcalloc(&pdev->dev, rdev_num,
@@ -1290,21 +1290,20 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 			devm_gpiod_unhinge(&pdev->dev, config.ena_gpiod);
 		regulator = devm_regulator_register(&pdev->dev,
 						&regulators[i], &config);
-		if (IS_ERR(regulator)) {
-			dev_err(&pdev->dev, "regulator init failed for %d\n",
-				i);
-			return PTR_ERR(regulator);
-		}
+		if (IS_ERR(regulator))
+			return dev_err_probe(&pdev->dev, PTR_ERR(regulator),
+					     "regulator init failed for %d/%s\n",
+					     regulators[i].id,
+					     regulators[i].name);
 
 		if (config.ena_gpiod) {
 			ret = s2mps14_pmic_enable_ext_control(s2mps11,
-					regulator);
-			if (ret < 0) {
-				dev_err(&pdev->dev,
-						"failed to enable GPIO control over %s: %d\n",
-						regulator->desc->name, ret);
-				return ret;
-			}
+							      regulator);
+			if (ret < 0)
+				return dev_err_probe(&pdev->dev, ret,
+						     "failed to enable GPIO control over %d/%s\n",
+						     regulator->desc->id,
+						     regulator->desc->name);
 		}
 	}
 

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 13/20] regulator: s2mps11: place constants on right side of comparison tests
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (11 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 12/20] regulator: s2mps11: use dev_err_probe() where appropriate André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-04  8:40   ` Krzysztof Kozlowski
  2025-11-03 19:14 ` [PATCH v3 14/20] regulator: s2mps11: update node parsing (allow -supply properties) André Draszik
                   ` (6 subsequent siblings)
  19 siblings, 1 reply; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

For the lines being changed, checkpatch reports:

    WARNING: Comparisons should place the constant on the right side of the test

Update the code accordingly.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
v3:
- new patch
---
 drivers/regulator/s2mps11.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 30586e9884bfb998ff07e3148813344b307506c0..8a36ab67b73e4151c7f67af0555a6465ee1e7a04 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -1221,32 +1221,32 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 	case S2MPS11X:
 		rdev_num = ARRAY_SIZE(s2mps11_regulators);
 		regulators = s2mps11_regulators;
-		BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mps11_regulators));
+		BUILD_BUG_ON(ARRAY_SIZE(s2mps11_regulators) > S2MPS_REGULATOR_MAX);
 		break;
 	case S2MPS13X:
 		rdev_num = ARRAY_SIZE(s2mps13_regulators);
 		regulators = s2mps13_regulators;
-		BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mps13_regulators));
+		BUILD_BUG_ON(ARRAY_SIZE(s2mps13_regulators) > S2MPS_REGULATOR_MAX);
 		break;
 	case S2MPS14X:
 		rdev_num = ARRAY_SIZE(s2mps14_regulators);
 		regulators = s2mps14_regulators;
-		BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mps14_regulators));
+		BUILD_BUG_ON(ARRAY_SIZE(s2mps14_regulators) > S2MPS_REGULATOR_MAX);
 		break;
 	case S2MPS15X:
 		rdev_num = ARRAY_SIZE(s2mps15_regulators);
 		regulators = s2mps15_regulators;
-		BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mps15_regulators));
+		BUILD_BUG_ON(ARRAY_SIZE(s2mps15_regulators) > S2MPS_REGULATOR_MAX);
 		break;
 	case S2MPU02:
 		rdev_num = ARRAY_SIZE(s2mpu02_regulators);
 		regulators = s2mpu02_regulators;
-		BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mpu02_regulators));
+		BUILD_BUG_ON(ARRAY_SIZE(s2mpu02_regulators) > S2MPS_REGULATOR_MAX);
 		break;
 	case S2MPU05:
 		rdev_num = ARRAY_SIZE(s2mpu05_regulators);
 		regulators = s2mpu05_regulators;
-		BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mpu05_regulators));
+		BUILD_BUG_ON(ARRAY_SIZE(s2mpu05_regulators) > S2MPS_REGULATOR_MAX);
 		break;
 	default:
 		return dev_err_probe(&pdev->dev, -ENODEV,

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 14/20] regulator: s2mps11: update node parsing (allow -supply properties)
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (12 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 13/20] regulator: s2mps11: place constants on right side of comparison tests André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-03 19:14 ` [PATCH v3 15/20] regulator: s2mps11: refactor handling of external rail control André Draszik
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

For the upcoming S2MPG10 and S2MPG11 support, we need to be able to
parse -supply properties in the PMIC's DT node.

This currently doesn't work, because the code here currently points the
regulator core at each individual regulator sub-node, and therefore the
regulator core is unable to find the -supply properties.

Update the code to simply let the regulator core handle all the parsing
by adding the ::of_match and ::regulators_node members to all existing
regulator descriptions, by adding ::of_parse_cb() to those
regulators which support the vendor-specific samsung,ext-control-gpios
to parse it (S2MPS14), and by dropping the explicit call to
of_regulator_match().

Configuring the PMIC to respect the external control GPIOs via
s2mps14_pmic_enable_ext_control() is left outside ::of_parse_cb()
because the regulator core ignores errors other than -EPROBE_DEFER from
that callback, while the code currently fails probe on register write
errors and I believe it should stay that way.

The driver can now avoid the devm_gpiod_unhinge() dance due to
simpler error handling of GPIO descriptor acquisition.

This change also has the advantage of reducing runtime memory
consumption by quite a bit as the driver doesn't need to allocate a
'struct of_regulator_match' and a 'struct gpio_desc *' for each
regulator for all PMICs as the regulator core does that. This saves
40+8 bytes on arm64 for each individual regulator on all supported
PMICs (even on non-S2MPS14 due to currently unnecessarily allocating
the extra memory unconditionally). With the upcoming S2MPG10 and
S2MPG11 support, this amounts to 1640+328 and 1120+224 bytes
respectively.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
v2:
- fix commit message typos: s2mp1 -> s2mpg1
---
 drivers/regulator/s2mps11.c | 192 ++++++++++++++++++++++++--------------------
 1 file changed, 105 insertions(+), 87 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 8a36ab67b73e4151c7f67af0555a6465ee1e7a04..88e21c90832a45547e5791b15cd1de274f81fed6 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -40,12 +40,6 @@ struct s2mps11_info {
 	 * the suspend mode was enabled.
 	 */
 	DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX);
-
-	/*
-	 * Array (size: number of regulators) with GPIO-s for external
-	 * sleep control.
-	 */
-	struct gpio_desc **ext_control_gpiod;
 };
 
 static int get_ramp_delay(int ramp_delay)
@@ -244,7 +238,7 @@ static int s2mps11_regulator_enable(struct regulator_dev *rdev)
 	case S2MPS14X:
 		if (test_bit(rdev_id, s2mps11->suspend_state))
 			val = S2MPS14_ENABLE_SUSPEND;
-		else if (s2mps11->ext_control_gpiod[rdev_id])
+		else if (rdev->ena_pin)
 			val = S2MPS14_ENABLE_EXT_CONTROL;
 		else
 			val = rdev->desc->enable_mask;
@@ -334,6 +328,58 @@ static int s2mps11_regulator_set_suspend_disable(struct regulator_dev *rdev)
 				  rdev->desc->enable_mask, state);
 }
 
+static int s2mps11_of_parse_cb(struct device_node *np,
+			       const struct regulator_desc *desc,
+			       struct regulator_config *config)
+{
+	const struct s2mps11_info *s2mps11 = config->driver_data;
+	struct gpio_desc *ena_gpiod;
+	int ret;
+
+	if (s2mps11->dev_type == S2MPS14X)
+		switch (desc->id) {
+		case S2MPS14_LDO10:
+		case S2MPS14_LDO11:
+		case S2MPS14_LDO12:
+			break;
+
+		default:
+			return 0;
+		}
+	else
+		return 0;
+
+	ena_gpiod = fwnode_gpiod_get_index(of_fwnode_handle(np),
+					   "samsung,ext-control", 0,
+					   GPIOD_OUT_HIGH |
+					   GPIOD_FLAGS_BIT_NONEXCLUSIVE,
+					   "s2mps11-regulator");
+	if (IS_ERR(ena_gpiod)) {
+		ret = PTR_ERR(ena_gpiod);
+
+		/* Ignore all errors except probe defer. */
+		if (ret == -EPROBE_DEFER)
+			return ret;
+
+		if (ret == -ENOENT)
+			dev_info(config->dev,
+				 "No entry for control GPIO for %d/%s in node %pOF\n",
+				 desc->id, desc->name, np);
+		else
+			dev_warn_probe(config->dev, ret,
+				       "Failed to get control GPIO for %d/%s in node %pOF\n",
+				       desc->id, desc->name, np);
+		return 0;
+	}
+
+	dev_info(config->dev, "Using GPIO for ext-control over %d/%s\n",
+		 desc->id, desc->name);
+
+	config->ena_gpiod = ena_gpiod;
+
+	return 0;
+}
+
 static const struct regulator_ops s2mps11_ldo_ops = {
 	.list_voltage		= regulator_list_voltage_linear,
 	.map_voltage		= regulator_map_voltage_linear,
@@ -362,6 +408,8 @@ static const struct regulator_ops s2mps11_buck_ops = {
 #define regulator_desc_s2mps11_ldo(num, step) {		\
 	.name		= "LDO"#num,			\
 	.id		= S2MPS11_LDO##num,		\
+	.of_match	= of_match_ptr("LDO"#num),	\
+	.regulators_node = of_match_ptr("regulators"),	\
 	.ops		= &s2mps11_ldo_ops,		\
 	.type		= REGULATOR_VOLTAGE,		\
 	.owner		= THIS_MODULE,			\
@@ -378,6 +426,8 @@ static const struct regulator_ops s2mps11_buck_ops = {
 #define regulator_desc_s2mps11_buck1_4(num) {			\
 	.name		= "BUCK"#num,				\
 	.id		= S2MPS11_BUCK##num,			\
+	.of_match	= of_match_ptr("BUCK"#num),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mps11_buck_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -395,6 +445,8 @@ static const struct regulator_ops s2mps11_buck_ops = {
 #define regulator_desc_s2mps11_buck5 {				\
 	.name		= "BUCK5",				\
 	.id		= S2MPS11_BUCK5,			\
+	.of_match	= of_match_ptr("BUCK5"),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mps11_buck_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -412,6 +464,8 @@ static const struct regulator_ops s2mps11_buck_ops = {
 #define regulator_desc_s2mps11_buck67810(num, min, step, min_sel, voltages) {	\
 	.name		= "BUCK"#num,				\
 	.id		= S2MPS11_BUCK##num,			\
+	.of_match	= of_match_ptr("BUCK"#num),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mps11_buck_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -429,6 +483,8 @@ static const struct regulator_ops s2mps11_buck_ops = {
 #define regulator_desc_s2mps11_buck9 {				\
 	.name		= "BUCK9",				\
 	.id		= S2MPS11_BUCK9,			\
+	.of_match	= of_match_ptr("BUCK9"),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mps11_buck_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -502,6 +558,8 @@ static const struct regulator_ops s2mps14_reg_ops;
 #define regulator_desc_s2mps13_ldo(num, min, step, min_sel) {	\
 	.name		= "LDO"#num,				\
 	.id		= S2MPS13_LDO##num,			\
+	.of_match	= of_match_ptr("LDO"#num),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mps14_reg_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -518,6 +576,8 @@ static const struct regulator_ops s2mps14_reg_ops;
 #define regulator_desc_s2mps13_buck(num, min, step, min_sel) {	\
 	.name		= "BUCK"#num,				\
 	.id		= S2MPS13_BUCK##num,			\
+	.of_match	= of_match_ptr("BUCK"#num),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mps14_reg_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -535,6 +595,8 @@ static const struct regulator_ops s2mps14_reg_ops;
 #define regulator_desc_s2mps13_buck7(num, min, step, min_sel) {	\
 	.name		= "BUCK"#num,				\
 	.id		= S2MPS13_BUCK##num,			\
+	.of_match	= of_match_ptr("BUCK"#num),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mps14_reg_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -552,6 +614,8 @@ static const struct regulator_ops s2mps14_reg_ops;
 #define regulator_desc_s2mps13_buck8_10(num, min, step, min_sel) {	\
 	.name		= "BUCK"#num,				\
 	.id		= S2MPS13_BUCK##num,			\
+	.of_match	= of_match_ptr("BUCK"#num),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mps14_reg_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -634,6 +698,9 @@ static const struct regulator_ops s2mps14_reg_ops = {
 #define regulator_desc_s2mps14_ldo(num, min, step) {	\
 	.name		= "LDO"#num,			\
 	.id		= S2MPS14_LDO##num,		\
+	.of_match	= of_match_ptr("LDO"#num),	\
+	.regulators_node = of_match_ptr("regulators"),	\
+	.of_parse_cb	= s2mps11_of_parse_cb,		\
 	.ops		= &s2mps14_reg_ops,		\
 	.type		= REGULATOR_VOLTAGE,		\
 	.owner		= THIS_MODULE,			\
@@ -649,6 +716,9 @@ static const struct regulator_ops s2mps14_reg_ops = {
 #define regulator_desc_s2mps14_buck(num, min, step, min_sel) {	\
 	.name		= "BUCK"#num,				\
 	.id		= S2MPS14_BUCK##num,			\
+	.of_match	= of_match_ptr("BUCK"#num),		\
+	.regulators_node = of_match_ptr("regulators"),		\
+	.of_parse_cb	= s2mps11_of_parse_cb,			\
 	.ops		= &s2mps14_reg_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -725,6 +795,8 @@ static const struct regulator_ops s2mps15_reg_buck_ops = {
 #define regulator_desc_s2mps15_ldo(num, range) {	\
 	.name		= "LDO"#num,			\
 	.id		= S2MPS15_LDO##num,		\
+	.of_match	= of_match_ptr("LDO"#num),	\
+	.regulators_node = of_match_ptr("regulators"),	\
 	.ops		= &s2mps15_reg_ldo_ops,		\
 	.type		= REGULATOR_VOLTAGE,		\
 	.owner		= THIS_MODULE,			\
@@ -740,6 +812,8 @@ static const struct regulator_ops s2mps15_reg_buck_ops = {
 #define regulator_desc_s2mps15_buck(num, range) {			\
 	.name		= "BUCK"#num,					\
 	.id		= S2MPS15_BUCK##num,				\
+	.of_match	= of_match_ptr("BUCK"#num),			\
+	.regulators_node = of_match_ptr("regulators"),			\
 	.ops		= &s2mps15_reg_buck_ops,			\
 	.type		= REGULATOR_VOLTAGE,				\
 	.owner		= THIS_MODULE,					\
@@ -835,60 +909,6 @@ static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11,
 			rdev->desc->enable_mask, S2MPS14_ENABLE_EXT_CONTROL);
 }
 
-static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
-		struct of_regulator_match *rdata, struct s2mps11_info *s2mps11)
-{
-	struct gpio_desc **gpio = s2mps11->ext_control_gpiod;
-	unsigned int i;
-	unsigned int valid_regulators[3] = { S2MPS14_LDO10, S2MPS14_LDO11,
-		S2MPS14_LDO12 };
-
-	for (i = 0; i < ARRAY_SIZE(valid_regulators); i++) {
-		unsigned int reg = valid_regulators[i];
-
-		if (!rdata[reg].init_data || !rdata[reg].of_node)
-			continue;
-
-		gpio[reg] = devm_fwnode_gpiod_get(&pdev->dev,
-				of_fwnode_handle(rdata[reg].of_node),
-				"samsung,ext-control",
-				GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
-				"s2mps11-regulator");
-		if (PTR_ERR(gpio[reg]) == -ENOENT)
-			gpio[reg] = NULL;
-		else if (IS_ERR(gpio[reg])) {
-			dev_err(&pdev->dev, "Failed to get control GPIO for %d/%s\n",
-				reg, rdata[reg].name);
-			gpio[reg] = NULL;
-			continue;
-		}
-		if (gpio[reg])
-			dev_dbg(&pdev->dev, "Using GPIO for ext-control over %d/%s\n",
-				reg, rdata[reg].name);
-	}
-}
-
-static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
-		struct of_regulator_match *rdata, struct s2mps11_info *s2mps11,
-		unsigned int rdev_num)
-{
-	struct device_node *reg_np;
-
-	reg_np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
-	if (!reg_np) {
-		dev_err(&pdev->dev, "could not find regulators sub-node\n");
-		return -EINVAL;
-	}
-
-	of_regulator_match(&pdev->dev, reg_np, rdata, rdev_num);
-	if (s2mps11->dev_type == S2MPS14X)
-		s2mps14_pmic_dt_parse_ext_control_gpio(pdev, rdata, s2mps11);
-
-	of_node_put(reg_np);
-
-	return 0;
-}
-
 static int s2mpu02_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
 {
 	unsigned int ramp_val, ramp_shift, ramp_reg;
@@ -946,6 +966,8 @@ static const struct regulator_ops s2mpu02_buck_ops = {
 #define regulator_desc_s2mpu02_ldo1(num) {		\
 	.name		= "LDO"#num,			\
 	.id		= S2MPU02_LDO##num,		\
+	.of_match	= of_match_ptr("LDO"#num),	\
+	.regulators_node = of_match_ptr("regulators"),	\
 	.ops		= &s2mpu02_ldo_ops,		\
 	.type		= REGULATOR_VOLTAGE,		\
 	.owner		= THIS_MODULE,			\
@@ -961,6 +983,8 @@ static const struct regulator_ops s2mpu02_buck_ops = {
 #define regulator_desc_s2mpu02_ldo2(num) {		\
 	.name		= "LDO"#num,			\
 	.id		= S2MPU02_LDO##num,		\
+	.of_match	= of_match_ptr("LDO"#num),	\
+	.regulators_node = of_match_ptr("regulators"),	\
 	.ops		= &s2mpu02_ldo_ops,		\
 	.type		= REGULATOR_VOLTAGE,		\
 	.owner		= THIS_MODULE,			\
@@ -976,6 +1000,8 @@ static const struct regulator_ops s2mpu02_buck_ops = {
 #define regulator_desc_s2mpu02_ldo3(num) {		\
 	.name		= "LDO"#num,			\
 	.id		= S2MPU02_LDO##num,		\
+	.of_match	= of_match_ptr("LDO"#num),	\
+	.regulators_node = of_match_ptr("regulators"),	\
 	.ops		= &s2mpu02_ldo_ops,		\
 	.type		= REGULATOR_VOLTAGE,		\
 	.owner		= THIS_MODULE,			\
@@ -991,6 +1017,8 @@ static const struct regulator_ops s2mpu02_buck_ops = {
 #define regulator_desc_s2mpu02_ldo4(num) {		\
 	.name		= "LDO"#num,			\
 	.id		= S2MPU02_LDO##num,		\
+	.of_match	= of_match_ptr("LDO"#num),	\
+	.regulators_node = of_match_ptr("regulators"),	\
 	.ops		= &s2mpu02_ldo_ops,		\
 	.type		= REGULATOR_VOLTAGE,		\
 	.owner		= THIS_MODULE,			\
@@ -1006,6 +1034,8 @@ static const struct regulator_ops s2mpu02_buck_ops = {
 #define regulator_desc_s2mpu02_ldo5(num) {		\
 	.name		= "LDO"#num,			\
 	.id		= S2MPU02_LDO##num,		\
+	.of_match	= of_match_ptr("LDO"#num),	\
+	.regulators_node = of_match_ptr("regulators"),	\
 	.ops		= &s2mpu02_ldo_ops,		\
 	.type		= REGULATOR_VOLTAGE,		\
 	.owner		= THIS_MODULE,			\
@@ -1022,6 +1052,8 @@ static const struct regulator_ops s2mpu02_buck_ops = {
 #define regulator_desc_s2mpu02_buck1234(num) {			\
 	.name		= "BUCK"#num,				\
 	.id		= S2MPU02_BUCK##num,			\
+	.of_match	= of_match_ptr("BUCK"#num),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mpu02_buck_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -1038,6 +1070,8 @@ static const struct regulator_ops s2mpu02_buck_ops = {
 #define regulator_desc_s2mpu02_buck5(num) {			\
 	.name		= "BUCK"#num,				\
 	.id		= S2MPU02_BUCK##num,			\
+	.of_match	= of_match_ptr("BUCK"#num),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mpu02_ldo_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -1054,6 +1088,8 @@ static const struct regulator_ops s2mpu02_buck_ops = {
 #define regulator_desc_s2mpu02_buck6(num) {			\
 	.name		= "BUCK"#num,				\
 	.id		= S2MPU02_BUCK##num,			\
+	.of_match	= of_match_ptr("BUCK"#num),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mpu02_ldo_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -1070,6 +1106,8 @@ static const struct regulator_ops s2mpu02_buck_ops = {
 #define regulator_desc_s2mpu02_buck7(num) {			\
 	.name		= "BUCK"#num,				\
 	.id		= S2MPU02_BUCK##num,			\
+	.of_match	= of_match_ptr("BUCK"#num),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mpu02_ldo_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -1125,6 +1163,8 @@ static const struct regulator_desc s2mpu02_regulators[] = {
 #define regulator_desc_s2mpu05_ldo_reg(num, min, step, reg) {	\
 	.name		= "ldo"#num,				\
 	.id		= S2MPU05_LDO##num,			\
+	.of_match	= of_match_ptr("ldo"#num),		\
+	.regulators_node = of_match_ptr("regulators"),		\
 	.ops		= &s2mpu02_ldo_ops,			\
 	.type		= REGULATOR_VOLTAGE,			\
 	.owner		= THIS_MODULE,				\
@@ -1156,6 +1196,8 @@ static const struct regulator_desc s2mpu02_regulators[] = {
 #define regulator_desc_s2mpu05_buck(num, which) {	\
 	.name		= "buck"#num,			\
 	.id		= S2MPU05_BUCK##num,		\
+	.of_match	= of_match_ptr("buck"#num),	\
+	.regulators_node = of_match_ptr("regulators"),	\
 	.ops		= &s2mpu02_buck_ops,		\
 	.type		= REGULATOR_VOLTAGE,		\
 	.owner		= THIS_MODULE,			\
@@ -1254,22 +1296,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 				     s2mps11->dev_type);
 	}
 
-	s2mps11->ext_control_gpiod = devm_kcalloc(&pdev->dev, rdev_num,
-			       sizeof(*s2mps11->ext_control_gpiod), GFP_KERNEL);
-	if (!s2mps11->ext_control_gpiod)
-		return -ENOMEM;
-
-	struct of_regulator_match *rdata __free(kfree) =
-		kcalloc(rdev_num, sizeof(*rdata), GFP_KERNEL);
-	if (!rdata)
-		return -ENOMEM;
-
-	for (i = 0; i < rdev_num; i++)
-		rdata[i].name = regulators[i].name;
-
-	ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11, rdev_num);
-	if (ret)
-		return ret;
+	device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
 
 	platform_set_drvdata(pdev, s2mps11);
 
@@ -1279,15 +1306,6 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 	for (i = 0; i < rdev_num; i++) {
 		struct regulator_dev *regulator;
 
-		config.init_data = rdata[i].init_data;
-		config.of_node = rdata[i].of_node;
-		config.ena_gpiod = s2mps11->ext_control_gpiod[i];
-		/*
-		 * Hand the GPIO descriptor management over to the regulator
-		 * core, remove it from devres management.
-		 */
-		if (config.ena_gpiod)
-			devm_gpiod_unhinge(&pdev->dev, config.ena_gpiod);
 		regulator = devm_regulator_register(&pdev->dev,
 						&regulators[i], &config);
 		if (IS_ERR(regulator))
@@ -1296,7 +1314,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 					     regulators[i].id,
 					     regulators[i].name);
 
-		if (config.ena_gpiod) {
+		if (regulator->ena_pin) {
 			ret = s2mps14_pmic_enable_ext_control(s2mps11,
 							      regulator);
 			if (ret < 0)

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 15/20] regulator: s2mps11: refactor handling of external rail control
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (13 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 14/20] regulator: s2mps11: update node parsing (allow -supply properties) André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-03 19:14 ` [PATCH v3 16/20] regulator: s2mps11: add S2MPG10 regulator André Draszik
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

Refactor s2mps14_pmic_enable_ext_control() and s2mps11_of_parse_cb()
slightly as a preparation for adding S2MPG10 and S2MPG11 support, as
both of those PMICs also support control of rails via GPIOs.

Signed-off-by: André Draszik <andre.draszik@linaro.org>
---
 drivers/regulator/s2mps11.c | 86 ++++++++++++++++++++++++++++++---------------
 1 file changed, 57 insertions(+), 29 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 88e21c90832a45547e5791b15cd1de274f81fed6..bb0a4f35ef47551f7171321fdde2c0202ce86ede 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -328,27 +328,13 @@ static int s2mps11_regulator_set_suspend_disable(struct regulator_dev *rdev)
 				  rdev->desc->enable_mask, state);
 }
 
-static int s2mps11_of_parse_cb(struct device_node *np,
-			       const struct regulator_desc *desc,
-			       struct regulator_config *config)
+static int s2mps11_of_parse_gpiod(struct device_node *np,
+				  const struct regulator_desc *desc,
+				  struct regulator_config *config)
 {
-	const struct s2mps11_info *s2mps11 = config->driver_data;
 	struct gpio_desc *ena_gpiod;
 	int ret;
 
-	if (s2mps11->dev_type == S2MPS14X)
-		switch (desc->id) {
-		case S2MPS14_LDO10:
-		case S2MPS14_LDO11:
-		case S2MPS14_LDO12:
-			break;
-
-		default:
-			return 0;
-		}
-	else
-		return 0;
-
 	ena_gpiod = fwnode_gpiod_get_index(of_fwnode_handle(np),
 					   "samsung,ext-control", 0,
 					   GPIOD_OUT_HIGH |
@@ -380,6 +366,28 @@ static int s2mps11_of_parse_cb(struct device_node *np,
 	return 0;
 }
 
+static int s2mps11_of_parse_cb(struct device_node *np,
+			       const struct regulator_desc *desc,
+			       struct regulator_config *config)
+{
+	const struct s2mps11_info *s2mps11 = config->driver_data;
+
+	if (s2mps11->dev_type == S2MPS14X)
+		switch (desc->id) {
+		case S2MPS14_LDO10:
+		case S2MPS14_LDO11:
+		case S2MPS14_LDO12:
+			break;
+
+		default:
+			return 0;
+		}
+	else
+		return 0;
+
+	return s2mps11_of_parse_gpiod(np, desc, config);
+}
+
 static const struct regulator_ops s2mps11_ldo_ops = {
 	.list_voltage		= regulator_list_voltage_linear,
 	.map_voltage		= regulator_map_voltage_linear,
@@ -903,10 +911,16 @@ static const struct regulator_desc s2mps15_regulators[] = {
 };
 
 static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11,
-		struct regulator_dev *rdev)
+					   struct regulator_dev *rdev)
 {
-	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-			rdev->desc->enable_mask, S2MPS14_ENABLE_EXT_CONTROL);
+	int ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+				     rdev->desc->enable_mask,
+				     S2MPS14_ENABLE_EXT_CONTROL);
+	if (ret < 0)
+		return dev_err_probe(rdev_get_dev(rdev), ret,
+				     "failed to enable GPIO control over %d/%s\n",
+				     rdev->desc->id, rdev->desc->name);
+	return 0;
 }
 
 static int s2mpu02_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
@@ -1244,6 +1258,26 @@ static const struct regulator_desc s2mpu05_regulators[] = {
 	regulator_desc_s2mpu05_buck45(5),
 };
 
+static int s2mps11_handle_ext_control(struct s2mps11_info *s2mps11,
+				      struct regulator_dev *rdev)
+{
+	int ret;
+
+	switch (s2mps11->dev_type) {
+	case S2MPS14X:
+		if (!rdev->ena_pin)
+			return 0;
+
+		ret = s2mps14_pmic_enable_ext_control(s2mps11, rdev);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return ret;
+}
+
 static int s2mps11_pmic_probe(struct platform_device *pdev)
 {
 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
@@ -1314,15 +1348,9 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 					     regulators[i].id,
 					     regulators[i].name);
 
-		if (regulator->ena_pin) {
-			ret = s2mps14_pmic_enable_ext_control(s2mps11,
-							      regulator);
-			if (ret < 0)
-				return dev_err_probe(&pdev->dev, ret,
-						     "failed to enable GPIO control over %d/%s\n",
-						     regulator->desc->id,
-						     regulator->desc->name);
-		}
+		ret = s2mps11_handle_ext_control(s2mps11, regulator);
+		if (ret < 0)
+			return ret;
 	}
 
 	return 0;

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 16/20] regulator: s2mps11: add S2MPG10 regulator
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (14 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 15/20] regulator: s2mps11: refactor handling of external rail control André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-03 19:14 ` [PATCH v3 17/20] regulator: s2mps11: refactor S2MPG10 ::set_voltage_time() for S2MPG11 reuse André Draszik
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

The S2MPG10 PMIC is a Power Management IC for mobile applications with
buck converters, various LDOs, power meters, RTC, clock outputs, and
additional GPIO interfaces.

It has 10 buck and 31 LDO rails. Several of these can either be
controlled via software (register writes) or via external signals, in
particular by:
    * one out of several input pins connected to a main processor's:
        * GPIO pins
        * other pins that are e.g. firmware- or power-domain-controlled
          without explicit driver intervention
    * a combination of input pins and register writes.

Control via input pins allows PMIC rails to be controlled by firmware,
e.g. during standby/suspend, or as part of power domain handling where
otherwise that would not be possible. Additionally toggling a pin is
faster than register writes, and it also allows the PMIC to ensure that
any necessary timing requirements between rails are respected
automatically if multiple rails are to be enabled or disabled quasi
simultaneously.

This commit implements support for all these rails and control
combinations.

Additional data needs to be stored for each regulator, e.g. the input
pin for external control, or a rail-specific ramp-rate for when
enabling a buck-rail. Therefore, probe() is updated slightly to make
that possible.

Note1: For an externally controlled rail, the regulator_ops provide an
empty ::enable() and no ::disable() implementations, even though Linux
can not enable the rail and one might think ::enable could be NULL.
Without ops->enable(), the regulator core will assume enabling such a
rail failed, though, and in turn never add a reference to its parent
(supplier) rail. Once a different (Linux-controlled) sibling (consumer)
rail on that same parent rail gets disabled, the parent gets disabled
(cutting power to the externally controlled rail although it should
stay on), and the system will misbehave.

Note2: The rails are instantiated as separate driver instances for each
rail, because S2MPG10 is typically used with an S2MPG11 sub-PMIC where
some bucks of one typically supply at least some of the LDOs of the
other. Using separate instances avoids issues around circular
dependencies which occur otherwise.

Note3: While external control via input pins appears to exist on other
versions of this PMIC, there is more flexibility in this version, in
particular there is a selection of input pins to choose from for each
rail (which must therefore be configured accordingly if in use),
whereas other versions don't have this flexibility.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
v3:
- one instance per actual rail, not per rail type (LDO or buck)
- use REGULATOR_LINEAR_VRANGE macro
- sort s2mpg10 bucks before LDOs throughout (alphabetic ordering)
- LDO 1 and 7 also support setting a ramp rate
- add ::enable() to ops for signal-controlled rails and update commit
  message detailing why
- more details around signal controlled rails in commit message
- switch to 'enable-gpios' instead of samsung,ext-control-gpios for
  OS-controlled GPIOs (Krzysztof)

v2:
- move assignment of ::of_parse_cb in regulator_desc_s2mpg10_buck() to
  match order of struct definition
---
 drivers/regulator/s2mps11.c         | 599 +++++++++++++++++++++++++++++++++++-
 include/linux/mfd/samsung/s2mpg10.h |  24 ++
 2 files changed, 617 insertions(+), 6 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index bb0a4f35ef47551f7171321fdde2c0202ce86ede..aff85138fa5da4cff83bdec5cdb3086a58afc7ce 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -3,6 +3,7 @@
 // Copyright (c) 2012-2014 Samsung Electronics Co., Ltd
 //              http://www.samsung.com
 
+#include <dt-bindings/regulator/samsung,s2mpg10-regulator.h>
 #include <linux/bug.h>
 #include <linux/cleanup.h>
 #include <linux/err.h>
@@ -15,7 +16,9 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
+#include <linux/mfd/core.h>
 #include <linux/mfd/samsung/core.h>
+#include <linux/mfd/samsung/s2mpg10.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps13.h>
 #include <linux/mfd/samsung/s2mps14.h>
@@ -23,6 +26,11 @@
 #include <linux/mfd/samsung/s2mpu02.h>
 #include <linux/mfd/samsung/s2mpu05.h>
 
+enum {
+	S2MPG10_REGULATOR_OPS_STD,
+	S2MPG10_REGULATOR_OPS_EXTCONTROL,
+};
+
 /* The highest number of possible regulators for supported devices. */
 #define S2MPS_REGULATOR_MAX		S2MPS13_REGULATOR_MAX
 struct s2mps11_info {
@@ -42,6 +50,21 @@ struct s2mps11_info {
 	DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX);
 };
 
+#define to_s2mpg10_regulator_desc(x) container_of((x), struct s2mpg10_regulator_desc, desc)
+
+struct s2mpg10_regulator_desc {
+	struct regulator_desc desc;
+
+	/* Ramp rate during enable, valid for bucks only. */
+	unsigned int enable_ramp_rate;
+
+	/* Registers for external control of rail. */
+	unsigned int pctrlsel_reg;
+	unsigned int pctrlsel_mask;
+	/* Populated from DT. */
+	unsigned int pctrlsel_val;
+};
+
 static int get_ramp_delay(int ramp_delay)
 {
 	unsigned char cnt = 0;
@@ -329,14 +352,14 @@ static int s2mps11_regulator_set_suspend_disable(struct regulator_dev *rdev)
 }
 
 static int s2mps11_of_parse_gpiod(struct device_node *np,
+				  const char *con_id,
 				  const struct regulator_desc *desc,
 				  struct regulator_config *config)
 {
 	struct gpio_desc *ena_gpiod;
 	int ret;
 
-	ena_gpiod = fwnode_gpiod_get_index(of_fwnode_handle(np),
-					   "samsung,ext-control", 0,
+	ena_gpiod = fwnode_gpiod_get_index(of_fwnode_handle(np), con_id, 0,
 					   GPIOD_OUT_HIGH |
 					   GPIOD_FLAGS_BIT_NONEXCLUSIVE,
 					   "s2mps11-regulator");
@@ -385,9 +408,533 @@ static int s2mps11_of_parse_cb(struct device_node *np,
 	else
 		return 0;
 
-	return s2mps11_of_parse_gpiod(np, desc, config);
+	return s2mps11_of_parse_gpiod(np, "samsung,ext-control", desc, config);
+}
+
+static int s2mpg10_of_parse_cb(struct device_node *np,
+			       const struct regulator_desc *desc,
+			       struct regulator_config *config)
+{
+	const struct s2mps11_info *s2mps11 = config->driver_data;
+	struct s2mpg10_regulator_desc *s2mpg10_desc = to_s2mpg10_regulator_desc(desc);
+	static const u32 ext_control_s2mpg10[] = {
+		[S2MPG10_EXTCTRL_PWREN] = S2MPG10_PCTRLSEL_PWREN,
+		[S2MPG10_EXTCTRL_PWREN_MIF] = S2MPG10_PCTRLSEL_PWREN_MIF,
+		[S2MPG10_EXTCTRL_AP_ACTIVE_N] = S2MPG10_PCTRLSEL_AP_ACTIVE_N,
+		[S2MPG10_EXTCTRL_CPUCL1_EN] = S2MPG10_PCTRLSEL_CPUCL1_EN,
+		[S2MPG10_EXTCTRL_CPUCL1_EN2] = S2MPG10_PCTRLSEL_CPUCL1_EN2,
+		[S2MPG10_EXTCTRL_CPUCL2_EN] = S2MPG10_PCTRLSEL_CPUCL2_EN,
+		[S2MPG10_EXTCTRL_CPUCL2_EN2] = S2MPG10_PCTRLSEL_CPUCL2_EN2,
+		[S2MPG10_EXTCTRL_TPU_EN] = S2MPG10_PCTRLSEL_TPU_EN,
+		[S2MPG10_EXTCTRL_TPU_EN2] = S2MPG10_PCTRLSEL_TPU_EN2,
+		[S2MPG10_EXTCTRL_TCXO_ON] = S2MPG10_PCTRLSEL_TCXO_ON,
+		[S2MPG10_EXTCTRL_TCXO_ON2] = S2MPG10_PCTRLSEL_TCXO_ON2,
+		[S2MPG10_EXTCTRL_LDO20M_EN2] = S2MPG10_PCTRLSEL_LDO20M_EN2,
+		[S2MPG10_EXTCTRL_LDO20M_EN] = S2MPG10_PCTRLSEL_LDO20M_EN,
+	};
+	u32 ext_control;
+
+	if (s2mps11->dev_type != S2MPG10)
+		return 0;
+
+	if (of_property_read_u32(np, "samsung,ext-control", &ext_control))
+		return 0;
+
+	switch (s2mps11->dev_type) {
+	case S2MPG10:
+		switch (desc->id) {
+		case S2MPG10_BUCK1 ... S2MPG10_BUCK7:
+		case S2MPG10_BUCK10:
+		case S2MPG10_LDO3 ... S2MPG10_LDO19:
+			if (ext_control > S2MPG10_EXTCTRL_TCXO_ON2)
+				return -EINVAL;
+			break;
+
+		case S2MPG10_LDO20:
+			if (ext_control < S2MPG10_EXTCTRL_LDO20M_EN2 ||
+			    ext_control > S2MPG10_EXTCTRL_LDO20M_EN)
+				return -EINVAL;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		if (ext_control > ARRAY_SIZE(ext_control_s2mpg10))
+			return -EINVAL;
+		ext_control = ext_control_s2mpg10[ext_control];
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * If the regulator should be configured for external control, then:
+	 * 1) the PCTRLSELx register needs to be set accordingly
+	 * 2) regulator_desc::enable_val needs to be:
+	 *    a) updated and
+	 *    b) written to the hardware
+	 * 3) we switch to the ::ops that provide an empty ::enable() and no
+	 *    ::disable() implementations
+	 *
+	 * Points 1) and 2b) will be handled in _probe(), after
+	 * devm_regulator_register() returns, so that we can properly act on
+	 * failures, since the regulator core ignores most return values from
+	 * this parse callback.
+	 */
+	s2mpg10_desc->pctrlsel_val = ext_control;
+	s2mpg10_desc->pctrlsel_val <<= (ffs(s2mpg10_desc->pctrlsel_mask) - 1);
+
+	s2mpg10_desc->desc.enable_val = S2MPG10_PMIC_CTRL_ENABLE_EXT;
+	s2mpg10_desc->desc.enable_val <<= (ffs(desc->enable_mask) - 1);
+
+	++s2mpg10_desc->desc.ops;
+
+	return s2mps11_of_parse_gpiod(np, "enable", desc, config);
+}
+
+static int s2mpg10_enable_ext_control(struct s2mps11_info *s2mps11,
+				      struct regulator_dev *rdev)
+{
+	const struct s2mpg10_regulator_desc *s2mpg10_desc;
+	int ret;
+
+	switch (s2mps11->dev_type) {
+	case S2MPG10:
+		s2mpg10_desc = to_s2mpg10_regulator_desc(rdev->desc);
+		break;
+
+	default:
+		return 0;
+	}
+
+	ret = regmap_update_bits(rdev_get_regmap(rdev),
+				 s2mpg10_desc->pctrlsel_reg,
+				 s2mpg10_desc->pctrlsel_mask,
+				 s2mpg10_desc->pctrlsel_val);
+	if (ret)
+		return dev_err_probe(rdev_get_dev(rdev), ret,
+				     "failed to configure pctrlsel for %s\n",
+				     rdev->desc->name);
+
+	/*
+	 * When using external control, the enable bit of the regulator still
+	 * needs to be set. The actual state will still be determined by the
+	 * external signal.
+	 */
+	ret = regulator_enable_regmap(rdev);
+	if (ret)
+		return dev_err_probe(rdev_get_dev(rdev), ret,
+				     "failed to enable regulator %s\n",
+				     rdev->desc->name);
+
+	return 0;
+}
+
+static int s2mpg10_regulator_enable_nop(struct regulator_dev *rdev)
+{
+	/*
+	 * We need to provide this, otherwise the regulator core's enable on
+	 * this regulator will return a failure and subsequently disable our
+	 * parent regulator.
+	 */
+	return 0;
+}
+
+static int s2mpg10_regulator_buck_enable_time(struct regulator_dev *rdev)
+{
+	const struct s2mpg10_regulator_desc * const s2mpg10_desc =
+		to_s2mpg10_regulator_desc(rdev->desc);
+	const struct regulator_ops * const ops = rdev->desc->ops;
+	int vsel, curr_uV;
+
+	vsel = ops->get_voltage_sel(rdev);
+	if (vsel < 0)
+		return vsel;
+
+	curr_uV = ops->list_voltage(rdev, vsel);
+	if (curr_uV < 0)
+		return curr_uV;
+
+	return (rdev->desc->enable_time
+		+ DIV_ROUND_UP(curr_uV, s2mpg10_desc->enable_ramp_rate));
 }
 
+static int s2mpg10_regulator_buck_set_voltage_time(struct regulator_dev *rdev,
+						   int old_uV, int new_uV)
+{
+	unsigned int ramp_reg, ramp_sel, ramp_rate;
+	int ret;
+
+	if (old_uV == new_uV)
+		return 0;
+
+	ramp_reg = rdev->desc->ramp_reg;
+	if (old_uV > new_uV)
+		/* The downwards ramp is at a different offset. */
+		ramp_reg += S2MPG10_PMIC_DVS_RAMP4 - S2MPG10_PMIC_DVS_RAMP1;
+
+	ret = regmap_read(rdev->regmap, ramp_reg, &ramp_sel);
+	if (ret)
+		return ret;
+
+	ramp_sel &= rdev->desc->ramp_mask;
+	ramp_sel >>= ffs(rdev->desc->ramp_mask) - 1;
+	if (ramp_sel >= rdev->desc->n_ramp_values ||
+	    !rdev->desc->ramp_delay_table)
+		return -EINVAL;
+
+	ramp_rate = rdev->desc->ramp_delay_table[ramp_sel];
+
+	return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_rate);
+}
+
+/*
+ * We assign both, ::set_voltage_time() and ::set_voltage_time_sel(), because
+ * only if the latter is != NULL, the regulator core will call neither during
+ * DVS if the regulator is disabled. If the latter is NULL, the core always
+ * calls the ::set_voltage_time() callback, which would give incorrect results
+ * if the regulator is off.
+ * At the same time, we do need ::set_voltage_time() due to differing upwards
+ * and downwards ramps and we can not make that code dependent on the regulator
+ * enable state, as that would break regulator_set_voltage_time() which
+ * expects a correct result no matter the enable state.
+ */
+static const struct regulator_ops s2mpg10_reg_buck_ops[] = {
+	[S2MPG10_REGULATOR_OPS_STD] = {
+		.list_voltage		= regulator_list_voltage_linear_range,
+		.map_voltage		= regulator_map_voltage_linear_range,
+		.is_enabled		= regulator_is_enabled_regmap,
+		.enable			= regulator_enable_regmap,
+		.disable		= regulator_disable_regmap,
+		.enable_time		= s2mpg10_regulator_buck_enable_time,
+		.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+		.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+		.set_voltage_time	= s2mpg10_regulator_buck_set_voltage_time,
+		.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+		.set_ramp_delay		= regulator_set_ramp_delay_regmap,
+	},
+	[S2MPG10_REGULATOR_OPS_EXTCONTROL] = {
+		.list_voltage		= regulator_list_voltage_linear_range,
+		.map_voltage		= regulator_map_voltage_linear_range,
+		.enable			= s2mpg10_regulator_enable_nop,
+		.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+		.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+		.set_voltage_time	= s2mpg10_regulator_buck_set_voltage_time,
+		.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+		.set_ramp_delay		= regulator_set_ramp_delay_regmap,
+	}
+};
+
+#define s2mpg10_buck_to_ramp_mask(n) (GENMASK(1, 0) << (((n) % 4) * 2))
+
+/*
+ * The ramp_delay during enable is fixed (12.5mV/μs), while the ramp during
+ * DVS can be adjusted. Linux can adjust the ramp delay via DT, in which case
+ * the regulator core will modify the regulator's constraints and call our
+ * .set_ramp_delay() which updates the DVS ramp in ramp_reg.
+ * For enable, our .enable_time() unconditionally uses enable_ramp_rate
+ * (12.5mV/μs) while our ::set_voltage_time() takes the value in ramp_reg
+ * into account.
+ */
+#define regulator_desc_s2mpg10_buck(_num, _vrange, _r_reg) {		\
+	.name		= "buck"#_num "m",				\
+	.supply_name	= "vinb"#_num "m",				\
+	.of_match	= of_match_ptr("buck"#_num "m"),		\
+	.regulators_node = of_match_ptr("regulators"),			\
+	.of_parse_cb	= s2mpg10_of_parse_cb,				\
+	.id		= S2MPG10_BUCK##_num,				\
+	.ops		= &s2mpg10_reg_buck_ops[0],			\
+	.type		= REGULATOR_VOLTAGE,				\
+	.owner		= THIS_MODULE,					\
+	.linear_ranges	= _vrange,					\
+	.n_linear_ranges = ARRAY_SIZE(_vrange),				\
+	.n_voltages	= _vrange##_count,				\
+	.vsel_reg	= S2MPG10_PMIC_B##_num##M_OUT1,			\
+	.vsel_mask	= 0xff,						\
+	.enable_reg	= S2MPG10_PMIC_B##_num##M_CTRL,			\
+	.enable_mask	= GENMASK(7, 6),				\
+	.ramp_reg	= S2MPG10_PMIC_##_r_reg,			\
+	.ramp_mask	= s2mpg10_buck_to_ramp_mask(S2MPG10_BUCK##_num	\
+						    - S2MPG10_BUCK1),	\
+	.ramp_delay_table = s2mpg10_buck_ramp_table,			\
+	.n_ramp_values	= ARRAY_SIZE(s2mpg10_buck_ramp_table),		\
+	.enable_time	= 30, /* + V/enable_ramp_rate */		\
+}
+
+#define s2mpg10_regulator_desc_buck_cm(_num, _vrange, _r_reg)		\
+	.desc = regulator_desc_s2mpg10_buck(_num, _vrange, _r_reg),	\
+	.enable_ramp_rate = 12500
+
+#define s2mpg10_regulator_desc_buck_gpio(_num, _vrange, _r_reg,		\
+					 _pc_reg, _pc_mask)		\
+	[S2MPG10_BUCK##_num] = {					\
+		s2mpg10_regulator_desc_buck_cm(_num, _vrange, _r_reg),	\
+		.pctrlsel_reg = S2MPG10_PMIC_##_pc_reg,			\
+		.pctrlsel_mask = _pc_mask,				\
+	}
+
+#define s2mpg10_regulator_desc_buck(_num, _vrange, _r_reg)		\
+	[S2MPG10_BUCK##_num] = {					\
+		s2mpg10_regulator_desc_buck_cm(_num, _vrange, _r_reg),	\
+	}
+
+/* ops for S2MPG1x LDO regulators without ramp control */
+static const struct regulator_ops s2mpg10_reg_ldo_ops[] = {
+	[S2MPG10_REGULATOR_OPS_STD] = {
+		.list_voltage		= regulator_list_voltage_linear_range,
+		.map_voltage		= regulator_map_voltage_linear_range,
+		.is_enabled		= regulator_is_enabled_regmap,
+		.enable			= regulator_enable_regmap,
+		.disable		= regulator_disable_regmap,
+		.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+		.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+		.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+	},
+	[S2MPG10_REGULATOR_OPS_EXTCONTROL] = {
+		.list_voltage		= regulator_list_voltage_linear_range,
+		.map_voltage		= regulator_map_voltage_linear_range,
+		.enable			= s2mpg10_regulator_enable_nop,
+		.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+		.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+		.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+	}
+};
+
+/* ops for S2MPG1x LDO regulators that have ramp control */
+static const struct regulator_ops s2mpg10_reg_ldo_ramp_ops[] = {
+	[S2MPG10_REGULATOR_OPS_STD] = {
+		.list_voltage		= regulator_list_voltage_linear_range,
+		.map_voltage		= regulator_map_voltage_linear_range,
+		.is_enabled		= regulator_is_enabled_regmap,
+		.enable			= regulator_enable_regmap,
+		.disable		= regulator_disable_regmap,
+		.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+		.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+		.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+		.set_ramp_delay		= regulator_set_ramp_delay_regmap,
+	},
+	[S2MPG10_REGULATOR_OPS_EXTCONTROL] = {
+		.list_voltage		= regulator_list_voltage_linear_range,
+		.map_voltage		= regulator_map_voltage_linear_range,
+		.enable			= s2mpg10_regulator_enable_nop,
+		.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+		.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+		.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+		.set_ramp_delay		= regulator_set_ramp_delay_regmap,
+	}
+};
+
+#define regulator_desc_s2mpg10_ldo_cmn(_num, _supply, _ops, _vrange,	\
+		_vsel_reg_sfx, _vsel_mask, _en_reg, _en_mask,		\
+		_ramp_delay, _r_reg, _r_mask, _r_table,	_r_table_sz) {	\
+	.name		= "ldo"#_num "m",				\
+	.supply_name	= _supply,					\
+	.of_match	= of_match_ptr("ldo"#_num "m"),			\
+	.regulators_node = of_match_ptr("regulators"),			\
+	.of_parse_cb	= s2mpg10_of_parse_cb,				\
+	.id		= S2MPG10_LDO##_num,				\
+	.ops		= &(_ops)[0],					\
+	.type		= REGULATOR_VOLTAGE,				\
+	.owner		= THIS_MODULE,					\
+	.linear_ranges	= _vrange,					\
+	.n_linear_ranges = ARRAY_SIZE(_vrange),				\
+	.n_voltages	= _vrange##_count,				\
+	.vsel_reg	= S2MPG10_PMIC_L##_num##M_##_vsel_reg_sfx,	\
+	.vsel_mask	= _vsel_mask,					\
+	.enable_reg	= S2MPG10_PMIC_##_en_reg,			\
+	.enable_mask	= _en_mask,					\
+	.ramp_delay	= _ramp_delay,					\
+	.ramp_reg	= _r_reg,					\
+	.ramp_mask	= _r_mask,					\
+	.ramp_delay_table = _r_table,					\
+	.n_ramp_values	= _r_table_sz,					\
+	.enable_time	= 130, /* startup 20+-10 + ramp 30..100μs */	\
+}
+
+#define s2mpg10_regulator_desc_ldo_cmn(_num, _supply, _ops, _vrange,	\
+		_vsel_reg_sfx, _vsel_mask, _en_reg, _en_mask,		\
+		_ramp_delay, _r_reg, _r_mask, _r_table,	_r_table_sz,	\
+		_pc_reg, _pc_mask)					\
+	[S2MPG10_LDO##_num] = {						\
+		.desc = regulator_desc_s2mpg10_ldo_cmn(_num, _supply,	\
+				_ops,					\
+				_vrange, _vsel_reg_sfx, _vsel_mask,	\
+				_en_reg, _en_mask,			\
+				_ramp_delay, _r_reg, _r_mask, _r_table,	\
+				_r_table_sz),				\
+		.pctrlsel_reg = _pc_reg,				\
+		.pctrlsel_mask = _pc_mask,				\
+	}
+
+/* standard LDO via LxM_CTRL */
+#define s2mpg10_regulator_desc_ldo(_num, _supply, _vrange)		\
+	s2mpg10_regulator_desc_ldo_cmn(_num, _supply,			\
+		s2mpg10_reg_ldo_ops, _vrange, CTRL, GENMASK(5, 0),	\
+		L##_num##M_CTRL, BIT(7),				\
+		0, 0, 0, NULL, 0,					\
+		0, 0)
+
+/* standard LDO but possibly GPIO controlled */
+#define s2mpg10_regulator_desc_ldo_gpio(_num, _supply, _vrange,		\
+					_pc_reg, _pc_mask)		\
+	s2mpg10_regulator_desc_ldo_cmn(_num, _supply,			\
+		s2mpg10_reg_ldo_ops, _vrange, CTRL, GENMASK(5, 0),	\
+		L##_num##M_CTRL, GENMASK(7, 6),				\
+		0, 0, 0, NULL, 0,					\
+		S2MPG10_PMIC_##_pc_reg, _pc_mask)
+
+/* LDO with ramp support and possibly GPIO controlled */
+#define s2mpg10_regulator_desc_ldo_ramp(_num, _supply, _vrange,		\
+		_en_mask, _r_reg, _pc_reg, _pc_mask)			\
+	s2mpg10_regulator_desc_ldo_cmn(_num, _supply,			\
+		s2mpg10_reg_ldo_ramp_ops, _vrange, CTRL1, GENMASK(6, 0), \
+		LDO_CTRL2, _en_mask,					\
+		6250, S2MPG10_PMIC_##_r_reg, GENMASK(1, 0),		\
+		s2mpg10_ldo_ramp_table,					\
+		ARRAY_SIZE(s2mpg10_ldo_ramp_table),			\
+		S2MPG10_PMIC_##_pc_reg, _pc_mask)
+
+#define S2MPG10_VOLTAGE_RANGE(_prefix, _idx, _offs_uV, _min_uV,		\
+			      _max_uV, _step_uV)			\
+static const struct linear_range _prefix##_vranges##_idx[] = {		\
+	REGULATOR_LINEAR_VRANGE(_offs_uV, _min_uV, _max_uV, _step_uV)	\
+};									\
+static const unsigned int _prefix##_vranges##_idx##_count =		\
+	((((_max_uV) - (_offs_uV)) / (_step_uV)) + 1)
+
+/* voltage range for s2mpg10 BUCK 1, 2, 3, 4, 5, 7, 8, 9, 10 */
+S2MPG10_VOLTAGE_RANGE(s2mpg10_buck, 1, 200000, 450000, 1300000, STEP_6_25_MV);
+
+/* voltage range for s2mpg10 BUCK 6 */
+S2MPG10_VOLTAGE_RANGE(s2mpg10_buck, 6, 200000, 450000, 1350000, STEP_6_25_MV);
+
+static const unsigned int s2mpg10_buck_ramp_table[] = {
+	6250, 12500, 25000
+};
+
+/* voltage range for s2mpg10 LDO 1, 11, 12 */
+S2MPG10_VOLTAGE_RANGE(s2mpg10_ldo, 1, 300000, 700000, 1300000, STEP_12_5_MV);
+
+/* voltage range for s2mpg10 LDO 2, 4, 9, 14, 18, 19, 20, 23, 25, 29, 30, 31 */
+S2MPG10_VOLTAGE_RANGE(s2mpg10_ldo, 2, 700000, 1600000, 1950000, STEP_25_MV);
+
+/* voltage range for s2mpg10 LDO 3, 5, 6, 8, 16, 17, 24, 28 */
+S2MPG10_VOLTAGE_RANGE(s2mpg10_ldo, 3, 725000, 725000, 1300000, STEP_12_5_MV);
+
+/* voltage range for s2mpg10 LDO 7 */
+S2MPG10_VOLTAGE_RANGE(s2mpg10_ldo, 7, 300000, 450000, 1300000, STEP_12_5_MV);
+
+/* voltage range for s2mpg10 LDO 13, 15 */
+S2MPG10_VOLTAGE_RANGE(s2mpg10_ldo, 13, 300000, 450000, 950000, STEP_12_5_MV);
+
+/* voltage range for s2mpg10 LDO 10 */
+S2MPG10_VOLTAGE_RANGE(s2mpg10_ldo, 10, 1800000, 1800000, 3350000, STEP_25_MV);
+
+/* voltage range for s2mpg10 LDO 21, 22, 26, 27 */
+S2MPG10_VOLTAGE_RANGE(s2mpg10_ldo, 21, 1800000, 2500000, 3300000, STEP_25_MV);
+
+/* possible ramp values for s2mpg10 LDO 1, 7, 11, 12, 13, 15 */
+static const unsigned int s2mpg10_ldo_ramp_table[] = {
+	6250, 12500
+};
+
+static const struct s2mpg10_regulator_desc s2mpg10_regulators[] = {
+	s2mpg10_regulator_desc_buck_gpio(1, s2mpg10_buck_vranges1, DVS_RAMP1,
+					 PCTRLSEL1, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_buck_gpio(2, s2mpg10_buck_vranges1, DVS_RAMP1,
+					 PCTRLSEL1, GENMASK(7, 4)),
+	s2mpg10_regulator_desc_buck_gpio(3, s2mpg10_buck_vranges1, DVS_RAMP1,
+					 PCTRLSEL2, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_buck_gpio(4, s2mpg10_buck_vranges1, DVS_RAMP1,
+					 PCTRLSEL2, GENMASK(7, 4)),
+	s2mpg10_regulator_desc_buck_gpio(5, s2mpg10_buck_vranges1, DVS_RAMP2,
+					 PCTRLSEL3, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_buck_gpio(6, s2mpg10_buck_vranges6, DVS_RAMP2,
+					 PCTRLSEL3, GENMASK(7, 4)),
+	s2mpg10_regulator_desc_buck_gpio(7, s2mpg10_buck_vranges1, DVS_RAMP2,
+					 PCTRLSEL4, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_buck(8, s2mpg10_buck_vranges1, DVS_RAMP2),
+	s2mpg10_regulator_desc_buck(9, s2mpg10_buck_vranges1, DVS_RAMP3),
+	s2mpg10_regulator_desc_buck_gpio(10, s2mpg10_buck_vranges1, DVS_RAMP3,
+					 PCTRLSEL4, GENMASK(7, 4)),
+	/*
+	 * Standard LDO via LxM_CTRL but non-standard (greater) V-range and with
+	 * ramp support.
+	 */
+	s2mpg10_regulator_desc_ldo_cmn(1, "vinl3m", s2mpg10_reg_ldo_ramp_ops,
+				       s2mpg10_ldo_vranges1,
+				       CTRL, GENMASK(6, 0),
+				       L1M_CTRL, BIT(7),
+				       6250, S2MPG10_PMIC_DVS_RAMP6,
+				       GENMASK(5, 4), s2mpg10_ldo_ramp_table,
+				       ARRAY_SIZE(s2mpg10_ldo_ramp_table),
+				       0, 0),
+	s2mpg10_regulator_desc_ldo(2, "vinl9m", s2mpg10_ldo_vranges2),
+	s2mpg10_regulator_desc_ldo_gpio(3, "vinl4m", s2mpg10_ldo_vranges3,
+					PCTRLSEL5, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_ldo_gpio(4, "vinl9m", s2mpg10_ldo_vranges2,
+					PCTRLSEL5, GENMASK(7, 4)),
+	s2mpg10_regulator_desc_ldo_gpio(5, "vinl3m", s2mpg10_ldo_vranges3,
+					PCTRLSEL6, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_ldo_gpio(6, "vinl7m", s2mpg10_ldo_vranges3,
+					PCTRLSEL6, GENMASK(7, 4)),
+	/*
+	 * Ramp support, possibly GPIO controlled, non-standard (greater) V-
+	 * range and enable reg & mask.
+	 */
+	s2mpg10_regulator_desc_ldo_cmn(7, "vinl3m", s2mpg10_reg_ldo_ramp_ops,
+				       s2mpg10_ldo_vranges7,
+				       CTRL, GENMASK(6, 0),
+				       LDO_CTRL1, GENMASK(4, 3),
+				       6250, S2MPG10_PMIC_DVS_RAMP6,
+				       GENMASK(7, 6), s2mpg10_ldo_ramp_table,
+				       ARRAY_SIZE(s2mpg10_ldo_ramp_table),
+				       S2MPG10_PMIC_PCTRLSEL7, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_ldo_gpio(8, "vinl4m", s2mpg10_ldo_vranges3,
+					PCTRLSEL7, GENMASK(7, 4)),
+	s2mpg10_regulator_desc_ldo_gpio(9, "vinl10m", s2mpg10_ldo_vranges2,
+					PCTRLSEL8, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_ldo_gpio(10, "vinl15m", s2mpg10_ldo_vranges10,
+					PCTRLSEL8, GENMASK(7, 4)),
+	s2mpg10_regulator_desc_ldo_ramp(11, "vinl7m", s2mpg10_ldo_vranges1,
+					GENMASK(1, 0), DVS_SYNC_CTRL3,
+					PCTRLSEL9, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_ldo_ramp(12, "vinl8m", s2mpg10_ldo_vranges1,
+					GENMASK(3, 2), DVS_SYNC_CTRL4,
+					PCTRLSEL9, GENMASK(7, 4)),
+	s2mpg10_regulator_desc_ldo_ramp(13, "vinl1m", s2mpg10_ldo_vranges13,
+					GENMASK(5, 4), DVS_SYNC_CTRL5,
+					PCTRLSEL10, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_ldo_gpio(14, "vinl10m", s2mpg10_ldo_vranges2,
+					PCTRLSEL10, GENMASK(7, 4)),
+	s2mpg10_regulator_desc_ldo_ramp(15, "vinl2m", s2mpg10_ldo_vranges13,
+					GENMASK(7, 6), DVS_SYNC_CTRL6,
+					PCTRLSEL11, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_ldo_gpio(16, "vinl5m", s2mpg10_ldo_vranges3,
+					PCTRLSEL11, GENMASK(7, 4)),
+	s2mpg10_regulator_desc_ldo_gpio(17, "vinl6m", s2mpg10_ldo_vranges3,
+					PCTRLSEL12, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_ldo_gpio(18, "vinl10m", s2mpg10_ldo_vranges2,
+					PCTRLSEL12, GENMASK(7, 4)),
+	s2mpg10_regulator_desc_ldo_gpio(19, "vinl10m", s2mpg10_ldo_vranges2,
+					PCTRLSEL13, GENMASK(3, 0)),
+	s2mpg10_regulator_desc_ldo_gpio(20, "vinl10m", s2mpg10_ldo_vranges2,
+					PCTRLSEL13, GENMASK(7, 4)),
+	s2mpg10_regulator_desc_ldo(21, "vinl14m", s2mpg10_ldo_vranges21),
+	s2mpg10_regulator_desc_ldo(22, "vinl15m", s2mpg10_ldo_vranges21),
+	s2mpg10_regulator_desc_ldo(23, "vinl11m", s2mpg10_ldo_vranges2),
+	s2mpg10_regulator_desc_ldo(24, "vinl7m", s2mpg10_ldo_vranges3),
+	s2mpg10_regulator_desc_ldo(25, "vinl10m", s2mpg10_ldo_vranges2),
+	s2mpg10_regulator_desc_ldo(26, "vinl15m", s2mpg10_ldo_vranges21),
+	s2mpg10_regulator_desc_ldo(27, "vinl15m", s2mpg10_ldo_vranges21),
+	s2mpg10_regulator_desc_ldo(28, "vinl7m", s2mpg10_ldo_vranges3),
+	s2mpg10_regulator_desc_ldo(29, "vinl12m", s2mpg10_ldo_vranges2),
+	s2mpg10_regulator_desc_ldo(30, "vinl13m", s2mpg10_ldo_vranges2),
+	s2mpg10_regulator_desc_ldo(31, "vinl11m", s2mpg10_ldo_vranges2)
+};
+
 static const struct regulator_ops s2mps11_ldo_ops = {
 	.list_voltage		= regulator_list_voltage_linear,
 	.map_voltage		= regulator_map_voltage_linear,
@@ -1271,6 +1818,18 @@ static int s2mps11_handle_ext_control(struct s2mps11_info *s2mps11,
 		ret = s2mps14_pmic_enable_ext_control(s2mps11, rdev);
 		break;
 
+	case S2MPG10:
+		/*
+		 * If desc.enable_val is != 0, then external control was
+		 * requested. We can not test s2mpg10_desc::ext_control,
+		 * because 0 is a valid value.
+		 */
+		if (!rdev->desc->enable_val)
+			return 0;
+
+		ret = s2mpg10_enable_ext_control(s2mps11, rdev);
+		break;
+
 	default:
 		return 0;
 	}
@@ -1281,11 +1840,13 @@ static int s2mps11_handle_ext_control(struct s2mps11_info *s2mps11,
 static int s2mps11_pmic_probe(struct platform_device *pdev)
 {
 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
 	struct regulator_config config = { };
 	struct s2mps11_info *s2mps11;
 	unsigned int rdev_num;
 	int i, ret;
 	const struct regulator_desc *regulators;
+	const struct s2mpg10_regulator_desc *s2mpg1x_regulators = NULL;
 
 	s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
 				GFP_KERNEL);
@@ -1294,6 +1855,16 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 
 	s2mps11->dev_type = platform_get_device_id(pdev)->driver_data;
 	switch (s2mps11->dev_type) {
+	case S2MPG10:
+		if (cell->id >= ARRAY_SIZE(s2mpg10_regulators))
+			return dev_err_probe(&pdev->dev, -ENODEV,
+					     "Unsupported regulator ID %d\n",
+					     cell->id);
+
+		rdev_num = 1;
+		s2mpg1x_regulators = &s2mpg10_regulators[cell->id];
+		BUILD_BUG_ON(ARRAY_SIZE(s2mpg10_regulators) > S2MPS_REGULATOR_MAX);
+		break;
 	case S2MPS11X:
 		rdev_num = ARRAY_SIZE(s2mps11_regulators);
 		regulators = s2mps11_regulators;
@@ -1338,15 +1909,30 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 	config.regmap = iodev->regmap_pmic;
 	config.driver_data = s2mps11;
 	for (i = 0; i < rdev_num; i++) {
+		const struct regulator_desc *rdesc;
 		struct regulator_dev *regulator;
 
+		if (s2mpg1x_regulators) {
+			struct s2mpg10_regulator_desc *s2mpg10_desc;
+
+			s2mpg10_desc = devm_kmemdup(&pdev->dev,
+						    &s2mpg1x_regulators[i],
+						    sizeof(*s2mpg10_desc),
+						    GFP_KERNEL);
+			if (!s2mpg10_desc)
+				return -ENOMEM;
+
+			rdesc = &s2mpg10_desc->desc;
+		} else {
+			rdesc = &regulators[i];
+		}
+
 		regulator = devm_regulator_register(&pdev->dev,
-						&regulators[i], &config);
+						    rdesc, &config);
 		if (IS_ERR(regulator))
 			return dev_err_probe(&pdev->dev, PTR_ERR(regulator),
 					     "regulator init failed for %d/%s\n",
-					     regulators[i].id,
-					     regulators[i].name);
+					     rdesc->id, rdesc->name);
 
 		ret = s2mps11_handle_ext_control(s2mps11, regulator);
 		if (ret < 0)
@@ -1357,6 +1943,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id s2mps11_pmic_id[] = {
+	{ "s2mpg10-regulator", S2MPG10},
 	{ "s2mps11-regulator", S2MPS11X},
 	{ "s2mps13-regulator", S2MPS13X},
 	{ "s2mps14-regulator", S2MPS14X},
diff --git a/include/linux/mfd/samsung/s2mpg10.h b/include/linux/mfd/samsung/s2mpg10.h
index 9f5919b89a3c286bf1cd6b3ef0e74bc993bff01a..995b99b2d583158f546b61d60a3b7011004650fa 100644
--- a/include/linux/mfd/samsung/s2mpg10.h
+++ b/include/linux/mfd/samsung/s2mpg10.h
@@ -290,6 +290,30 @@ enum s2mpg10_pmic_reg {
 	S2MPG10_PMIC_LDO_SENSE4,
 };
 
+/* rail controlled externally, based on PCTRLSELx */
+#define S2MPG10_PMIC_CTRL_ENABLE_EXT BIT(0)
+
+/* For S2MPG10_PMIC_PCTRLSELx */
+#define S2MPG10_PCTRLSEL_PWREN           0x1 /* PWREN pin */
+#define S2MPG10_PCTRLSEL_PWREN_TRG       0x2 /* PWREN_TRG bit in MIMICKING_CTRL */
+#define S2MPG10_PCTRLSEL_PWREN_MIF       0x3 /* PWREN_MIF pin */
+#define S2MPG10_PCTRLSEL_PWREN_MIF_TRG   0x4 /* PWREN_MIF_TRG bit in MIMICKING_CTRL */
+#define S2MPG10_PCTRLSEL_AP_ACTIVE_N     0x5 /* ~AP_ACTIVE_N pin */
+#define S2MPG10_PCTRLSEL_AP_ACTIVE_N_TRG 0x6 /* ~AP_ACTIVE_N_TRG bit in MIMICKING_CTRL */
+#define S2MPG10_PCTRLSEL_CPUCL1_EN       0x7 /* CPUCL1_EN pin */
+#define S2MPG10_PCTRLSEL_CPUCL1_EN2      0x8 /* CPUCL1_EN & PWREN pins */
+#define S2MPG10_PCTRLSEL_CPUCL2_EN       0x9 /* CPUCL2_EN pin */
+#define S2MPG10_PCTRLSEL_CPUCL2_EN2      0xa /* CPUCL2_E2 & PWREN pins */
+#define S2MPG10_PCTRLSEL_TPU_EN          0xb /* TPU_EN pin */
+#define S2MPG10_PCTRLSEL_TPU_EN2         0xc /* TPU_EN & ~AP_ACTIVE_N pins */
+#define S2MPG10_PCTRLSEL_TCXO_ON         0xd /* TCXO_ON pin */
+#define S2MPG10_PCTRLSEL_TCXO_ON2        0xe /* TCXO_ON & ~AP_ACTIVE_N pins */
+
+/* For S2MPG10_PMIC_PCTRLSELx of LDO20M */
+#define S2MPG10_PCTRLSEL_LDO20M_EN2      0x1 /* VLDO20M_EN & LDO20M_SFR */
+#define S2MPG10_PCTRLSEL_LDO20M_EN       0x2 /* VLDO20M_EN pin */
+#define S2MPG10_PCTRLSEL_LDO20M_SFR      0x3 /* LDO20M_SFR bit in LDO_CTRL1 register */
+
 /* Meter registers (type 0xa00) */
 enum s2mpg10_meter_reg {
 	S2MPG10_METER_CTRL1,

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 17/20] regulator: s2mps11: refactor S2MPG10 ::set_voltage_time() for S2MPG11 reuse
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (15 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 16/20] regulator: s2mps11: add S2MPG10 regulator André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-03 19:14 ` [PATCH v3 18/20] regulator: s2mps11: refactor S2MPG10 regulator macros " André Draszik
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

The upcoming S2MPG11 support needs a similar, but different version of
::set_voltage_time(). For S2MPG10, the downwards and upwards ramps for
a rail are at different offsets at the same bit positions, while for
S2MPG11 the ramps are at the same offset at different bit positions.

Refactor the existing version slightly to allow reuse.

Signed-off-by: André Draszik <andre.draszik@linaro.org>
---
 drivers/regulator/s2mps11.c | 32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index aff85138fa5da4cff83bdec5cdb3086a58afc7ce..d840aec236dcbdc8b460f89b4cd04e42e3b3da7d 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -561,26 +561,23 @@ static int s2mpg10_regulator_buck_enable_time(struct regulator_dev *rdev)
 		+ DIV_ROUND_UP(curr_uV, s2mpg10_desc->enable_ramp_rate));
 }
 
-static int s2mpg10_regulator_buck_set_voltage_time(struct regulator_dev *rdev,
-						   int old_uV, int new_uV)
+static int s2mpg1x_regulator_buck_set_voltage_time(struct regulator_dev *rdev,
+						   int old_uV, int new_uV,
+						   unsigned int ramp_reg,
+						   unsigned int ramp_mask)
 {
-	unsigned int ramp_reg, ramp_sel, ramp_rate;
+	unsigned int ramp_sel, ramp_rate;
 	int ret;
 
 	if (old_uV == new_uV)
 		return 0;
 
-	ramp_reg = rdev->desc->ramp_reg;
-	if (old_uV > new_uV)
-		/* The downwards ramp is at a different offset. */
-		ramp_reg += S2MPG10_PMIC_DVS_RAMP4 - S2MPG10_PMIC_DVS_RAMP1;
-
 	ret = regmap_read(rdev->regmap, ramp_reg, &ramp_sel);
 	if (ret)
 		return ret;
 
-	ramp_sel &= rdev->desc->ramp_mask;
-	ramp_sel >>= ffs(rdev->desc->ramp_mask) - 1;
+	ramp_sel &= ramp_mask;
+	ramp_sel >>= ffs(ramp_mask) - 1;
 	if (ramp_sel >= rdev->desc->n_ramp_values ||
 	    !rdev->desc->ramp_delay_table)
 		return -EINVAL;
@@ -590,6 +587,21 @@ static int s2mpg10_regulator_buck_set_voltage_time(struct regulator_dev *rdev,
 	return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_rate);
 }
 
+static int s2mpg10_regulator_buck_set_voltage_time(struct regulator_dev *rdev,
+						   int old_uV, int new_uV)
+{
+	unsigned int ramp_reg;
+
+	ramp_reg = rdev->desc->ramp_reg;
+	if (old_uV > new_uV)
+		/* The downwards ramp is at a different offset. */
+		ramp_reg += S2MPG10_PMIC_DVS_RAMP4 - S2MPG10_PMIC_DVS_RAMP1;
+
+	return s2mpg1x_regulator_buck_set_voltage_time(rdev, old_uV, new_uV,
+						       ramp_reg,
+						       rdev->desc->ramp_mask);
+}
+
 /*
  * We assign both, ::set_voltage_time() and ::set_voltage_time_sel(), because
  * only if the latter is != NULL, the regulator core will call neither during

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 18/20] regulator: s2mps11: refactor S2MPG10 regulator macros for S2MPG11 reuse
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (16 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 17/20] regulator: s2mps11: refactor S2MPG10 ::set_voltage_time() for S2MPG11 reuse André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-03 19:14 ` [PATCH v3 19/20] regulator: s2mps11: add S2MPG11 regulator André Draszik
  2025-11-03 19:14 ` [PATCH v3 20/20] regulator: s2mps11: more descriptive gpio consumer name André Draszik
  19 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

Rails in the S2MPG11 share a very similar set of properties with
S2MPG10 with slight differences. Update the existing macros to allow
reuse by the upcoming S2MPG11 driver.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
Note: checkpatch complains about unused macro arguments _r_mask,
_r_table, and _r_table_sz, but these are false-positives due to patch
context.

v2:
- fix commit message typos: s2mp1 -> s2mpg1
- drop duplicated assignment of ::of_parse_cb in
  regulator_desc_s2mpg1x_buck_cmn() macro
---
 drivers/regulator/s2mps11.c | 69 +++++++++++++++++++++++++++------------------
 1 file changed, 42 insertions(+), 27 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index d840aec236dcbdc8b460f89b4cd04e42e3b3da7d..35cfea6b6d8091ba21f00e1cb82b11a8dc9bc3ec 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -650,31 +650,44 @@ static const struct regulator_ops s2mpg10_reg_buck_ops[] = {
  * (12.5mV/μs) while our ::set_voltage_time() takes the value in ramp_reg
  * into account.
  */
-#define regulator_desc_s2mpg10_buck(_num, _vrange, _r_reg) {		\
-	.name		= "buck"#_num "m",				\
-	.supply_name	= "vinb"#_num "m",				\
-	.of_match	= of_match_ptr("buck"#_num "m"),		\
+#define regulator_desc_s2mpg1x_buck_cmn(_name, _id, _supply, _ops,	\
+		_vrange, _vsel_reg, _vsel_mask, _en_reg, _en_mask,	\
+		_r_reg, _r_mask, _r_table, _r_table_sz,			\
+		_en_time) {						\
+	.name		= "buck" _name,					\
+	.supply_name	= _supply,					\
+	.of_match	= of_match_ptr("buck" _name),			\
 	.regulators_node = of_match_ptr("regulators"),			\
 	.of_parse_cb	= s2mpg10_of_parse_cb,				\
-	.id		= S2MPG10_BUCK##_num,				\
-	.ops		= &s2mpg10_reg_buck_ops[0],			\
+	.id		= _id,						\
+	.ops		= &(_ops)[0],					\
 	.type		= REGULATOR_VOLTAGE,				\
 	.owner		= THIS_MODULE,					\
 	.linear_ranges	= _vrange,					\
 	.n_linear_ranges = ARRAY_SIZE(_vrange),				\
 	.n_voltages	= _vrange##_count,				\
-	.vsel_reg	= S2MPG10_PMIC_B##_num##M_OUT1,			\
-	.vsel_mask	= 0xff,						\
-	.enable_reg	= S2MPG10_PMIC_B##_num##M_CTRL,			\
-	.enable_mask	= GENMASK(7, 6),				\
-	.ramp_reg	= S2MPG10_PMIC_##_r_reg,			\
-	.ramp_mask	= s2mpg10_buck_to_ramp_mask(S2MPG10_BUCK##_num	\
-						    - S2MPG10_BUCK1),	\
-	.ramp_delay_table = s2mpg10_buck_ramp_table,			\
-	.n_ramp_values	= ARRAY_SIZE(s2mpg10_buck_ramp_table),		\
-	.enable_time	= 30, /* + V/enable_ramp_rate */		\
+	.vsel_reg	= _vsel_reg,					\
+	.vsel_mask	= _vsel_mask,					\
+	.enable_reg	= _en_reg,					\
+	.enable_mask	= _en_mask,					\
+	.ramp_reg	= _r_reg,					\
+	.ramp_mask	= _r_mask,					\
+	.ramp_delay_table = _r_table,					\
+	.n_ramp_values	= _r_table_sz,					\
+	.enable_time	= _en_time, /* + V/enable_ramp_rate */		\
 }
 
+#define regulator_desc_s2mpg10_buck(_num, _vrange, _r_reg)		\
+	regulator_desc_s2mpg1x_buck_cmn(#_num "m", S2MPG10_BUCK##_num,	\
+		"vinb"#_num "m", s2mpg10_reg_buck_ops, _vrange,		\
+		S2MPG10_PMIC_B##_num##M_OUT1, GENMASK(7, 0),		\
+		S2MPG10_PMIC_B##_num##M_CTRL, GENMASK(7, 6),		\
+		S2MPG10_PMIC_##_r_reg,					\
+		s2mpg10_buck_to_ramp_mask(S2MPG10_BUCK##_num		\
+					  - S2MPG10_BUCK1),		\
+		s2mpg10_buck_ramp_table,				\
+		ARRAY_SIZE(s2mpg10_buck_ramp_table), 30)
+
 #define s2mpg10_regulator_desc_buck_cm(_num, _vrange, _r_reg)		\
 	.desc = regulator_desc_s2mpg10_buck(_num, _vrange, _r_reg),	\
 	.enable_ramp_rate = 12500
@@ -738,24 +751,24 @@ static const struct regulator_ops s2mpg10_reg_ldo_ramp_ops[] = {
 	}
 };
 
-#define regulator_desc_s2mpg10_ldo_cmn(_num, _supply, _ops, _vrange,	\
-		_vsel_reg_sfx, _vsel_mask, _en_reg, _en_mask,		\
+#define regulator_desc_s2mpg1x_ldo_cmn(_name, _id, _supply, _ops,	\
+		_vrange, _vsel_reg, _vsel_mask, _en_reg, _en_mask,	\
 		_ramp_delay, _r_reg, _r_mask, _r_table,	_r_table_sz) {	\
-	.name		= "ldo"#_num "m",				\
+	.name		= "ldo" _name,					\
 	.supply_name	= _supply,					\
-	.of_match	= of_match_ptr("ldo"#_num "m"),			\
+	.of_match	= of_match_ptr("ldo" _name),			\
 	.regulators_node = of_match_ptr("regulators"),			\
 	.of_parse_cb	= s2mpg10_of_parse_cb,				\
-	.id		= S2MPG10_LDO##_num,				\
+	.id		= _id,						\
 	.ops		= &(_ops)[0],					\
 	.type		= REGULATOR_VOLTAGE,				\
 	.owner		= THIS_MODULE,					\
 	.linear_ranges	= _vrange,					\
 	.n_linear_ranges = ARRAY_SIZE(_vrange),				\
 	.n_voltages	= _vrange##_count,				\
-	.vsel_reg	= S2MPG10_PMIC_L##_num##M_##_vsel_reg_sfx,	\
+	.vsel_reg	= _vsel_reg,					\
 	.vsel_mask	= _vsel_mask,					\
-	.enable_reg	= S2MPG10_PMIC_##_en_reg,			\
+	.enable_reg	= _en_reg,					\
 	.enable_mask	= _en_mask,					\
 	.ramp_delay	= _ramp_delay,					\
 	.ramp_reg	= _r_reg,					\
@@ -770,10 +783,12 @@ static const struct regulator_ops s2mpg10_reg_ldo_ramp_ops[] = {
 		_ramp_delay, _r_reg, _r_mask, _r_table,	_r_table_sz,	\
 		_pc_reg, _pc_mask)					\
 	[S2MPG10_LDO##_num] = {						\
-		.desc = regulator_desc_s2mpg10_ldo_cmn(_num, _supply,	\
-				_ops,					\
-				_vrange, _vsel_reg_sfx, _vsel_mask,	\
-				_en_reg, _en_mask,			\
+		.desc = regulator_desc_s2mpg1x_ldo_cmn(#_num "m",	\
+				S2MPG10_LDO##_num, _supply, _ops,	\
+				_vrange,				\
+				S2MPG10_PMIC_L##_num##M_##_vsel_reg_sfx, \
+				_vsel_mask,				\
+				S2MPG10_PMIC_##_en_reg, _en_mask,	\
 				_ramp_delay, _r_reg, _r_mask, _r_table,	\
 				_r_table_sz),				\
 		.pctrlsel_reg = _pc_reg,				\

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 19/20] regulator: s2mps11: add S2MPG11 regulator
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (17 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 18/20] regulator: s2mps11: refactor S2MPG10 regulator macros " André Draszik
@ 2025-11-03 19:14 ` André Draszik
  2025-11-03 19:14 ` [PATCH v3 20/20] regulator: s2mps11: more descriptive gpio consumer name André Draszik
  19 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

The S2MPG11 PMIC is a Power Management IC for mobile applications with
buck converters, various LDOs, power meters, and additional GPIO
interfaces. It typically complements an S2MPG10 PMIC in a main/sub
configuration as the sub-PMIC.

It has 12 buck, 1 buck-boost, and 15 LDO rails. Several of these can
either be controlled via software (register writes) or via external
signals, in particular by:
    * input pins connected to a main processor's:
        * GPIO pins
        * other pins that are e.g. firmware- or power-domain-controlled
          without explicit driver intervention
    * a combination of input pins and register writes.

Control via input pins allows PMIC rails to be controlled by firmware,
e.g. during standby/suspend or as part of power domain handling where
otherwise that would not be possible. Additionally toggling a pin is
faster than register writes, and it also allows the PMIC to ensure that
any necessary timing requirements between rails are respected
automatically if multiple rails are to be enabled or disabled quasi
simultaneously.

This commit implements support for all these rails and control
combination.

Note1: For an externally controlled rail, the regulator_ops provide an
empty ::enable() and no ::disable() implementations, even though Linux
can not enable the rail and one might think ::enable could be NULL.
Without ops->enable(), the regulator core will assume enabling such a
rail failed, though, and in turn never add a reference to its parent
(supplier) rail. Once a different (Linux-controlled) sibling (consumer)
rail on that same parent rail gets disabled, the parent gets disabled
(cutting power to the externally controlled rail although it should
stay on), and the system will misbehave.

Note2: The rails are instantiated as separate driver instances for each
rail, because S2MPG11 is typically used with an S2MPG10 main-PMIC where
some bucks of one typically supply at least some of the LDOs of the
other. Using separate instances avoids issues around circular
dependencies which occur otherwise.

Note3:  While external control via input pins appears to exist on other
versions of this PMIC, there is more flexibility in this version, in
particular there is a selection of input pins to choose from for each
rail (which must therefore be configured accordingly if in use),
whereas other versions don't have this flexibility.

Signed-off-by: André Draszik <andre.draszik@linaro.org>

---
v3:
- one instance per actual rail, not per rail type (LDO or buck)
- assign correct ::ops for LDOs with ramp support
- sort s2mpg11 bucks before LDOs throughout (alphabetic ordering)
- add ::enable() to ops for signal-controlled rails and update commit
  message detailing why
- more details around signal controlled rails in commit message

v2:
- fix commit message typo
- mention GPIOs in commit message
---
 drivers/regulator/s2mps11.c | 307 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 306 insertions(+), 1 deletion(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 35cfea6b6d8091ba21f00e1cb82b11a8dc9bc3ec..f19140e97b9d7a5e7c07cdc5e002de345aad32d9 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -19,6 +19,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/s2mpg10.h>
+#include <linux/mfd/samsung/s2mpg11.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps13.h>
 #include <linux/mfd/samsung/s2mps14.h>
@@ -432,9 +433,20 @@ static int s2mpg10_of_parse_cb(struct device_node *np,
 		[S2MPG10_EXTCTRL_LDO20M_EN2] = S2MPG10_PCTRLSEL_LDO20M_EN2,
 		[S2MPG10_EXTCTRL_LDO20M_EN] = S2MPG10_PCTRLSEL_LDO20M_EN,
 	};
+	static const u32 ext_control_s2mpg11[] = {
+		[S2MPG11_EXTCTRL_PWREN] = S2MPG10_PCTRLSEL_PWREN,
+		[S2MPG11_EXTCTRL_PWREN_MIF] = S2MPG10_PCTRLSEL_PWREN_MIF,
+		[S2MPG11_EXTCTRL_AP_ACTIVE_N] = S2MPG10_PCTRLSEL_AP_ACTIVE_N,
+		[S2MPG11_EXTCTRL_G3D_EN] = S2MPG10_PCTRLSEL_CPUCL1_EN,
+		[S2MPG11_EXTCTRL_G3D_EN2] = S2MPG10_PCTRLSEL_CPUCL1_EN2,
+		[S2MPG11_EXTCTRL_AOC_VDD] = S2MPG10_PCTRLSEL_CPUCL2_EN,
+		[S2MPG11_EXTCTRL_AOC_RET] = S2MPG10_PCTRLSEL_CPUCL2_EN2,
+		[S2MPG11_EXTCTRL_UFS_EN] = S2MPG10_PCTRLSEL_TPU_EN,
+		[S2MPG11_EXTCTRL_LDO13S_EN] = S2MPG10_PCTRLSEL_TPU_EN2,
+	};
 	u32 ext_control;
 
-	if (s2mps11->dev_type != S2MPG10)
+	if (s2mps11->dev_type != S2MPG10 && s2mps11->dev_type != S2MPG11)
 		return 0;
 
 	if (of_property_read_u32(np, "samsung,ext-control", &ext_control))
@@ -465,6 +477,31 @@ static int s2mpg10_of_parse_cb(struct device_node *np,
 		ext_control = ext_control_s2mpg10[ext_control];
 		break;
 
+	case S2MPG11:
+		switch (desc->id) {
+		case S2MPG11_BUCK1 ... S2MPG11_BUCK3:
+		case S2MPG11_BUCK5:
+		case S2MPG11_BUCK8:
+		case S2MPG11_BUCK9:
+		case S2MPG11_BUCKD:
+		case S2MPG11_BUCKA:
+		case S2MPG10_LDO1:
+		case S2MPG10_LDO2:
+		case S2MPG10_LDO8:
+		case S2MPG10_LDO13:
+			if (ext_control > S2MPG11_EXTCTRL_LDO13S_EN)
+				return -EINVAL;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		if (ext_control > ARRAY_SIZE(ext_control_s2mpg11))
+			return -EINVAL;
+		ext_control = ext_control_s2mpg11[ext_control];
+		break;
+
 	default:
 		return -EINVAL;
 	}
@@ -502,6 +539,7 @@ static int s2mpg10_enable_ext_control(struct s2mps11_info *s2mps11,
 
 	switch (s2mps11->dev_type) {
 	case S2MPG10:
+	case S2MPG11:
 		s2mpg10_desc = to_s2mpg10_regulator_desc(rdev->desc);
 		break;
 
@@ -602,6 +640,21 @@ static int s2mpg10_regulator_buck_set_voltage_time(struct regulator_dev *rdev,
 						       rdev->desc->ramp_mask);
 }
 
+static int s2mpg11_regulator_buck_set_voltage_time(struct regulator_dev *rdev,
+						   int old_uV, int new_uV)
+{
+	unsigned int ramp_mask;
+
+	ramp_mask = rdev->desc->ramp_mask;
+	if (old_uV > new_uV)
+		/* The downwards mask is at a different position. */
+		ramp_mask >>= 2;
+
+	return s2mpg1x_regulator_buck_set_voltage_time(rdev, old_uV, new_uV,
+						       rdev->desc->ramp_reg,
+						       ramp_mask);
+}
+
 /*
  * We assign both, ::set_voltage_time() and ::set_voltage_time_sel(), because
  * only if the latter is != NULL, the regulator core will call neither during
@@ -962,6 +1015,246 @@ static const struct s2mpg10_regulator_desc s2mpg10_regulators[] = {
 	s2mpg10_regulator_desc_ldo(31, "vinl11m", s2mpg10_ldo_vranges2)
 };
 
+static const struct regulator_ops s2mpg11_reg_buck_ops[] = {
+	[S2MPG10_REGULATOR_OPS_STD] = {
+		.list_voltage		= regulator_list_voltage_linear_range,
+		.map_voltage		= regulator_map_voltage_linear_range,
+		.is_enabled		= regulator_is_enabled_regmap,
+		.enable			= regulator_enable_regmap,
+		.disable		= regulator_disable_regmap,
+		.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+		.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+		.set_voltage_time	= s2mpg11_regulator_buck_set_voltage_time,
+		.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+		.enable_time		= s2mpg10_regulator_buck_enable_time,
+		.set_ramp_delay		= regulator_set_ramp_delay_regmap,
+	},
+	[S2MPG10_REGULATOR_OPS_EXTCONTROL] = {
+		.list_voltage		= regulator_list_voltage_linear_range,
+		.map_voltage		= regulator_map_voltage_linear_range,
+		.enable			= s2mpg10_regulator_enable_nop,
+		.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+		.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+		.set_voltage_time	= s2mpg11_regulator_buck_set_voltage_time,
+		.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+		.enable_time		= s2mpg10_regulator_buck_enable_time,
+		.set_ramp_delay		= regulator_set_ramp_delay_regmap,
+	}
+};
+
+#define s2mpg11_buck_to_ramp_mask(n) (GENMASK(3, 2) << (((n) % 2) * 4))
+
+#define regulator_desc_s2mpg11_buckx(_name, _id, _supply, _vrange,	\
+		_vsel_reg, _en_reg, _en_mask, _r_reg)			\
+	regulator_desc_s2mpg1x_buck_cmn(_name, _id, _supply,		\
+		s2mpg11_reg_buck_ops,  _vrange,				\
+		S2MPG11_PMIC_##_vsel_reg, GENMASK(7, 0),		\
+		S2MPG11_PMIC_##_en_reg, _en_mask,			\
+		S2MPG11_PMIC_##_r_reg,					\
+		s2mpg11_buck_to_ramp_mask(_id - S2MPG11_BUCK1),		\
+		s2mpg10_buck_ramp_table,				\
+		ARRAY_SIZE(s2mpg10_buck_ramp_table), 30)
+
+#define s2mpg11_regulator_desc_buck_xm(_num, _vrange, _vsel_reg_sfx,	\
+				       _en_mask, _r_reg, _en_rrate)	\
+	.desc = regulator_desc_s2mpg11_buckx(#_num"s",			\
+				S2MPG11_BUCK##_num, "vinb"#_num"s",	\
+				_vrange,				\
+				B##_num##S_##_vsel_reg_sfx,		\
+				B##_num##S_CTRL, _en_mask,		\
+				_r_reg),				\
+	.enable_ramp_rate = _en_rrate
+
+#define s2mpg11_regulator_desc_buck_cm(_num, _vrange, _vsel_reg_sfx,	\
+				       _en_mask, _r_reg)		\
+	[S2MPG11_BUCK##_num] = {					\
+		s2mpg11_regulator_desc_buck_xm(_num, _vrange,		\
+			_vsel_reg_sfx, _en_mask, _r_reg, 12500),	\
+	}
+
+#define s2mpg11_regulator_desc_buckn_cm_gpio(_num, _vrange,		\
+		_vsel_reg_sfx, _en_mask, _r_reg, _pc_reg, _pc_mask)	\
+	[S2MPG11_BUCK##_num] = {					\
+		s2mpg11_regulator_desc_buck_xm(_num, _vrange,		\
+			_vsel_reg_sfx, _en_mask, _r_reg, 12500),	\
+		.pctrlsel_reg = S2MPG11_PMIC_##_pc_reg,			\
+		.pctrlsel_mask = _pc_mask,				\
+	}
+
+#define s2mpg11_regulator_desc_buck_vm(_num, _vrange, _vsel_reg_sfx,	\
+				       _en_mask, _r_reg)		\
+	[S2MPG11_BUCK##_num] = {					\
+		s2mpg11_regulator_desc_buck_xm(_num, _vrange,		\
+			_vsel_reg_sfx, _en_mask, _r_reg, 25000),	\
+	}
+
+#define s2mpg11_regulator_desc_bucka(_num, _num_lower, _r_reg,		\
+				     _pc_reg, _pc_mask)			\
+	[S2MPG11_BUCK##_num] = {					\
+		.desc = regulator_desc_s2mpg11_buckx(#_num_lower,	\
+				S2MPG11_BUCK##_num, "vinb"#_num_lower,	\
+				s2mpg11_buck_vranges##_num_lower,	\
+				BUCK##_num##_OUT,			\
+				BUCK##_num##_CTRL, GENMASK(7, 6),	\
+				_r_reg),				\
+		.enable_ramp_rate = 25000,				\
+		.pctrlsel_reg = S2MPG11_PMIC_##_pc_reg,			\
+		.pctrlsel_mask = _pc_mask,				\
+	}
+
+#define s2mpg11_regulator_desc_buckboost()				\
+	[S2MPG11_BUCKBOOST] = {						\
+		.desc = regulator_desc_s2mpg1x_buck_cmn("boost",	\
+				S2MPG11_BUCKBOOST, "vinbb",		\
+				s2mpg10_reg_ldo_ops,			\
+				s2mpg11_buck_vrangesboost,		\
+				S2MPG11_PMIC_BB_OUT1, GENMASK(6, 0),	\
+				S2MPG11_PMIC_BB_CTRL, BIT(7),		\
+				0, 0, NULL, 0, 35),			\
+		.enable_ramp_rate = 17500,				\
+	}
+
+#define s2mpg11_regulator_desc_ldo_cmn(_num, _supply, _ops,		\
+		_vrange, _vsel_reg_sfx, _vsel_mask, _en_reg, _en_mask,	\
+		_ramp_delay, _r_reg, _r_mask, _r_table, _r_table_sz,	\
+		_pc_reg, _pc_mask)					\
+	[S2MPG11_LDO##_num] = {						\
+		.desc = regulator_desc_s2mpg1x_ldo_cmn(#_num "s",	\
+				S2MPG11_LDO##_num, _supply, _ops,	\
+				_vrange,				\
+				S2MPG11_PMIC_L##_num##S_##_vsel_reg_sfx, \
+				_vsel_mask,				\
+				S2MPG11_PMIC_##_en_reg, _en_mask,	\
+				_ramp_delay, _r_reg, _r_mask, _r_table,	\
+				_r_table_sz),				\
+		.pctrlsel_reg = _pc_reg,				\
+		.pctrlsel_mask = _pc_mask,				\
+	}
+
+/* standard LDO via LxM_CTRL */
+#define s2mpg11_regulator_desc_ldo(_num, _supply, _vrange)		\
+	s2mpg11_regulator_desc_ldo_cmn(_num, _supply,			\
+		s2mpg10_reg_ldo_ops, _vrange, CTRL, GENMASK(5, 0),	\
+		L##_num##S_CTRL, BIT(7),				\
+		0, 0, 0, NULL, 0,					\
+		0, 0)
+
+/* standard LDO but possibly GPIO controlled */
+#define s2mpg11_regulator_desc_ldo_gpio(_num, _supply, _vrange,		\
+					_pc_reg, _pc_mask)		\
+	s2mpg11_regulator_desc_ldo_cmn(_num, _supply,			\
+		s2mpg10_reg_ldo_ops, _vrange, CTRL, GENMASK(5, 0),	\
+		L##_num##S_CTRL, GENMASK(7, 6),				\
+		0, 0, 0, NULL, 0,					\
+		S2MPG11_PMIC_##_pc_reg, _pc_mask)
+
+/* LDO with ramp support and possibly GPIO controlled */
+#define s2mpg11_regulator_desc_ldo_ramp(_num, _supply, _vrange,		\
+		_en_mask, _r_reg, _pc_reg, _pc_mask)			\
+	s2mpg11_regulator_desc_ldo_cmn(_num, _supply,			\
+		s2mpg10_reg_ldo_ramp_ops, _vrange, CTRL1, GENMASK(6, 0), \
+		LDO_CTRL1, _en_mask,					\
+		6250, S2MPG11_PMIC_##_r_reg, GENMASK(1, 0),		\
+		s2mpg10_ldo_ramp_table,					\
+		ARRAY_SIZE(s2mpg10_ldo_ramp_table),			\
+		S2MPG11_PMIC_##_pc_reg, _pc_mask)
+
+/* voltage range for s2mpg11 BUCK 1, 2, 3, 4, 8, 9, 10 */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_buck, 1, 200000, 450000, 1300000, STEP_6_25_MV);
+
+/* voltage range for s2mpg11 BUCK 5 */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_buck, 5, 200000, 400000, 1300000, STEP_6_25_MV);
+
+/* voltage range for s2mpg11 BUCK 6 */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_buck, 6, 200000, 1000000, 1500000, STEP_6_25_MV);
+
+/* voltage range for s2mpg11 BUCK 7 */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_buck, 7, 600000, 1500000, 2200000, STEP_12_5_MV);
+
+/* voltage range for s2mpg11 BUCK D */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_buck, d, 600000, 2400000, 3300000, STEP_12_5_MV);
+
+/* voltage range for s2mpg11 BUCK A */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_buck, a, 600000, 1700000, 2100000, STEP_12_5_MV);
+
+/* voltage range for s2mpg11 BUCK BOOST */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_buck, boost,
+		      2600000, 3000000, 3600000, STEP_12_5_MV);
+
+/* voltage range for s2mpg11 LDO 1, 2 */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_ldo, 1, 300000, 450000, 950000, STEP_12_5_MV);
+
+/* voltage range for s2mpg11 LDO 3, 7, 10, 11, 12, 14, 15 */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_ldo, 3, 700000, 1600000, 1950000, STEP_25_MV);
+
+/* voltage range for s2mpg11 LDO 4, 6 */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_ldo, 4, 1800000, 2500000, 3300000, STEP_25_MV);
+
+/* voltage range for s2mpg11 LDO 5 */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_ldo, 5, 1600000, 1600000, 1950000, STEP_12_5_MV);
+
+/* voltage range for s2mpg11 LDO 8 */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_ldo, 8, 979600, 1130400, 1281200, 5800);
+
+/* voltage range for s2mpg11 LDO 9 */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_ldo, 9, 725000, 725000, 1300000, STEP_12_5_MV);
+
+/* voltage range for s2mpg11 LDO 13 */
+S2MPG10_VOLTAGE_RANGE(s2mpg11_ldo, 13, 1800000, 1800000, 3350000, STEP_25_MV);
+
+static const struct s2mpg10_regulator_desc s2mpg11_regulators[] = {
+	s2mpg11_regulator_desc_buckboost(),
+	s2mpg11_regulator_desc_buckn_cm_gpio(1, s2mpg11_buck_vranges1,
+					     OUT1, GENMASK(7, 6), DVS_RAMP1,
+					     PCTRLSEL1, GENMASK(3, 0)),
+	s2mpg11_regulator_desc_buckn_cm_gpio(2, s2mpg11_buck_vranges1,
+					     OUT1, GENMASK(7, 6), DVS_RAMP1,
+					     PCTRLSEL1, GENMASK(7, 4)),
+	s2mpg11_regulator_desc_buckn_cm_gpio(3, s2mpg11_buck_vranges1,
+					     OUT1, GENMASK(7, 6), DVS_RAMP2,
+					     PCTRLSEL2, GENMASK(3, 0)),
+	s2mpg11_regulator_desc_buck_cm(4, s2mpg11_buck_vranges1,
+				       OUT, BIT(7), DVS_RAMP2),
+	s2mpg11_regulator_desc_buckn_cm_gpio(5, s2mpg11_buck_vranges5,
+					     OUT, GENMASK(7, 6), DVS_RAMP3,
+					     PCTRLSEL2, GENMASK(7, 4)),
+	s2mpg11_regulator_desc_buck_cm(6, s2mpg11_buck_vranges6,
+				       OUT1, BIT(7), DVS_RAMP3),
+	s2mpg11_regulator_desc_buck_vm(7, s2mpg11_buck_vranges7,
+				       OUT1, BIT(7), DVS_RAMP4),
+	s2mpg11_regulator_desc_buckn_cm_gpio(8, s2mpg11_buck_vranges1,
+					     OUT1, GENMASK(7, 6), DVS_RAMP4,
+					     PCTRLSEL3, GENMASK(3, 0)),
+	s2mpg11_regulator_desc_buckn_cm_gpio(9, s2mpg11_buck_vranges1,
+					     OUT1, GENMASK(7, 6), DVS_RAMP5,
+					     PCTRLSEL3, GENMASK(7, 4)),
+	s2mpg11_regulator_desc_buck_cm(10, s2mpg11_buck_vranges1,
+				       OUT, BIT(7), DVS_RAMP5),
+	s2mpg11_regulator_desc_bucka(D, d, DVS_RAMP6, PCTRLSEL4, GENMASK(3, 0)),
+	s2mpg11_regulator_desc_bucka(A, a, DVS_RAMP6, PCTRLSEL4, GENMASK(7, 4)),
+	s2mpg11_regulator_desc_ldo_ramp(1, "vinl1s", s2mpg11_ldo_vranges1,
+					GENMASK(5, 4), DVS_SYNC_CTRL1,
+					PCTRLSEL5, GENMASK(3, 0)),
+	s2mpg11_regulator_desc_ldo_ramp(2, "vinl1s", s2mpg11_ldo_vranges1,
+					GENMASK(7, 6), DVS_SYNC_CTRL2,
+					PCTRLSEL5, GENMASK(7, 4)),
+	s2mpg11_regulator_desc_ldo(3, "vinl3s", s2mpg11_ldo_vranges3),
+	s2mpg11_regulator_desc_ldo(4, "vinl5s", s2mpg11_ldo_vranges4),
+	s2mpg11_regulator_desc_ldo(5, "vinl3s", s2mpg11_ldo_vranges5),
+	s2mpg11_regulator_desc_ldo(6, "vinl5s", s2mpg11_ldo_vranges4),
+	s2mpg11_regulator_desc_ldo(7, "vinl3s", s2mpg11_ldo_vranges3),
+	s2mpg11_regulator_desc_ldo_gpio(8, "vinl2s", s2mpg11_ldo_vranges8,
+					PCTRLSEL6, GENMASK(3, 0)),
+	s2mpg11_regulator_desc_ldo(9, "vinl2s", s2mpg11_ldo_vranges9),
+	s2mpg11_regulator_desc_ldo(10, "vinl4s", s2mpg11_ldo_vranges3),
+	s2mpg11_regulator_desc_ldo(11, "vinl4s", s2mpg11_ldo_vranges3),
+	s2mpg11_regulator_desc_ldo(12, "vinl4s", s2mpg11_ldo_vranges3),
+	s2mpg11_regulator_desc_ldo_gpio(13, "vinl6s", s2mpg11_ldo_vranges13,
+					PCTRLSEL6, GENMASK(7, 4)),
+	s2mpg11_regulator_desc_ldo(14, "vinl4s", s2mpg11_ldo_vranges3),
+	s2mpg11_regulator_desc_ldo(15, "vinl3s", s2mpg11_ldo_vranges3)
+};
+
 static const struct regulator_ops s2mps11_ldo_ops = {
 	.list_voltage		= regulator_list_voltage_linear,
 	.map_voltage		= regulator_map_voltage_linear,
@@ -1846,6 +2139,7 @@ static int s2mps11_handle_ext_control(struct s2mps11_info *s2mps11,
 		break;
 
 	case S2MPG10:
+	case S2MPG11:
 		/*
 		 * If desc.enable_val is != 0, then external control was
 		 * requested. We can not test s2mpg10_desc::ext_control,
@@ -1892,6 +2186,16 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 		s2mpg1x_regulators = &s2mpg10_regulators[cell->id];
 		BUILD_BUG_ON(ARRAY_SIZE(s2mpg10_regulators) > S2MPS_REGULATOR_MAX);
 		break;
+	case S2MPG11:
+		if (cell->id >= ARRAY_SIZE(s2mpg11_regulators))
+			return dev_err_probe(&pdev->dev, -ENODEV,
+					     "Unsupported regulator ID %d\n",
+					     cell->id);
+
+		rdev_num = 1;
+		s2mpg1x_regulators = &s2mpg11_regulators[cell->id];
+		BUILD_BUG_ON(ARRAY_SIZE(s2mpg11_regulators) > S2MPS_REGULATOR_MAX);
+		break;
 	case S2MPS11X:
 		rdev_num = ARRAY_SIZE(s2mps11_regulators);
 		regulators = s2mps11_regulators;
@@ -1971,6 +2275,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 
 static const struct platform_device_id s2mps11_pmic_id[] = {
 	{ "s2mpg10-regulator", S2MPG10},
+	{ "s2mpg11-regulator", S2MPG11},
 	{ "s2mps11-regulator", S2MPS11X},
 	{ "s2mps13-regulator", S2MPS13X},
 	{ "s2mps14-regulator", S2MPS14X},

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 20/20] regulator: s2mps11: more descriptive gpio consumer name
  2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
                   ` (18 preceding siblings ...)
  2025-11-03 19:14 ` [PATCH v3 19/20] regulator: s2mps11: add S2MPG11 regulator André Draszik
@ 2025-11-03 19:14 ` André Draszik
  19 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-03 19:14 UTC (permalink / raw)
  To: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio, André Draszik

Currently, GPIOs claimed by this driver for external rail control
all show up with "s2mps11-regulator" as consumer, which is not
very informative.

Switch to using the regulator name via desc->name instead, using the
device name as fallback.

Signed-off-by: André Draszik <andre.draszik@linaro.org>
---
 drivers/regulator/s2mps11.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index f19140e97b9d7a5e7c07cdc5e002de345aad32d9..3e9da15081e680d7660c60270af54ba2a4f8da1d 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -363,7 +363,8 @@ static int s2mps11_of_parse_gpiod(struct device_node *np,
 	ena_gpiod = fwnode_gpiod_get_index(of_fwnode_handle(np), con_id, 0,
 					   GPIOD_OUT_HIGH |
 					   GPIOD_FLAGS_BIT_NONEXCLUSIVE,
-					   "s2mps11-regulator");
+					   desc->name
+					   ? : dev_name(config->dev));
 	if (IS_ERR(ena_gpiod)) {
 		ret = PTR_ERR(ena_gpiod);
 

-- 
2.51.2.997.g839fc31de9-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 02/20] dt-bindings: mfd: samsung,s2mps11: split s2mpg10 into separate file
  2025-11-03 19:14 ` [PATCH v3 02/20] dt-bindings: mfd: samsung,s2mps11: split s2mpg10 into separate file André Draszik
@ 2025-11-04  8:26   ` Krzysztof Kozlowski
  2025-11-07 11:01     ` André Draszik
  0 siblings, 1 reply; 41+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-04  8:26 UTC (permalink / raw)
  To: André Draszik
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

On Mon, Nov 03, 2025 at 07:14:41PM +0000, André Draszik wrote:
> +properties:
> +  compatible:
> +    const: samsung,s2mpg10-pmic
> +
> +  clocks:
> +    $ref: /schemas/clock/samsung,s2mps11.yaml
> +    description:
> +      Child node describing clock provider.
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  regulators:
> +    type: object
> +    description:
> +      List of child nodes that specify the regulators.
> +
> +  system-power-controller: true
> +
> +  wakeup-source: true
> +
> +required:
> +  - compatible
> +  - interrupts
> +  - regulators
> +
> +additionalProperties: false

You need a complete example here.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 05/20] dt-bindings: mfd: samsung,s2mpg10: Link s2mpg10-pmic to its regulators
  2025-11-03 19:14 ` [PATCH v3 05/20] dt-bindings: mfd: samsung,s2mpg10: Link s2mpg10-pmic to its regulators André Draszik
@ 2025-11-04  8:28   ` Krzysztof Kozlowski
  2025-11-08 13:48     ` André Draszik
  0 siblings, 1 reply; 41+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-04  8:28 UTC (permalink / raw)
  To: André Draszik
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

On Mon, Nov 03, 2025 at 07:14:44PM +0000, André Draszik wrote:
>  required:
>    - compatible
>    - interrupts
>    - regulators
>  
>  additionalProperties: false
> +
> +allOf:
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: samsung,s2mpg10-pmic
> +    then:
> +      properties:

This is not correct now. You do not have other variants here and ref
should be directly in top level "regulators" part of schema.


> +        regulators:
> +          $ref: /schemas/regulator/samsung,s2mpg10-regulator.yaml
> 
> -- 
> 2.51.2.997.g839fc31de9-goog
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 07/20] dt-bindings: firmware: google,gs101-acpm-ipc: update PMIC examples
  2025-11-03 19:14 ` [PATCH v3 07/20] dt-bindings: firmware: google,gs101-acpm-ipc: update PMIC examples André Draszik
@ 2025-11-04  8:31   ` Krzysztof Kozlowski
  2025-11-08 14:08     ` André Draszik
  2025-11-04  9:46   ` Krzysztof Kozlowski
  1 sibling, 1 reply; 41+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-04  8:31 UTC (permalink / raw)
  To: André Draszik
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

On Mon, Nov 03, 2025 at 07:14:46PM +0000, André Draszik wrote:
> In a typical system using the Samsung S2MPG10 PMIC, an S2MPG11 is used
> as a sub-PMIC.
> 
> The interface for both is the ACPM firmware protocol, so update the
> example here to describe the connection for both.
> 
> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> ---
>  .../bindings/firmware/google,gs101-acpm-ipc.yaml   | 40 ++++++++++++++++++++--
>  1 file changed, 37 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
> index 4a1e3e3c0505aad6669cadf9b7b58aa4c7f284cb..c25e155926e5f44bd74f195cdbff3672c7499f8e 100644
> --- a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
> +++ b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
> @@ -45,6 +45,15 @@ properties:
>        compatible:
>          const: samsung,s2mpg10-pmic
>  
> +  pmic2:

pmic-2

Are there more pmics? Bindings are supposed to be complete (see writing
bindings) and if you did follow this approach earlier, you would nicely
call first "pmic-1" (instead of "pmic") and then "pmic-2".

> +    description: Child node describing the sub PMIC.
> +    type: object
> +    additionalProperties: true

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 06/20] dt-bindings: mfd: samsung,s2mpg10: Add s2mpg11-pmic
  2025-11-03 19:14 ` [PATCH v3 06/20] dt-bindings: mfd: samsung,s2mpg10: Add s2mpg11-pmic André Draszik
@ 2025-11-04  8:37   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 41+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-04  8:37 UTC (permalink / raw)
  To: André Draszik
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

On Mon, Nov 03, 2025 at 07:14:45PM +0000, André Draszik wrote:
> +  "^vinb[abd]-supply$":
> +    description: |
> +      Phandle to the power supply for the additional buck rails of the S2MPG11
> +      PMIC. The mapping of supply to rail is as follows::
> +        vinba - bucka
> +        vinbb - buck boost
> +        vinbd - buckd
> +
> +  "^vinl[1-6]s-supply$":
> +    description: |
> +      Phandle to the power supply for one or multiple LDO rails of the S2MPG11
> +      PMIC. The mapping of supply to rail(s) is as follows:
> +        vinl1s - ldo1s, ldo2s
> +        vinl2s - ldo8s, ldo9s
> +        vinl3s - ldo3s, ldo5s, ldo7s, ldo15s
> +        vinl4s - ldo10s, ldo11s, ldo12s, ldo14s
> +        vinl5s - ldo4s, ldo6s
> +        vinl6s - ldo13s
> +
>  required:
>    - compatible
>    - interrupts
> @@ -81,3 +102,23 @@ allOf:
>        properties:
>          regulators:
>            $ref: /schemas/regulator/samsung,s2mpg10-regulator.yaml
> +
> +      patternProperties:
> +        "[^m]-supply$": false
> +
> +  - if:

OK, so this explains why earlier you put $ref in if:then:. I propose to
move it to separate new MFD schema, because half or more of properties
are not applicable between each of the devices.


Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 13/20] regulator: s2mps11: place constants on right side of comparison tests
  2025-11-03 19:14 ` [PATCH v3 13/20] regulator: s2mps11: place constants on right side of comparison tests André Draszik
@ 2025-11-04  8:40   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 41+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-04  8:40 UTC (permalink / raw)
  To: André Draszik, Tudor Ambarus, Rob Herring, Conor Dooley,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio

On 03/11/2025 20:14, André Draszik wrote:
> For the lines being changed, checkpatch reports:
> 
>     WARNING: Comparisons should place the constant on the right side of the test
> 
> Update the code accordingly.
> 
> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> 


Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 11/20] regulator: s2mps11: drop two needless variable initialisations
  2025-11-03 19:14 ` [PATCH v3 11/20] regulator: s2mps11: drop two needless variable initialisations André Draszik
@ 2025-11-04  8:41   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 41+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-04  8:41 UTC (permalink / raw)
  To: André Draszik, Tudor Ambarus, Rob Herring, Conor Dooley,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio

On 03/11/2025 20:14, André Draszik wrote:
> The initialisations being removed are needless, as both variables are
> being assigned values unconditionally further down. Additionally, doing
> this eager init here might lead to preventing the compiler from issuing
> a warning if a future code change actually forgets to assign a useful
> value in some code path.
> 
> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> ---
>  drivers/regulator/s2mps11.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 



Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 12/20] regulator: s2mps11: use dev_err_probe() where appropriate
  2025-11-03 19:14 ` [PATCH v3 12/20] regulator: s2mps11: use dev_err_probe() where appropriate André Draszik
@ 2025-11-04  8:41   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 41+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-04  8:41 UTC (permalink / raw)
  To: André Draszik, Tudor Ambarus, Rob Herring, Conor Dooley,
	Liam Girdwood, Mark Brown, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Krzysztof Kozlowski
  Cc: Peter Griffin, Will McVicker, kernel-team, linux-kernel,
	linux-samsung-soc, devicetree, linux-gpio

On 03/11/2025 20:14, André Draszik wrote:
> dev_err_probe() exists to simplify code and harmonise error messages,
> there's no reason not to use it here.
> 
> While at it, harmonise some error messages to add regulator name and ID
> like in other messages in this driver, and update messages to be more
> similar to other child-drivers of this PMIC (e.g. RTC).
> 
> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> ---
>  drivers/regulator/s2mps11.c | 29 ++++++++++++++---------------
>  1 file changed, 14 insertions(+), 15 deletions(-)



Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 04/20] regulator: dt-bindings: add s2mpg11-pmic regulators
  2025-11-03 19:14 ` [PATCH v3 04/20] regulator: dt-bindings: add s2mpg11-pmic regulators André Draszik
@ 2025-11-04  9:39   ` Krzysztof Kozlowski
  2025-11-07 11:14     ` André Draszik
  0 siblings, 1 reply; 41+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-04  9:39 UTC (permalink / raw)
  To: André Draszik
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

On Mon, Nov 03, 2025 at 07:14:43PM +0000, André Draszik wrote:
> +  The S2MPG11 PMIC provides 12 buck, 1 buck-boost, and 15 LDO regulators.
> +
> +  See also Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml for
> +  additional information and example.
> +
> +definitions:

defs:


> +  s2mpg11-ext-control:
> +    properties:
> +      samsung,ext-control:
> +        description: |
> +          These rails can be controlled via one of several possible external
> +          (hardware) signals. If so, this property configures the signal the PMIC
> +          should monitor. The following values generally corresponding to the
> +          respective on-chip pin are valid:
> +            - 0 # S2MPG11_PCTRLSEL_PWREN - PWREN pin
> +            - 1 # S2MPG11_PCTRLSEL_PWREN_MIF - PWREN_MIF pin
> +            - 2 # S2MPG11_PCTRLSEL_AP_ACTIVE_N - ~AP_ACTIVE_N pin
> +            - 3 # S2MPG11_PCTRLSEL_G3D_EN - G3D_EN pin
> +            - 4 # S2MPG11_PCTRLSEL_G3D_EN2 - G3D_EN & ~AP_ACTIVE_N pins
> +            - 5 # S2MPG11_PCTRLSEL_AOC_VDD - AOC_VDD pin
> +            - 6 # S2MPG11_PCTRLSEL_AOC_RET - AOC_RET pin
> +            - 7 # S2MPG11_PCTRLSEL_UFS_EN - UFS_EN pin
> +            - 8 # S2MPG11_PCTRLSEL_LDO13S_EN - VLDO13S_EN pin
> +
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        minimum: 0
> +        maximum: 8
> +
> +      enable-gpios:
> +        description:
> +          For rails where external control is done via a GPIO, this optional
> +          property describes the GPIO line used.
> +
> +    dependentRequired:
> +      enable-gpios: [ "samsung,ext-control" ]
> +
> +properties:
> +  buckboost:
> +    type: object
> +    $ref: regulator.yaml#
> +    unevaluatedProperties: false
> +    description:
> +      Properties for the buck-boost regulator.
> +
> +    properties:
> +      regulator-ramp-delay: false
> +
> +patternProperties:
> +  # 12 bucks
> +  "^buck(([1-9]|10)s|[ad])$":
> +    type: object
> +    $ref: regulator.yaml#
> +    unevaluatedProperties: false
> +    description:
> +      Properties for a single buck regulator.
> +
> +    allOf:
> +      - $ref: "#/definitions/s2mpg11-ext-control"

defs

> +
> +    properties:
> +      regulator-ramp-delay:
> +        enum: [6250, 12500, 25000]
> +        default: 6250
> +

....


> +    allOf:
> +      - $ref: "#/definitions/s2mpg11-ext-control"
> +
> +    properties:
> +      regulator-ramp-delay:
> +        enum: [6250, 12500]
> +        default: 6250
> +
> +additionalProperties: false

This goes to the end, after allOf, see example-schema.

> +
> +allOf:
> +  # Bucks 4, 6, 7 and 10 can not be controlled externally - above definition
> +  # allows it and we deny it here. This approach reduces repetition.
> +  - if:
> +      anyOf:
> +        - required: [buck4s]
> +        - required: [buck6s]
> +        - required: [buck7s]
> +        - required: [buck10s]
> +    then:
> +      patternProperties:
> +        "^buck([467]|10)s$":
> +          properties:
> +            samsung,ext-control: false

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 07/20] dt-bindings: firmware: google,gs101-acpm-ipc: update PMIC examples
  2025-11-03 19:14 ` [PATCH v3 07/20] dt-bindings: firmware: google,gs101-acpm-ipc: update PMIC examples André Draszik
  2025-11-04  8:31   ` Krzysztof Kozlowski
@ 2025-11-04  9:46   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 41+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-04  9:46 UTC (permalink / raw)
  To: André Draszik
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

On Mon, Nov 03, 2025 at 07:14:46PM +0000, André Draszik wrote:
> In a typical system using the Samsung S2MPG10 PMIC, an S2MPG11 is used
> as a sub-PMIC.

Subject: add S2MPG11 secondary PMIC

> 
> The interface for both is the ACPM firmware protocol, so update the
> example here to describe the connection for both.
> 
> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> ---
>  .../bindings/firmware/google,gs101-acpm-ipc.yaml   | 40 ++++++++++++++++++++--
>  1 file changed, 37 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
> index 4a1e3e3c0505aad6669cadf9b7b58aa4c7f284cb..c25e155926e5f44bd74f195cdbff3672c7499f8e 100644
> --- a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
> +++ b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
> @@ -45,6 +45,15 @@ properties:
>        compatible:
>          const: samsung,s2mpg10-pmic
>  
> +  pmic2:

pmic-2

> +    description: Child node describing the sub PMIC.
> +    type: object
> +    additionalProperties: true
> +
> +    properties:
> +      compatible:
> +        const: samsung,s2mpg11-pmic

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 10/20] regulator: add REGULATOR_LINEAR_VRANGE macro
  2025-11-03 19:14 ` [PATCH v3 10/20] regulator: add REGULATOR_LINEAR_VRANGE macro André Draszik
@ 2025-11-04 14:27   ` Mark Brown
  2025-11-05 16:15     ` André Draszik
  0 siblings, 1 reply; 41+ messages in thread
From: Mark Brown @ 2025-11-04 14:27 UTC (permalink / raw)
  To: André Draszik
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

[-- Attachment #1: Type: text/plain, Size: 669 bytes --]

On Mon, Nov 03, 2025 at 07:14:49PM +0000, André Draszik wrote:

> REGULATOR_LINEAR_VRANGE is similar to REGULATOR_LINEAR_RANGE, but
> allows a more natural declaration of a voltage range for a regulator,
> in that it expects the minimum and maximum values as voltages rather
> than as selectors.

> Using voltages arguably makes this macro easier to use by drivers and
> code using it can become easier to read compared to
> REGULATOR_LINEAR_RANGE.

It does introduce an additional layer of indirection into the validation
that the configuration is correct, the reason we use selectors is that
they should map directly onto the register in the datasheet.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 10/20] regulator: add REGULATOR_LINEAR_VRANGE macro
  2025-11-04 14:27   ` Mark Brown
@ 2025-11-05 16:15     ` André Draszik
  0 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-05 16:15 UTC (permalink / raw)
  To: Mark Brown
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

Thanks Mark for your review!

On Tue, 2025-11-04 at 14:27 +0000, Mark Brown wrote:
> On Mon, Nov 03, 2025 at 07:14:49PM +0000, André Draszik wrote:
> 
> > REGULATOR_LINEAR_VRANGE is similar to REGULATOR_LINEAR_RANGE, but
> > allows a more natural declaration of a voltage range for a regulator,
> > in that it expects the minimum and maximum values as voltages rather
> > than as selectors.
> 
> > Using voltages arguably makes this macro easier to use by drivers and
> > code using it can become easier to read compared to
> > REGULATOR_LINEAR_RANGE.
> 
> It does introduce an additional layer of indirection into the validation
> that the configuration is correct, the reason we use selectors is that
> they should map directly onto the register in the datasheet.

My datasheet mentions the range more prominently than the selectors, and as driver
author I can easily validate both (neither macro does any validation itself). I do
believe code like this:

    REGULATOR_LINEAR_VRANGE(200000, 450000, 1300000, STEP_6_25_MV)

looks more meaningful and is more naturally readable than

    REGULATOR_LINEAR_RANGE(450000, 0x28, 0xb0, STEP_6_25_MV)

as it's much easier to see the actual range without doing any additional calculations.
I'd prefer to keep the alternative macro, but will drop this patch if you really
disagree that it adds any value


Cheers,
Andre'

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 02/20] dt-bindings: mfd: samsung,s2mps11: split s2mpg10 into separate file
  2025-11-04  8:26   ` Krzysztof Kozlowski
@ 2025-11-07 11:01     ` André Draszik
  2025-11-09 18:59       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 41+ messages in thread
From: André Draszik @ 2025-11-07 11:01 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

Hi Krzysztof,

Thanks for your review.

On Tue, 2025-11-04 at 09:26 +0100, Krzysztof Kozlowski wrote:
> On Mon, Nov 03, 2025 at 07:14:41PM +0000, André Draszik wrote:
> > +properties:
> > +  compatible:
> > +    const: samsung,s2mpg10-pmic
> > +
> > +  clocks:
> > +    $ref: /schemas/clock/samsung,s2mps11.yaml
> > +    description:
> > +      Child node describing clock provider.
> > +
> > +  interrupts:
> > +    maxItems: 1
> > +
> > +  regulators:
> > +    type: object
> > +    description:
> > +      List of child nodes that specify the regulators.
> > +
> > +  system-power-controller: true
> > +
> > +  wakeup-source: true
> > +
> > +required:
> > +  - compatible
> > +  - interrupts
> > +  - regulators
> > +
> > +additionalProperties: false
> 
> You need a complete example here.

Patch 7 adds / updates the example for these to the ACPM binding. I can extend that
example, but I'd prefer to keep it there to give it a bit more context. Adding an
example here would duplicate things.

Do you agree to that approach?

Thanks,
Andre


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 04/20] regulator: dt-bindings: add s2mpg11-pmic regulators
  2025-11-04  9:39   ` Krzysztof Kozlowski
@ 2025-11-07 11:14     ` André Draszik
  2025-11-09 19:00       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 41+ messages in thread
From: André Draszik @ 2025-11-07 11:14 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

On Tue, 2025-11-04 at 10:39 +0100, Krzysztof Kozlowski wrote:
> On Mon, Nov 03, 2025 at 07:14:43PM +0000, André Draszik wrote:
> > +  The S2MPG11 PMIC provides 12 buck, 1 buck-boost, and 15 LDO regulators.
> > +
> > +  See also Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml for
> > +  additional information and example.
> > +
> > +definitions:
> 
> defs:

All existing bindings are using definitions, not defs. Shouldn't this stay
consistent?

[...]

> > +patternProperties:
> > +  # 12 bucks
> > +  "^buck(([1-9]|10)s|[ad])$":
> > +    type: object
> > +    $ref: regulator.yaml#
> > +    unevaluatedProperties: false
> > +    description:
> > +      Properties for a single buck regulator.
> > +
> > +    allOf:
> > +      - $ref: "#/definitions/s2mpg11-ext-control"
> 
> defs
> 
> > +
> > +    properties:
> > +      regulator-ramp-delay:
> > +        enum: [6250, 12500, 25000]
> > +        default: 6250
> > +
> 
> ....
> 
> 
> > +    allOf:
> > +      - $ref: "#/definitions/s2mpg11-ext-control"
> > +
> > +    properties:
> > +      regulator-ramp-delay:
> > +        enum: [6250, 12500]
> > +        default: 6250
> > +
> > +additionalProperties: false
> 
> This goes to the end, after allOf, see example-schema.

Will fix.

Thanks for your review Krzysztof.

Cheers,
A.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 05/20] dt-bindings: mfd: samsung,s2mpg10: Link s2mpg10-pmic to its regulators
  2025-11-04  8:28   ` Krzysztof Kozlowski
@ 2025-11-08 13:48     ` André Draszik
  0 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-08 13:48 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

Thanks Krzysztof for your review!

On Tue, 2025-11-04 at 09:28 +0100, Krzysztof Kozlowski wrote:
> On Mon, Nov 03, 2025 at 07:14:44PM +0000, André Draszik wrote:
> >  required:
> >    - compatible
> >    - interrupts
> >    - regulators
> >  
> >  additionalProperties: false
> > +
> > +allOf:
> > +  - if:
> > +      properties:
> > +        compatible:
> > +          contains:
> > +            const: samsung,s2mpg10-pmic
> > +    then:
> > +      properties:
> 
> This is not correct now. You do not have other variants here and ref
> should be directly in top level "regulators" part of schema.

The commit message explains why, and with your comment on patch 6 I have changed
this now as you suggest.

Thank you,
Andre

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 07/20] dt-bindings: firmware: google,gs101-acpm-ipc: update PMIC examples
  2025-11-04  8:31   ` Krzysztof Kozlowski
@ 2025-11-08 14:08     ` André Draszik
  2025-11-09 19:02       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 41+ messages in thread
From: André Draszik @ 2025-11-08 14:08 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

Hi Krzysztof,

Thanks for your review!

On Tue, 2025-11-04 at 09:31 +0100, Krzysztof Kozlowski wrote:
> On Mon, Nov 03, 2025 at 07:14:46PM +0000, André Draszik wrote:
> > In a typical system using the Samsung S2MPG10 PMIC, an S2MPG11 is used
> > as a sub-PMIC.
> > 
> > The interface for both is the ACPM firmware protocol, so update the
> > example here to describe the connection for both.
> > 
> > Signed-off-by: André Draszik <andre.draszik@linaro.org>
> > ---
> >  .../bindings/firmware/google,gs101-acpm-ipc.yaml   | 40 ++++++++++++++++++++--
> >  1 file changed, 37 insertions(+), 3 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
> > b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
> > index 4a1e3e3c0505aad6669cadf9b7b58aa4c7f284cb..c25e155926e5f44bd74f195cdbff3672c7499f8e 100644
> > --- a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
> > +++ b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
> > @@ -45,6 +45,15 @@ properties:
> >        compatible:
> >          const: samsung,s2mpg10-pmic
> >  
> > +  pmic2:
> 
> pmic-2
> 
> Are there more pmics? Bindings are supposed to be complete (see writing
> bindings) and if you did follow this approach earlier, you would nicely
> call first "pmic-1" (instead of "pmic") and then "pmic-2".

There aren't any more PMICs on ACPM, no. At the time 'pmic' was added, it wasn't clear
unfortunately that two nodes would be needed in the end.

See also https://lore.kernel.org/all/963bbf8db71efc0d729bb9141c133df2c56881fc.camel@linaro.org/

That said, I believe we can change the existing node name from pmic to pmic-1 without
any driver breaking. The sysfs path would change, but I don't think anybody cares about
it at this stage, so I think such a change would be fine. The ACPM driver doesn't care
about node names and instantiates all children regardless of name.

I propose to update the binding (and DTS subsequently) to add pmic-1, to allow 'pmic' as
a legacy fallback (i.e. to not issue errors during validation of existing DTSs until
they're updated) and to use pmic-2 for the 2nd pmic.

OK?


Cheers,
Andre'

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 02/20] dt-bindings: mfd: samsung,s2mps11: split s2mpg10 into separate file
  2025-11-07 11:01     ` André Draszik
@ 2025-11-09 18:59       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 41+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-09 18:59 UTC (permalink / raw)
  To: André Draszik
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

On 07/11/2025 12:01, André Draszik wrote:
> Hi Krzysztof,
> 
> Thanks for your review.
> 
> On Tue, 2025-11-04 at 09:26 +0100, Krzysztof Kozlowski wrote:
>> On Mon, Nov 03, 2025 at 07:14:41PM +0000, André Draszik wrote:
>>> +properties:
>>> +  compatible:
>>> +    const: samsung,s2mpg10-pmic
>>> +
>>> +  clocks:
>>> +    $ref: /schemas/clock/samsung,s2mps11.yaml
>>> +    description:
>>> +      Child node describing clock provider.
>>> +
>>> +  interrupts:
>>> +    maxItems: 1
>>> +
>>> +  regulators:
>>> +    type: object
>>> +    description:
>>> +      List of child nodes that specify the regulators.
>>> +
>>> +  system-power-controller: true
>>> +
>>> +  wakeup-source: true
>>> +
>>> +required:
>>> +  - compatible
>>> +  - interrupts
>>> +  - regulators
>>> +
>>> +additionalProperties: false
>>
>> You need a complete example here.
> 
> Patch 7 adds / updates the example for these to the ACPM binding. I can extend that
> example, but I'd prefer to keep it there to give it a bit more context. Adding an
> example here would duplicate things.
> 
> Do you agree to that approach?

You should have here example, because ACPM can come in the future, e.g.
next Tensor SoCs with different devices under pmic and pmic-2. This is
the binding for S2MPS11 device, so this should be complete - including
the example. If it gets duplicated with ACPM, that's fine for now.


Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 04/20] regulator: dt-bindings: add s2mpg11-pmic regulators
  2025-11-07 11:14     ` André Draszik
@ 2025-11-09 19:00       ` Krzysztof Kozlowski
  2025-11-10  6:30         ` André Draszik
  0 siblings, 1 reply; 41+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-09 19:00 UTC (permalink / raw)
  To: André Draszik
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

On 07/11/2025 12:14, André Draszik wrote:
> On Tue, 2025-11-04 at 10:39 +0100, Krzysztof Kozlowski wrote:
>> On Mon, Nov 03, 2025 at 07:14:43PM +0000, André Draszik wrote:
>>> +  The S2MPG11 PMIC provides 12 buck, 1 buck-boost, and 15 LDO regulators.
>>> +
>>> +  See also Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml for
>>> +  additional information and example.
>>> +
>>> +definitions:
>>
>> defs:
> 
> All existing bindings are using definitions, not defs. Shouldn't this stay
> consistent?

Huh? git grep gives me 3 cases, so how is it "all existing"?

But for defs it gives me ~98!	


Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 07/20] dt-bindings: firmware: google,gs101-acpm-ipc: update PMIC examples
  2025-11-08 14:08     ` André Draszik
@ 2025-11-09 19:02       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 41+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-09 19:02 UTC (permalink / raw)
  To: André Draszik
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

On 08/11/2025 15:08, André Draszik wrote:
> Hi Krzysztof,
> 
> Thanks for your review!
> 
> On Tue, 2025-11-04 at 09:31 +0100, Krzysztof Kozlowski wrote:
>> On Mon, Nov 03, 2025 at 07:14:46PM +0000, André Draszik wrote:
>>> In a typical system using the Samsung S2MPG10 PMIC, an S2MPG11 is used
>>> as a sub-PMIC.
>>>
>>> The interface for both is the ACPM firmware protocol, so update the
>>> example here to describe the connection for both.
>>>
>>> Signed-off-by: André Draszik <andre.draszik@linaro.org>
>>> ---
>>>  .../bindings/firmware/google,gs101-acpm-ipc.yaml   | 40 ++++++++++++++++++++--
>>>  1 file changed, 37 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
>>> b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
>>> index 4a1e3e3c0505aad6669cadf9b7b58aa4c7f284cb..c25e155926e5f44bd74f195cdbff3672c7499f8e 100644
>>> --- a/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
>>> +++ b/Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
>>> @@ -45,6 +45,15 @@ properties:
>>>        compatible:
>>>          const: samsung,s2mpg10-pmic
>>>  
>>> +  pmic2:
>>
>> pmic-2
>>
>> Are there more pmics? Bindings are supposed to be complete (see writing
>> bindings) and if you did follow this approach earlier, you would nicely
>> call first "pmic-1" (instead of "pmic") and then "pmic-2".
> 
> There aren't any more PMICs on ACPM, no. At the time 'pmic' was added, it wasn't clear
> unfortunately that two nodes would be needed in the end.
> 
> See also https://lore.kernel.org/all/963bbf8db71efc0d729bb9141c133df2c56881fc.camel@linaro.org/
> 
> That said, I believe we can change the existing node name from pmic to pmic-1 without
> any driver breaking. The sysfs path would change, but I don't think anybody cares about
> it at this stage, so I think such a change would be fine. The ACPM driver doesn't care
> about node names and instantiates all children regardless of name.
> 
> I propose to update the binding (and DTS subsequently) to add pmic-1, to allow 'pmic' as
> a legacy fallback (i.e. to not issue errors during validation of existing DTSs until
> they're updated) and to use pmic-2 for the 2nd pmic.
> 
> OK?

So deprecate 'pmic' and add new 'pmic-1'.

Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 04/20] regulator: dt-bindings: add s2mpg11-pmic regulators
  2025-11-09 19:00       ` Krzysztof Kozlowski
@ 2025-11-10  6:30         ` André Draszik
  0 siblings, 0 replies; 41+ messages in thread
From: André Draszik @ 2025-11-10  6:30 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Liam Girdwood,
	Mark Brown, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

On Sun, 2025-11-09 at 20:00 +0100, Krzysztof Kozlowski wrote:
> On 07/11/2025 12:14, André Draszik wrote:
> > On Tue, 2025-11-04 at 10:39 +0100, Krzysztof Kozlowski wrote:
> > > On Mon, Nov 03, 2025 at 07:14:43PM +0000, André Draszik wrote:
> > > > +  The S2MPG11 PMIC provides 12 buck, 1 buck-boost, and 15 LDO regulators.
> > > > +
> > > > +  See also Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml for
> > > > +  additional information and example.
> > > > +
> > > > +definitions:
> > > 
> > > defs:
> > 
> > All existing bindings are using definitions, not defs. Shouldn't this stay
> > consistent?
> 
> Huh? git grep gives me 3 cases, so how is it "all existing"?
> 
> But for defs it gives me ~98!	

Didn't know it's ^$defs:, not ^defs: - thanks Krzysztof.

Cheers,
Andre'

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 09/20] mfd: sec: Add support for S2MPG11 PMIC via ACPM
  2025-11-03 19:14 ` [PATCH v3 09/20] mfd: sec: Add support for S2MPG11 PMIC via ACPM André Draszik
@ 2025-11-13 16:25   ` Lee Jones
  0 siblings, 0 replies; 41+ messages in thread
From: Lee Jones @ 2025-11-13 16:25 UTC (permalink / raw)
  To: André Draszik
  Cc: Tudor Ambarus, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Linus Walleij, Bartosz Golaszewski,
	Krzysztof Kozlowski, Peter Griffin, Will McVicker, kernel-team,
	linux-kernel, linux-samsung-soc, devicetree, linux-gpio

Mark, something for you below.

> Add support for Samsung's S2MPG11 PMIC, which is a Power Management IC
> for mobile applications with buck converters, various LDOs, power
> meters, NTC thermistor inputs, and additional GPIO interfaces. It
> typically complements an S2MPG10 PMIC in a main/sub configuration as
> the sub-PMIC.
> 
> Like S2MPG10, communication is not via I2C, but via the Samsung ACPM
> firmware.
> 
> Also like S2MPG10, the regulator rails will need to be instantiated
> individually to allow probe to succeed due to rails being used as
> supplies for S2MPG10, and to avoid supply rails from being disabled
> unexpectedly due to probe deferral.
> 
> Note: The firmware uses the ACPM channel ID and the Speedy channel ID
> to select the PMIC address. Since these are firmware properties, they
> can not be retrieved from DT, but instead are deducted from the
> compatible for now.
> 
> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> 
> ---
> Note: checkpatch suggests to update MAINTAINERS, but the new file is
> covered already due to using a wildcard.
> 
> v3:
> - mention NTC thermistor inputs in commit message
> - one instance per actual rail, not per rail type (LDO or buck)
> 
> v2:
> - mention GPIOs in commit message
> ---
>  drivers/mfd/sec-acpm.c              | 213 +++++++++++++++++-
>  drivers/mfd/sec-common.c            |  45 +++-
>  drivers/mfd/sec-irq.c               |  67 +++++-
>  include/linux/mfd/samsung/core.h    |   1 +
>  include/linux/mfd/samsung/irq.h     |  99 ++++++++
>  include/linux/mfd/samsung/s2mpg11.h | 434 ++++++++++++++++++++++++++++++++++++
>  6 files changed, 848 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/mfd/sec-acpm.c b/drivers/mfd/sec-acpm.c
> index 8b31c816d65b86c54a108fa994384abfac0e7da4..b44af6f8b1cdfcb75cf9d4c55c9d973a88fd510c 100644
> --- a/drivers/mfd/sec-acpm.c
> +++ b/drivers/mfd/sec-acpm.c
> @@ -13,6 +13,7 @@
>  #include <linux/mfd/samsung/core.h>
>  #include <linux/mfd/samsung/rtc.h>
>  #include <linux/mfd/samsung/s2mpg10.h>
> +#include <linux/mfd/samsung/s2mpg11.h>
>  #include <linux/mod_devicetable.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
> @@ -216,6 +217,155 @@ static const struct regmap_config s2mpg10_regmap_config_meter = {
>  	.cache_type = REGCACHE_FLAT,
>  };
>  
> +static const struct regmap_range s2mpg11_common_registers[] = {
> +	regmap_reg_range(0x00, 0x02), /* CHIP_ID_S, INT, INT_MASK */
> +	regmap_reg_range(0x0a, 0x0c), /* Speedy control */
> +	regmap_reg_range(0x1a, 0x27), /* Debug */

These numbers are usually defined, and rightfully so.

> +};
> +
> +static const struct regmap_range s2mpg11_common_ro_registers[] = {
> +	regmap_reg_range(0x00, 0x01), /* CHIP_ID_S, INT */
> +	regmap_reg_range(0x25, 0x27), /* Debug */
> +};
> +
> +static const struct regmap_range s2mpg11_common_nonvolatile_registers[] = {
> +	regmap_reg_range(0x00, 0x00), /* CHIP_ID_S */
> +	regmap_reg_range(0x02, 0x02), /* INT_MASK */
> +	regmap_reg_range(0x0a, 0x0c), /* Speedy control */
> +};
> +
> +static const struct regmap_range s2mpg11_common_precious_registers[] = {
> +	regmap_reg_range(0x01, 0x01), /* INT */
> +};
> +
> +static const struct regmap_access_table s2mpg11_common_wr_table = {
> +	.yes_ranges = s2mpg11_common_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg11_common_registers),
> +	.no_ranges = s2mpg11_common_ro_registers,
> +	.n_no_ranges = ARRAY_SIZE(s2mpg11_common_ro_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg11_common_rd_table = {
> +	.yes_ranges = s2mpg11_common_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg11_common_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg11_common_volatile_table = {
> +	.no_ranges = s2mpg11_common_nonvolatile_registers,
> +	.n_no_ranges = ARRAY_SIZE(s2mpg11_common_nonvolatile_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg11_common_precious_table = {
> +	.yes_ranges = s2mpg11_common_precious_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg11_common_precious_registers),
> +};
> +
> +static const struct regmap_config s2mpg11_regmap_config_common = {
> +	.name = "common",
> +	.reg_bits = ACPM_ADDR_BITS,
> +	.val_bits = 8,
> +	.max_register = S2MPG11_COMMON_SPD_DEBUG4,
> +	.wr_table = &s2mpg11_common_wr_table,
> +	.rd_table = &s2mpg11_common_rd_table,
> +	.volatile_table = &s2mpg11_common_volatile_table,
> +	.precious_table = &s2mpg11_common_precious_table,
> +	.num_reg_defaults_raw = S2MPG11_COMMON_SPD_DEBUG4 + 1,
> +	.cache_type = REGCACHE_FLAT,
> +};
> +
> +static const struct regmap_range s2mpg11_pmic_registers[] = {
> +	regmap_reg_range(0x00, 0x5a), /* All PMIC registers */
> +	regmap_reg_range(0x5c, 0xb7), /* All PMIC registers */
> +};
> +
> +static const struct regmap_range s2mpg11_pmic_ro_registers[] = {
> +	regmap_reg_range(0x00, 0x05), /* INTx */
> +	regmap_reg_range(0x0c, 0x0d), /* STATUS OFFSRC */
> +	regmap_reg_range(0x98, 0x98), /* GPIO input */
> +};
> +
> +static const struct regmap_range s2mpg11_pmic_nonvolatile_registers[] = {
> +	regmap_reg_range(0x06, 0x0b), /* INTxM */
> +};
> +
> +static const struct regmap_range s2mpg11_pmic_precious_registers[] = {
> +	regmap_reg_range(0x00, 0x05), /* INTx */
> +};
> +
> +static const struct regmap_access_table s2mpg11_pmic_wr_table = {
> +	.yes_ranges = s2mpg11_pmic_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg11_pmic_registers),
> +	.no_ranges = s2mpg11_pmic_ro_registers,
> +	.n_no_ranges = ARRAY_SIZE(s2mpg11_pmic_ro_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg11_pmic_rd_table = {
> +	.yes_ranges = s2mpg11_pmic_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg11_pmic_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg11_pmic_volatile_table = {
> +	.no_ranges = s2mpg11_pmic_nonvolatile_registers,
> +	.n_no_ranges = ARRAY_SIZE(s2mpg11_pmic_nonvolatile_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg11_pmic_precious_table = {
> +	.yes_ranges = s2mpg11_pmic_precious_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg11_pmic_precious_registers),
> +};
> +
> +static const struct regmap_config s2mpg11_regmap_config_pmic = {
> +	.name = "pmic",
> +	.reg_bits = ACPM_ADDR_BITS,
> +	.val_bits = 8,
> +	.max_register = S2MPG11_PMIC_LDO_SENSE2,
> +	.wr_table = &s2mpg11_pmic_wr_table,
> +	.rd_table = &s2mpg11_pmic_rd_table,
> +	.volatile_table = &s2mpg11_pmic_volatile_table,
> +	.precious_table = &s2mpg11_pmic_precious_table,
> +	.num_reg_defaults_raw = S2MPG11_PMIC_LDO_SENSE2 + 1,
> +	.cache_type = REGCACHE_FLAT,
> +};
> +
> +static const struct regmap_range s2mpg11_meter_registers[] = {
> +	regmap_reg_range(0x00, 0x3e), /* Meter config */
> +	regmap_reg_range(0x40, 0x8a), /* Meter data */
> +	regmap_reg_range(0x8d, 0x9c), /* Meter data */
> +};
> +
> +static const struct regmap_range s2mpg11_meter_ro_registers[] = {
> +	regmap_reg_range(0x40, 0x9c), /* Meter data */
> +};
> +
> +static const struct regmap_access_table s2mpg11_meter_wr_table = {
> +	.yes_ranges = s2mpg11_meter_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg11_meter_registers),
> +	.no_ranges = s2mpg11_meter_ro_registers,
> +	.n_no_ranges = ARRAY_SIZE(s2mpg11_meter_ro_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg11_meter_rd_table = {
> +	.yes_ranges = s2mpg11_meter_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg11_meter_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg11_meter_volatile_table = {
> +	.yes_ranges = s2mpg11_meter_ro_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg11_meter_ro_registers),
> +};
> +
> +static const struct regmap_config s2mpg11_regmap_config_meter = {
> +	.name = "meter",
> +	.reg_bits = ACPM_ADDR_BITS,
> +	.val_bits = 8,
> +	.max_register = S2MPG11_METER_LPF_DATA_NTC7_2,
> +	.wr_table = &s2mpg11_meter_wr_table,
> +	.rd_table = &s2mpg11_meter_rd_table,
> +	.volatile_table = &s2mpg11_meter_volatile_table,
> +	.num_reg_defaults_raw = S2MPG11_METER_LPF_DATA_NTC7_2 + 1,
> +	.cache_type = REGCACHE_FLAT,
> +};
> +
>  struct sec_pmic_acpm_shared_bus_context {
>  	const struct acpm_handle *acpm;
>  	unsigned int acpm_chan_id;
> @@ -325,16 +475,22 @@ static struct regmap *sec_pmic_acpm_regmap_init(struct device *dev,
>  	return regmap;
>  }
>  
> -static void sec_pmic_acpm_mask_common_irqs(void *regmap_common)
> +static void sec_pmic_acpm_mask_common_s2mpg10_irqs(void *regmap_common)
>  {
>  	regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
>  }
>  
> +static void sec_pmic_acpm_mask_common_s2mpg11_irqs(void *regmap_common)
> +{
> +	regmap_write(regmap_common, S2MPG11_COMMON_INT_MASK, S2MPG11_COMMON_INT_SRC);
> +}
> +
>  static int sec_pmic_acpm_probe(struct platform_device *pdev)
>  {
>  	struct regmap *regmap_common, *regmap_pmic, *regmap;
>  	const struct sec_pmic_acpm_platform_data *pdata;
>  	struct sec_pmic_acpm_shared_bus_context *shared_ctx;
> +	void (*masq_irqs_handler)(void *data);
>  	const struct acpm_handle *acpm;
>  	struct device *dev = &pdev->dev;
>  	int ret, irq;
> @@ -365,7 +521,19 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev)
>  		return PTR_ERR(regmap_common);
>  
>  	/* Mask all interrupts from 'common' block, until successful init */
> -	ret = regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
> +	switch (pdata->device_type) {
> +	case S2MPG10:
> +		ret = regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
> +		break;
> +
> +	case S2MPG11:
> +		ret = regmap_write(regmap_common, S2MPG11_COMMON_INT_MASK, S2MPG11_COMMON_INT_SRC);
> +		break;
> +
> +	default:
> +		return dev_err_probe(dev, -EINVAL, "Unsupported device type %d\n",
> +				     pdata->device_type);
> +	}
>  	if (ret)
>  		return dev_err_probe(dev, ret, "failed to mask common block interrupts\n");
>  
> @@ -374,10 +542,12 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev)
>  	if (IS_ERR(regmap_pmic))
>  		return PTR_ERR(regmap_pmic);
>  
> -	regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_RTC,
> -					   pdata->regmap_cfg_rtc, true);
> -	if (IS_ERR(regmap))
> -		return PTR_ERR(regmap);
> +	if (pdata->regmap_cfg_rtc) {
> +		regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_RTC,
> +						   pdata->regmap_cfg_rtc, true);
> +		if (IS_ERR(regmap))
> +			return PTR_ERR(regmap);
> +	}
>  
>  	regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_METER,
>  					   pdata->regmap_cfg_meter, true);
> @@ -392,13 +562,28 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev)
>  		devm_device_init_wakeup(dev);
>  
>  	/* Unmask PMIC interrupt from 'common' block, now that everything is in place. */
> -	ret = regmap_clear_bits(regmap_common, S2MPG10_COMMON_INT_MASK,
> -				S2MPG10_COMMON_INT_SRC_PMIC);
> +	switch (pdata->device_type) {
> +	case S2MPG10:
> +		ret = regmap_clear_bits(regmap_common, S2MPG10_COMMON_INT_MASK,
> +					S2MPG10_COMMON_INT_SRC_PMIC);
> +		masq_irqs_handler = sec_pmic_acpm_mask_common_s2mpg10_irqs;
> +		break;
> +
> +	case S2MPG11:
> +		ret = regmap_clear_bits(regmap_common, S2MPG11_COMMON_INT_MASK,
> +					S2MPG11_COMMON_INT_SRC_PMIC);
> +		masq_irqs_handler = sec_pmic_acpm_mask_common_s2mpg11_irqs;
> +		break;
> +
> +	default:
> +		return dev_err_probe(dev, -EINVAL, "Unsupported device type %d\n",
> +				     pdata->device_type);
> +	}
>  	if (ret)
>  		return dev_err_probe(dev, ret, "failed to unmask PMIC interrupt\n");
>  
>  	/* Mask all interrupts from 'common' block on shutdown */
> -	ret = devm_add_action_or_reset(dev, sec_pmic_acpm_mask_common_irqs, regmap_common);
> +	ret = devm_add_action_or_reset(dev, masq_irqs_handler, regmap_common);
>  	if (ret)
>  		return ret;
>  
> @@ -420,8 +605,18 @@ static const struct sec_pmic_acpm_platform_data s2mpg10_data = {
>  	.regmap_cfg_meter = &s2mpg10_regmap_config_meter,
>  };
>  
> +static const struct sec_pmic_acpm_platform_data s2mpg11_data = {
> +	.device_type = S2MPG11,
> +	.acpm_chan_id = 2,
> +	.speedy_channel = 1,
> +	.regmap_cfg_common = &s2mpg11_regmap_config_common,
> +	.regmap_cfg_pmic = &s2mpg11_regmap_config_pmic,
> +	.regmap_cfg_meter = &s2mpg11_regmap_config_meter,
> +};
> +
>  static const struct of_device_id sec_pmic_acpm_of_match[] = {
>  	{ .compatible = "samsung,s2mpg10-pmic", .data = &s2mpg10_data, },
> +	{ .compatible = "samsung,s2mpg11-pmic", .data = &s2mpg11_data, },
>  	{ },
>  };
>  MODULE_DEVICE_TABLE(of, sec_pmic_acpm_of_match);
> diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
> index b722481594801e545d24014af6afd5e1e39d7522..4daa0ece91dc783560dfad499f11193b689c2fd1 100644
> --- a/drivers/mfd/sec-common.c
> +++ b/drivers/mfd/sec-common.c
> @@ -15,6 +15,7 @@
>  #include <linux/mfd/samsung/core.h>
>  #include <linux/mfd/samsung/irq.h>
>  #include <linux/mfd/samsung/s2mpg10.h>
> +#include <linux/mfd/samsung/s2mpg11.h>
>  #include <linux/mfd/samsung/s2mps11.h>
>  #include <linux/mfd/samsung/s2mps13.h>
>  #include <linux/module.h>
> @@ -82,6 +83,39 @@ static const struct mfd_cell s2mpg10_devs[] = {
>  	MFD_CELL_OF("s2mpg10-gpio", NULL, NULL, 0, 0, "samsung,s2mpg10-gpio"),
>  };
>  
> +static const struct mfd_cell s2mpg11_devs[] = {
> +	MFD_CELL_NAME("s2mpg11-meter"),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCKBOOST),

This is highly irregular - in that, we've never done this before.

We're going to need to have Mark look at this.

> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK1),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK2),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK3),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK4),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK5),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK6),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK7),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK8),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK9),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCK10),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCKD),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_BUCKA),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO1),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO2),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO3),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO4),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO5),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO6),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO7),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO8),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO9),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO10),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO11),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO12),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO13),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO14),
> +	MFD_CELL_BASIC("s2mpg11-regulator", NULL, NULL, 0, S2MPG11_LDO15),
> +	MFD_CELL_OF("s2mpg11-gpio", NULL, NULL, 0, 0, "samsung,s2mpg11-gpio"),
> +};
> +
>  static const struct mfd_cell s2mps11_devs[] = {
>  	MFD_CELL_NAME("s2mps11-regulator"),
>  	MFD_CELL_NAME("s2mps14-rtc"),
> @@ -125,8 +159,13 @@ static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)
>  	unsigned int val;
>  
>  	/* For s2mpg1x, the revision is in a different regmap */
> -	if (sec_pmic->device_type == S2MPG10)
> +	switch (sec_pmic->device_type) {
> +	case S2MPG10:
> +	case S2MPG11:
>  		return;
> +	default:
> +		break;
> +	}
>  
>  	/* For each device type, the REG_ID is always the first register */
>  	if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val))
> @@ -231,6 +270,10 @@ int sec_pmic_probe(struct device *dev, int device_type, unsigned int irq,
>  		sec_devs = s2mpg10_devs;
>  		num_sec_devs = ARRAY_SIZE(s2mpg10_devs);
>  		break;
> +	case S2MPG11:
> +		sec_devs = s2mpg11_devs;
> +		num_sec_devs = ARRAY_SIZE(s2mpg11_devs);
> +		break;
>  	case S2MPS11X:
>  		sec_devs = s2mps11_devs;
>  		num_sec_devs = ARRAY_SIZE(s2mps11_devs);
> diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
> index c5c80b1ba104e6c5a55b442d2f10a8554201a961..a04e46144baae6a195a84df56c53e399e3875e3d 100644
> --- a/drivers/mfd/sec-irq.c
> +++ b/drivers/mfd/sec-irq.c
> @@ -11,6 +11,7 @@
>  #include <linux/mfd/samsung/core.h>
>  #include <linux/mfd/samsung/irq.h>
>  #include <linux/mfd/samsung/s2mpg10.h>
> +#include <linux/mfd/samsung/s2mpg11.h>
>  #include <linux/mfd/samsung/s2mps11.h>
>  #include <linux/mfd/samsung/s2mps14.h>
>  #include <linux/mfd/samsung/s2mpu02.h>
> @@ -73,6 +74,58 @@ static const struct regmap_irq s2mpg10_irqs[] = {
>  	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH7, 5, S2MPG10_IRQ_PWR_WARN_CH7_MASK),
>  };
>  
> +static const struct regmap_irq s2mpg11_irqs[] = {
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PWRONF, 0, S2MPG11_IRQ_PWRONF_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PWRONR, 0, S2MPG11_IRQ_PWRONR_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PIF_TIMEOUT_MIF, 0, S2MPG11_IRQ_PIF_TIMEOUT_MIF_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PIF_TIMEOUTS, 0, S2MPG11_IRQ_PIF_TIMEOUTS_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_WTSR, 0, S2MPG11_IRQ_WTSR_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_SPD_ABNORMAL_STOP, 0, S2MPG11_IRQ_SPD_ABNORMAL_STOP_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_SPD_PARITY_ERR, 0, S2MPG11_IRQ_SPD_PARITY_ERR_MASK),
> +
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_140C, 1, S2MPG11_IRQ_INT140C_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_120C, 1, S2MPG11_IRQ_INT120C_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_TSD, 1, S2MPG11_IRQ_TSD_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_WRST, 1, S2MPG11_IRQ_WRST_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_CYCLE_DONE, 1, S2MPG11_IRQ_NTC_CYCLE_DONE_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PMETER_OVERF, 1, S2MPG11_IRQ_PMETER_OVERF_MASK),
> +
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B1S, 2, S2MPG11_IRQ_OCP_B1S_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B2S, 2, S2MPG11_IRQ_OCP_B2S_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B3S, 2, S2MPG11_IRQ_OCP_B3S_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B4S, 2, S2MPG11_IRQ_OCP_B4S_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B5S, 2, S2MPG11_IRQ_OCP_B5S_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B6S, 2, S2MPG11_IRQ_OCP_B6S_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B7S, 2, S2MPG11_IRQ_OCP_B7S_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B8S, 2, S2MPG11_IRQ_OCP_B8S_MASK),
> +
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B9S, 3, S2MPG11_IRQ_OCP_B9S_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_B10S, 3, S2MPG11_IRQ_OCP_B10S_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_BDS, 3, S2MPG11_IRQ_OCP_BDS_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_BAS, 3, S2MPG11_IRQ_OCP_BAS_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_OCP_BBS, 3, S2MPG11_IRQ_OCP_BBS_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_WLWP_ACC, 3, S2MPG11_IRQ_WLWP_ACC_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_SPD_SRP_PKT_RST, 3, S2MPG11_IRQ_SPD_SRP_PKT_RST_MASK),
> +
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH0, 4, S2MPG11_IRQ_PWR_WARN_CH0_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH1, 4, S2MPG11_IRQ_PWR_WARN_CH1_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH2, 4, S2MPG11_IRQ_PWR_WARN_CH2_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH3, 4, S2MPG11_IRQ_PWR_WARN_CH3_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH4, 4, S2MPG11_IRQ_PWR_WARN_CH4_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH5, 4, S2MPG11_IRQ_PWR_WARN_CH5_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH6, 4, S2MPG11_IRQ_PWR_WARN_CH6_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_PWR_WARN_CH7, 4, S2MPG11_IRQ_PWR_WARN_CH7_MASK),
> +
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH0, 5, S2MPG11_IRQ_NTC_WARN_CH0_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH1, 5, S2MPG11_IRQ_NTC_WARN_CH1_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH2, 5, S2MPG11_IRQ_NTC_WARN_CH2_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH3, 5, S2MPG11_IRQ_NTC_WARN_CH3_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH4, 5, S2MPG11_IRQ_NTC_WARN_CH4_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH5, 5, S2MPG11_IRQ_NTC_WARN_CH5_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH6, 5, S2MPG11_IRQ_NTC_WARN_CH6_MASK),
> +	REGMAP_IRQ_REG(S2MPG11_IRQ_NTC_WARN_CH7, 5, S2MPG11_IRQ_NTC_WARN_CH7_MASK),
> +};
> +
>  static const struct regmap_irq s2mps11_irqs[] = {
>  	REGMAP_IRQ_REG(S2MPS11_IRQ_PWRONF, 0, S2MPS11_IRQ_PWRONF_MASK),
>  	REGMAP_IRQ_REG(S2MPS11_IRQ_PWRONR, 0, S2MPS11_IRQ_PWRONR_MASK),
> @@ -180,7 +233,7 @@ static const struct regmap_irq s5m8767_irqs[] = {
>  	REGMAP_IRQ_REG(S5M8767_IRQ_WTSR, 2, S5M8767_IRQ_WTSR_MASK),
>  };
>  
> -/* All S2MPG10 interrupt sources are read-only and don't require clearing */
> +/* All S2MPG1x interrupt sources are read-only and don't require clearing */
>  static const struct regmap_irq_chip s2mpg10_irq_chip = {
>  	.name = "s2mpg10",
>  	.irqs = s2mpg10_irqs,
> @@ -190,6 +243,15 @@ static const struct regmap_irq_chip s2mpg10_irq_chip = {
>  	.mask_base = S2MPG10_PMIC_INT1M,
>  };
>  
> +static const struct regmap_irq_chip s2mpg11_irq_chip = {
> +	.name = "s2mpg11",
> +	.irqs = s2mpg11_irqs,
> +	.num_irqs = ARRAY_SIZE(s2mpg11_irqs),
> +	.num_regs = 6,
> +	.status_base = S2MPG11_PMIC_INT1,
> +	.mask_base = S2MPG11_PMIC_INT1M,
> +};
> +
>  static const struct regmap_irq_chip s2mps11_irq_chip = {
>  	.name = "s2mps11",
>  	.irqs = s2mps11_irqs,
> @@ -270,6 +332,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
>  	case S2MPG10:
>  		sec_irq_chip = &s2mpg10_irq_chip;
>  		break;
> +	case S2MPG11:
> +		sec_irq_chip = &s2mpg11_irq_chip;
> +		break;
>  	case S2MPS11X:
>  		sec_irq_chip = &s2mps11_irq_chip;
>  		break;
> diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
> index d785e101fe795a5d8f9cccf4ccc4232437e89416..f5fba117bea61b3e3fb308759dc2748f6dd01dfb 100644
> --- a/include/linux/mfd/samsung/core.h
> +++ b/include/linux/mfd/samsung/core.h
> @@ -40,6 +40,7 @@ enum sec_device_type {
>  	S2DOS05,
>  	S2MPA01,
>  	S2MPG10,
> +	S2MPG11,
>  	S2MPS11X,
>  	S2MPS13X,
>  	S2MPS14X,
> diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h
> index b4805cbd949bd605004bd88cf361109d1cbbc3bf..08b1ab33bad48194491fef88d48d5d0027e06a7c 100644
> --- a/include/linux/mfd/samsung/irq.h
> +++ b/include/linux/mfd/samsung/irq.h
> @@ -160,6 +160,105 @@ enum s2mpg10_irq {
>  	S2MPG10_IRQ_NR,
>  };
>  
> +enum s2mpg11_irq {
> +	/* PMIC */
> +	S2MPG11_IRQ_PWRONF,
> +	S2MPG11_IRQ_PWRONR,
> +	S2MPG11_IRQ_PIF_TIMEOUT_MIF,
> +	S2MPG11_IRQ_PIF_TIMEOUTS,
> +	S2MPG11_IRQ_WTSR,
> +	S2MPG11_IRQ_SPD_ABNORMAL_STOP,
> +	S2MPG11_IRQ_SPD_PARITY_ERR,
> +#define S2MPG11_IRQ_PWRONF_MASK			BIT(0)
> +#define S2MPG11_IRQ_PWRONR_MASK			BIT(1)
> +#define S2MPG11_IRQ_PIF_TIMEOUT_MIF_MASK	BIT(3)
> +#define S2MPG11_IRQ_PIF_TIMEOUTS_MASK		BIT(4)
> +#define S2MPG11_IRQ_WTSR_MASK			BIT(5)
> +#define S2MPG11_IRQ_SPD_ABNORMAL_STOP_MASK	BIT(6)
> +#define S2MPG11_IRQ_SPD_PARITY_ERR_MASK		BIT(7)
> +
> +	S2MPG11_IRQ_140C,
> +	S2MPG11_IRQ_120C,
> +	S2MPG11_IRQ_TSD,
> +	S2MPG11_IRQ_WRST,
> +	S2MPG11_IRQ_NTC_CYCLE_DONE,
> +	S2MPG11_IRQ_PMETER_OVERF,
> +#define S2MPG11_IRQ_INT140C_MASK	BIT(0)
> +#define S2MPG11_IRQ_INT120C_MASK	BIT(1)
> +#define S2MPG11_IRQ_TSD_MASK		BIT(2)
> +#define S2MPG11_IRQ_WRST_MASK		BIT(5)
> +#define S2MPG11_IRQ_NTC_CYCLE_DONE_MASK	BIT(6)
> +#define S2MPG11_IRQ_PMETER_OVERF_MASK	BIT(7)
> +
> +	S2MPG11_IRQ_OCP_B1S,
> +	S2MPG11_IRQ_OCP_B2S,
> +	S2MPG11_IRQ_OCP_B3S,
> +	S2MPG11_IRQ_OCP_B4S,
> +	S2MPG11_IRQ_OCP_B5S,
> +	S2MPG11_IRQ_OCP_B6S,
> +	S2MPG11_IRQ_OCP_B7S,
> +	S2MPG11_IRQ_OCP_B8S,
> +#define S2MPG11_IRQ_OCP_B1S_MASK	BIT(0)
> +#define S2MPG11_IRQ_OCP_B2S_MASK	BIT(1)
> +#define S2MPG11_IRQ_OCP_B3S_MASK	BIT(2)
> +#define S2MPG11_IRQ_OCP_B4S_MASK	BIT(3)
> +#define S2MPG11_IRQ_OCP_B5S_MASK	BIT(4)
> +#define S2MPG11_IRQ_OCP_B6S_MASK	BIT(5)
> +#define S2MPG11_IRQ_OCP_B7S_MASK	BIT(6)
> +#define S2MPG11_IRQ_OCP_B8S_MASK	BIT(7)
> +
> +	S2MPG11_IRQ_OCP_B9S,
> +	S2MPG11_IRQ_OCP_B10S,
> +	S2MPG11_IRQ_OCP_BDS,
> +	S2MPG11_IRQ_OCP_BAS,
> +	S2MPG11_IRQ_OCP_BBS,
> +	S2MPG11_IRQ_WLWP_ACC,
> +	S2MPG11_IRQ_SPD_SRP_PKT_RST,
> +#define S2MPG11_IRQ_OCP_B9S_MASK		BIT(0)
> +#define S2MPG11_IRQ_OCP_B10S_MASK		BIT(1)
> +#define S2MPG11_IRQ_OCP_BDS_MASK		BIT(2)
> +#define S2MPG11_IRQ_OCP_BAS_MASK		BIT(3)
> +#define S2MPG11_IRQ_OCP_BBS_MASK		BIT(4)
> +#define S2MPG11_IRQ_WLWP_ACC_MASK		BIT(5)
> +#define S2MPG11_IRQ_SPD_SRP_PKT_RST_MASK	BIT(7)
> +
> +	S2MPG11_IRQ_PWR_WARN_CH0,
> +	S2MPG11_IRQ_PWR_WARN_CH1,
> +	S2MPG11_IRQ_PWR_WARN_CH2,
> +	S2MPG11_IRQ_PWR_WARN_CH3,
> +	S2MPG11_IRQ_PWR_WARN_CH4,
> +	S2MPG11_IRQ_PWR_WARN_CH5,
> +	S2MPG11_IRQ_PWR_WARN_CH6,
> +	S2MPG11_IRQ_PWR_WARN_CH7,
> +#define S2MPG11_IRQ_PWR_WARN_CH0_MASK	BIT(0)
> +#define S2MPG11_IRQ_PWR_WARN_CH1_MASK	BIT(1)
> +#define S2MPG11_IRQ_PWR_WARN_CH2_MASK	BIT(2)
> +#define S2MPG11_IRQ_PWR_WARN_CH3_MASK	BIT(3)
> +#define S2MPG11_IRQ_PWR_WARN_CH4_MASK	BIT(4)
> +#define S2MPG11_IRQ_PWR_WARN_CH5_MASK	BIT(5)
> +#define S2MPG11_IRQ_PWR_WARN_CH6_MASK	BIT(6)
> +#define S2MPG11_IRQ_PWR_WARN_CH7_MASK	BIT(7)
> +
> +	S2MPG11_IRQ_NTC_WARN_CH0,
> +	S2MPG11_IRQ_NTC_WARN_CH1,
> +	S2MPG11_IRQ_NTC_WARN_CH2,
> +	S2MPG11_IRQ_NTC_WARN_CH3,
> +	S2MPG11_IRQ_NTC_WARN_CH4,
> +	S2MPG11_IRQ_NTC_WARN_CH5,
> +	S2MPG11_IRQ_NTC_WARN_CH6,
> +	S2MPG11_IRQ_NTC_WARN_CH7,
> +#define S2MPG11_IRQ_NTC_WARN_CH0_MASK	BIT(0)
> +#define S2MPG11_IRQ_NTC_WARN_CH1_MASK	BIT(1)
> +#define S2MPG11_IRQ_NTC_WARN_CH2_MASK	BIT(2)
> +#define S2MPG11_IRQ_NTC_WARN_CH3_MASK	BIT(3)
> +#define S2MPG11_IRQ_NTC_WARN_CH4_MASK	BIT(4)
> +#define S2MPG11_IRQ_NTC_WARN_CH5_MASK	BIT(5)
> +#define S2MPG11_IRQ_NTC_WARN_CH6_MASK	BIT(6)
> +#define S2MPG11_IRQ_NTC_WARN_CH7_MASK	BIT(7)
> +
> +	S2MPG11_IRQ_NR,
> +};
> +
>  enum s2mps11_irq {
>  	S2MPS11_IRQ_PWRONF,
>  	S2MPS11_IRQ_PWRONR,
> diff --git a/include/linux/mfd/samsung/s2mpg11.h b/include/linux/mfd/samsung/s2mpg11.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..db300cb3bcef1b5b8630e189c58dbb92df8e6cb4
> --- /dev/null
> +++ b/include/linux/mfd/samsung/s2mpg11.h
> @@ -0,0 +1,434 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2015 Samsung Electronics
> + * Copyright 2020 Google Inc
> + * Copyright 2025 Linaro Ltd.
> + */
> +
> +#ifndef __LINUX_MFD_S2MPG11_H
> +#define __LINUX_MFD_S2MPG11_H
> +
> +/* Common registers (type 0x000) */
> +enum s2mpg11_common_reg {
> +	S2MPG11_COMMON_CHIPID,
> +	S2MPG11_COMMON_INT,
> +	S2MPG11_COMMON_INT_MASK,
> +	S2MPG11_COMMON_SPD_CTRL1 = 0x0a,
> +	S2MPG11_COMMON_SPD_CTRL2,
> +	S2MPG11_COMMON_SPD_CTRL3,
> +	S2MPG11_COMMON_MON1SEL = 0x1a,
> +	S2MPG11_COMMON_MON2SEL,
> +	S2MPG11_COMMON_MONR,
> +	S2MPG11_COMMON_DEBUG_CTRL1,
> +	S2MPG11_COMMON_DEBUG_CTRL2,
> +	S2MPG11_COMMON_DEBUG_CTRL3,
> +	S2MPG11_COMMON_DEBUG_CTRL4,
> +	S2MPG11_COMMON_DEBUG_CTRL5,
> +	S2MPG11_COMMON_DEBUG_CTRL6,
> +	S2MPG11_COMMON_TEST_MODE1,
> +	S2MPG11_COMMON_SPD_DEBUG1,
> +	S2MPG11_COMMON_SPD_DEBUG2,
> +	S2MPG11_COMMON_SPD_DEBUG3,
> +	S2MPG11_COMMON_SPD_DEBUG4,
> +};
> +
> +/* For S2MPG11_COMMON_INT and S2MPG11_COMMON_INT_MASK */
> +#define S2MPG11_COMMON_INT_SRC       GENMASK(2, 0)
> +#define S2MPG11_COMMON_INT_SRC_PMIC  BIT(0)
> +
> +/* PMIC registers (type 0x100) */
> +enum s2mpg11_pmic_reg {
> +	S2MPG11_PMIC_INT1,
> +	S2MPG11_PMIC_INT2,
> +	S2MPG11_PMIC_INT3,
> +	S2MPG11_PMIC_INT4,
> +	S2MPG11_PMIC_INT5,
> +	S2MPG11_PMIC_INT6,
> +	S2MPG11_PMIC_INT1M,
> +	S2MPG11_PMIC_INT2M,
> +	S2MPG11_PMIC_INT3M,
> +	S2MPG11_PMIC_INT4M,
> +	S2MPG11_PMIC_INT5M,
> +	S2MPG11_PMIC_INT6M,
> +	S2MPG11_PMIC_STATUS1,
> +	S2MPG11_PMIC_OFFSRC,
> +	S2MPG11_PMIC_COMMON_CTRL1,
> +	S2MPG11_PMIC_COMMON_CTRL2,
> +	S2MPG11_PMIC_COMMON_CTRL3,
> +	S2MPG11_PMIC_MIMICKING_CTRL,
> +	S2MPG11_PMIC_B1S_CTRL,
> +	S2MPG11_PMIC_B1S_OUT1,
> +	S2MPG11_PMIC_B1S_OUT2,
> +	S2MPG11_PMIC_B2S_CTRL,
> +	S2MPG11_PMIC_B2S_OUT1,
> +	S2MPG11_PMIC_B2S_OUT2,
> +	S2MPG11_PMIC_B3S_CTRL,
> +	S2MPG11_PMIC_B3S_OUT1,
> +	S2MPG11_PMIC_B3S_OUT2,
> +	S2MPG11_PMIC_B4S_CTRL,
> +	S2MPG11_PMIC_B4S_OUT,
> +	S2MPG11_PMIC_B5S_CTRL,
> +	S2MPG11_PMIC_B5S_OUT,
> +	S2MPG11_PMIC_B6S_CTRL,
> +	S2MPG11_PMIC_B6S_OUT1,
> +	S2MPG11_PMIC_B6S_OUT2,
> +	S2MPG11_PMIC_B7S_CTRL,
> +	S2MPG11_PMIC_B7S_OUT1,
> +	S2MPG11_PMIC_B7S_OUT2,
> +	S2MPG11_PMIC_B8S_CTRL,
> +	S2MPG11_PMIC_B8S_OUT1,
> +	S2MPG11_PMIC_B8S_OUT2,
> +	S2MPG11_PMIC_B9S_CTRL,
> +	S2MPG11_PMIC_B9S_OUT1,
> +	S2MPG11_PMIC_B9S_OUT2,
> +	S2MPG11_PMIC_B10S_CTRL,
> +	S2MPG11_PMIC_B10S_OUT,
> +	S2MPG11_PMIC_BUCKD_CTRL,
> +	S2MPG11_PMIC_BUCKD_OUT,
> +	S2MPG11_PMIC_BUCKA_CTRL,
> +	S2MPG11_PMIC_BUCKA_OUT,
> +	S2MPG11_PMIC_BB_CTRL,
> +	S2MPG11_PMIC_BB_OUT1,
> +	S2MPG11_PMIC_BB_OUT2,
> +	S2MPG11_PMIC_BUCK1S_USONIC,
> +	S2MPG11_PMIC_BUCK2S_USONIC,
> +	S2MPG11_PMIC_BUCK3S_USONIC,
> +	S2MPG11_PMIC_BUCK4S_USONIC,
> +	S2MPG11_PMIC_BUCK5S_USONIC,
> +	S2MPG11_PMIC_BUCK6S_USONIC,
> +	S2MPG11_PMIC_BUCK7S_USONIC,
> +	S2MPG11_PMIC_BUCK8S_USONIC,
> +	S2MPG11_PMIC_BUCK9S_USONIC,
> +	S2MPG11_PMIC_BUCK10S_USONIC,
> +	S2MPG11_PMIC_BUCKD_USONIC,
> +	S2MPG11_PMIC_BUCKA_USONIC,
> +	S2MPG11_PMIC_BB_USONIC,
> +	S2MPG11_PMIC_L1S_CTRL1,
> +	S2MPG11_PMIC_L1S_CTRL2,
> +	S2MPG11_PMIC_L2S_CTRL1,
> +	S2MPG11_PMIC_L2S_CTRL2,
> +	S2MPG11_PMIC_L3S_CTRL,
> +	S2MPG11_PMIC_L4S_CTRL,
> +	S2MPG11_PMIC_L5S_CTRL,
> +	S2MPG11_PMIC_L6S_CTRL,
> +	S2MPG11_PMIC_L7S_CTRL,
> +	S2MPG11_PMIC_L8S_CTRL,
> +	S2MPG11_PMIC_L9S_CTRL,
> +	S2MPG11_PMIC_L10S_CTRL,
> +	S2MPG11_PMIC_L11S_CTRL,
> +	S2MPG11_PMIC_L12S_CTRL,
> +	S2MPG11_PMIC_L13S_CTRL,
> +	S2MPG11_PMIC_L14S_CTRL,
> +	S2MPG11_PMIC_L15S_CTRL,
> +	S2MPG11_PMIC_LDO_CTRL1,
> +	S2MPG11_PMIC_LDO_DSCH1,
> +	S2MPG11_PMIC_LDO_DSCH2,
> +	S2MPG11_PMIC_DVS_RAMP1,
> +	S2MPG11_PMIC_DVS_RAMP2,
> +	S2MPG11_PMIC_DVS_RAMP3,
> +	S2MPG11_PMIC_DVS_RAMP4,
> +	S2MPG11_PMIC_DVS_RAMP5,
> +	S2MPG11_PMIC_DVS_RAMP6,
> +	/* Nothing @ 0x5a */
> +	S2MPG11_PMIC_DVS_SYNC_CTRL1 = 0x5c,
> +	S2MPG11_PMIC_DVS_SYNC_CTRL2,
> +	S2MPG11_PMIC_OFF_CTRL1,
> +	S2MPG11_PMIC_OFF_CTRL2,
> +	S2MPG11_PMIC_OFF_CTRL3,
> +	S2MPG11_PMIC_SEQ_CTRL1,
> +	S2MPG11_PMIC_SEQ_CTRL2,
> +	S2MPG11_PMIC_SEQ_CTRL3,
> +	S2MPG11_PMIC_SEQ_CTRL4,
> +	S2MPG11_PMIC_SEQ_CTRL5,
> +	S2MPG11_PMIC_SEQ_CTRL6,
> +	S2MPG11_PMIC_SEQ_CTRL7,
> +	S2MPG11_PMIC_SEQ_CTRL8,
> +	S2MPG11_PMIC_SEQ_CTRL9,
> +	S2MPG11_PMIC_SEQ_CTRL10,
> +	S2MPG11_PMIC_SEQ_CTRL11,
> +	S2MPG11_PMIC_SEQ_CTRL12,
> +	S2MPG11_PMIC_SEQ_CTRL13,
> +	S2MPG11_PMIC_SEQ_CTRL14,
> +	S2MPG11_PMIC_SEQ_CTRL15,
> +	S2MPG11_PMIC_SEQ_CTRL16,
> +	S2MPG11_PMIC_SEQ_CTRL17,
> +	S2MPG11_PMIC_SEQ_CTRL18,
> +	S2MPG11_PMIC_SEQ_CTRL19,
> +	S2MPG11_PMIC_SEQ_CTRL20,
> +	S2MPG11_PMIC_SEQ_CTRL21,
> +	S2MPG11_PMIC_SEQ_CTRL22,
> +	S2MPG11_PMIC_SEQ_CTRL23,
> +	S2MPG11_PMIC_SEQ_CTRL24,
> +	S2MPG11_PMIC_SEQ_CTRL25,
> +	S2MPG11_PMIC_SEQ_CTRL26,
> +	S2MPG11_PMIC_SEQ_CTRL27,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL1,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL2,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL3,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL4,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL5,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL6,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL7,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL8,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL9,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL10,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL11,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL12,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL13,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL14,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL15,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL16,
> +	S2MPG11_PMIC_OFF_SEQ_CTRL17,
> +	S2MPG11_PMIC_PCTRLSEL1,
> +	S2MPG11_PMIC_PCTRLSEL2,
> +	S2MPG11_PMIC_PCTRLSEL3,
> +	S2MPG11_PMIC_PCTRLSEL4,
> +	S2MPG11_PMIC_PCTRLSEL5,
> +	S2MPG11_PMIC_PCTRLSEL6,
> +	S2MPG11_PMIC_DCTRLSEL1,
> +	S2MPG11_PMIC_DCTRLSEL2,
> +	S2MPG11_PMIC_DCTRLSEL3,
> +	S2MPG11_PMIC_DCTRLSEL4,
> +	S2MPG11_PMIC_DCTRLSEL5,
> +	S2MPG11_PMIC_GPIO_CTRL1,
> +	S2MPG11_PMIC_GPIO_CTRL2,
> +	S2MPG11_PMIC_GPIO_CTRL3,
> +	S2MPG11_PMIC_GPIO_CTRL4,
> +	S2MPG11_PMIC_GPIO_CTRL5,
> +	S2MPG11_PMIC_GPIO_CTRL6,
> +	S2MPG11_PMIC_GPIO_CTRL7,
> +	S2MPG11_PMIC_B2S_OCP_WARN,
> +	S2MPG11_PMIC_B2S_OCP_WARN_X,
> +	S2MPG11_PMIC_B2S_OCP_WARN_Y,
> +	S2MPG11_PMIC_B2S_OCP_WARN_Z,
> +	S2MPG11_PMIC_B2S_SOFT_OCP_WARN,
> +	S2MPG11_PMIC_B2S_SOFT_OCP_WARN_X,
> +	S2MPG11_PMIC_B2S_SOFT_OCP_WARN_Y,
> +	S2MPG11_PMIC_B2S_SOFT_OCP_WARN_Z,
> +	S2MPG11_PMIC_BUCK_OCP_EN1,
> +	S2MPG11_PMIC_BUCK_OCP_EN2,
> +	S2MPG11_PMIC_BUCK_OCP_PD_EN1,
> +	S2MPG11_PMIC_BUCK_OCP_PD_EN2,
> +	S2MPG11_PMIC_BUCK_OCP_CTRL1,
> +	S2MPG11_PMIC_BUCK_OCP_CTRL2,
> +	S2MPG11_PMIC_BUCK_OCP_CTRL3,
> +	S2MPG11_PMIC_BUCK_OCP_CTRL4,
> +	S2MPG11_PMIC_BUCK_OCP_CTRL5,
> +	S2MPG11_PMIC_BUCK_OCP_CTRL6,
> +	S2MPG11_PMIC_BUCK_OCP_CTRL7,
> +	S2MPG11_PMIC_PIF_CTRL,
> +	S2MPG11_PMIC_BUCK_HR_MODE1,
> +	S2MPG11_PMIC_BUCK_HR_MODE2,
> +	S2MPG11_PMIC_FAULTOUT_CTRL,
> +	S2MPG11_PMIC_LDO_SENSE1,
> +	S2MPG11_PMIC_LDO_SENSE2,
> +};
> +
> +/* For S2MPG11_PMIC_PCTRLSELx */
> +#define S2MPG11_PCTRLSEL_PWREN           0x1 /* PWREN pin */
> +#define S2MPG11_PCTRLSEL_PWREN_TRG       0x2 /* PWREN_TRG bit in MIMICKING_CTRL */
> +#define S2MPG11_PCTRLSEL_PWREN_MIF       0x3 /* PWREN_MIF pin */
> +#define S2MPG11_PCTRLSEL_PWREN_MIF_TRG   0x4 /* PWREN_MIF_TRG bit in MIMICKING_CTRL */
> +#define S2MPG11_PCTRLSEL_AP_ACTIVE_N     0x5 /* ~AP_ACTIVE_N pin */
> +#define S2MPG11_PCTRLSEL_AP_ACTIVE_N_TRG 0x6 /* ~AP_ACTIVE_N_TRG bit in MIMICKING_CTRL */
> +#define S2MPG11_PCTRLSEL_G3D_EN          0x7 /* G3D_EN pin */
> +#define S2MPG11_PCTRLSEL_G3D_EN2         0x8 /* G3D_EN & ~AP_ACTIVE_N pins */
> +#define S2MPG11_PCTRLSEL_AOC_VDD         0x9 /* AOC_VDD pin */
> +#define S2MPG11_PCTRLSEL_AOC_RET         0xa /* AOC_RET pin */
> +#define S2MPG11_PCTRLSEL_UFS_EN          0xb /* UFS_EN pin */
> +#define S2MPG11_PCTRLSEL_LDO13S_EN       0xc /* VLDO13S_EN pin */
> +
> +/* Meter registers (type 0xa00) */
> +enum s2mpg11_meter_reg {
> +	S2MPG11_METER_CTRL1,
> +	S2MPG11_METER_CTRL2,
> +	S2MPG11_METER_CTRL3,
> +	S2MPG11_METER_CTRL4,
> +	S2MPG11_METER_CTRL5,
> +	S2MPG11_METER_BUCKEN1,
> +	S2MPG11_METER_BUCKEN2,
> +	S2MPG11_METER_MUXSEL0,
> +	S2MPG11_METER_MUXSEL1,
> +	S2MPG11_METER_MUXSEL2,
> +	S2MPG11_METER_MUXSEL3,
> +	S2MPG11_METER_MUXSEL4,
> +	S2MPG11_METER_MUXSEL5,
> +	S2MPG11_METER_MUXSEL6,
> +	S2MPG11_METER_MUXSEL7,
> +	S2MPG11_METER_LPF_C0_0,
> +	S2MPG11_METER_LPF_C0_1,
> +	S2MPG11_METER_LPF_C0_2,
> +	S2MPG11_METER_LPF_C0_3,
> +	S2MPG11_METER_LPF_C0_4,
> +	S2MPG11_METER_LPF_C0_5,
> +	S2MPG11_METER_LPF_C0_6,
> +	S2MPG11_METER_LPF_C0_7,
> +	S2MPG11_METER_NTC_LPF_C0_0,
> +	S2MPG11_METER_NTC_LPF_C0_1,
> +	S2MPG11_METER_NTC_LPF_C0_2,
> +	S2MPG11_METER_NTC_LPF_C0_3,
> +	S2MPG11_METER_NTC_LPF_C0_4,
> +	S2MPG11_METER_NTC_LPF_C0_5,
> +	S2MPG11_METER_NTC_LPF_C0_6,
> +	S2MPG11_METER_NTC_LPF_C0_7,
> +	S2MPG11_METER_PWR_WARN0,
> +	S2MPG11_METER_PWR_WARN1,
> +	S2MPG11_METER_PWR_WARN2,
> +	S2MPG11_METER_PWR_WARN3,
> +	S2MPG11_METER_PWR_WARN4,
> +	S2MPG11_METER_PWR_WARN5,
> +	S2MPG11_METER_PWR_WARN6,
> +	S2MPG11_METER_PWR_WARN7,
> +	S2MPG11_METER_NTC_L_WARN0,
> +	S2MPG11_METER_NTC_L_WARN1,
> +	S2MPG11_METER_NTC_L_WARN2,
> +	S2MPG11_METER_NTC_L_WARN3,
> +	S2MPG11_METER_NTC_L_WARN4,
> +	S2MPG11_METER_NTC_L_WARN5,
> +	S2MPG11_METER_NTC_L_WARN6,
> +	S2MPG11_METER_NTC_L_WARN7,
> +	S2MPG11_METER_NTC_H_WARN0,
> +	S2MPG11_METER_NTC_H_WARN1,
> +	S2MPG11_METER_NTC_H_WARN2,
> +	S2MPG11_METER_NTC_H_WARN3,
> +	S2MPG11_METER_NTC_H_WARN4,
> +	S2MPG11_METER_NTC_H_WARN5,
> +	S2MPG11_METER_NTC_H_WARN6,
> +	S2MPG11_METER_NTC_H_WARN7,
> +	S2MPG11_METER_PWR_HYS1,
> +	S2MPG11_METER_PWR_HYS2,
> +	S2MPG11_METER_PWR_HYS3,
> +	S2MPG11_METER_PWR_HYS4,
> +	S2MPG11_METER_NTC_HYS1,
> +	S2MPG11_METER_NTC_HYS2,
> +	S2MPG11_METER_NTC_HYS3,
> +	S2MPG11_METER_NTC_HYS4,
> +	/* Nothing @ 0x3f */
> +	S2MPG11_METER_ACC_DATA_CH0_1 = 0x40,
> +	S2MPG11_METER_ACC_DATA_CH0_2,
> +	S2MPG11_METER_ACC_DATA_CH0_3,
> +	S2MPG11_METER_ACC_DATA_CH0_4,
> +	S2MPG11_METER_ACC_DATA_CH0_5,
> +	S2MPG11_METER_ACC_DATA_CH0_6,
> +	S2MPG11_METER_ACC_DATA_CH1_1,
> +	S2MPG11_METER_ACC_DATA_CH1_2,
> +	S2MPG11_METER_ACC_DATA_CH1_3,
> +	S2MPG11_METER_ACC_DATA_CH1_4,
> +	S2MPG11_METER_ACC_DATA_CH1_5,
> +	S2MPG11_METER_ACC_DATA_CH1_6,
> +	S2MPG11_METER_ACC_DATA_CH2_1,
> +	S2MPG11_METER_ACC_DATA_CH2_2,
> +	S2MPG11_METER_ACC_DATA_CH2_3,
> +	S2MPG11_METER_ACC_DATA_CH2_4,
> +	S2MPG11_METER_ACC_DATA_CH2_5,
> +	S2MPG11_METER_ACC_DATA_CH2_6,
> +	S2MPG11_METER_ACC_DATA_CH3_1,
> +	S2MPG11_METER_ACC_DATA_CH3_2,
> +	S2MPG11_METER_ACC_DATA_CH3_3,
> +	S2MPG11_METER_ACC_DATA_CH3_4,
> +	S2MPG11_METER_ACC_DATA_CH3_5,
> +	S2MPG11_METER_ACC_DATA_CH3_6,
> +	S2MPG11_METER_ACC_DATA_CH4_1,
> +	S2MPG11_METER_ACC_DATA_CH4_2,
> +	S2MPG11_METER_ACC_DATA_CH4_3,
> +	S2MPG11_METER_ACC_DATA_CH4_4,
> +	S2MPG11_METER_ACC_DATA_CH4_5,
> +	S2MPG11_METER_ACC_DATA_CH4_6,
> +	S2MPG11_METER_ACC_DATA_CH5_1,
> +	S2MPG11_METER_ACC_DATA_CH5_2,
> +	S2MPG11_METER_ACC_DATA_CH5_3,
> +	S2MPG11_METER_ACC_DATA_CH5_4,
> +	S2MPG11_METER_ACC_DATA_CH5_5,
> +	S2MPG11_METER_ACC_DATA_CH5_6,
> +	S2MPG11_METER_ACC_DATA_CH6_1,
> +	S2MPG11_METER_ACC_DATA_CH6_2,
> +	S2MPG11_METER_ACC_DATA_CH6_3,
> +	S2MPG11_METER_ACC_DATA_CH6_4,
> +	S2MPG11_METER_ACC_DATA_CH6_5,
> +	S2MPG11_METER_ACC_DATA_CH6_6,
> +	S2MPG11_METER_ACC_DATA_CH7_1,
> +	S2MPG11_METER_ACC_DATA_CH7_2,
> +	S2MPG11_METER_ACC_DATA_CH7_3,
> +	S2MPG11_METER_ACC_DATA_CH7_4,
> +	S2MPG11_METER_ACC_DATA_CH7_5,
> +	S2MPG11_METER_ACC_DATA_CH7_6,
> +	S2MPG11_METER_ACC_COUNT_1,
> +	S2MPG11_METER_ACC_COUNT_2,
> +	S2MPG11_METER_ACC_COUNT_3,
> +	S2MPG11_METER_LPF_DATA_CH0_1,
> +	S2MPG11_METER_LPF_DATA_CH0_2,
> +	S2MPG11_METER_LPF_DATA_CH0_3,
> +	S2MPG11_METER_LPF_DATA_CH1_1,
> +	S2MPG11_METER_LPF_DATA_CH1_2,
> +	S2MPG11_METER_LPF_DATA_CH1_3,
> +	S2MPG11_METER_LPF_DATA_CH2_1,
> +	S2MPG11_METER_LPF_DATA_CH2_2,
> +	S2MPG11_METER_LPF_DATA_CH2_3,
> +	S2MPG11_METER_LPF_DATA_CH3_1,
> +	S2MPG11_METER_LPF_DATA_CH3_2,
> +	S2MPG11_METER_LPF_DATA_CH3_3,
> +	S2MPG11_METER_LPF_DATA_CH4_1,
> +	S2MPG11_METER_LPF_DATA_CH4_2,
> +	S2MPG11_METER_LPF_DATA_CH4_3,
> +	S2MPG11_METER_LPF_DATA_CH5_1,
> +	S2MPG11_METER_LPF_DATA_CH5_2,
> +	S2MPG11_METER_LPF_DATA_CH5_3,
> +	S2MPG11_METER_LPF_DATA_CH6_1,
> +	S2MPG11_METER_LPF_DATA_CH6_2,
> +	S2MPG11_METER_LPF_DATA_CH6_3,
> +	S2MPG11_METER_LPF_DATA_CH7_1,
> +	S2MPG11_METER_LPF_DATA_CH7_2,
> +	S2MPG11_METER_LPF_DATA_CH7_3,
> +	/* Nothing @ 0x8b 0x8c */
> +	S2MPG11_METER_LPF_DATA_NTC0_1 = 0x8d,
> +	S2MPG11_METER_LPF_DATA_NTC0_2,
> +	S2MPG11_METER_LPF_DATA_NTC1_1,
> +	S2MPG11_METER_LPF_DATA_NTC1_2,
> +	S2MPG11_METER_LPF_DATA_NTC2_1,
> +	S2MPG11_METER_LPF_DATA_NTC2_2,
> +	S2MPG11_METER_LPF_DATA_NTC3_1,
> +	S2MPG11_METER_LPF_DATA_NTC3_2,
> +	S2MPG11_METER_LPF_DATA_NTC4_1,
> +	S2MPG11_METER_LPF_DATA_NTC4_2,
> +	S2MPG11_METER_LPF_DATA_NTC5_1,
> +	S2MPG11_METER_LPF_DATA_NTC5_2,
> +	S2MPG11_METER_LPF_DATA_NTC6_1,
> +	S2MPG11_METER_LPF_DATA_NTC6_2,
> +	S2MPG11_METER_LPF_DATA_NTC7_1,
> +	S2MPG11_METER_LPF_DATA_NTC7_2,
> +};
> +
> +/* S2MPG11 regulator IDs */
> +enum s2mpg11_regulators {
> +	S2MPG11_LDO1,
> +	S2MPG11_LDO2,
> +	S2MPG11_LDO3,
> +	S2MPG11_LDO4,
> +	S2MPG11_LDO5,
> +	S2MPG11_LDO6,
> +	S2MPG11_LDO7,
> +	S2MPG11_LDO8,
> +	S2MPG11_LDO9,
> +	S2MPG11_LDO10,
> +	S2MPG11_LDO11,
> +	S2MPG11_LDO12,
> +	S2MPG11_LDO13,
> +	S2MPG11_LDO14,
> +	S2MPG11_LDO15,
> +	S2MPG11_BUCK1,
> +	S2MPG11_BUCK2,
> +	S2MPG11_BUCK3,
> +	S2MPG11_BUCK4,
> +	S2MPG11_BUCK5,
> +	S2MPG11_BUCK6,
> +	S2MPG11_BUCK7,
> +	S2MPG11_BUCK8,
> +	S2MPG11_BUCK9,
> +	S2MPG11_BUCK10,
> +	S2MPG11_BUCKD,
> +	S2MPG11_BUCKA,
> +	S2MPG11_BUCKBOOST,
> +	S2MPG11_REGULATOR_MAX,
> +};
> +
> +#endif /* __LINUX_MFD_S2MPG11_H */
> 
> -- 
> 2.51.2.997.g839fc31de9-goog
> 

-- 
Lee Jones [李琼斯]

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2025-11-13 16:25 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-03 19:14 [PATCH v3 00/20] Samsung S2MPG10 regulator and S2MPG11 PMIC drivers André Draszik
2025-11-03 19:14 ` [PATCH v3 01/20] dt-bindings: firmware: google,gs101-acpm-ipc: convert regulators to lowercase André Draszik
2025-11-03 19:14 ` [PATCH v3 02/20] dt-bindings: mfd: samsung,s2mps11: split s2mpg10 into separate file André Draszik
2025-11-04  8:26   ` Krzysztof Kozlowski
2025-11-07 11:01     ` André Draszik
2025-11-09 18:59       ` Krzysztof Kozlowski
2025-11-03 19:14 ` [PATCH v3 03/20] regulator: dt-bindings: add s2mpg10-pmic regulators André Draszik
2025-11-03 19:14 ` [PATCH v3 04/20] regulator: dt-bindings: add s2mpg11-pmic regulators André Draszik
2025-11-04  9:39   ` Krzysztof Kozlowski
2025-11-07 11:14     ` André Draszik
2025-11-09 19:00       ` Krzysztof Kozlowski
2025-11-10  6:30         ` André Draszik
2025-11-03 19:14 ` [PATCH v3 05/20] dt-bindings: mfd: samsung,s2mpg10: Link s2mpg10-pmic to its regulators André Draszik
2025-11-04  8:28   ` Krzysztof Kozlowski
2025-11-08 13:48     ` André Draszik
2025-11-03 19:14 ` [PATCH v3 06/20] dt-bindings: mfd: samsung,s2mpg10: Add s2mpg11-pmic André Draszik
2025-11-04  8:37   ` Krzysztof Kozlowski
2025-11-03 19:14 ` [PATCH v3 07/20] dt-bindings: firmware: google,gs101-acpm-ipc: update PMIC examples André Draszik
2025-11-04  8:31   ` Krzysztof Kozlowski
2025-11-08 14:08     ` André Draszik
2025-11-09 19:02       ` Krzysztof Kozlowski
2025-11-04  9:46   ` Krzysztof Kozlowski
2025-11-03 19:14 ` [PATCH v3 08/20] mfd: sec-common: Instantiate s2mpg10 bucks and ldos separately André Draszik
2025-11-03 19:14 ` [PATCH v3 09/20] mfd: sec: Add support for S2MPG11 PMIC via ACPM André Draszik
2025-11-13 16:25   ` Lee Jones
2025-11-03 19:14 ` [PATCH v3 10/20] regulator: add REGULATOR_LINEAR_VRANGE macro André Draszik
2025-11-04 14:27   ` Mark Brown
2025-11-05 16:15     ` André Draszik
2025-11-03 19:14 ` [PATCH v3 11/20] regulator: s2mps11: drop two needless variable initialisations André Draszik
2025-11-04  8:41   ` Krzysztof Kozlowski
2025-11-03 19:14 ` [PATCH v3 12/20] regulator: s2mps11: use dev_err_probe() where appropriate André Draszik
2025-11-04  8:41   ` Krzysztof Kozlowski
2025-11-03 19:14 ` [PATCH v3 13/20] regulator: s2mps11: place constants on right side of comparison tests André Draszik
2025-11-04  8:40   ` Krzysztof Kozlowski
2025-11-03 19:14 ` [PATCH v3 14/20] regulator: s2mps11: update node parsing (allow -supply properties) André Draszik
2025-11-03 19:14 ` [PATCH v3 15/20] regulator: s2mps11: refactor handling of external rail control André Draszik
2025-11-03 19:14 ` [PATCH v3 16/20] regulator: s2mps11: add S2MPG10 regulator André Draszik
2025-11-03 19:14 ` [PATCH v3 17/20] regulator: s2mps11: refactor S2MPG10 ::set_voltage_time() for S2MPG11 reuse André Draszik
2025-11-03 19:14 ` [PATCH v3 18/20] regulator: s2mps11: refactor S2MPG10 regulator macros " André Draszik
2025-11-03 19:14 ` [PATCH v3 19/20] regulator: s2mps11: add S2MPG11 regulator André Draszik
2025-11-03 19:14 ` [PATCH v3 20/20] regulator: s2mps11: more descriptive gpio consumer name André Draszik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).