On Thu, Mar 10, 2016 at 8:55 PM, Peter Hurley <peter@xxxxxxxxxxxxxxxxxx> wrote: > On 03/10/2016 08:36 AM, Peter Hurley wrote: >> Hi Yegor, >> >> On 03/09/2016 03:03 AM, yegorslists@xxxxxxxxxxxxxx wrote: >>> From: Yegor Yefremov <yegorslists@xxxxxxxxxxxxxx> >>> >>> This patch permits the usage fo GPIOs to control the CTS/RTS/DTR/DSR/DCD/RI >>> signals. >> >> Comments below. >> >> >>> 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"; >> >> Drop the DMA example; omap3 sdma is broken wrt to uart. >> >> >>> + 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); > > Also, autoRTS needs to be disabled if RTS is a gpio. > Similarly for autoCTS. > > >>> + >>> 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); >> >> This is ugly; why is mctrl pass-by-reference when it's returned anyway? >> >> return mctrl_gpio_get(up->gpio, 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); >> >> The 8250 driver virtualizes RTS because some h/w does not >> support RTS override with autoRTS on. >> >> So this won't work properly. >> And this won't work for RS485. >> >> Rather, transform >> >> serial_out(port, UART_MCR, val); >> serial_port_out(up, UART_MCR, val); >> >> to >> >> serial8250_out_MCR(up, val); >> >> and add the gpio setting to that. >> Do the transform first in a prequel patch; then add gpio to that. >> >> Similarly for serial_in(port, UART_MCR) To implement serial8250_in_MCR() we will need something like mctrl_gpio_get_mcr(), because mctrl_gpio_get() returns only GPIO values in input mode. Peter, Uwe what do you think about it? Yegor >>> } >>> >>> 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) >>> >>> /* >>> >> > -- 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