Skip to contentSkip to conversation

regulator: add the Will Semiconductor WL2868C camera PMIC

PATCH New Qianhui Xu 1 participant 3 messages Nov 11

Subsystems (3)
lore
Share & tools
lore

Qianhui Xu

author
#0 lore raw

v10 cover regulator: add the Will Semiconductor WL2868C camera PMIC

*** AI-assistance disclosure ***
This cover letter and the two patches below were prepared with the help of an LLM coding assistant. The author reviewed every line, ran every gate quoted in this letter himself, and takes full responsibility for the content.

This is v10 of the WL2868C binding+driver series. It supersedes v9 (<[email protected]>).

What changed in v10
===================

v10 addresses the three Medium findings sashiko posted on v9 2/2 (<[email protected]>, 2026-11-09) and the two Low binding points from the v7 review (<[email protected]>) that v9 did not carry forward. Sorry for the round trip: v9 2/2 is byte-identical to v8 and v8 2/2 to v7, so those reports predate v9, and v9 only carried Rob's binding points. v10 fixes all five.

2/2 regulator: willsemi,wl2868c: add the WL2868C camera PMIC driver

1) [Medium] "reset released before enabling vsys in wl2868c_probe()". Accepted; all three sub-points were real. v9 got the GPIO, registered the reset action and waited 1 ms before enabling the control supply, so the deassertion and the delay ran while the chip could be unpowered, the device ID read followed the supply turn-on with no startup delay, and the reverse-order devres teardown disabled the supply before asserting reset. In v10 (drivers/regulator/ wl2868c-regulator.c, wl2868c_probe()) the reset GPIO is taken with GPIOD_OUT_HIGH (RST_N asserted), the control supply is enabled first (wl2868c_enable_control_supply(), new), and only then is RST_N explicitly released with gpiod_set_value_cansleep(reset, 0) followed by a startup delay before the device ID is read. The reset action (wl2868c_reset_assert(), renamed from wl2868c_reset()) is registered after the supply action on purpose: devres unwinds in reverse order, so on unbind RST_N is asserted again before the supply is disabled, not after. The 1 ms values are now WL2868C_RESET_RELEASE_US / WL2868C_STARTUP_US; I could not quote a datasheet page (see the note at the end), so the letter keeps the same conservative 1 ms as v9.

2) [Medium] "vin7-supply not enabled for I2C in wl2868c_probe()". Accepted. The binding allows either supply, but v9 only asked for "vsys" with devm_regulator_get_enable(), so a vin7-only board got a dummy regulator and the control logic never came up. v10 adds wl2868c_enable_control_supply() (drivers/regulator/ wl2868c-regulator.c): it uses devm_regulator_get_enable_optional() for "vsys" first and falls back to "vin7" only on -ENODEV, keeping whichever is present enabled for as long as the driver is bound. The -ENODEV check (not IS_ERR) matters: -EPROBE_DEFER for a vsys provider that has not probed yet is returned as-is instead of being misread as "no vsys described". On boards that describe both, only VSYS is enabled as the control supply and VIN7 stays available to the regulator core as LDO7's input, unchanged from v9 behaviour.

3) [Medium] "preset LDOs enabled by wl2868c_probe() when SYS_EN is 0". Accepted; this is a real bug on a board whose firmware presets LDO bits with SYS_EN clear. v9 seeded chip->enabled from the whole LDO_ENABLE byte, so the first enable() of any single output wrote SYS_EN | (preset bits | own bit) and switched on outputs no consumer asked for. v10 seeds the tracked set only when the register already has SYS_EN set (wl2868c_probe(), right after reading WL2868C_LDO_ENABLE); with SYS_EN clear chip->enabled stays 0, which matches what is_enabled() reports, and the first enable() writes SYS_EN | <that one output>. The comment in wl2868c_enable() was updated accordingly.

1/2 regulator: dt-bindings: willsemi,wl2868c: add the WL2868C camera PMIC

4) [Low] example enables ldo1 without describing its input. The provider node is already gone since v9 (Rob's point); the remaining half is fixed here: the example now also describes vin12-supply = <&vreg_vin12> next to vsys-supply, since the binding says an input may only be left out when the outputs it feeds are unused on a given board (willsemi,wl2868c.yaml, examples).

5) [Low] MAINTAINERS driver pattern dangling in the dt-bindings patch. The "F: drivers/regulator/wl2868c-regulator.c" line moved from 1/2 into 2/2, where the file is actually created, so scripts/get_maintainer.pl --self-test=patterns has no dangling pattern at any commit of the series.

