Johan is the maintainer of the serial device subsystem, and also works on Greybus support.
Serial device bus aims to make serial devices fit better in the Linux device model. Currently there is no good way to model associated resources: GPIOs and interrupts, regulators, clocks, …. Also, the line discipline drivers make things complicated.
Current TTY driver: character device goes to line discipline (ldisc), goes to TTY port (buffering + abstraction layer), goes to TTY driver (device-specific). the console TTY is also a TTY driver.
Ldisc can register further class devices for higher-level functionality, e.g. for bluetooth there is a separate character device to represent the BT connection. But the ldisc has to be attached from userspace, that has to do a bunch of ioctls and it has to keep the port open to make sure the ldisc still exists as long as there is a user. So there is a hciattach daemon that keeps running. This approach (partly in userspace) has a lot of disadvantages:
- no auto discovery;
- difficult to use additional resources, e.g. reset or powerdown of the BT chip;
- no automatic power management possible;
- port must be kept open by hciattach, so the serial port can never go to suspend.
Therefore a new abstract bus for UART-attached devices, called serdev (the bus type is “serial”, the device “serdev”). Merged in 4.11 with major fixes in 4.12.
Currently only TTY-port serial controller defined. If a client is found, the serdev device will register instead of the TTY device. The serdev controller device sits on top of the TTY port abstraction. On top of that, there is a device-specific serdev client (= slave = device) (e.g. hci_serdev) that creates the device nodes. So ldisc is no longer involved, no hciattach daemon that keeps the port open. serdev client can directly load firmware in the usual way.
Internally, the TTY port is extended with suport for a TTY client. When a cient is registered, that is used instead of the ldisc. In DT, the client device is a child of the serial port node. The driver is supposed to know that the baud rate etc. is so that’s not specified in DT. In the sysfs tree, the serial device will have a “serial” directory instead of a “tty” directory.
serdev client interface resembles that of ldisc: open, close, tcget/set, flow control. Note that there is no serialisation of write() operations, since the TTY device is supposed to take care of that, but in practice usually not tested. There are callbacks for receive and write wakeup.
There are currently some limitations. There is no hotplug support, only a single slave per port (so no RS485 a mux, a serdev mux subsystem has been posted but it still has issues), flow control only works for output, not for input, only raw terminal so no XON/XOFF etc.
Hotplugging is currently done using TTY hangups and file operations, but these are not available in the serdev interface. Because of this, it doesn’t work on USB serial. Also we need a DT description but with hotpluggable devices that’s not possible. DT overlays could be solution.
There are some quirks left. There is still an ldisc allocated (and called into) even if it’s not really used. The controller is always registered even if there is no child node, so inefficient. The ordering of operations is fragile. There is no bus PM, but that’s OK because you really want your serial port to go to suspend even if the child is still attached.
Future work (in addition to the above) is to convert more devices from ldisc to serdev.
For more information: LWN article written while serdev was being developed.