* [PATCH v1 0/2] gpio: 74x164: seed the chain from DT at probe time
@ 2026-04-22 16:05 Chanhong Jung
2026-04-22 16:05 ` [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property Chanhong Jung
2026-04-22 16:05 ` [PATCH v1 2/2] gpio: 74x164: support 'registers-default' DT property for initial state Chanhong Jung
0 siblings, 2 replies; 5+ messages in thread
From: Chanhong Jung @ 2026-04-22 16:05 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Maxime Ripard
Cc: linux-gpio, devicetree, linux-kernel
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
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property
2026-04-22 16:05 [PATCH v1 0/2] gpio: 74x164: seed the chain from DT at probe time Chanhong Jung
@ 2026-04-22 16:05 ` Chanhong Jung
2026-04-23 8:59 ` Krzysztof Kozlowski
2026-04-22 16:05 ` [PATCH v1 2/2] gpio: 74x164: support 'registers-default' DT property for initial state Chanhong Jung
1 sibling, 1 reply; 5+ messages in thread
From: Chanhong Jung @ 2026-04-22 16:05 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Maxime Ripard
Cc: linux-gpio, devicetree, linux-kernel
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.
Signed-off-by: Chanhong Jung <happycpu@gmail.com>
---
.../devicetree/bindings/gpio/fairchild,74hc595.yaml | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml b/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
index 23410aeca..c6221ed75 100644
--- a/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
+++ b/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
@@ -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>;
};
};
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v1 2/2] gpio: 74x164: support 'registers-default' DT property for initial state
2026-04-22 16:05 [PATCH v1 0/2] gpio: 74x164: seed the chain from DT at probe time Chanhong Jung
2026-04-22 16:05 ` [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property Chanhong Jung
@ 2026-04-22 16:05 ` Chanhong Jung
1 sibling, 0 replies; 5+ messages in thread
From: Chanhong Jung @ 2026-04-22 16:05 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Maxime Ripard
Cc: linux-gpio, devicetree, linux-kernel
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.
Signed-off-by: Chanhong Jung <happycpu@gmail.com>
---
drivers/gpio/gpio-74x164.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index c226524ef..b433a4a61 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -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);
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property
2026-04-22 16:05 ` [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property Chanhong Jung
@ 2026-04-23 8:59 ` Krzysztof Kozlowski
2026-04-23 10:33 ` Chanhong Jung
0 siblings, 1 reply; 5+ messages in thread
From: Krzysztof Kozlowski @ 2026-04-23 8:59 UTC (permalink / raw)
To: Chanhong Jung
Cc: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Maxime Ripard, linux-gpio,
devicetree, linux-kernel
On Thu, Apr 23, 2026 at 01:05:03AM +0900, Chanhong Jung wrote:
> 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.
>
> 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.
>
> Signed-off-by: Chanhong Jung <happycpu@gmail.com>
> ---
> .../devicetree/bindings/gpio/fairchild,74hc595.yaml | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml b/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
> index 23410aeca..c6221ed75 100644
> --- a/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
> +++ b/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
> @@ -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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property
2026-04-23 8:59 ` Krzysztof Kozlowski
@ 2026-04-23 10:33 ` Chanhong Jung
0 siblings, 0 replies; 5+ messages in thread
From: Chanhong Jung @ 2026-04-23 10:33 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Chanhong Jung, Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Maxime Ripard, linux-gpio,
devicetree, linux-kernel
Hi Krzysztof,
Thanks for the review.
> 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
<happycpu@gmail.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-04-23 10:33 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-22 16:05 [PATCH v1 0/2] gpio: 74x164: seed the chain from DT at probe time Chanhong Jung
2026-04-22 16:05 ` [PATCH v1 1/2] dt-bindings: gpio: fairchild,74hc595: add registers-default property Chanhong Jung
2026-04-23 8:59 ` Krzysztof Kozlowski
2026-04-23 10:33 ` Chanhong Jung
2026-04-22 16:05 ` [PATCH v1 2/2] gpio: 74x164: support 'registers-default' DT property for initial state Chanhong Jung
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox