From: Yegor Yefremov <yegorslists@xxxxxxxxxxxxxx> This patch permits the usage fo GPIOs to control the CTS/RTS/DTR/DSR/DCD/RI signals. Signed-off-by: Yegor Yefremov <yegorslists@xxxxxxxxxxxxxx> --- Documentation/devicetree/bindings/serial/8250.txt | 21 +++++++++++++++++++++ drivers/tty/serial/8250/8250.h | 2 ++ drivers/tty/serial/8250/8250_core.c | 5 +++++ drivers/tty/serial/8250/8250_port.c | 11 ++++++++++- drivers/tty/serial/8250/Kconfig | 1 + include/linux/serial_8250.h | 1 + 6 files changed, 40 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/serial/8250.txt b/Documentation/devicetree/bindings/serial/8250.txt index 936ab5b..277e0ee 100644 --- a/Documentation/devicetree/bindings/serial/8250.txt +++ b/Documentation/devicetree/bindings/serial/8250.txt @@ -42,6 +42,9 @@ Optional properties: - auto-flow-control: one way to enable automatic flow control support. The driver is allowed to detect support for the capability even without this property. +- {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD + line respectively. It will use specified GPIO instead of the peripheral + function pin for the UART feature. If unsure, don't specify this property. Note: * fsl,ns16550: @@ -63,3 +66,21 @@ Example: interrupts = <10>; reg-shift = <2>; }; + +Example for OMAP UART using GPIO-based modem control signals: + + uart4: serial@49042000 { + compatible = "ti,omap3-uart"; + reg = <0x49042000 0x400>; + interrupts = <80>; + dmas = <&sdma 81 &sdma 82>; + dma-names = "tx", "rx"; + ti,hwmods = "uart4"; + clock-frequency = <48000000>; + cts-gpios = <&gpio3 5 GPIO_ACTIVE_LOW>; + rts-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>; + dtr-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; + dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; + dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; + }; diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index d54dcd8..98ee73c 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -15,6 +15,8 @@ #include <linux/serial_reg.h> #include <linux/dmaengine.h> +#include "../serial_mctrl_gpio.h" + struct uart_8250_dma { int (*tx_dma)(struct uart_8250_port *p); int (*rx_dma)(struct uart_8250_port *p, unsigned int iir); diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index c9720a9..cadcaa5 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1004,6 +1004,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up) if (up->port.flags & UPF_FIXED_TYPE) uart->port.type = up->port.type; + uart->gpios = mctrl_gpio_init(&uart->port, 0); + if (IS_ERR(uart->gpios)) + return PTR_ERR(uart->gpios); + serial8250_set_defaults(uart); /* Possibly override default I/O functions. */ @@ -1049,6 +1053,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up) ret = 0; } + } mutex_unlock(&serial_mutex); diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 8d262bc..e7bfeef 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1393,6 +1393,8 @@ static void serial8250_disable_ms(struct uart_port *port) if (up->bugs & UART_BUG_NOMSR) return; + mctrl_gpio_disable_ms(up->gpios); + up->ier &= ~UART_IER_MSI; serial_port_out(port, UART_IER, up->ier); } @@ -1405,6 +1407,8 @@ static void serial8250_enable_ms(struct uart_port *port) if (up->bugs & UART_BUG_NOMSR) return; + mctrl_gpio_enable_ms(up->gpios); + up->ier |= UART_IER_MSI; serial8250_rpm_get(up); @@ -1680,7 +1684,8 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port) ret |= TIOCM_DSR; if (status & UART_MSR_CTS) ret |= TIOCM_CTS; - return ret; + + return mctrl_gpio_get(up->gpios, &ret); } void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl) @@ -1707,10 +1712,14 @@ EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl); static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) { + struct uart_8250_port *up = up_to_u8250p(port); + if (port->set_mctrl) port->set_mctrl(port, mctrl); else serial8250_do_set_mctrl(port, mctrl); + + mctrl_gpio_set(up->gpios, mctrl); } static void serial8250_break_ctl(struct uart_port *port, int break_state) diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index b03cb517..997e9a8 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -6,6 +6,7 @@ config SERIAL_8250 tristate "8250/16550 and compatible serial support" select SERIAL_CORE + select SERIAL_MCTRL_GPIO if GPIOLIB ---help--- This selects whether you want to include the driver for the standard serial ports. The standard answer is Y. People who might say N diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index faa0e03..86a3ef4 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -104,6 +104,7 @@ struct uart_8250_port { * if no_console_suspend */ unsigned char probe; + struct mctrl_gpios *gpios; #define UART_PROBE_RSA (1 << 0) /* -- 2.1.4 -- 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