1
0
Fork 0

tty/serial/8250: use mctrl_gpio helpers

This patch permits the usage for GPIOs to control
the CTS/RTS/DTR/DSR/DCD/RI signals.

Changed by Stefan:
Only call mctrl_gpio_init(), if the device has no ACPI companion device
to not break existing ACPI based systems. Also only use the mctrl_gpio_
functions when "gpios" is available.

Use MSR / MCR <-> TIOCM wrapper functions.

Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
Signed-off-by: Stefan Roese <sr@denx.de>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Tested-by: Yegor Yefremov <yegorslists@googlemail.com>
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Giulio Benetti <giulio.benetti@micronovasrl.com>
Cc: Yegor Yefremov <yegorslists@googlemail.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
alistair/sunxi64-5.4-dsi
Yegor Yefremov 2019-06-20 08:24:20 +02:00 committed by Greg Kroah-Hartman
parent d99482673f
commit 4a96895f74
7 changed files with 81 additions and 15 deletions

View File

@ -53,6 +53,9 @@ Optional properties:
programmable TX FIFO thresholds. programmable TX FIFO thresholds.
- resets : phandle + reset specifier pairs - resets : phandle + reset specifier pairs
- overrun-throttle-ms : how long to pause uart rx when input overrun is encountered. - overrun-throttle-ms : how long to pause uart rx when input overrun is encountered.
- {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: Note:
* fsl,ns16550: * fsl,ns16550:
@ -74,3 +77,19 @@ Example:
interrupts = <10>; interrupts = <10>;
reg-shift = <2>; 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>;
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>;
};

View File

@ -11,6 +11,8 @@
#include <linux/serial_reg.h> #include <linux/serial_reg.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include "../serial_mctrl_gpio.h"
struct uart_8250_dma { struct uart_8250_dma {
int (*tx_dma)(struct uart_8250_port *p); int (*tx_dma)(struct uart_8250_port *p);
int (*rx_dma)(struct uart_8250_port *p); int (*rx_dma)(struct uart_8250_port *p);
@ -214,11 +216,25 @@ static inline int serial8250_MSR_to_TIOCM(int msr)
static inline void serial8250_out_MCR(struct uart_8250_port *up, int value) static inline void serial8250_out_MCR(struct uart_8250_port *up, int value)
{ {
serial_out(up, UART_MCR, value); serial_out(up, UART_MCR, value);
if (up->gpios)
mctrl_gpio_set(up->gpios, serial8250_MCR_to_TIOCM(value));
} }
static inline int serial8250_in_MCR(struct uart_8250_port *up) static inline int serial8250_in_MCR(struct uart_8250_port *up)
{ {
return serial_in(up, UART_MCR); int mctrl;
mctrl = serial_in(up, UART_MCR);
if (up->gpios) {
unsigned int mctrl_gpio = 0;
mctrl_gpio = mctrl_gpio_get_outputs(up->gpios, &mctrl_gpio);
mctrl |= serial8250_TIOCM_to_MCR(mctrl_gpio);
}
return mctrl;
} }
#if defined(__alpha__) && !defined(CONFIG_PCI) #if defined(__alpha__) && !defined(CONFIG_PCI)

View File

@ -14,6 +14,7 @@
* serial8250_register_8250_port() ports * serial8250_register_8250_port() ports
*/ */
#include <linux/acpi.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/ioport.h> #include <linux/ioport.h>
@ -982,6 +983,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
uart = serial8250_find_match_or_unused(&up->port); uart = serial8250_find_match_or_unused(&up->port);
if (uart && uart->port.type != PORT_8250_CIR) { if (uart && uart->port.type != PORT_8250_CIR) {
struct mctrl_gpios *gpios;
if (uart->port.dev) if (uart->port.dev)
uart_remove_one_port(&serial8250_reg, &uart->port); uart_remove_one_port(&serial8250_reg, &uart->port);
@ -1016,6 +1019,20 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
if (up->port.flags & UPF_FIXED_TYPE) if (up->port.flags & UPF_FIXED_TYPE)
uart->port.type = up->port.type; uart->port.type = up->port.type;
/*
* Only call mctrl_gpio_init(), if the device has no ACPI
* companion device
*/
if (!has_acpi_companion(uart->port.dev)) {
gpios = mctrl_gpio_init(&uart->port, 0);
if (IS_ERR(gpios)) {
if (PTR_ERR(gpios) != -ENOSYS)
return PTR_ERR(gpios);
} else {
uart->gpios = gpios;
}
}
serial8250_set_defaults(uart); serial8250_set_defaults(uart);
/* Possibly override default I/O functions. */ /* Possibly override default I/O functions. */

View File

@ -141,18 +141,20 @@ static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
serial8250_do_set_mctrl(port, mctrl); serial8250_do_set_mctrl(port, mctrl);
/* if (!up->gpios) {
* Turn off autoRTS if RTS is lowered and restore autoRTS setting /*
* if RTS is raised * Turn off autoRTS if RTS is lowered and restore autoRTS
*/ * setting if RTS is raised
lcr = serial_in(up, UART_LCR); */
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); lcr = serial_in(up, UART_LCR);
if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS)) serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
priv->efr |= UART_EFR_RTS; if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
else priv->efr |= UART_EFR_RTS;
priv->efr &= ~UART_EFR_RTS; else
serial_out(up, UART_EFR, priv->efr); priv->efr &= ~UART_EFR_RTS;
serial_out(up, UART_LCR, lcr); serial_out(up, UART_EFR, priv->efr);
serial_out(up, UART_LCR, lcr);
}
} }
/* /*
@ -453,7 +455,8 @@ static void omap_8250_set_termios(struct uart_port *port,
priv->efr = 0; priv->efr = 0;
up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) { if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW &&
!up->gpios) {
/* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */ /* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */
up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;
priv->efr |= UART_EFR_CTS; priv->efr |= UART_EFR_CTS;

