In some hardware I am developing, I have used the SC16IS7XX to connect two AVR microcontrollers back to my main processor running Linux. These microcontrollers implement an control interface which is modelled in Linux as a multi-function device. The set up is based on the driver for the RAVE Supervisory Processor: https://lwn.net/Articles/724765/ One issue during initialisation when using serdev with SC16IS7XX is that after uart_add_one_port has been called, the child driver may be started on a different kernel thread and may start calling the startup or set_termios functions of the serial driver before it has finished probing. I temporarily resolved this issue with a hack which involved adding a "ready" boolean to the driver. However, there are two proper solutions to this problem that I can think of: either serdev should somehow check that the probe was completed (successfully) before trying to load child drivers or the SC16IS7XX should have a mutex that better enforces the order in which its functions are called (particularly during initialization). My testing suggests that the latter may be the better solution, since even outside of the initialization context and when using the two ttys heavily at the same time, it is not hard to knock the SC16IS7XX device into a state where, at a minimum, the silicon stops sending interrupts. I think this ordering of function calls may also be partly responsible for "sc16is7xx 1-0048: ttySC0: Unexpected interrupt: 8" kernel messages that are mentioned in other threads. To support multiple ttys on a single device, the serdev code and its DT binding need to be slightly modified. My solution is to modify the code to parse the following: uart56: sc16is762@48 { compatible = "nxp,sc16is762"; reg = <0x48>; clocks = <&some_clock>; interrupt-parent = <&some_gpio_controller>; interrupts = <X IRQ_TYPE_EDGE_FALLING>; #address-cells = <1>; #size-cells = <0>; uart0: serial@0 { reg = <0>; uc0: microcontroller { compatible = "atmel,atmega328p"; current-speed = <57600>; }; }; uart1: serial@1 { reg = <1>; uc1: microcontroller { compatible = "atmel,atmega328p"; current-speed = <57600>; }; }; }; The code to parse this is as follows and uses the tty_idx to indicate which of the sc16is7xx ttys we are referring to. This works nicely with a single chip, however, when you have more than one sc16is7xx device, the reg value needs to be 2 and 3 for the second chip instead 0 and 1 as with the first chip. The second thing that is not so nice about this solution is that I needed to move struct serport from drivers/tty/serdev/serdev-ttyport.c to include/linux/serdev.h so that I could access tty_idx from drivers/tty/serdev/core.c. static int of_serdev_register_devices(struct serdev_controller *ctrl) { struct device_node *port, *node; struct serdev_device *serdev = NULL; struct serport *serport = serdev_controller_get_drvdata(ctrl); int err; unsigned reg; bool found = false; for_each_available_child_of_node(ctrl->dev.of_node, port) { of_property_read_u32(port, "reg", ®); if (serport->tty_idx != reg) continue; for_each_available_child_of_node(port, node) { if (!of_get_property(node, "compatible", NULL)) continue; dev_err(&ctrl->dev, "adding child %pOF\n", node); serdev = serdev_device_alloc(ctrl); if (!serdev) continue; serdev->dev.of_node = node; err = serdev_device_add(serdev); if (err) { dev_err(&serdev->dev, "failure adding device. status %d\n", err); serdev_device_put(serdev); } else found = true; } } if (!found) return -ENODEV; return 0; } Anyway, these are the results from my testing. If anyone is interested in proposing some better solutions or collaborating on some patches, I am happy to contribute and to do some more testing. -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html