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.
Unified · Split
| @@ -53,6 +53,9 @@ Optional properties: · 52 unmodified lines | ||
| 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: |
| @@ -74,3 +77,19 @@ Example: · 15 unmodified lines | ||
| 74 | 77 | interrupts = <10>; |
| 75 | 78 | reg-shift = <2>; |
| 76 | 79 | }; |
| 80 | + | |
| 81 | +Example for OMAP UART using GPIO-based modem control signals: | |
| 82 | + | |
| 83 | + uart4: serial@49042000 { | |
| 84 | + compatible = "ti,omap3-uart"; | |
| 85 | + reg = <0x49042000 0x400>; | |
| 86 | + interrupts = <80>; | |
| 87 | + ti,hwmods = "uart4"; | |
| 88 | + clock-frequency = <48000000>; | |
| 89 | + cts-gpios = <&gpio3 5 GPIO_ACTIVE_LOW>; | |
| 90 | + rts-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>; | |
| 91 | + dtr-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; | |
| 92 | + dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; | |
| 93 | + dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; | |
| 94 | + rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; | |
| 95 | + }; | |
| @@ -11,6 +11,8 @@ · 10 unmodified lines | ||
| 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); |
| @@ -214,11 +216,25 @@ static inline int serial8250_MSR_to_TIOCM(int msr) · 197 unmodified lines | ||
| 214 | 216 | static inline void serial8250_out_MCR(struct uart_8250_port *up, int value) |
| 215 | 217 | { |
| 216 | 218 | serial_out(up, UART_MCR, value); |
| 219 | + | |
| 220 | + if (up->gpios) | |
| 221 | + mctrl_gpio_set(up->gpios, serial8250_MCR_to_TIOCM(value)); | |
| 217 | 222 | } |
| 218 | 223 | |
| 219 | 224 | static inline int serial8250_in_MCR(struct uart_8250_port *up) |
| 220 | 225 | { |
| 221 | − return serial_in(up, UART_MCR); | |
| 226 | + int mctrl; | |
| 227 | + | |
| 228 | + mctrl = serial_in(up, UART_MCR); | |
| 229 | + | |
| 230 | + if (up->gpios) { | |
| 231 | + unsigned int mctrl_gpio = 0; | |
| 232 | + | |
| 233 | + mctrl_gpio = mctrl_gpio_get_outputs(up->gpios, &mctrl_gpio); | |
| 234 | + mctrl |= serial8250_TIOCM_to_MCR(mctrl_gpio); | |
| 235 | + } | |
| 236 | + | |
| 237 | + return mctrl; | |
| 222 | 238 | } |
| 223 | 239 | |
| 224 | 240 | #if defined(__alpha__) && !defined(CONFIG_PCI) |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 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> |
| @@ -982,6 +983,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up) · 962 unmodified lines | ||
| 982 | 983 | |
| 983 | 984 | uart = serial8250_find_match_or_unused(&up->port); |
| 984 | 985 | if (uart && uart->port.type != PORT_8250_CIR) { |
| 986 | + struct mctrl_gpios *gpios; | |
| 987 | + | |
| 985 | 988 | if (uart->port.dev) |
| 986 | 989 | uart_remove_one_port(&serial8250_reg, &uart->port); |
| 987 | 990 | |
| @@ -1016,6 +1019,20 @@ int serial8250_register_8250_port(struct uart_8250_port *up) · 28 unmodified lines | ||
| 1016 | 1019 | if (up->port.flags & UPF_FIXED_TYPE) |
| 1017 | 1020 | uart->port.type = up->port.type; |
| 1018 | 1021 | |
| 1022 | + /* | |
| 1023 | + * Only call mctrl_gpio_init(), if the device has no ACPI | |
| 1024 | + * companion device | |
| 1025 | + */ | |
| 1026 | + if (!has_acpi_companion(uart->port.dev)) { | |
| 1027 | + gpios = mctrl_gpio_init(&uart->port, 0); | |
| 1028 | + if (IS_ERR(gpios)) { | |
| 1029 | + if (PTR_ERR(gpios) != -ENOSYS) | |
| 1030 | + return PTR_ERR(gpios); | |
| 1031 | + } else { | |
| 1032 | + uart->gpios = gpios; | |
| 1033 | + } | |
| 1034 | + } | |
| 1035 | + | |
| 1019 | 1036 | serial8250_set_defaults(uart); |
| 1020 | 1037 | |
| 1021 | 1038 | /* Possibly override default I/O functions. */ |
| @@ -141,18 +141,20 @@ static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) · 140 unmodified lines | ||
| 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 | /* |
| @@ -453,7 +455,8 @@ static void omap_8250_set_termios(struct uart_port *port, · 294 unmodified lines | ||
| 453 | 455 | priv->efr = 0; |
| 454 | 456 | up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); |
| 455 | 457 | |
| 456 | − if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) { | |
| 458 | + if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW && | |
| 459 | + !up->gpios) { | |
| 457 | 460 | /* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */ |
| 458 | 461 | up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; |
| 459 | 462 | priv->efr |= UART_EFR_CTS; |
| @@ -1656,6 +1656,8 @@ static void serial8250_disable_ms(struct uart_port *port) · 1655 unmodified lines | ||
| 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 | } |
| @@ -1668,6 +1670,8 @@ static void serial8250_enable_ms(struct uart_port *port) · 6 unmodified lines | ||
| 1668 | 1670 | if (up->bugs & UART_BUG_NOMSR) |
| 1669 | 1671 | return; |
| 1670 | 1672 | |
| 1673 | + mctrl_gpio_enable_ms(up->gpios); | |
| 1674 | + | |
| 1671 | 1675 | up->ier |= UART_IER_MSI; |
| 1672 | 1676 | |
| 1673 | 1677 | serial8250_rpm_get(up); |
| @@ -1939,12 +1943,17 @@ unsigned int serial8250_do_get_mctrl(struct uart_port *port) · 265 unmodified lines | ||
| 1939 | 1943 | { |
| 1940 | 1944 | struct uart_8250_port *up = up_to_u8250p(port); |
| 1941 | 1945 | unsigned int status; |
| 1946 | + unsigned int val; | |
| 1942 | 1947 | |
| 1943 | 1948 | serial8250_rpm_get(up); |
| 1944 | 1949 | status = serial8250_modem_status(up); |
| 1945 | 1950 | serial8250_rpm_put(up); |
| 1946 | 1951 | |
| 1947 | − return serial8250_MSR_to_TIOCM(status); | |
| 1952 | + val = serial8250_MSR_to_TIOCM(status); | |
| 1953 | + if (up->gpios) | |
| 1954 | + return mctrl_gpio_get(up->gpios, &val); | |
| 1955 | + | |
| 1956 | + return val; | |
| 1948 | 1957 | } |
| 1949 | 1958 | EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl); |
| 1950 | 1959 | |
| @@ -8,6 +8,7 @@ config SERIAL_8250 · 7 unmodified lines | ||
| 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 |
| @@ -110,6 +110,7 @@ struct uart_8250_port { · 109 unmodified lines | ||
| 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 | /* |