Re: [RFC] tty/serial/8250: use mctrl_gpio helpers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux