* [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open
@ 2026-08-10 13:06 Michał Kardaś
2026-08-10 13:06 ` [PATCH v1 1/2] pinctrl: core: Allow drivers to keep "init" pinctrl state after probe Michał Kardaś
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Michał Kardaś @ 2026-08-10 13:06 UTC (permalink / raw)
To: Linus Walleij, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby
Cc: Andy Shevchenko, Douglas Anderson, Vic Huang, linux-gpio,
linux-serial, linux-kernel, Michał Kardaś
During device probe, pinctrl_bind_pins() binds pins to their "init" state
if specified in Device Tree. When probe finishes, pinctrl_init_done()
automatically transitions the pins from "init" to "default" state.
While this auto-transition works well for devices that are immediately
active upon driver binding, certain peripherals (such as power-sequenced
devices connected over UART, SPI, or other buses) remain unpowered until
userspace explicitly opens the device node or attaches a protocol driver.
On board designs where the connected peripheral is kept unpowered during
boot, auto-selecting "default" pin states (where signals such as TXD or
RTS may be driven high or pulled up) can cause parasitic back-powering
into the unpowered peripheral through its ESD protection diodes.
To address this without requiring new Device Tree binding names, this
series extends the existing "init" pinctrl state mechanism (introduced
in commit ef0eebc05130 ("drivers/pinctrl: Add the concept of an "init"
state")):
1. Patch 1 (pinctrl core):
Adds pinctrl_keep_init_state(dev). When called during probe,
pinctrl_init_done() opts out of the automatic "init" -> "default"
transition, allowing the driver to keep pins in the safe "init" state
upon probe completion. Updates Documentation/driver-api/pin-control.rst.
Board configurations that do not define an "init" state are completely
unaffected.
2. Patch 2 (8250_dw serial driver):
Updates 8250_dw so that when an "init" state is defined for the port,
the driver calls pinctrl_keep_init_state() and preserves the "init"
state until the port is first opened via dw8250_do_pm(), at which point
it transitions to "default" state and resumes normal operation.
Testing:
- Built and verified with CONFIG_PINCTRL=y and CONFIG_PINCTRL=n on
upstream tree.
- Verified zero checkpatch warnings (`checkpatch.pl --strict`).
- Note: Functional hardware testing was performed on a downstream kernel
tree where the physical back-powering issue was reproduced and verified
fixed. The underlying UART pinctrl lifecycle issue and core logic apply
identically to upstream.
Michał Kardaś (2):
pinctrl: core: Allow drivers to keep "init" pinctrl state after probe
tty: serial: 8250_dw: Keep init pinctrl state until first open
Documentation/driver-api/pin-control.rst | 10 ++++++----
drivers/pinctrl/core.c | 20 ++++++++++++++++++++
drivers/tty/serial/8250/8250_dw.c | 13 ++++++++++++-
include/linux/pinctrl/consumer.h | 6 ++++++
include/linux/pinctrl/devinfo.h | 2 ++
5 files changed, 46 insertions(+), 5 deletions(-)
--
2.55.0.654.g21b8a5bc05-goog
^ permalink raw reply [flat|nested] 14+ messages in thread* [PATCH v1 1/2] pinctrl: core: Allow drivers to keep "init" pinctrl state after probe 2026-08-10 13:06 [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open Michał Kardaś @ 2026-08-10 13:06 ` Michał Kardaś 2026-08-10 18:12 ` Andy Shevchenko 2026-08-10 13:06 ` [PATCH v1 2/2] tty: serial: 8250_dw: Keep init pinctrl state until first open Michał Kardaś 2026-08-11 6:34 ` [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep " Linus Walleij 2 siblings, 1 reply; 14+ messages in thread From: Michał Kardaś @ 2026-08-10 13:06 UTC (permalink / raw) To: Linus Walleij, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby Cc: Andy Shevchenko, Douglas Anderson, Vic Huang, linux-gpio, linux-serial, linux-kernel, Michał Kardaś During device probe, pinctrl_bind_pins() binds pins to their "init" state if specified in Device Tree. When probe finishes, pinctrl_init_done() automatically transitions the pins from "init" to "default" state. While this auto-transition works well for devices that are immediately active upon driver binding, certain peripherals (such as power-sequenced devices connected over UART, SPI, or other buses) remain unpowered until userspace explicitly opens the device node or attaches a protocol driver. On board designs where the connected peripheral is kept unpowered during boot, auto-selecting "default" or "sleep" pin states (where signals such as TXD or RTS may be driven high or pulled up) can cause parasitic back-powering into the unpowered peripheral through its ESD protection diodes. Allow drivers to explicitly opt out of the automatic "init" -> "default" transition by calling pinctrl_keep_init_state(dev) during probe. When this helper is called, pinctrl_init_done() leaves the pins in their "init" state upon probe completion. The driver can then transition to the "default" state when the device is first opened by calling pinctrl_pm_select_default_state(dev). Suggested-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Michał Kardaś <mkmkl@google.com> --- Documentation/driver-api/pin-control.rst | 10 ++++++---- drivers/pinctrl/core.c | 20 ++++++++++++++++++++ include/linux/pinctrl/consumer.h | 6 ++++++ include/linux/pinctrl/devinfo.h | 2 ++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/Documentation/driver-api/pin-control.rst b/Documentation/driver-api/pin-control.rst index 1f585ecca63c..8d52bf74da6c 100644 --- a/Documentation/driver-api/pin-control.rst +++ b/Documentation/driver-api/pin-control.rst @@ -1172,7 +1172,8 @@ Possible standard state names are: "default", "init", "sleep" and "idle". - if ``init`` and ``default`` are defined in the device tree, the "init" state is selected before the driver probe and the "default" state is - selected after the driver probe. + selected after the driver probe, unless the driver explicitly opts out + by calling ``pinctrl_keep_init_state()`` during probe. - the ``sleep`` and ``idle`` states are for power management and can only be selected with the PM API bellow. @@ -1233,9 +1234,10 @@ operation and going to sleep, moving from the ``PINCTRL_STATE_DEFAULT`` to current in sleep mode. Another case is when the pinctrl needs to switch to a certain mode during -probe and then revert to the default state at the end of probe. For example -a PINMUX may need to be configured as a GPIO during probe. In this case, use -``PINCTRL_STATE_INIT`` to switch state before probe, then move to +probe and then revert to the default state at the end of probe (or remain +in the init state until activated if ``pinctrl_keep_init_state()`` is called). +For example a PINMUX may need to be configured as a GPIO during probe. In this +case, use ``PINCTRL_STATE_INIT`` to switch state before probe, then move to ``PINCTRL_STATE_DEFAULT`` at the end of probe for normal operation. A driver may request a certain control state to be activated, usually just the diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 1675dd36bd5c..fd0c91610338 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -1640,6 +1640,9 @@ int pinctrl_init_done(struct device *dev) if (pins->p->state != pins->init_state) return 0; /* Not at init anyway */ + if (pins->keep_init) + return 0; /* Driver explicitly requested to stay in init state */ + if (IS_ERR(pins->default_state)) return 0; /* No default state */ @@ -1678,6 +1681,23 @@ int pinctrl_select_default_state(struct device *dev) } EXPORT_SYMBOL_GPL(pinctrl_select_default_state); +/** + * pinctrl_keep_init_state() - mark pinctrl handle to stay in init state after probe + * @dev: device to keep init state for + * + * Return: true if the device has a valid init state and keep_init flag was set, + * false otherwise. + */ +bool pinctrl_keep_init_state(struct device *dev) +{ + if (!dev->pins || IS_ERR(dev->pins->init_state)) + return false; + + dev->pins->keep_init = true; + return true; +} +EXPORT_SYMBOL_GPL(pinctrl_keep_init_state); + #ifdef CONFIG_PM /** diff --git a/include/linux/pinctrl/consumer.h b/include/linux/pinctrl/consumer.h index 11b8f0b8da0c..4312a098fb4c 100644 --- a/include/linux/pinctrl/consumer.h +++ b/include/linux/pinctrl/consumer.h @@ -47,6 +47,7 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s); struct pinctrl * __must_check devm_pinctrl_get(struct device *dev); void devm_pinctrl_put(struct pinctrl *p); int pinctrl_select_default_state(struct device *dev); +bool pinctrl_keep_init_state(struct device *dev); #ifdef CONFIG_PM int pinctrl_pm_select_default_state(struct device *dev); @@ -152,6 +153,11 @@ static inline int pinctrl_select_default_state(struct device *dev) return 0; } +static inline bool pinctrl_keep_init_state(struct device *dev) +{ + return false; +} + static inline int pinctrl_pm_select_default_state(struct device *dev) { return 0; diff --git a/include/linux/pinctrl/devinfo.h b/include/linux/pinctrl/devinfo.h index de4228eea90a..13dac33f2df1 100644 --- a/include/linux/pinctrl/devinfo.h +++ b/include/linux/pinctrl/devinfo.h @@ -32,6 +32,7 @@ struct pinctrl; * @init_state: the state at probe time, if found * @sleep_state: the state at suspend time, if found * @idle_state: the state at idle (runtime suspend) time, if found + * @keep_init: flag indicating if init state should persist after probe */ struct dev_pin_info { struct pinctrl *p; @@ -41,6 +42,7 @@ struct dev_pin_info { struct pinctrl_state *sleep_state; struct pinctrl_state *idle_state; #endif + bool keep_init:1; }; extern int pinctrl_init_done(struct device *dev); -- 2.55.0.654.g21b8a5bc05-goog ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v1 1/2] pinctrl: core: Allow drivers to keep "init" pinctrl state after probe 2026-08-10 13:06 ` [PATCH v1 1/2] pinctrl: core: Allow drivers to keep "init" pinctrl state after probe Michał Kardaś @ 2026-08-10 18:12 ` Andy Shevchenko 0 siblings, 0 replies; 14+ messages in thread From: Andy Shevchenko @ 2026-08-10 18:12 UTC (permalink / raw) To: Michał Kardaś Cc: Linus Walleij, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Douglas Anderson, Vic Huang, linux-gpio, linux-serial, linux-kernel On Mon, Aug 10, 2026 at 01:06:34PM +0000, Michał Kardaś wrote: > During device probe, pinctrl_bind_pins() binds pins to their "init" state > if specified in Device Tree. When probe finishes, pinctrl_init_done() > automatically transitions the pins from "init" to "default" state. > > While this auto-transition works well for devices that are immediately > active upon driver binding, certain peripherals (such as power-sequenced > devices connected over UART, SPI, or other buses) remain unpowered until > userspace explicitly opens the device node or attaches a protocol driver. > > On board designs where the connected peripheral is kept unpowered during > boot, auto-selecting "default" or "sleep" pin states (where signals such > as TXD or RTS may be driven high or pulled up) can cause parasitic > back-powering into the unpowered peripheral through its ESD protection > diodes. > > Allow drivers to explicitly opt out of the automatic "init" -> "default" > transition by calling pinctrl_keep_init_state(dev) during probe. When this > helper is called, pinctrl_init_done() leaves the pins in their "init" > state upon probe completion. The driver can then transition to the > "default" state when the device is first opened by calling > pinctrl_pm_select_default_state(dev). ... > +/** > + * pinctrl_keep_init_state() - mark pinctrl handle to stay in init state after probe > + * @dev: device to keep init state for > + * > + * Return: true if the device has a valid init state and keep_init flag was set, > + * false otherwise. > + */ > +bool pinctrl_keep_init_state(struct device *dev) > +{ > + if (!dev->pins || IS_ERR(dev->pins->init_state)) > + return false; The above keeps_init in the initial state which may or may not be wrong. I would avoid the ambiguity by rewriting this as > + dev->pins->keep_init = true; > + return true; dev->pins->keep_init = dev->pins && !IS_ERR(dev->pins->init_state); return dev->pins->keep_init; But please, check if that is what you want. > +} ... > + bool keep_init:1; What is ':1' supposed to mean (for boolean)? I understand that for say unsigned int. -- With Best Regards, Andy Shevchenko ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v1 2/2] tty: serial: 8250_dw: Keep init pinctrl state until first open 2026-08-10 13:06 [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open Michał Kardaś 2026-08-10 13:06 ` [PATCH v1 1/2] pinctrl: core: Allow drivers to keep "init" pinctrl state after probe Michał Kardaś @ 2026-08-10 13:06 ` Michał Kardaś 2026-08-10 18:17 ` Andy Shevchenko 2026-08-11 6:36 ` Linus Walleij 2026-08-11 6:34 ` [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep " Linus Walleij 2 siblings, 2 replies; 14+ messages in thread From: Michał Kardaś @ 2026-08-10 13:06 UTC (permalink / raw) To: Linus Walleij, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby Cc: Andy Shevchenko, Douglas Anderson, Vic Huang, linux-gpio, linux-serial, linux-kernel, Michał Kardaś When a UART port is connected to an external peripheral whose power domain is kept powered off until first use, transitioning the UART pins from the "init" state to the "default" state prematurely at probe completion can cause parasitic back-powering into the unpowered peripheral. Ensure that on boards specifying an "init" pinctrl state for the port, the "init" state is preserved until the port is first opened: 1. In dw8250_probe(), call pinctrl_keep_init_state(dev) to opt out of the automatic "init" -> "default" transition at probe completion and record this in data->in_init_state. 2. In dw8250_do_pm(), when the port is opened (state == 0), transition pins from "init" to "default" if data->in_init_state is set, and clear the flag. Suggested-by: Douglas Anderson <dianders@chromium.org> Co-developed-by: Vic Huang <vich@google.com> Signed-off-by: Vic Huang <vich@google.com> Signed-off-by: Michał Kardaś <mkmkl@google.com> --- drivers/tty/serial/8250/8250_dw.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 5fba913f3301..74e568e2a0d3 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -18,6 +18,7 @@ #include <linux/io.h> #include <linux/lockdep.h> #include <linux/module.h> +#include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/property.h> @@ -77,6 +78,7 @@ struct dw8250_data { unsigned int skip_autocfg:1; unsigned int uart_16550_compatible:1; unsigned int in_idle:1; + unsigned int in_init_state:1; u8 no_int_count; }; @@ -461,8 +463,15 @@ static int dw8250_handle_irq(struct uart_port *p) static void dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) { - if (!state) + struct dw8250_data *d = to_dw8250_data(port->private_data); + + if (!state) { pm_runtime_get_sync(port->dev); + if (d->in_init_state) { + d->in_init_state = false; + pinctrl_pm_select_default_state(port->dev); + } + } serial8250_do_pm(port, state, old); @@ -770,6 +779,8 @@ static int dw8250_probe(struct platform_device *pdev) if (data->data.line < 0) return data->data.line; + data->in_init_state = pinctrl_keep_init_state(dev); + platform_set_drvdata(pdev, data); pm_runtime_enable(dev); -- 2.55.0.654.g21b8a5bc05-goog ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v1 2/2] tty: serial: 8250_dw: Keep init pinctrl state until first open 2026-08-10 13:06 ` [PATCH v1 2/2] tty: serial: 8250_dw: Keep init pinctrl state until first open Michał Kardaś @ 2026-08-10 18:17 ` Andy Shevchenko 2026-08-11 6:36 ` Linus Walleij 1 sibling, 0 replies; 14+ messages in thread From: Andy Shevchenko @ 2026-08-10 18:17 UTC (permalink / raw) To: Michał Kardaś Cc: Linus Walleij, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Douglas Anderson, Vic Huang, linux-gpio, linux-serial, linux-kernel On Mon, Aug 10, 2026 at 01:06:35PM +0000, Michał Kardaś wrote: > When a UART port is connected to an external peripheral whose power > domain is kept powered off until first use, transitioning the UART > pins from the "init" state to the "default" state prematurely at probe > completion can cause parasitic back-powering into the unpowered > peripheral. > > Ensure that on boards specifying an "init" pinctrl state for the port, > the "init" state is preserved until the port is first opened: > > 1. In dw8250_probe(), call pinctrl_keep_init_state(dev) to opt out of the > automatic "init" -> "default" transition at probe completion and record > this in data->in_init_state. > 2. In dw8250_do_pm(), when the port is opened (state == 0), transition > pins from "init" to "default" if data->in_init_state is set, and clear > the flag. ... > dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) > { > - if (!state) > + struct dw8250_data *d = to_dw8250_data(port->private_data); > + > + if (!state) { > pm_runtime_get_sync(port->dev); > + if (d->in_init_state) { > + d->in_init_state = false; Mistyped assignee. Should be 0. > + pinctrl_pm_select_default_state(port->dev); > + } > + } Obviously the above needs a good comment in the code explaining why it is doing that. ... > if (data->data.line < 0) > return data->data.line; And a good comment explaining what you put in the commit message. > + data->in_init_state = pinctrl_keep_init_state(dev); > platform_set_drvdata(pdev, data); > > pm_runtime_enable(dev); ... Wondering if this anyhow affects the future idea of the OOB wakeup for the UART using its Rx as GPIO wake source in the suspend. -- With Best Regards, Andy Shevchenko ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 2/2] tty: serial: 8250_dw: Keep init pinctrl state until first open 2026-08-10 13:06 ` [PATCH v1 2/2] tty: serial: 8250_dw: Keep init pinctrl state until first open Michał Kardaś 2026-08-10 18:17 ` Andy Shevchenko @ 2026-08-11 6:36 ` Linus Walleij 1 sibling, 0 replies; 14+ messages in thread From: Linus Walleij @ 2026-08-11 6:36 UTC (permalink / raw) To: Michał Kardaś Cc: Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko, Douglas Anderson, Vic Huang, linux-gpio, linux-serial, linux-kernel Hi Michal, thanks for your patch! On Mon, Aug 10, 2026 at 3:06 PM Michał Kardaś <mkmkl@google.com> wrote: > @@ -77,6 +78,7 @@ struct dw8250_data { > unsigned int skip_autocfg:1; > unsigned int uart_16550_compatible:1; > unsigned int in_idle:1; > + unsigned int in_init_state:1; Side comment: why are these not bool? > + if (!state) { > pm_runtime_get_sync(port->dev); > + if (d->in_init_state) { > + d->in_init_state = false; > + pinctrl_pm_select_default_state(port->dev); > + } > + } As noticed in 0/2 don't use the default state for this, create and use a custom but optional "online" state. It needs to be optional so current users keep working without it. Yours, Linus Walleij ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open 2026-08-10 13:06 [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open Michał Kardaś 2026-08-10 13:06 ` [PATCH v1 1/2] pinctrl: core: Allow drivers to keep "init" pinctrl state after probe Michał Kardaś 2026-08-10 13:06 ` [PATCH v1 2/2] tty: serial: 8250_dw: Keep init pinctrl state until first open Michał Kardaś @ 2026-08-11 6:34 ` Linus Walleij 2026-08-11 17:00 ` Doug Anderson 2 siblings, 1 reply; 14+ messages in thread From: Linus Walleij @ 2026-08-11 6:34 UTC (permalink / raw) To: Michał Kardaś Cc: Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko, Douglas Anderson, Vic Huang, linux-gpio, linux-serial, linux-kernel Hi Michal, thanks for your patches! On Mon, Aug 10, 2026 at 3:06 PM Michał Kardaś <mkmkl@google.com> wrote: > During device probe, pinctrl_bind_pins() binds pins to their "init" state > if specified in Device Tree. When probe finishes, pinctrl_init_done() > automatically transitions the pins from "init" to "default" state. (...) > 1. Patch 1 (pinctrl core): > Adds pinctrl_keep_init_state(dev). When called during probe, > pinctrl_init_done() opts out of the automatic "init" -> "default" > transition, allowing the driver to keep pins in the safe "init" state > upon probe completion. Updates Documentation/driver-api/pin-control.rst. > Board configurations that do not define an "init" state are completely > unaffected. I think this is the wrong approach to this problem. You are changing the transition from "init" to "default" for all devices on the entire system. What if this is not good for all devices? I think the right approach is to create a new custom pin control state for 8250dw, something like "active" or "online", and then actively retrieve this state when the device goes online. The "init" state can just be the exact same as "default", or you can just define "default" to be what "init" is and skip "init" altogether. Pin control supports any kind of arbitrarily named custom states. In wherever the UART is actually opened: #include <linux/pinctrl/consumer.h> probe(): mydev->p = devm_pinctrl_get(dev); mydev->pins_online_state = = pinctrl_lookup_state(dev->pins->p, "online"); open(): ret = pinctrl_select_state(dev->pins->p, mydev->pins_online_state); close(): ret = pinctrl_pm_select_default_state(dev); + all error handling and stuff, see e.g. drivers/base/pinctrl.c for good coding practice. Yours, Linus Walleij ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open 2026-08-11 6:34 ` [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep " Linus Walleij @ 2026-08-11 17:00 ` Doug Anderson 2026-08-11 18:47 ` Linus Walleij 0 siblings, 1 reply; 14+ messages in thread From: Doug Anderson @ 2026-08-11 17:00 UTC (permalink / raw) To: Linus Walleij Cc: Michał Kardaś, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko, Vic Huang, linux-gpio, linux-serial, linux-kernel Hi, On Mon, Aug 10, 2026 at 11:34 PM Linus Walleij <linusw@kernel.org> wrote: > > Hi Michal, > > thanks for your patches! > > On Mon, Aug 10, 2026 at 3:06 PM Michał Kardaś <mkmkl@google.com> wrote: > > > During device probe, pinctrl_bind_pins() binds pins to their "init" state > > if specified in Device Tree. When probe finishes, pinctrl_init_done() > > automatically transitions the pins from "init" to "default" state. > (...) > > 1. Patch 1 (pinctrl core): > > Adds pinctrl_keep_init_state(dev). When called during probe, > > pinctrl_init_done() opts out of the automatic "init" -> "default" > > transition, allowing the driver to keep pins in the safe "init" state > > upon probe completion. Updates Documentation/driver-api/pin-control.rst. > > Board configurations that do not define an "init" state are completely > > unaffected. > > I think this is the wrong approach to this problem. > > You are changing the transition from "init" to "default" for all devices > on the entire system. I don't _think_ that's what his patches are doing, though? It's only changing the transition for drivers that actually call pinctrl_keep_init_state(). For any drivers that don't call pinctrl_keep_init_state() then the behavior is unchanged. Furthermore, this would only affect hardware that specifically has an "init" state defined. When brainstorming this with Michał, my thought was that for a certain class of drivers we could unconditionally declare: if an "init" state is defined for the hardware, the correct time to transition away from the "init" state is upon the first device open, not upon completion of probe. Specifically, I was thinking that for "bus" drivers (UART, SPI, I2C) that the end of probe doesn't really mean that everything is set up and pins can be configured normally. It's only after the actual endpoint driver (the one using the bus) probes that you can really transition off the "init" state. > What if this is not good for all devices? At the moment, I couldn't find any device that the above rules would break. Certainly I could have missed something. > I think the right approach is to create a new custom pin control > state for 8250dw, something like "active" or "online", and then > actively retrieve this state when the device goes online. > The "init" state can just be the exact same as "default", > or you can just define "default" to be what "init" is and skip > "init" altogether. > > Pin control supports any kind of arbitrarily named custom > states. > > In wherever the UART is actually opened: > > #include <linux/pinctrl/consumer.h> > > probe(): > mydev->p = devm_pinctrl_get(dev); > mydev->pins_online_state = = pinctrl_lookup_state(dev->pins->p, "online"); > > open(): > ret = pinctrl_select_state(dev->pins->p, mydev->pins_online_state); > > close(): > ret = pinctrl_pm_select_default_state(dev); > > + all error handling and stuff, see e.g. drivers/base/pinctrl.c for > good coding practice. Definitely the things Michał wants to achieve can be done without changing the pinctrl core by using named pinctrl states and transitioning at the right times. One of the solutions we looked at together was functionally equivalent to what he proposed here: he defined a state "unopened" that was a complete copy of "init". At the end of probe he transitioned to "unopened" and then later transitioned to "default" upon the first open, never to use "unopened" again. Personally I didn't love this because it required duplicating the "unopened" and "init" states when really we just wanted to keep the "init" state longer. ...and I couldn't think of any time when a UART driver would have an "init" state when it _shouldn't_ persist until the first open. :-P That being said, it worked and wasn't too ugly or anything. FWIW, that is a _slightly_ different solution to what you've proposed. In normal pinctrl usage the "init" state is a temporary state used just at system startup time before all the pieces are together. In the solution above "unopened" had this same property as being just a temporary state during init time. As I understand, the idea is that the "init" state isn't necessarily the same as the "closed" or "sleep" state but can also be a "safe" state to make sure lines don't glitch until we're certain everything has been initialized properly. In your proposal, the initial state needs to be equivalent to the "closed" state, right? That may be fine for some cases, but maybe not everything? -Doug ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open 2026-08-11 17:00 ` Doug Anderson @ 2026-08-11 18:47 ` Linus Walleij 2026-08-11 20:15 ` Doug Anderson 0 siblings, 1 reply; 14+ messages in thread From: Linus Walleij @ 2026-08-11 18:47 UTC (permalink / raw) To: Doug Anderson Cc: Michał Kardaś, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko, Vic Huang, linux-gpio, linux-serial, linux-kernel Hi Doug, On Tue, Aug 11, 2026 at 7:00 PM Doug Anderson <dianders@chromium.org> wrote: > I don't _think_ that's what his patches are doing, though? It's only > changing the transition for drivers that actually call > pinctrl_keep_init_state(). For any drivers that don't call > pinctrl_keep_init_state() then the behavior is unchanged. Aha OK I get it. You're right, the behaviour change will only affect this one device. > Furthermore, this would only affect hardware that specifically has an > "init" state defined. > > When brainstorming this with Michał, my thought was that for a certain > class of drivers we could unconditionally declare: if an "init" state > is defined for the hardware, the correct time to transition away from > the "init" state is upon the first device open, not upon completion of > probe. Specifically, I was thinking that for "bus" drivers (UART, SPI, > I2C) that the end of probe doesn't really mean that everything is set > up and pins can be configured normally. It's only after the actual > endpoint driver (the one using the bus) probes that you can really > transition off the "init" state. But why is it such a good idea to alter the core semantics of "init" and "default" for certain devices instead of just coming up with some custom state? git grep pinctrl_lookup_state gives a lot of cases of custom states, it's a normal thing to do. Maybe not common but whenever you want something not the usual semantics, use a custom state. > > What if this is not good for all devices? > > At the moment, I couldn't find any device that the above rules would > break. Certainly I could have missed something. No you're right, nothing breaks other than the that for one instance of a driver the default/init semantics change. Which isn't elegant IMO, but it works. > Definitely the things Michał wants to achieve can be done without > changing the pinctrl core by using named pinctrl states and > transitioning at the right times. I think we need to do that. This approach is a hack, it will be hard for others to understand and lead to a lot of questions about why this is done and so on. Better use a custom state. > One of the solutions we looked at > together was functionally equivalent to what he proposed here: he > defined a state "unopened" that was a complete copy of "init". At the > end of probe he transitioned to "unopened" and then later transitioned > to "default" upon the first open, never to use "unopened" again. I think you should step back and thing about what state names are the most relevant for a UART. Why would you want "unopened"? Just use "default". The states are just state transitions such as any finite state machine. These are perfectly fine semantics: open() close() open() "default" ------> "open" -------> "default" ------> "open" The device core doesn't touch the states after probe() so the "default" state can be reused without any problems. No need to have any "unopened" state. Yours, Linus Walleij ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open 2026-08-11 18:47 ` Linus Walleij @ 2026-08-11 20:15 ` Doug Anderson 2026-08-12 1:26 ` Doug Anderson ` (2 more replies) 0 siblings, 3 replies; 14+ messages in thread From: Doug Anderson @ 2026-08-11 20:15 UTC (permalink / raw) To: Linus Walleij Cc: Michał Kardaś, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko, Vic Huang, linux-gpio, linux-serial, linux-kernel Hi, On Tue, Aug 11, 2026 at 11:47 AM Linus Walleij <linusw@kernel.org> wrote: > > Hi Doug, > > > > What if this is not good for all devices? > > > > At the moment, I couldn't find any device that the above rules would > > break. Certainly I could have missed something. > > No you're right, nothing breaks other than the that for one > instance of a driver the default/init semantics change. > Which isn't elegant IMO, but it works. > > > Definitely the things Michał wants to achieve can be done without > > changing the pinctrl core by using named pinctrl states and > > transitioning at the right times. > > I think we need to do that. This approach is a hack, it will be > hard for others to understand and lead to a lot of questions > about why this is done and so on. Better use a custom state. Sure, that's a fair argument. To me, it felt like adding the extra state was more of a hack / working around the pinctrl limitations, but I can certainly see both perspectives. > > One of the solutions we looked at > > together was functionally equivalent to what he proposed here: he > > defined a state "unopened" that was a complete copy of "init". At the > > end of probe he transitioned to "unopened" and then later transitioned > > to "default" upon the first open, never to use "unopened" again. > > I think you should step back and thing about what state names > are the most relevant for a UART. > > Why would you want "unopened"? Just use "default". > The states are just state transitions such as any finite > state machine. > > These are perfectly fine semantics: > > open() close() open() > "default" ------> "open" -------> "default" ------> "open" > > The device core doesn't touch the states after probe() > so the "default" state can be reused without any problems. > No need to have any "unopened" state. The idea in my mind, at least, was that the state of the system isn't all that well known at boot time. The bootloader may not have left pins / peripherals in a consistent state. Until all system components finish probing and finding each other, it may be hard to know the correct pin state. It is during this unstable period of system boot that I envision we'd want this "init" / "unopened" state. After we get out of the uncertainty of boot, we'd never need to go back to this "init" state. Said another way, the "init" state might account for some uncertainty about the state of the device that the pins are connected to. On the other hand, there should be no uncertainty in the "closed" state. This is why I was thinking that they could/should be different states. This all being said, you're right that we may need to take a step back and look again at all the options. In the specific case Michał is trying to solve, the "init" state and the "closed" state probably can be the same. Thus using a solution like you proposed can make sense. One thing I guess we'd have to work out is whether we'd really want to use "default" and "open". I usually think of "default" as the active state and then the two common states "sleep" and "idle" as the inactive states. I guess looking at all the states, maybe you'd suggest: * At probe time, select "default" state since the port is closed. * At port open time, select "open" state if it exists. * If a port runtime suspends while open, select "idle" state if it exists. * If a port runtime resumes while open, try to select "open" if it exists, or fallback to "default". * If a port does system suspend while open, select "sleep" state if it exists. * If a port does system resume while open, try to select "open" if it exists, or fallback to "default". * If any kind of suspend/resume happens while a port is closed, it stays in "default" The above assumes that if a port is closed that it doesn't need / shouldn't transition to "sleep" / "idle" states. That's probably true (?) for any port that defines an "open" state, implying that "default" means "closed". If someone only defines "default" and "sleep" or "idle", though, maybe they'd expect transitions to "sleep" / "idle" at suspend time? Does that sound roughly like what you're thinking? -Doug ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open 2026-08-11 20:15 ` Doug Anderson @ 2026-08-12 1:26 ` Doug Anderson 2026-08-12 7:00 ` Andy Shevchenko 2026-08-12 6:51 ` Andy Shevchenko 2026-08-12 7:46 ` Linus Walleij 2 siblings, 1 reply; 14+ messages in thread From: Doug Anderson @ 2026-08-12 1:26 UTC (permalink / raw) To: Linus Walleij Cc: Michał Kardaś, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko, Vic Huang, linux-gpio, linux-serial, linux-kernel Hi, On Tue, Aug 11, 2026 at 1:15 PM Doug Anderson <dianders@chromium.org> wrote: > > > > One of the solutions we looked at > > > together was functionally equivalent to what he proposed here: he > > > defined a state "unopened" that was a complete copy of "init". At the > > > end of probe he transitioned to "unopened" and then later transitioned > > > to "default" upon the first open, never to use "unopened" again. > > > > I think you should step back and thing about what state names > > are the most relevant for a UART. > > > > Why would you want "unopened"? Just use "default". > > The states are just state transitions such as any finite > > state machine. > > > > These are perfectly fine semantics: > > > > open() close() open() > > "default" ------> "open" -------> "default" ------> "open" > > > > The device core doesn't touch the states after probe() > > so the "default" state can be reused without any problems. > > No need to have any "unopened" state. > > The idea in my mind, at least, was that the state of the system isn't > all that well known at boot time. The bootloader may not have left > pins / peripherals in a consistent state. Until all system components > finish probing and finding each other, it may be hard to know the > correct pin state. It is during this unstable period of system boot > that I envision we'd want this "init" / "unopened" state. After we get > out of the uncertainty of boot, we'd never need to go back to this > "init" state. Said another way, the "init" state might account for > some uncertainty about the state of the device that the pins are > connected to. On the other hand, there should be no uncertainty in the > "closed" state. This is why I was thinking that they could/should be > different states. > > This all being said, you're right that we may need to take a step back > and look again at all the options. In the specific case Michał is > trying to solve, the "init" state and the "closed" state probably can > be the same. Thus using a solution like you proposed can make sense. > > One thing I guess we'd have to work out is whether we'd really want to > use "default" and "open". I usually think of "default" as the active > state and then the two common states "sleep" and "idle" as the > inactive states. I guess looking at all the states, maybe you'd > suggest: > > * At probe time, select "default" state since the port is closed. > * At port open time, select "open" state if it exists. > * If a port runtime suspends while open, select "idle" state if it exists. > * If a port runtime resumes while open, try to select "open" if it > exists, or fallback to "default". > * If a port does system suspend while open, select "sleep" state if it exists. > * If a port does system resume while open, try to select "open" if it > exists, or fallback to "default". > * If any kind of suspend/resume happens while a port is closed, it > stays in "default" > > The above assumes that if a port is closed that it doesn't need / > shouldn't transition to "sleep" / "idle" states. That's probably true > (?) for any port that defines an "open" state, implying that "default" > means "closed". If someone only defines "default" and "sleep" or > "idle", though, maybe they'd expect transitions to "sleep" / "idle" at > suspend time? > > Does that sound roughly like what you're thinking? FWIW, we are in basically the same situation for SPI on the same board. Specifically, this happens: 1. Remote side starts unpowered. 2. SPI bus driver probes and pinctrl sets SPI pins to their default state. Importantly, the SPI chip select (CS_N) is high, which backpowers the device (illegal). What we need is we need to _assert_ chip select (make CS_N low) until we know that the other side is powered. ...we can try to use the "init" state that exists today, but by the time the SPI's probe function finishes, there is no guarantee that the SPI client's probe function has run. The module might not have been loaded yet. This means that "init" state (as currently defined) doesn't help. ...we can't use the "opened" we've been talking about in UART because there's no real idea of "open"ing a SPI bus. It's transaction oriented. ...we can't use the normal "runtime pm" concept in SPI and start the SPI bus in suspended state because the "runtime suspended" state of the bus would want the chip select deasserted (CS_N high). Using an extended "init" state (as in Michał's patch) and transitioning to "default" upon the first SPI transfer would work, since we'd know that the client is powered by then. After that point in time, if the client wanted to power the device off it could manually assert "chip select" before powering off. Of course, I'll admit that using the extended "init" state like this is still a bit ugly, whether doing it like Michał's patch does or by doing something like the "unopened" solution that I talked about. Other options for SPI could be: 1. Hack something into the SPI bus driver to turn on the regulator for the device. This is pretty ugly, but would work. Probably not upstreamable. 2. Invent a "pwrseq" solution for SPI where we run a sequence of steps (turning the regulator on) before probing the SPI bus, like other "pwrseq" drivers. Of course, most of those are for "discoverable" busses, but the idea of powering up a peripheral before probing the bus it's on is similar. This seems an extreme amount of work. 3. Hack the "CS GPIO" to be controlled by the client. It looks like we could fully move the GPIO (including the pinctrl in the DT) to the client. Then the client could call spi_set_csgpiod() after it's turned on the regulator. The client could have an "init" state for the GPIO that keeps it low and then transition to "default" right before calling spi_set_csgpiod(). Of everything, solution #3 doesn't seem terrible. I also still don't totally hate the idea of extending the "init" state... Of course, there's also some chance we can figure out other ways to get this regulator turned on sooner. -Doug ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open 2026-08-12 1:26 ` Doug Anderson @ 2026-08-12 7:00 ` Andy Shevchenko 0 siblings, 0 replies; 14+ messages in thread From: Andy Shevchenko @ 2026-08-12 7:00 UTC (permalink / raw) To: Doug Anderson Cc: Linus Walleij, Michał Kardaś, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Vic Huang, linux-gpio, linux-serial, linux-kernel On Tue, Aug 11, 2026 at 06:26:53PM -0700, Doug Anderson wrote: > On Tue, Aug 11, 2026 at 1:15 PM Doug Anderson <dianders@chromium.org> wrote: ... > FWIW, we are in basically the same situation for SPI on the same > board. Specifically, this happens: > > 1. Remote side starts unpowered. > > 2. SPI bus driver probes and pinctrl sets SPI pins to their default > state. Importantly, the SPI chip select (CS_N) is high, which > backpowers the device (illegal). > > What we need is we need to _assert_ chip select (make CS_N low) until > we know that the other side is powered. Isn't this dangerous? Some noise on the bus for whatever reason might produce undesired "communication". > ...we can try to use the "init" state that exists today, but by the > time the SPI's probe function finishes, there is no guarantee that the > SPI client's probe function has run. The module might not have been > loaded yet. This means that "init" state (as currently defined) > doesn't help. > > ...we can't use the "opened" we've been talking about in UART because > there's no real idea of "open"ing a SPI bus. It's transaction > oriented. But any SPI message that is queued is basically an "open" stage. So, it sounds like SPI core should change pin control states when message is queued and when it's done. Like be coupled with runtime PM? > ...we can't use the normal "runtime pm" concept in SPI and start the > SPI bus in suspended state because the "runtime suspended" state of > the bus would want the chip select deasserted (CS_N high). Sounds like a PCB / electrical level of design issue. I would solve this by gating CS signal using power of the peripheral connected. Have you talked to your HW engineers about this problem? > Using an extended "init" state (as in Michał's patch) and > transitioning to "default" upon the first SPI transfer would work, > since we'd know that the client is powered by then. After that point > in time, if the client wanted to power the device off it could > manually assert "chip select" before powering off. > > Of course, I'll admit that using the extended "init" state like this > is still a bit ugly, whether doing it like Michał's patch does or by > doing something like the "unopened" solution that I talked about. > > Other options for SPI could be: > > 1. Hack something into the SPI bus driver to turn on the regulator for > the device. This is pretty ugly, but would work. Probably not > upstreamable. > > 2. Invent a "pwrseq" solution for SPI where we run a sequence of steps > (turning the regulator on) before probing the SPI bus, like other > "pwrseq" drivers. Of course, most of those are for "discoverable" > busses, but the idea of powering up a peripheral before probing the > bus it's on is similar. This seems an extreme amount of work. Btw, isn't there some development for the undiscoverable buses? > 3. Hack the "CS GPIO" to be controlled by the client. It looks like we > could fully move the GPIO (including the pinctrl in the DT) to the > client. Then the client could call spi_set_csgpiod() after it's turned > on the regulator. The client could have an "init" state for the GPIO > that keeps it low and then transition to "default" right before > calling spi_set_csgpiod(). > Of everything, solution #3 doesn't seem terrible. I also still don't > totally hate the idea of extending the "init" state... Of course, > there's also some chance we can figure out other ways to get this > regulator turned on sooner. Yes, #3 seems okay, but wouldn't be even better to have some flag in SPI core or pin control on per message basis (see also above)? -- With Best Regards, Andy Shevchenko ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open 2026-08-11 20:15 ` Doug Anderson 2026-08-12 1:26 ` Doug Anderson @ 2026-08-12 6:51 ` Andy Shevchenko 2026-08-12 7:46 ` Linus Walleij 2 siblings, 0 replies; 14+ messages in thread From: Andy Shevchenko @ 2026-08-12 6:51 UTC (permalink / raw) To: Doug Anderson Cc: Linus Walleij, Michał Kardaś, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Vic Huang, linux-gpio, linux-serial, linux-kernel On Tue, Aug 11, 2026 at 01:15:27PM -0700, Doug Anderson wrote: > On Tue, Aug 11, 2026 at 11:47 AM Linus Walleij <linusw@kernel.org> wrote: ... > > > > What if this is not good for all devices? > > > > > > At the moment, I couldn't find any device that the above rules would > > > break. Certainly I could have missed something. > > > > No you're right, nothing breaks other than the that for one > > instance of a driver the default/init semantics change. > > Which isn't elegant IMO, but it works. > > > > > Definitely the things Michał wants to achieve can be done without > > > changing the pinctrl core by using named pinctrl states and > > > transitioning at the right times. > > > > I think we need to do that. This approach is a hack, it will be > > hard for others to understand and lead to a lot of questions > > about why this is done and so on. Better use a custom state. > > Sure, that's a fair argument. To me, it felt like adding the extra > state was more of a hack / working around the pinctrl limitations, but > I can certainly see both perspectives. FWIW, I'm also with Linus here, the fixing code and make exceptions smells like a hack. Even having duplicating states with different names (mean semantics) is much better approach. ... > * At probe time, select "default" state since the port is closed. > * At port open time, select "open" state if it exists. > * If a port runtime suspends while open, select "idle" state if it exists. > * If a port runtime resumes while open, try to select "open" if it > exists, or fallback to "default". > * If a port does system suspend while open, select "sleep" state if it exists. > * If a port does system resume while open, try to select "open" if it > exists, or fallback to "default". > * If any kind of suspend/resume happens while a port is closed, it > stays in "default" Not sure about this one as it might be tricky for the case with OOB wake. Yeah, it's questionable if we want wake source on never opened port (kernel console?). -- With Best Regards, Andy Shevchenko ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open 2026-08-11 20:15 ` Doug Anderson 2026-08-12 1:26 ` Doug Anderson 2026-08-12 6:51 ` Andy Shevchenko @ 2026-08-12 7:46 ` Linus Walleij 2 siblings, 0 replies; 14+ messages in thread From: Linus Walleij @ 2026-08-12 7:46 UTC (permalink / raw) To: Doug Anderson Cc: Michał Kardaś, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko, Vic Huang, linux-gpio, linux-serial, linux-kernel Hi Doug, On Tue, Aug 11, 2026 at 10:15 PM Doug Anderson <dianders@chromium.org> wrote: > One thing I guess we'd have to work out is whether we'd really want to > use "default" and "open". I usually think of "default" as the active > state and then the two common states "sleep" and "idle" as the > inactive states. I guess looking at all the states, maybe you'd > suggest: > > * At probe time, select "default" state since the port is closed. > * At port open time, select "open" state if it exists. > * If a port runtime suspends while open, select "idle" state if it exists. > * If a port runtime resumes while open, try to select "open" if it > exists, or fallback to "default". > * If a port does system suspend while open, select "sleep" state if it exists. > * If a port does system resume while open, try to select "open" if it > exists, or fallback to "default". > * If any kind of suspend/resume happens while a port is closed, it > stays in "default" > > The above assumes that if a port is closed that it doesn't need / > shouldn't transition to "sleep" / "idle" states. That's probably true > (?) for any port that defines an "open" state, implying that "default" > means "closed". If someone only defines "default" and "sleep" or > "idle", though, maybe they'd expect transitions to "sleep" / "idle" at > suspend time? > > Does that sound roughly like what you're thinking? Attention to detail is officially your middle name Doug! It's what I would have been thinking, if I had sat down and had the same attention to detail. So I really like what I'm seeing here, go ahead with this design, provided it checks out and you can somewhat test it. I guess you have hardware where you can actually test the hairy transitions between open, idle, sleep etc and that is more than most will do. Yours, Linus Walleij ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-08-12 7:47 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-08-10 13:06 [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep init pinctrl state until first open Michał Kardaś 2026-08-10 13:06 ` [PATCH v1 1/2] pinctrl: core: Allow drivers to keep "init" pinctrl state after probe Michał Kardaś 2026-08-10 18:12 ` Andy Shevchenko 2026-08-10 13:06 ` [PATCH v1 2/2] tty: serial: 8250_dw: Keep init pinctrl state until first open Michał Kardaś 2026-08-10 18:17 ` Andy Shevchenko 2026-08-11 6:36 ` Linus Walleij 2026-08-11 6:34 ` [PATCH v1 0/2] pinctrl / 8250_dw: Allow drivers to keep " Linus Walleij 2026-08-11 17:00 ` Doug Anderson 2026-08-11 18:47 ` Linus Walleij 2026-08-11 20:15 ` Doug Anderson 2026-08-12 1:26 ` Doug Anderson 2026-08-12 7:00 ` Andy Shevchenko 2026-08-12 6:51 ` Andy Shevchenko 2026-08-12 7:46 ` Linus Walleij
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox