Skip to contentSkip to conversation

gpio: 74x164: seed the chain from DT at probe time

PATCH Superseded Chanhong Jung 6 participants 20 messages Apr 22 – May 6

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover gpio: 74x164: seed the chain from DT at probe time

Hi all,

This short series lets the 74HC595/74LVC594 shift-register driver initialise its chain to a board-specified pattern before the gpiochip is registered, via a new optional 'registers-default' DT property.

Motivation
----------

74HC595 chains latch their outputs from the first serial write onwards. The current driver always issues that first write from a zeroed buffer during probe, so every output comes up low until user space intervenes.

Boards that wire the chain to signals whose power-on state matters (active-low indicators, reset lines, early-boot status LEDs, etc.) have no DT-level way to express the intended initial pattern today, and must recreate it in user space after every probe.

The property and layout documented here have been honoured by U-Boot's matching driver (drivers/gpio/74x164_gpio.c) for years, so this change also restores binding parity between the two boot stages: whichever one owns the chain first can leave it in a known state for the next.

Validation
----------

Tested on stm32mp153d-ssonic, which drives 16 active-low LEDs from two cascaded 74HC595s with 'registers-default = /bits/ 8 <0xff 0xff 0x00 0x00>;'. With the series applied, the LED bank comes up in its defined off-state from probe onwards; without it, the bank flashes on briefly on every reboot until the user-space init writes the pattern.

Tooling:
- scripts/checkpatch.pl --strict: 0 errors, 0 warnings on each patch
- make dt_binding_check DT_SCHEMA_FILES=fairchild,74hc595: passes (example DTS extracted, compiled, and validated against the new schema)
- dt-validate on a built stm32mp153d-ssonic.dtb against the updated processed-schema.json: 'registers-default' accepted cleanly; no regressions against the rest of the 74hc595 binding

Patch 1 adds the binding property. Patch 2 consumes it in the driver.

Thanks for your time and reviews — feedback very welcome.

Chanhong

Chanhong Jung (2):
dt-bindings: gpio: fairchild,74hc595: add registers-default property
gpio: 74x164: support 'registers-default' DT property for initial
state

 .../bindings/gpio/fairchild,74hc595.yaml           | 10 ++++++++++
 drivers/gpio/gpio-74x164.c                         | 14 ++++++++++++++
 2 files changed, 24 insertions(+)

--
2.34.1

#1 lore raw

PATCH 1/2 dt-bindings: gpio: fairchild,74hc595: add registers-default property

The 74HC595 and 74LVC594 shift registers latch their outputs until the first serial write, so boards that depend on a specific power-on pattern (for example active-low indicators, reset lines, or other signals that must come up non-zero) have no way to express that today: the Linux driver always writes zeros from its zero-initialised buffer during probe.

Describe a new optional 'registers-default' property that carries a u8 array - one byte per cascaded register, in the same order used by the driver's internal buffer (first byte targets the last register in the chain). The Linux driver change that consumes this property follows.

This property is already recognised by the corresponding U-Boot driver (drivers/gpio/74x164_gpio.c), so documenting it here brings the two bindings back in sync and allows boards to initialise the chain once from the bootloader DT and keep the same value after the kernel takes over.

---
 .../devicetree/bindings/gpio/fairchild,74hc595.yaml    | 10 ++++++++++
 1 file changed, 10 insertions(+)
Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml +10 -0
index 23410aeca..c6221ed75 100644
@@ -45,6 +45,15 @@ properties:
     $ref: /schemas/types.yaml#/definitions/uint32
     description: Number of daisy-chained shift registers
 
+  registers-default:
+    $ref: /schemas/types.yaml#/definitions/uint8-array
+    description:
+      Initial state of the daisy-chained outputs, written by the driver
+      before the gpiochip is registered. One byte per cascaded register,
+      in the same order used by the driver's buffer (the first byte
+      targets the last register in the chain). When absent, outputs come
+      up zeroed. The number of entries must match 'registers-number'.
+
   enable-gpios:
     description: GPIO connected to the OE (Output Enable) pin.
     maxItems: 1
@@ -79,6 +88,7 @@ examples:
             gpio-controller;
             #gpio-cells = <2>;
             registers-number = <4>;
+            registers-default = /bits/ 8 <0xff 0xff 0x00 0x00>;
             spi-max-frequency = <100000>;
         };
     };