Gates run on v10 (on the 7.2 pristine base, commit 25f7927e6ccb)
===============================================================

  git am of 1/2 + 2/2 on a pristine checkout: clean, git status clean
  scripts/checkpatch.pl --strict --no-tree v10-0001 -> 0 errors, 0 warnings, 0 checks
  scripts/checkpatch.pl --strict --no-tree v10-0002 -> 0 errors, 0 warnings, 0 checks
  make ARCH=arm64 W=1 drivers/regulator/wl2868c-regulator.o
    -> rc=0, no warning
  make ARCH=arm64 DT_SCHEMA_FILES=.../willsemi,wl2868c.yaml dt_binding_check
    -> rc=0 (CHKDT/LINT/STYLE/DTEX/DTC all pass)
  scripts/get_maintainer.pl --self-test=patterns at both commits
    -> no new warnings (pre-existing unrelated upstream warnings only)

The 1 ms reset/startup delays and the 150 us enable_time come from the WL2868C datasheet; I do not have a citable document revision to link, so I kept the same conservative values v9 already used.

Qianhui Xu (2):
regulator: dt-bindings: willsemi,wl2868c: add the WL2868C camera PMIC
regulator: willsemi,wl2868c: add the WL2868C camera PMIC driver

 .../bindings/regulator/willsemi,wl2868c.yaml  |  99 +++++++
 MAINTAINERS                                   |   7 +
 drivers/regulator/Kconfig                     |  11 +
 drivers/regulator/Makefile                    |   1 +
 drivers/regulator/wl2868c-regulator.c         | 280 ++++++++++++++++++
 5 files changed, 398 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/willsemi,wl2868c.yaml
 create mode 100644 drivers/regulator/wl2868c-regulator.c

base-commit: 25f7927e6ccb6f4d8652b2b474d4c935faf580f6 --
2.53.0

author
#1 lore raw

PATCH v10 1/2 regulator: dt-bindings: willsemi,wl2868c: add the WL2868C camera PMIC

The WL2868C is an I2C-controlled camera power management IC from Will Semiconductor. It provides seven programmable LDOs: LDO1 and LDO2 are fed from a shared VIN12 input and cover 0.496 V to 1.512 V, LDO3 and LDO4 share VIN34, and LDO5 to LDO7 each have their own input, covering 1.504 V to 3.544 V. All outputs are programmable in 8 mV steps and are gated by per-output enable bits with a chip-wide SYS_EN master. The chip also exposes an optional active-low RST_N input.

VIN7 and VSYS are both inputs of the internal control logic, which is powered from the higher of the two voltages, so a device tree has to describe at least one of them. The remaining inputs only feed LDOs, so they stay optional: an input can be left unconnected when the outputs it feeds are unused on a given board.

The example enables ldo1, which is fed from VIN12, so it also describes vin12-supply; the binding says an input may only be left out when the outputs it feeds are unused on a given board.

---
 .../bindings/regulator/willsemi,wl2868c.yaml  | 99 +++++++++++++++++++
 MAINTAINERS                                   |  6 ++
 2 files changed, 105 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/willsemi,wl2868c.yaml
Documentation/devicetree/bindings/regulator/willsemi,wl2868c.yaml new file +99 -0
new file mode 100644
index 000000000..972813fbd
@@ -0,0 +1,99 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/willsemi,wl2868c.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Will Semiconductor WL2868C camera power management IC
+
+maintainers:
+  - Qianhui Xu <[email protected]>
+
+description: >
+  The WL2868C is a camera power management IC with seven programmable LDOs.
+  LDO1 and LDO2 share the VIN12 input and cover 0.496 V to 1.512 V; LDO3 and
+  LDO4 share VIN34, and LDO5 to LDO7 have one input each, covering 1.504 V to
+  3.544 V. All outputs are programmable in 8 mV steps.
+
+  VIN7 and VSYS feed the internal control logic, which is powered from the
+  higher of the two, so at least one of them has to be connected. The other
+  inputs only feed LDOs, so an input may be left unconnected on a board that
+  does not use the outputs it feeds, which is why they are not mandatory.
+
+properties:
+  compatible:
+    const: willsemi,wl2868c
+
+  reg:
+    maxItems: 1
+
+  reset-gpios:
+    maxItems: 1
+    description: Active-low RST_N input.
+
+  vin12-supply:
+    description: Input supply for LDO1 and LDO2.
+
+  vin34-supply:
+    description: Input supply for LDO3 and LDO4.
+
+  vin5-supply:
+    description: Input supply for LDO5.
+
+  vin6-supply:
+    description: Input supply for LDO6.
+
+  vin7-supply:
+    description: >
+      Input supply for LDO7 and one of the two supplies of the internal
+      control logic.
+
+  vsys-supply:
+    description: >
+      System supply, the other supply of the internal control logic. The
+      control logic is powered from the higher of VIN7 and VSYS.
+
+  regulators:
+    type: object
+    additionalProperties: false
+
+    patternProperties:
+      "^ldo[1-7]$":
+        type: object
+        $ref: regulator.yaml#
+        unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+  - regulators
+
+anyOf:
+  - required:
+      - vin7-supply
+  - required:
+      - vsys-supply
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        pmic@2f {
+            compatible = "willsemi,wl2868c";
+            reg = <0x2f>;
+            vsys-supply = <&vreg_vsys>;
+            vin12-supply = <&vreg_vin12>;
+
+            regulators {
+                ldo1 {
+                    regulator-max-microvolt = <1128000>;
+                    regulator-min-microvolt = <1128000>;
+                };
+            };
+        };
+    };
+...
MAINTAINERS +6 -0
index 8014b9f82..435beaf95 100644
@@ -29058,6 +29058,12 @@ L:	[email protected]
 S:	Maintained
 F:	drivers/hid/hid-wiimote*
 
+WILLSEMI WL2868C CAMERA PMIC
+M:	Qianhui Xu <[email protected]>
+L:	[email protected]
+S:	Maintained
+F:	Documentation/devicetree/bindings/regulator/willsemi,wl2868c.yaml
+
 WILOCITY WIL6210 WIRELESS DRIVER
 L:	[email protected]
 S:	Orphan
Signature · 1 line
2.53.0
author
#2 lore raw

PATCH v10 2/2 regulator: willsemi,wl2868c: add the WL2868C camera PMIC driver

In reply to Qianhui Xu

The WL2868C is an I2C camera power management IC with seven LDOs. LDO1 and LDO2 are fed from VIN12 and cover 0.496 V to 1.512 V with a 7-bit voltage selector; LDO3 and LDO4 share VIN34, and LDO5 to LDO7 have one input each, covering 1.504 V to 3.544 V with an 8-bit selector. All outputs step by 8 mV.

Every output is gated by a per-LDO bit in the enable register, and the whole chip is additionally gated by the SYS_EN bit in the same register. The driver sets SYS_EN together with the LDO bit on enable and requires both to read back before reporting the regulator as enabled, because no output comes up while SYS_EN is clear. An optional active-low RST_N GPIO starts asserted, is released only after the control supply is up, followed by a delay for the device to come up, and is asserted again before the supply is disabled on unbind.

The enable register is written as a whole rather than updated bit by
bit: the per-LDO bits can be preset by the firmware while SYS_EN is clear, and setting SYS_EN together with a single LDO bit would then switch the preset outputs on as well. The driver therefore tracks the set of LDOs enabled by consumers and writes exactly those bits, so enabling one output cannot power another one. That set is seeded from the register during probe, but only when SYS_EN is already set: with SYS_EN clear the per-LDO bits are presets for outputs that are off, and seeding them would make the first enable() of one output switch all of them on. disable() commits the tracked state only after the register write went through, so a failed write cannot make a later enable() switch off an output that the core still believes is on.

The control logic and the I2C interface are powered from the higher of VIN7 and VSYS. The driver enables VSYS, falling back to VIN7 on boards that do not describe VSYS, and keeps it enabled for as long as it is
bound: without it the device does not answer on the bus. The device ID is read only after the control supply is up and RST_N has been released.

---
 MAINTAINERS                           |   1 +
 drivers/regulator/Kconfig             |  11 +
 drivers/regulator/Makefile            |   1 +
 drivers/regulator/wl2868c-regulator.c | 280 ++++++++++++++++++++++++++
 4 files changed, 293 insertions(+)
 create mode 100644 drivers/regulator/wl2868c-regulator.c
MAINTAINERS +1 -0
index 435beaf95..5a3913c45 100644
@@ -29063,6 +29063,7 @@ M:	Qianhui Xu <[email protected]>
 L:	[email protected]
 S:	Maintained
 F:	Documentation/devicetree/bindings/regulator/willsemi,wl2868c.yaml
+F:	drivers/regulator/wl2868c-regulator.c
 
 WILOCITY WIL6210 WIRELESS DRIVER
 L:	[email protected]
drivers/regulator/Kconfig +11 -0
index a54a54919..79bdba077 100644
@@ -1851,6 +1851,17 @@ config REGULATOR_VQMMC_IPQ4019
 	  This driver provides support for the VQMMC LDO I/0
 	  voltage regulator of the IPQ4019 SD/EMMC controller.
 
+config REGULATOR_WL2868C
+	tristate "Will Semiconductor WL2868C regulator"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  Support the seven LDO outputs of the Will Semiconductor WL2868C
+	  camera power management IC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wl2868c-regulator.
+
 config REGULATOR_WM831X
 	tristate "Wolfson Microelectronics WM831x PMIC regulators"
 	depends on MFD_WM831X
drivers/regulator/Makefile +1 -0
index 134eee274..662f31a14 100644
@@ -211,6 +211,7 @@ obj-$(CONFIG_REGULATOR_RZG2L_VBCTRL) += renesas-usb-vbus-regulator.o
 obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o
 obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o
 obj-$(CONFIG_REGULATOR_VQMMC_IPQ4019) += vqmmc-ipq4019-regulator.o
+obj-$(CONFIG_REGULATOR_WL2868C) += wl2868c-regulator.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
drivers/regulator/wl2868c-regulator.c new file +280 -0

280 lines not on this page · raw message

Signature · 1 line
2.53.0