A "uart slave" is a device permanently connected via UART.
Such a device may need its own driver, e.g. for powering
it up on tty open and powering it down on tty release.
When a device is connected to a UART by a 'standard' bus, such as
RS-232, signaling for power control typically uses "DTR". When the
connection is permanent, as is common on "embedded" boards, separate
signaling may be needed and this requires a separate driver.
uart-slave is a new bus-type which drivers can be written and devices
created.
A "uart slave" device is declared as a child of the uart in
device-tree:
&uart1 {
bluetooth {
compatible = "wi2wi,w2cbw003";
vdd-supply = <&vaux4>;
};
};
This device will be inserted in the driver-model tree between the uart
and the tty.
The uart-slave driver can replace any of the tty_operations functions
so a call by the tty can be intercepted before being handled by the
uart.
When the tty port is initialized, the uart_slave device is created and
waits for a driver to be bound to it. Once this happens the tty
device, which was previously initialized, will be added. This slave
is now considered "finalized".
Any "finalized" slaves will be removed when the tty device is
unregistered. e.g. by destruct_tty_driver.
While slaves are non-finalized they hold a reference to the tty driver
to prevent destruct_tty_driver from being called, as it cannot find
and free slave devices.
Signed-off-by: NeilBrown
---
drivers/tty/serial/Kconfig |1
drivers/tty/serial/Makefile|2
drivers/tty/serial/serial_core.c |9 +-
drivers/tty/serial/slave/Kconfig |6 +
drivers/tty/serial/slave/Makefile |2
drivers/tty/serial/slave/uart_slave_core.c | 168
drivers/tty/tty_io.c |3 +
include/linux/uart_slave.h | 29 +
8 files changed, 219 insertions(+), 1 deletion(-)
create mode 100644 drivers/tty/serial/slave/Kconfig
create mode 100644 drivers/tty/serial/slave/Makefile
create mode 100644 drivers/tty/serial/slave/uart_slave_core.c
create mode 100644 include/linux/uart_slave.h
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index f8120c1bde14..2601a8fb41a3 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1594,4 +1594,5 @@ endmenu
config SERIAL_MCTRL_GPIO
tristate
+source drivers/tty/serial/slave/Kconfig
endif # TTY
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index c3ac3d930b33..7a6ed85257f6 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -96,3 +96,5 @@ obj-$(CONFIG_SERIAL_SPRD) += sprd_serial.o
# GPIOLIB helpers for modem control lines
obj-$(CONFIG_SERIAL_MCTRL_GPIO)+= serial_mctrl_gpio.o
+
+obj-y += slave/
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 3ea16f524e89..fcad5b30486f 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -34,6 +34,7 @@
#include
#include
#include
+#include
#include
#include
@@ -2710,10 +2711,16 @@ int uart_add_one_port(struct uart_driver *drv, struct
uart_port *uport)
* Register the port whether it's detected or not. This allows
* setserial to be used to alter this port's parameters.
*/
- tty_dev = tty_port_register_device_attr(port, drv->tty_driver,
+ tty_dev = tty_port_initialize_device_attr(port, drv->tty_driver,
uport->line, uport->dev, port, uport->tty_groups);
if (likely(!IS_ERR(tty_dev))) {
device_set_wakeup_capable(tty_dev, 1);
+ if (uart_slave_register(uport->dev, tty_dev,
+ drv->tty_driver) < 0) {
+ ret = tty_device_add(drv->tty_driver, tty_dev);
+ if (ret)
+ put_device(tty_dev);
+ }
} else {
dev_err(uport->dev, "Cannot register tty device on line %d\n",
uport->line);
diff --git a/drivers/tty/serial/slave/Kconfig b/drivers/tty/serial/slave/Kconfig
new file mode 100644
index ..6620e78b763e
--- /dev/null
+++ b/drivers/tty/serial/slave/Kconfig
@@ -0,0 +1,6 @@
+menuconfig UART_SLAVE
+ tristate "UART slave devices"
+ depends on OF
+ help
+Devices which attach via a uart, but need extra
+driver support for power management etc.
diff --git a/drivers/tty/serial/slave/Makefile
b/drivers/tty/serial/slave/Makefile
new file mode 100644
index ..aac8697fa406
--- /dev/null
+++ b/drivers/tty/serial/slave/Makefile
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_UART_SLAVE) += uart_slave_core.o
diff --git a/drivers/tty/serial/slave/uart_slave_core.c
b/drivers/tty/serial/slave/uart_slave_core.c
new file mode 100644
index ..d48d672300c2
--- /dev/null
+++ b/drivers/tty/serial/slav