Signature · 1 line
2.34.1
#11 lore raw

PATCH 2/2 gpio: 74x164: support 'registers-default' DT property for initial state

In reply to Chanhong Jung

74HC595 and 74LVC594 chains retain their output state from the first serial write onwards. Today the driver always kicks that first write from a zero-initialised buffer, so every output comes up low until user space issues a write. Boards that rely on the chain to drive signals whose power-on state matters (active-low indicators, reset lines, etc.) have no way to express the desired initial pattern via DT, and must reinvent it from user space each time after probe.

Read the new optional 'registers-default' u8 array into chip->buffer after the buffer's size becomes known (so __counted_by() is satisfied) and before the first __gen_74x164_write_config(). Absence of the property keeps the current zeroing behaviour; an invalid size is rejected with dev_err_probe() so that dtbs_check violations surface loudly at probe time.

The matching binding change documents the property's layout. The corresponding U-Boot driver (drivers/gpio/74x164_gpio.c) has honoured the same property for years, so the two bootstages can now agree on the initial state without user-space involvement.

---
 drivers/gpio/gpio-74x164.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
drivers/gpio/gpio-74x164.c +14 -0
index c226524ef..b433a4a61 100644
@@ -134,6 +134,20 @@ static int gen_74x164_probe(struct spi_device *spi)
 
 	chip->registers = nregs;
 
+	/*
+	 * Optionally seed the chain with a board-specified pattern so that
+	 * the outputs come up in a known state on the first SPI write. When
+	 * the property is absent, the buffer stays zeroed by devm_kzalloc()
+	 * and the existing behaviour is preserved.
+	 */
+	if (device_property_present(dev, "registers-default")) {
+		ret = device_property_read_u8_array(dev, "registers-default",
+						    chip->buffer, nregs);
+		if (ret)
+			return dev_err_probe(dev, ret,
+					     "Invalid 'registers-default'\n");
+	}
+
 	chip->gpiod_oe = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);
 	if (IS_ERR(chip->gpiod_oe))
 		return PTR_ERR(chip->gpiod_oe);
Signature · 1 line
2.34.1
#2 lore raw

