[PATCH v3 0/3] pps-gpio: restore pin mux on unbind and shutdown
From: Eliav Farber
Date: Thu Sep 17 2026 - 03:58:57 EST
Some boards route the PPS input GPIO through a pin controller and mux the
pins to a different function when the pps-gpio driver is not active.
The driver core already selects the "default" pinctrl state before probe,
so the pins can be muxed for GPIO/PPS use while the driver is bound without
any driver change. Nothing, however, hands the pins back when the driver
is unbound or the system is shut down (for example before kexec), leaving
them stuck in the GPIO mux for the next kernel.
This series lets pps-gpio select an optional "inactive" pinctrl state in
remove() and shutdown(), so a board can describe the alternate mux there
and have it restored. The state is looked up and selected by the driver
itself (devm_pinctrl_get() + pinctrl_lookup_state() + pinctrl_select_
state()), so its meaning is unambiguous and it does not depend on
CONFIG_PM. It is a no-op for boards that do not describe an "inactive"
state.
Patch 1 is a small preparatory fix to propagate the gpiod_to_irq() and
request_threaded_irq() error codes (rather than a hardcoded -EINVAL) on
the probe error paths that patch 3 then converts to gotos. Patch 2
documents the optional "default"/"inactive" pinctrl-names in the binding;
patch 3 implements the driver side.
Tested on an AL11 K2V6 JRD10 board: binding/unbinding each pps-gpio device
toggles the corresponding PBS pin-mux register between the GPIO function
and the alternate ec_ptp_trigger_in function as expected, and re-binding
restores the GPIO function via the core-applied "default" state. Reading
the mux register with the devices left unbound confirms the "inactive"
mux persists. Also tested with a pps-gpio node that describes no pinctrl
at all, where probe, remove and shutdown behave as before.
Changes in v3 (addressing Sashiko's and Rodolfo Giometti's
review):
- New preparatory patch 1: propagate the gpiod_to_irq() and
request_threaded_irq() error codes instead of overwriting them with
-EINVAL, and log the errno on the request_threaded_irq() failure. The
pinctrl patch only converts those returns into gotos, so fixing the
discarded errors separately keeps them out of the pinctrl change
- Do not constrain pinctrl-names to a fixed ["default", "inactive"] tuple
in the binding. The driver looks the states up by name, so "inactive"
may appear in any position and other states may coexist; the binding
now only requires that a "default" state exists
- Treat -ENODEV from devm_pinctrl_get() as "no pinctrl described" rather
than a probe failure. A DT device without a "pinctrl-0" property gets
-ENODEV from the pinctrl core; that is expected, not an error. Real
errors, including -EPROBE_DEFER, are still propagated
- Restore the "inactive" mux on probe failure too. The error paths after
pps_gpio_get_pins() now go through a new err_release_pins label, so a
probe that fails in gpiod_to_irq(), pps_register_source() or
request_threaded_irq() no longer leaves the pins stuck in the
core-applied "default" state
- Warn if applying the "inactive" state fails rather than ignoring the
pinctrl_select_state() return silently
- Trim and de-duplicate the comments added in v2
Changes in v2 (all addressing Rodolfo Giometti's review):
- Rename the released state from "idle" to "inactive". "idle" is the
runtime-PM state in pinctrl-state.h; overloading it for "driver not
active" would clash with any future runtime PM or .suspend() and was
being baked into the binding as ABI. "inactive" is not a well-known
state, so no generic PM helper will ever auto-select it -- the driver
drives it explicitly
- Look the state up in the driver (devm_pinctrl_get() +
pinctrl_lookup_state() + pinctrl_select_state()) instead of
pinctrl_pm_select_idle_state(), removing the CONFIG_PM dependency so a
CONFIG_PM=n kernel that describes an "inactive" state now honors it
instead of silently doing nothing
- Fix shutdown(): tear down in the same order as remove() -- free_irq()
and timer_delete_sync() first, the mux change last -- so no IRQ or echo
timer callback can drive a pin after it has been handed back to another
function; shutdown() no longer changes the mux while the hardware is
still live
- Require a "default" state whenever "inactive" is present and reject the
mismatch, rather than releasing pins that were never put into a defined
PPS state
Link: https://lore.kernel.org/all/20260916134744.46354-1-farbere@xxxxxxxxxx/ [v1]
Link: https://lore.kernel.org/all/20260916182641.9768-1-farbere@xxxxxxxxxx/ [v2]
Eliav Farber (3):
pps: clients: gpio: propagate probe error codes
dt-bindings: pps: pps-gpio: document optional pinctrl states
pps: clients: gpio: release pins to an inactive state on remove and
shutdown
.../devicetree/bindings/pps/pps-gpio.yaml | 16 ++-
drivers/pps/clients/pps-gpio.c | 102 +++++++++++++++++-
2 files changed, 113 insertions(+), 5 deletions(-)
--
2.47.3