Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Yegor Yefremov and committed by
Greg Kroah-Hartman
4a96895f d9948267

+81 -15
+19
Documentation/devicetree/bindings/serial/8250.txt
··· 53 53 programmable TX FIFO thresholds. 54 54 - resets : phandle + reset specifier pairs 55 55 - overrun-throttle-ms : how long to pause uart rx when input overrun is encountered. 56 + - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD 57 + line respectively. It will use specified GPIO instead of the peripheral 58 + function pin for the UART feature. If unsure, don't specify this property. 56 59 57 60 Note: 58 61 * fsl,ns16550: ··· 76 73 clock-frequency = <3686400>; 77 74 interrupts = <10>; 78 75 reg-shift = <2>; 76 + }; 77 + 78 + Example for OMAP UART using GPIO-based modem control signals: 79 + 80 + uart4: serial@49042000 { 81 + compatible = "ti,omap3-uart"; 82 + reg = <0x49042000 0x400>; 83 + interrupts = <80>; 84 + ti,hwmods = "uart4"; 85 + clock-frequency = <48000000>; 86 + cts-gpios = <&gpio3 5 GPIO_ACTIVE_LOW>; 87 + rts-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>; 88 + dtr-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; 89 + dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; 90 + dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; 91 + rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; 79 92 };
+17 -1
drivers/tty/serial/8250/8250.h
··· 11 11 #include <linux/serial_reg.h> 12 12 #include <linux/dmaengine.h> 13 13 14 + #include "../serial_mctrl_gpio.h" 15 + 14 16 struct uart_8250_dma { 15 17 int (*tx_dma)(struct uart_8250_port *p); 16 18 int (*rx_dma)(struct uart_8250_port *p); ··· 216 214 static inline void serial8250_out_MCR(struct uart_8250_port *up, int value) 217 215 { 218 216 serial_out(up, UART_MCR, value); 217 + 218 + if (up->gpios) 219 + mctrl_gpio_set(up->gpios, serial8250_MCR_to_TIOCM(value)); 219 220 } 220 221 221 222 static inline int serial8250_in_MCR(struct uart_8250_port *up) 222 223 { 223 - return serial_in(up, UART_MCR); 224 + int mctrl; 225 + 226 + mctrl = serial_in(up, UART_MCR); 227 + 228 + if (up->gpios) { 229 + unsigned int mctrl_gpio = 0; 230 + 231 + mctrl_gpio = mctrl_gpio_get_outputs(up->gpios, &mctrl_gpio); 232 + mctrl |= serial8250_TIOCM_to_MCR(mctrl_gpio); 233 + } 234 + 235 + return mctrl; 224 236 } 225 237 226 238 #if defined(__alpha__) && !defined(CONFIG_PCI)
+17
drivers/tty/serial/8250/8250_core.c
··· 14 14 * serial8250_register_8250_port() ports 15 15 */ 16 16 17 + #include <linux/acpi.h> 17 18 #include <linux/module.h> 18 19 #include <linux/moduleparam.h> 19 20 #include <linux/ioport.h> ··· 983 982 984 983 uart = serial8250_find_match_or_unused(&up->port); 985 984 if (uart && uart->port.type != PORT_8250_CIR) { 985 + struct mctrl_gpios *gpios; 986 + 986 987 if (uart->port.dev) 987 988 uart_remove_one_port(&serial8250_reg, &uart->port); 988 989 ··· 1018 1015 1019 1016 if (up->port.flags & UPF_FIXED_TYPE) 1020 1017 uart->port.type = up->port.type; 1018 + 1019 + /* 1020 + * Only call mctrl_gpio_init(), if the device has no ACPI 1021 + * companion device 1022 + */ 1023 + if (!has_acpi_companion(uart->port.dev)) { 1024 + gpios = mctrl_gpio_init(&uart->port, 0); 1025 + if (IS_ERR(gpios)) { 1026 + if (PTR_ERR(gpios) != -ENOSYS) 1027 + return PTR_ERR(gpios); 1028 + } else { 1029 + uart->gpios = gpios; 1030 + } 1031 + } 1021 1032 1022 1033 serial8250_set_defaults(uart); 1023 1034
+16 -13
drivers/tty/serial/8250/8250_omap.c
··· 141 141 142 142 serial8250_do_set_mctrl(port, mctrl); 143 143 144 - /* 145 - * Turn off autoRTS if RTS is lowered and restore autoRTS setting 146 - * if RTS is raised 147 - */ 148 - lcr = serial_in(up, UART_LCR); 149 - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 150 - if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS)) 151 - priv->efr |= UART_EFR_RTS; 152 - else 153 - priv->efr &= ~UART_EFR_RTS; 154 - serial_out(up, UART_EFR, priv->efr); 155 - serial_out(up, UART_LCR, lcr); 144 + if (!up->gpios) { 145 + /* 146 + * Turn off autoRTS if RTS is lowered and restore autoRTS 147 + * setting if RTS is raised 148 + */ 149 + lcr = serial_in(up, UART_LCR); 150 + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 151 + if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS)) 152 + priv->efr |= UART_EFR_RTS; 153 + else 154 + priv->efr &= ~UART_EFR_RTS; 155 + serial_out(up, UART_EFR, priv->efr); 156 + serial_out(up, UART_LCR, lcr); 157 + } 156 158 } 157 159 158 160 /* ··· 455 453 priv->efr = 0; 456 454 up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); 457 455 458 - if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) { 456 + if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW && 457 + !up->gpios) { 459 458 /* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */ 460 459 up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; 461 460 priv->efr |= UART_EFR_CTS;
+10 -1
drivers/tty/serial/8250/8250_port.c
··· 1656 1656 if (up->bugs & UART_BUG_NOMSR) 1657 1657 return; 1658 1658 1659 + mctrl_gpio_disable_ms(up->gpios); 1660 + 1659 1661 up->ier &= ~UART_IER_MSI; 1660 1662 serial_port_out(port, UART_IER, up->ier); 1661 1663 } ··· 1669 1667 /* no MSR capabilities */ 1670 1668 if (up->bugs & UART_BUG_NOMSR) 1671 1669 return; 1670 + 1671 + mctrl_gpio_enable_ms(up->gpios); 1672 1672 1673 1673 up->ier |= UART_IER_MSI; 1674 1674 ··· 1943 1939 { 1944 1940 struct uart_8250_port *up = up_to_u8250p(port); 1945 1941 unsigned int status; 1942 + unsigned int val; 1946 1943 1947 1944 serial8250_rpm_get(up); 1948 1945 status = serial8250_modem_status(up); 1949 1946 serial8250_rpm_put(up); 1950 1947 1951 - return serial8250_MSR_to_TIOCM(status); 1948 + val = serial8250_MSR_to_TIOCM(status); 1949 + if (up->gpios) 1950 + return mctrl_gpio_get(up->gpios, &val); 1951 + 1952 + return val; 1952 1953 } 1953 1954 EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl); 1954 1955
+1
drivers/tty/serial/8250/Kconfig
··· 8 8 tristate "8250/16550 and compatible serial support" 9 9 depends on !S390 10 10 select SERIAL_CORE 11 + select SERIAL_MCTRL_GPIO if GPIOLIB 11 12 ---help--- 12 13 This selects whether you want to include the driver for the standard 13 14 serial ports. The standard answer is Y. People who might say N
+1
include/linux/serial_8250.h
··· 110 110 * if no_console_suspend 111 111 */ 112 112 unsigned char probe; 113 + struct mctrl_gpios *gpios; 113 114 #define UART_PROBE_RSA (1 << 0) 114 115 115 116 /*