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

Chanhong Jung
2026-04-29T03:51:42Z

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.

Suggested-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Chanhong Jung <happycpu@gmail.com>
---
drivers/gpio/gpio-74x164.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index c226524ef..5ca61cf52 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -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);
--
2.34.1