On Thu, Mar 10, 2016 at 8:43 AM, Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx> wrote: > Hello, > > On Wed, Mar 09, 2016 at 12:07:39PM +0100, Yegor Yefremov wrote: >> On Wed, Mar 9, 2016 at 12:03 PM, <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. >> > >> > 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; >> > } >> > + > > This hunk should be dropped. OK > Otherwise the patch looks good. > >> > } >> > 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) >> > >> > /* >> >> This patch was tested on a am335x based machine. So far everything is >> working as expected aside from interrupts. As soon as the first CTS >> interrupt comes I get: >> >> ------------[ cut here ]------------ >> WARNING: CPU: 0 PID: 0 at drivers/tty/serial/serial_core.c:2893 >> uart_handle_cts_change+0x9c/0xd8() >> Modules linked in: musb_dsps musb_am335x >> CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 4.5.0-rc6 #37 >> Hardware name: Generic AM33XX (Flattened Device Tree) >> [<c0017e34>] (unwind_backtrace) from [<c0014088>] (show_stack+0x10/0x14) >> [<c0014088>] (show_stack) from [<c02c5b24>] (dump_stack+0xb0/0xe4) >> [<c02c5b24>] (dump_stack) from [<c003bca4>] (warn_slowpath_common+0x7c/0xb8) >> [<c003bca4>] (warn_slowpath_common) from [<c003bd7c>] >> (warn_slowpath_null+0x1c/0x24) >> [<c003bd7c>] (warn_slowpath_null) from [<c0337bc8>] >> (uart_handle_cts_change+0x9c/0xd8) >> [<c0337bc8>] (uart_handle_cts_change) from [<c033f430>] >> (mctrl_gpio_irq_handle+0xb0/0xcc) >> [<c033f430>] (mctrl_gpio_irq_handle) from [<c0096db4>] >> (handle_irq_event_percpu+0x50/0x268) >> [<c0096db4>] (handle_irq_event_percpu) from [<c0097004>] >> (handle_irq_event+0x38/0x5c) >> [<c0097004>] (handle_irq_event) from [<c009a3a0>] (handle_edge_irq+0xf0/0x1bc) >> [<c009a3a0>] (handle_edge_irq) from [<c0096438>] (generic_handle_irq+0x20/0x34) >> [<c0096438>] (generic_handle_irq) from [<c0302038>] >> (omap_gpio_irq_handler+0x12c/0x16c) >> [<c0302038>] (omap_gpio_irq_handler) from [<c0096db4>] >> (handle_irq_event_percpu+0x50/0x268) >> [<c0096db4>] (handle_irq_event_percpu) from [<c0097004>] >> (handle_irq_event+0x38/0x5c) >> [<c0097004>] (handle_irq_event) from [<c009a070>] (handle_level_irq+0xb8/0x14c) >> [<c009a070>] (handle_level_irq) from [<c0096438>] (generic_handle_irq+0x20/0x34) >> [<c0096438>] (generic_handle_irq) from [<c009672c>] >> (__handle_domain_irq+0x64/0xe0) >> [<c009672c>] (__handle_domain_irq) from [<c06802f8>] (__irq_svc+0x58/0x78) >> [<c06802f8>] (__irq_svc) from [<c00103a0>] (arch_cpu_idle+0x20/0x3c) >> [<c00103a0>] (arch_cpu_idle) from [<c007fea4>] (cpu_startup_entry+0x2d0/0x358) >> [<c007fea4>] (cpu_startup_entry) from [<c08eac24>] (start_kernel+0x364/0x3e8) >> ---[ end trace 68b3b5769f257e1c ]--- >> >> When I toggle on CTS once more I don't get such an error and for both >> toggle sessions I get the proper CTS value. >> >> Any idea? > > The warning at line drivers/tty/serial/serial_core.c:2893 is > > lockdep_assert_held_once(&uport->lock); > > That means mctrl_gpio_irq_handle lacks some locking. > > I think we need to take port->lock (with irqs off) before > > mctrl = gpios->mctrl_prev > > and drop it before returning. > > Note there is another issue with mctrl-gpio reported with Message-Id: > 1456225442-27184-1-git-send-email-inguin@xxxxxx. Could you add me to CC, if you'll answer to this thread? Thanks. Yegor -- 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