Re: [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property

In reply to Chanhong Jung
Quoted 6 lines · Chanhong Jung

The 74HC595 and 74LVC594 shift registers latch their outputs until the first serial write, so boards that depend on a specific power-on pattern (for example active-low indicators, reset lines, or other signals that must come up non-zero) have no way to express that today: the Linux driver always writes zeros from its zero-initialised buffer during probe.

You can fix the driver not to do that. Or fix the driver to properly parse hogs. I don't understand why exactly this one driver needs default registers stored in DT, but all other drivers in the kernel don't.

Quoted 22 lines

Describe a new optional 'registers-default' property that carries a u8 array - one byte per cascaded register, in the same order used by the driver's internal buffer (first byte targets the last register in the chain). The Linux driver change that consumes this property follows.

This property is already recognised by the corresponding U-Boot driver (drivers/gpio/74x164_gpio.c), so documenting it here brings the two bindings back in sync and allows boards to initialise the chain once from the bootloader DT and keep the same value after the kernel takes over.

---
 .../devicetree/bindings/gpio/fairchild,74hc595.yaml    | 10 ++++++++++
 1 file changed, 10 insertions(+)
Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml +0 -0
index 23410aeca..c6221ed75 100644

Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml properties: · line 48

Quoted 4 lines
Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml +1 -0
@@ -45,6 +45,15 @@ properties:
     $ref: /schemas/types.yaml#/definitions/uint32
     description: Number of daisy-chained shift registers
 
+  registers-default:

Where is this property defined (lack of vendor prefix means it is generic property)? Otherwise you always need vendor properties. I really dislike a generic "registers-default" property, because this is can of worms for all sorts of poor DT.

Best regards,
Krzysztof

#3 lore raw

Re: [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property

Hi Krzysztof,

Thanks for the review.

Quoted 4 lines

You can fix the driver not to do that. Or fix the driver to properly parse hogs. I don't understand why exactly this one driver needs default registers stored in DT, but all other drivers in the kernel don't.

I thought about both, but I don't think either works for this chip.

74HC595/74LVC594 is pure write-only: no MISO path, no register read-back, and the data sheet defines the power-on state of the parallel outputs as whatever /SRCLR and /OE do before the SPI master is up. That's different from MCP23xxx, PCA953x, STMPE and the rest, which are either readable (so the driver can RMW) or have a defined reset value. None of those drivers need a seed property. This one does, because there is nothing to read back and no defined state to fall back on.

Partial updates aren't possible either. set_value() has to shift the full chain every time - see __gen_74x164_write_config() - so whatever is in chip->buffer at the first ->set() call gets published to every output at once. If probe doesn't seed the buffer, the first consumer's set() runs off the kzalloc'd 0x00 and publishes that. On the board that motivated this series there are 16 active-low indicator LEDs on the chain; the 0x00 publish briefly lights every one of them before gpio-leds finishes walking its children. That glitch is what the probe-time write was preventing.

gpio-hog isn't a substitute here either:

- gpio_request() refuses the second claim on a line (EBUSY), so a hog and a gpio-leds / reset-gpios consumer can't coexist on the same line. This board already has gpio-leds consumers on every output of the chain, so there is no free line to hog. In general, if a line has no consumer its initial state doesn't matter; if it does have one, you can't put a hog on it.

- Each hog is applied sequentially by of_gpiochip_scan_gpios(), and because partial updates aren't possible every hog produces a full-chain write from an intermediate shadow. Seeding {0xFF 0xFF 0x00 0x00} through 16 hogs walks the physical pins through 16 intermediate patterns. A u8-array property collapses that to one atomic 4-byte transfer on the first SPI transaction.

- bindings/gpio/gpio.txt describes gpio-hog as a mechanism for lines no driver claims. Using it to paper over a missing probe-time seed is the wrong semantic for a chip whose only hardware primitive is "shift the whole chain", not "set one bit".

On the vendor prefix you're right - "registers-default" is too generic. In v2 I'll rename it to "fairchild,registers-default" (scoped to the fairchild,74hc595 compatible), which addresses the can-of-worms concern without changing the semantics. If you'd prefer a more descriptive name, "fairchild,initial-latch-state" or "fairchild,power-on-pattern" both work for me - let me know which one you'd ack and I'll send v2 accordingly.

Best regards,
Chanhong Jung
<[email protected]>

#4 lore raw

Re: [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property

Quoted 20 lines · Chanhong Jung

Hi Krzysztof,

Thanks for the review.

Quoted 4 lines

You can fix the driver not to do that. Or fix the driver to properly parse hogs. I don't understand why exactly this one driver needs default registers stored in DT, but all other drivers in the kernel don't.

I thought about both, but I don't think either works for this chip.

74HC595/74LVC594 is pure write-only: no MISO path, no register read-back, and the data sheet defines the power-on state of the parallel outputs as whatever /SRCLR and /OE do before the SPI master is up. That's different from MCP23xxx, PCA953x, STMPE and the rest, which are either readable (so the driver can RMW) or have a defined reset value. None of those drivers need a seed property. This one does, because there is nothing to read back and no defined state to fall back on.

Quoted 2 lines

Partial updates aren't possible either. set_value() has to shift the full chain every time - see __gen_74x164_write_config() - so whatever

This should also be explained in the commit msg.

Best regards,
Krzysztof

maintainer
#5 lore raw

Re: [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property

In reply to Chanhong Jung
Quoted 12 lines · Chanhong Jung

The 74HC595 and 74LVC594 shift registers latch their outputs until the first serial write, so boards that depend on a specific power-on pattern (for example active-low indicators, reset lines, or other signals that must come up non-zero) have no way to express that today: the Linux driver always writes zeros from its zero-initialised buffer during probe.

Describe a new optional 'registers-default' property that carries a u8 array - one byte per cascaded register, in the same order used by the driver's internal buffer (first byte targets the last register in the chain). The Linux driver change that consumes this property follows.

Quoted 7 lines

This property is already recognised by the corresponding U-Boot driver (drivers/gpio/74x164_gpio.c), so documenting it here brings the two bindings back in sync and allows boards to initialise the chain once from the bootloader DT and keep the same value after the kernel takes over.

See Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml

lines-initial-states:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Bitmask that specifies the initial state of each line.
When a bit is set to zero, the corresponding line will be initialized to the input (pulled-up) state.
When the bit is set to one, the line will be initialized to the low-level output state.
If the property is not specified all lines will be initialized to the input state.

If you want to set up initial states, use this property.

This also makes it possible for us to centralize the handling later on.

Yours,
Linus Walleij

#6 lore raw

Re: [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property

Hi Linus,

Thank you for the thoughtful review - this is exactly the kind of pointer I was hoping for. Reusing 'lines-initial-states' is a much cleaner fit than the new property I proposed, and it elegantly resolves Krzysztof's concern in the same stroke: 'lines-initial-states' is already documented under a sibling binding (nxp,pcf8575), so v2 only widens its applicability rather than introducing a generic, non-vendor-prefixed property to a vendor-specific binding. Two problems, one existing convention - that's a really nice call.

Quoted 11 lines

See Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml

lines-initial-states:
$ref: /schemas/types.yaml#/definitions/uint32 description:
Bitmask that specifies the initial state of each line.
...
If the property is not specified all lines will be initialized to the input state.

Quoted 1 line

If you want to set up initial states, use this property.

You're absolutely right. I've reworked the series to drop 'registers-default' entirely and read 'lines-initial-states' as a u32 bitmask, mapping bit N -> GPIO line N (matching the pcf8575 convention). For this output-only family the polarity falls out
naturally: bit=0 drives the line low and bit=1 drives it high. The bitmask covers up to 32 lines (4-chip cascades), which fits all current in-tree users of this binding; longer chains can extend the property later without breaking the bit-N=line-N mapping.

Quoted 1 line

This also makes it possible for us to centralize the handling later on.

That's a great forward-looking point, and I really appreciate you flagging it. Keeping the property name aligned with pcf8575 leaves the door wide open for a future common helper without anyone having to churn the binding to get there.

v2 will follow shortly in this thread (--in-reply-to of the v1 cover), and I've added

to the driver patch in recognition of the much better direction you pointed me to. Happy to move the attribution elsewhere or adjust the form if you'd prefer.

Thanks again for the careful read and for steering this in a cleaner direction.

Yours,
Chanhong

#12 lore raw

v2 cover gpio: 74x164: seed the chain from DT at probe time

In reply to Chanhong Jung

This v2 reuses the existing lines-initial-states bitmask, as suggested by Linus Walleij, instead of inventing a new property. That sidesteps both the v1 review concerns at once: there is no vendor-specific property to argue about, and the bit-N-equals-line-N convention is already documented for nxp,pcf8575.

Background (carried over from v1):
The 74HC595 / 74LVC594 family is push-pull output only. There is no read-back path, no defined power-on state for the parallel outputs, and __gen_74x164_write_config() always shifts the full chain on every transaction. The driver therefore publishes whatever sits in chip->buffer on the very first ->set() call, and today that buffer is fresh from kzalloc(), so all outputs come up low. On boards with active- low indicators or other signals whose initial level matters, the 0x00 publish glitches the chain before user space (or gpio-leds default-state walking) gets a chance to run.

gpio-hog is not a substitute here: each hog is applied sequentially and forces an intermediate full-chain write per line, and on this board gpio-leds already claims every output, leaving no free lines to hog.

Approach in v2:
Patch 1 documents the existing lines-initial-states property under the fairchild,74hc595 binding, with the small wording change that on this output-only family bit=0 drives the line low and bit=1 drives it high.

Patch 2 wires the driver to read that bitmask into chip->buffer before the first __gen_74x164_write_config(), so the chain comes up in the configured pattern atomically on the first SPI transaction. Property absence keeps the existing zeroing behaviour.

The bitmask covers up to 32 lines (four cascaded chips), which fits all existing in-tree users and the typical 1-4 chip cascades. If a longer chain ever needs seeding, the property can be extended to a uint32-array without breaking the bit-N-equals-line-N convention.

Tested on a 4-chip 74HC595 chain (32 outputs, active-low LEDs); the 0x00 glitch on first write goes away with lines-initial-states set to the desired idle pattern, and absence of the property leaves behaviour unchanged.

Changes since v1
[https://lore.kernel.org/linux-gpio/[email protected]/]:
- Drop the new 'registers-default' u8-array property; reuse the existing 'lines-initial-states' uint32 bitmask instead, as suggested by Linus Walleij. This also addresses Krzysztof Kozlowski's concern about adding a generic, non-vendor-prefixed property to a vendor-specific binding (the property is already documented for nxp,pcf8575).
- Driver now reads a single u32 and maps bit N to GPIO line N, matching the nxp,pcf8575 convention. For this output-only device the polarity is the natural one: bit=0 drives the line low, bit=1 drives it high.
- Binding example updated accordingly.

Chanhong Jung (2):
dt-bindings: gpio: fairchild,74hc595: add lines-initial-states
property
gpio: 74x164: support lines-initial-states for boot-time output state

 .../bindings/gpio/fairchild,74hc595.yaml        | 13 +++++++++++++
 drivers/gpio/gpio-74x164.c                      | 17 ++++++++++++++++-
 2 files changed, 29 insertions(+), 1 deletion(-)
Signature · 1 line
2.34.1
#14 lore raw

PATCH v2 1/2 dt-bindings: gpio: fairchild,74hc595: add lines-initial-states property

In reply to Chanhong Jung

The 74HC595 and 74LVC594 shift registers latch their outputs until the first serial write, so boards that depend on a specific power-on pattern (for example active-low indicators, reset lines, or other signals that must come up non-zero) have no way to express that today: the Linux driver always writes zeros from its zero-initialised buffer during probe.

Document support for the existing lines-initial-states bitmask, already defined for nxp,pcf8575, so the same convention covers this output-only device. Bit N corresponds to GPIO line N. Because the 74HC595/74LVC594 family is push-pull output only (no input mode, no high-impedance state under software control), bit=0 drives the line low and bit=1 drives it high; this differs from nxp,pcf8575, where the 0/1 polarity reflects the quasi-bidirectional nature of that part.

The bitmask covers up to 32 lines, which fits the typical 1-4 chip cascades that appear in tree. Should longer chains require seeding in the future, the property can be extended to a uint32-array without breaking the bit-N-equals-line-N convention.

---
 .../devicetree/bindings/gpio/fairchild,74hc595.yaml | 13 +++++++++++++
 1 file changed, 13 insertions(+)
Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml +13 -0
index 23410aeca..451538df6 100644
@@ -45,6 +45,18 @@ properties:
     $ref: /schemas/types.yaml#/definitions/uint32
     description: Number of daisy-chained shift registers
 
+  lines-initial-states:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      Bitmask that specifies the initial state of each output line, written
+      by the driver before the gpiochip is registered. Bit N corresponds to
+      GPIO line N, following the convention already documented for
+      nxp,pcf8575. Because the 74HC595/74LVC594 family is push-pull output
+      only, a bit set to zero drives the line low and a bit set to one
+      drives it high. The bitmask covers up to 32 lines (four cascaded
+      registers); outputs beyond that come up zeroed. When the property is
+      absent all outputs come up low, preserving the previous behaviour.
+
   enable-gpios:
     description: GPIO connected to the OE (Output Enable) pin.
     maxItems: 1
@@ -79,6 +91,7 @@ examples:
             gpio-controller;
             #gpio-cells = <2>;
             registers-number = <4>;
+            lines-initial-states = <0xffff0000>;
             spi-max-frequency = <100000>;
         };
     };
Signature · 1 line
2.34.1
#17 lore raw

PATCH v2 2/2 gpio: 74x164: support lines-initial-states for boot-time output state

In reply to Chanhong Jung

74HC595 and 74LVC594 chains retain their output state from the first serial write onwards. Today the driver always kicks that first write from a zero-initialised buffer, so every output comes up low until user space issues a write. Boards that rely on the chain to drive signals whose power-on state matters (active-low indicators, reset lines, etc.) have no way to express the desired initial pattern via DT.

Read the optional lines-initial-states bitmask, recently documented for this binding, into chip->buffer before the first __gen_74x164_write_config() so the chain comes up in a known state on the very first SPI transaction. Bit N maps to GPIO line N (matching the nxp,pcf8575 convention); on this output-only device, bit=0 drives the line low and bit=1 drives it high. Property absence keeps the existing zeroing behaviour intact.

---
 drivers/gpio/gpio-74x164.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
drivers/gpio/gpio-74x164.c +16 -1
index c226524ef..5ca61cf52 100644
@@ -112,7 +112,7 @@ static int gen_74x164_probe(struct spi_device *spi)
 {
 	struct device *dev = &spi->dev;
 	struct gen_74x164_chip *chip;
-	u32 nregs;
+	u32 nregs, init_state;
 	int ret;
 
 	/*
@@ -134,6 +134,21 @@ static int gen_74x164_probe(struct spi_device *spi)
 
 	chip->registers = nregs;
 
+	/*
+	 * Optionally seed the chain with a board-specified pattern so the
+	 * outputs come up in a known state on the first SPI write. The
+	 * property follows the nxp,pcf8575 convention where bit N maps to
+	 * GPIO line N. On this output-only device, bit=0 drives the line
+	 * low and bit=1 drives it high. The bitmask covers up to 32 lines;
+	 * any further outputs come up zeroed by devm_kzalloc().
+	 */
+	if (!device_property_read_u32(dev, "lines-initial-states", &init_state)) {
+		unsigned int i;
+
+		for (i = 0; i < min(nregs, 4U); i++)
+			chip->buffer[nregs - 1 - i] = (init_state >> (i * 8)) & 0xff;
+	}
+
 	chip->gpiod_oe = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);
 	if (IS_ERR(chip->gpiod_oe))
 		return PTR_ERR(chip->gpiod_oe);
Signature · 1 line
2.34.1
#7 lore raw

Re: [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property

In reply to Linus Walleij
Quoted 37 lines · Linus Walleij
Quoted 12 lines · Chanhong Jung

The 74HC595 and 74LVC594 shift registers latch their outputs until the first serial write, so boards that depend on a specific power-on pattern (for example active-low indicators, reset lines, or other signals that must come up non-zero) have no way to express that today: the Linux driver always writes zeros from its zero-initialised buffer during probe.

Describe a new optional 'registers-default' property that carries a u8 array - one byte per cascaded register, in the same order used by the driver's internal buffer (first byte targets the last register in the chain). The Linux driver change that consumes this property follows.

Quoted 7 lines

This property is already recognised by the corresponding U-Boot driver (drivers/gpio/74x164_gpio.c), so documenting it here brings the two bindings back in sync and allows boards to initialise the chain once from the bootloader DT and keep the same value after the kernel takes over.

See Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml

lines-initial-states:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Bitmask that specifies the initial state of each line.
When a bit is set to zero, the corresponding line will be initialized to the input (pulled-up) state.
When the bit is set to one, the line will be initialized to the low-level output state.
If the property is not specified all lines will be initialized to the input state.

Quoted 4 lines

If you want to set up initial states, use this property.

This also makes it possible for us to centralize the handling later on.

Ah, the old initial/default GPIO values problem strikes again. :(

IMO this is software configuration, not HW description. I think the driver should do it based on the compatible and/or machine. It should not be a property but if Krzysztof is fine with it, I'll queue it.

Bart

maintainer Reviewed-by on v2 1/2
#15 lore raw

Re: [PATCH v2 1/2] dt-bindings: gpio: fairchild,74hc595: add lines-initial-states property

In reply to Chanhong Jung
Quoted 15 lines · Chanhong Jung

The 74HC595 and 74LVC594 shift registers latch their outputs until the first serial write, so boards that depend on a specific power-on pattern (for example active-low indicators, reset lines, or other signals that must come up non-zero) have no way to express that today: the Linux driver always writes zeros from its zero-initialised buffer during probe.

Document support for the existing lines-initial-states bitmask, already defined for nxp,pcf8575, so the same convention covers this output-only device. Bit N corresponds to GPIO line N. Because the 74HC595/74LVC594 family is push-pull output only (no input mode, no high-impedance state under software control), bit=0 drives the line low and bit=1 drives it high; this differs from nxp,pcf8575, where the 0/1 polarity reflects the quasi-bidirectional nature of that part.

Quoted 6 lines

The bitmask covers up to 32 lines, which fits the typical 1-4 chip cascades that appear in tree. Should longer chains require seeding in the future, the property can be extended to a uint32-array without breaking the bit-N-equals-line-N convention.

My old email but who cares.

Quoted 1 line

This works for me.

Yours,
Linus Walleij

maintainer Reviewed-by on v2 2/2
#18 lore raw

Re: [PATCH v2 2/2] gpio: 74x164: support lines-initial-states for boot-time output state

In reply to Chanhong Jung
Quoted 15 lines · Chanhong Jung

74HC595 and 74LVC594 chains retain their output state from the first serial write onwards. Today the driver always kicks that first write from a zero-initialised buffer, so every output comes up low until user space issues a write. Boards that rely on the chain to drive signals whose power-on state matters (active-low indicators, reset lines, etc.) have no way to express the desired initial pattern via DT.

Read the optional lines-initial-states bitmask, recently documented for this binding, into chip->buffer before the first __gen_74x164_write_config() so the chain comes up in a known state on the very first SPI transaction. Bit N maps to GPIO line N (matching the nxp,pcf8575 convention); on this output-only device, bit=0 drives the line low and bit=1 drives it high. Property absence keeps the existing zeroing behaviour intact.

Quoted 2 lines

If more users of this appears we can start thinking about brining the support code into the core gpiolib but for now this works fine I think.

Yours,
Linus Walleij

author
#19 lore raw

Re: [PATCH v2 2/2] gpio: 74x164: support lines-initial-states for boot-time output state

Thanks Linus, appreciate the review.

2026년 4월 30일 (목) 오후 9:09, Linus Walleij <[email protected]>님이 작성:

Quoted 29 lines · Chanhong Jung
Quoted 16 lines

74HC595 and 74LVC594 chains retain their output state from the first serial write onwards. Today the driver always kicks that first write from a zero-initialised buffer, so every output comes up low until user space issues a write. Boards that rely on the chain to drive signals whose power-on state matters (active-low indicators, reset lines, etc.) have no way to express the desired initial pattern via DT.

Read the optional lines-initial-states bitmask, recently documented for this binding, into chip->buffer before the first __gen_74x164_write_config() so the chain comes up in a known state on the very first SPI transaction. Bit N maps to GPIO line N (matching the nxp,pcf8575 convention); on this output-only device, bit=0 drives the line low and bit=1 drives it high. Property absence keeps the existing zeroing behaviour intact.

Quoted 2 lines

If more users of this appears we can start thinking about brining the support code into the core gpiolib but for now this works fine I think.

Yours,
Linus Walleij

maintainer
#8 lore raw

Re: [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property

In reply to Bartosz Golaszewski
Quoted 13 lines · Bartosz Golaszewski
Quoted 13 lines

lines-initial-states:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Bitmask that specifies the initial state of each line.
When a bit is set to zero, the corresponding line will be initialized to the input (pulled-up) state.
When the bit is set to one, the line will be initialized to the low-level output state.
If the property is not specified all lines will be initialized to the input state.

If you want to set up initial states, use this property.

Quoted 8 lines
Quoted 2 lines

This also makes it possible for us to centralize the handling later on.

Ah, the old initial/default GPIO values problem strikes again. :(

IMO this is software configuration, not HW description. I think the driver should do it based on the compatible and/or machine. It should not be a property but if Krzysztof is fine with it, I'll queue it.

This one is particularly uncomfortably hard to define.

If we depend on the machine we need to sprinkle
of_machine_is_compatible() over all drivers.

A lot of detailed properties that could have been handled by a few gazillion of_machine_is_compatible():s are already present in the kernel.

What is good about the property that has the same name is that we can create nicer looking kernel code that is easier to maintain. The DT maintainers may not care about that, but from a GPIO subsystem PoV I think the line-initial-states are better.

Yours,
Linus Walleij

#9 lore raw

Re: [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property

Quoted 34 lines · Linus Walleij
Quoted 13 lines · Bartosz Golaszewski
Quoted 13 lines

lines-initial-states:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Bitmask that specifies the initial state of each line.
When a bit is set to zero, the corresponding line will be initialized to the input (pulled-up) state.
When the bit is set to one, the line will be initialized to the low-level output state.
If the property is not specified all lines will be initialized to the input state.

If you want to set up initial states, use this property.

Quoted 8 lines
Quoted 2 lines

This also makes it possible for us to centralize the handling later on.

Ah, the old initial/default GPIO values problem strikes again. :(

IMO this is software configuration, not HW description. I think the driver should do it based on the compatible and/or machine. It should not be a property but if Krzysztof is fine with it, I'll queue it.

This one is particularly uncomfortably hard to define.

If we depend on the machine we need to sprinkle
of_machine_is_compatible() over all drivers.

A lot of detailed properties that could have been handled by a few gazillion of_machine_is_compatible():s are already present in the kernel.

Quoted 6 lines

What is good about the property that has the same name is that we can create nicer looking kernel code that is easier to maintain. The DT maintainers may not care about that, but from a GPIO subsystem PoV I think the line-initial-states are better.

Fair enough. I'll still wait for DT maintainers' formal Ack before we carve it in stone do avoid getting hit on th ehead with said stone later on. :)

Bart

maintainer
#10 lore raw

Re: [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property

In reply to Bartosz Golaszewski
Quoted 40 lines · Bartosz Golaszewski
Quoted 39 lines · Linus Walleij
Quoted 12 lines · Chanhong Jung

The 74HC595 and 74LVC594 shift registers latch their outputs until the first serial write, so boards that depend on a specific power-on pattern (for example active-low indicators, reset lines, or other signals that must come up non-zero) have no way to express that today: the Linux driver always writes zeros from its zero-initialised buffer during probe.

Describe a new optional 'registers-default' property that carries a u8 array - one byte per cascaded register, in the same order used by the driver's internal buffer (first byte targets the last register in the chain). The Linux driver change that consumes this property follows.

Quoted 7 lines

This property is already recognised by the corresponding U-Boot driver (drivers/gpio/74x164_gpio.c), so documenting it here brings the two bindings back in sync and allows boards to initialise the chain once from the bootloader DT and keep the same value after the kernel takes over.

See Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml

lines-initial-states:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Bitmask that specifies the initial state of each line.
When a bit is set to zero, the corresponding line will be initialized to the input (pulled-up) state.
When the bit is set to one, the line will be initialized to the low-level output state.
If the property is not specified all lines will be initialized to the input state.

If you want to set up initial states, use this property.

Quoted 8 lines
Quoted 2 lines

This also makes it possible for us to centralize the handling later on.

Ah, the old initial/default GPIO values problem strikes again. :(

IMO this is software configuration, not HW description. I think the driver should do it based on the compatible and/or machine. It should not be a property but if Krzysztof is fine with it, I'll queue it.

Sounds like h/w configuration to me. It's the board design dicating the config rather than the user.

Rob

maintainer Reviewed-by on v2 1/2
#16 lore raw

Re: [PATCH v2 1/2] dt-bindings: gpio: fairchild,74hc595: add lines-initial-states property

In reply to Chanhong Jung
Quoted 20 lines · Chanhong Jung

The 74HC595 and 74LVC594 shift registers latch their outputs until the first serial write, so boards that depend on a specific power-on pattern (for example active-low indicators, reset lines, or other signals that must come up non-zero) have no way to express that today: the Linux driver always writes zeros from its zero-initialised buffer during probe.

Document support for the existing lines-initial-states bitmask, already defined for nxp,pcf8575, so the same convention covers this output-only device. Bit N corresponds to GPIO line N. Because the 74HC595/74LVC594 family is push-pull output only (no input mode, no high-impedance state under software control), bit=0 drives the line low and bit=1 drives it high; this differs from nxp,pcf8575, where the 0/1 polarity reflects the quasi-bidirectional nature of that part.

The bitmask covers up to 32 lines, which fits the typical 1-4 chip cascades that appear in tree. Should longer chains require seeding in the future, the property can be extended to a uint32-array without breaking the bit-N-equals-line-N convention.

Quoted 6 lines
---
 .../devicetree/bindings/gpio/fairchild,74hc595.yaml | 13 +++++++++++++
 1 file changed, 13 insertions(+)
#13 lore raw
In reply to Chanhong Jung
Quoted 17 lines · Chanhong Jung

This v2 reuses the existing lines-initial-states bitmask, as suggested by Linus Walleij, instead of inventing a new property. That sidesteps both the v1 review concerns at once: there is no vendor-specific property to argue about, and the bit-N-equals-line-N convention is already documented for nxp,pcf8575.

Background (carried over from v1):
The 74HC595 / 74LVC594 family is push-pull output only. There is no read-back path, no defined power-on state for the parallel outputs, and __gen_74x164_write_config() always shifts the full chain on every transaction. The driver therefore publishes whatever sits in chip->buffer on the very first ->set() call, and today that buffer is fresh from kzalloc(), so all outputs come up low. On boards with active- low indicators or other signals whose initial level matters, the 0x00 publish glitches the chain before user space (or gpio-leds default-state walking) gets a chance to run.

Quoted 1 line

[...]

Reluctantly applied.

[1/2] dt-bindings: gpio: fairchild,74hc595: add lines-initial-states property

      https://git.kernel.org/brgl/c/d6e1a94888f5a4306c9998944a0f29f7bcd49411
[2/2] gpio: 74x164: support lines-initial-states for boot-time output state
      https://git.kernel.org/brgl/c/cb77f8933467d08c8896674cd39ca98550a70fd6

Best regards,

Signature · 1 line
Bartosz Golaszewski <[email protected]>