View File

@ -1656,6 +1656,8 @@ static void serial8250_disable_ms(struct uart_port *port)
if (up->bugs & UART_BUG_NOMSR) if (up->bugs & UART_BUG_NOMSR)
return; return;
mctrl_gpio_disable_ms(up->gpios);
up->ier &= ~UART_IER_MSI; up->ier &= ~UART_IER_MSI;
serial_port_out(port, UART_IER, up->ier); serial_port_out(port, UART_IER, up->ier);
} }
@ -1668,6 +1670,8 @@ static void serial8250_enable_ms(struct uart_port *port)
if (up->bugs & UART_BUG_NOMSR) if (up->bugs & UART_BUG_NOMSR)
return; return;
mctrl_gpio_enable_ms(up->gpios);
up->ier |= UART_IER_MSI; up->ier |= UART_IER_MSI;
serial8250_rpm_get(up); serial8250_rpm_get(up);
@ -1939,12 +1943,17 @@ unsigned int serial8250_do_get_mctrl(struct uart_port *port)
{ {
struct uart_8250_port *up = up_to_u8250p(port); struct uart_8250_port *up = up_to_u8250p(port);
unsigned int status; unsigned int status;
unsigned int val;
serial8250_rpm_get(up); serial8250_rpm_get(up);
status = serial8250_modem_status(up); status = serial8250_modem_status(up);
serial8250_rpm_put(up); serial8250_rpm_put(up);
return serial8250_MSR_to_TIOCM(status); val = serial8250_MSR_to_TIOCM(status);
if (up->gpios)
return mctrl_gpio_get(up->gpios, &val);
return val;
} }
EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl); EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl);

View File

@ -8,6 +8,7 @@ config SERIAL_8250
tristate "8250/16550 and compatible serial support" tristate "8250/16550 and compatible serial support"
depends on !S390 depends on !S390
select SERIAL_CORE select SERIAL_CORE
select SERIAL_MCTRL_GPIO if GPIOLIB
---help--- ---help---
This selects whether you want to include the driver for the standard This selects whether you want to include the driver for the standard
serial ports. The standard answer is Y. People who might say N serial ports. The standard answer is Y. People who might say N

View File

@ -110,6 +110,7 @@ struct uart_8250_port {
* if no_console_suspend * if no_console_suspend
*/ */
unsigned char probe; unsigned char probe;
struct mctrl_gpios *gpios;
#define UART_PROBE_RSA (1 << 0) #define UART_PROBE_RSA (1 << 0)
/* /*