Re: [PATCH 08/13] HID: ft260: uart: add modem pins control via ioctl
From: Michael Zaidman
Date: Thu Aug 27 2026 - 18:08:35 EST
On Tue, 25 Aug 2026 at 10:08 +0200, Linus Walleij wrote:
> I'm not the authortative expert on modem control using GPIO,
> but what I think you should do is to
>
> select GPIOLIB
> select SERIAL_MCTRL_GPIO
>
> On Kconfig, so that gpiolib is always available and you can use
> the generic modem control helpers for modem control over GPIO.
I looked into this, and it does not work for the FT260 without
changing serial_mctrl_gpio.c first. Three blockers:
- Every GPIO access on this chip is a USB transfer, so the
gpiochip has can_sleep = true. mctrl_gpio_set() calls
gpiod_set_array_value() and mctrl_gpio_get() calls
gpiod_get_value(), and gpiolib does WARN_ON(can_sleep) in both,
so every TIOCMGET/TIOCMSET would give a WARN backtrace.
- mctrl_gpio_init() takes a struct uart_port and its IRQ handler
needs it: uart_port_lock_irqsave(), uart_handle_dcd_change(),
port->icount, delta_msr_wait. This UART is a plain tty_driver
with a tty_port, so only mctrl_gpio_init_noauto() is left - and
the FT260 GPIO lines have no interrupts anyway.
- mctrl_gpio_init_noauto() only picks up lines that exist as
firmware properties: device_property_present(dev, "cts-gpios")
and friends. A gpiod_add_lookup_table() table is the machine
lookup path, so every line would be skipped, all descriptors
would stay NULL and both helpers would silently do nothing.
Software nodes could satisfy that check, but there is no
PROPERTY_ENTRY_GPIO in the tree to build them with.
serial_mctrl_gpio.h is also private to drivers/tty/serial - all
eleven users are serial_core drivers in that directory.
Registering a uart_port instead was tried for this device and
turned down. Daniel Beer's 2022 FT260 UART patch was built on
serial_core and called uart_add_one_port(); Greg asked for
usb-serial, and Johan Hovold answered that "neither USB-serial or
serial (core) is a good fit for such a HID device", pointing at
Christina Quast's tty driver as the right approach - which patch
1 of this series is a port of.
https://lore.kernel.org/lkml/638c51a2.170a0220.3af16.18f8@xxxxxxxxxxxxx/
https://lore.kernel.org/lkml/Y6WNl6+ySy8zcSyg@xxxxxxxxxxxxxxxxxxxx/
That patch left set_mctrl empty and get_mctrl returning a
constant, which is this same constraint seen from the other side:
uart_ops.set_mctrl and .get_mctrl must not sleep, while every
FT260 line access is a HID feature report over USB.
> This can be a bit delicate in this case since the gpiochip that you
> use for mctrl is also registered in this driver, so you need to
> register the gpiochip *first*, then add a look-up table for the
> GPIOs, then register this modem control.
>
> Then look in e.g. drivers/mfd/sm501.c which is an
> MFD device that register a gpiochip and then consume
> GPIOs from itself.
Agreed on the ordering, and thanks for the reference. The UART
probe currently registers the tty port before the gpiochip, so
that would have to be inverted, and the gpiochip label is built
from the HID device name, so the table would have to be built at
probe rather than being static. Both are workable; they are not
what blocks this. sm501 does not hit the sleeping problem because
its gpiochip is memory mapped.
> The core idea is that the serial modem control should look
> up the GPIOs from its own gpiochip and use the MCTRL
> library helpers, then this should result in very little and
> compact code that is easy to read.
No argument with the goal - I would rather have that than my own
TIOCM handling. But making it usable here means work inside the
serial helpers: cansleep set/get, a path that does not require a
uart_port, a lookup that works without firmware properties, and
the header moved to include/linux. That is a serial subsystem
series to agree with Greg and Jiri Slaby, so I propose keeping
the ioctl implementation in this series and doing the conversion
as a follow-up.
Even then only the set/get helpers would apply: with no GPIO
interrupts, modem status changes come from the FT260's own
interrupt status input report (0xB1), so that part stays in the
driver either way.
Thanks,
Michael