History

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.

Yegor Yefremov committed 7 years ago

Commit 4a968951 parent d9948267 files · +81 −15Browse files

Unified · Split

7 files
  1. Documentation/devicetree/bindings/serial/8250.txt +19 −0
  2. drivers/tty/serial/8250/8250.h +17 −1
  3. drivers/tty/serial/8250/8250_core.c +17 −0
  4. drivers/tty/serial/8250/8250_omap.c +16 −13
  5. drivers/tty/serial/8250/8250_port.c +10 −1
  6. drivers/tty/serial/8250/Kconfig +1 −0
  7. include/linux/serial_8250.h +1 −0
Documentation/devicetree/bindings/serial/8250.txt+19−0
@@ -53,6 +53,9 @@ Optional properties: · 52 unmodified lines
53 programmable TX FIFO thresholds.53 programmable TX FIFO thresholds.
54- resets : phandle + reset specifier pairs54- resets : phandle + reset specifier pairs
55- overrun-throttle-ms : how long to pause uart rx when input overrun is encountered.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
57Note:60Note:
58* fsl,ns16550:61* fsl,ns16550:
@@ -74,3 +77,19 @@ Example: · 15 unmodified lines
74 interrupts = <10>;77 interrupts = <10>;
75 reg-shift = <2>;78 reg-shift = <2>;
76 };79 };
80
81Example 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 };
drivers/tty/serial/8250/8250.h+17−1
@@ -11,6 +11,8 @@ · 10 unmodified lines
11#include <linux/serial_reg.h>11#include <linux/serial_reg.h>
12#include <linux/dmaengine.h>12#include <linux/dmaengine.h>
13 13
14#include "../serial_mctrl_gpio.h"
15
14struct uart_8250_dma {16struct uart_8250_dma {
15 int (*tx_dma)(struct uart_8250_port *p);17 int (*tx_dma)(struct uart_8250_port *p);
16 int (*rx_dma)(struct uart_8250_port *p);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
214static inline void serial8250_out_MCR(struct uart_8250_port *up, int value)216static inline void serial8250_out_MCR(struct uart_8250_port *up, int value)
215{217{
216 serial_out(up, UART_MCR, value);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
219static inline int serial8250_in_MCR(struct uart_8250_port *up)224static 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#if defined(__alpha__) && !defined(CONFIG_PCI)240#if defined(__alpha__) && !defined(CONFIG_PCI)
drivers/tty/serial/8250/8250_core.c+17−0
@@ -14,6 +14,7 @@ · 13 unmodified lines
14 * serial8250_register_8250_port() ports14 * serial8250_register_8250_port() ports
15 */15 */
16 16
17#include <linux/acpi.h>
17#include <linux/module.h>18#include <linux/module.h>
18#include <linux/moduleparam.h>19#include <linux/moduleparam.h>
19#include <linux/ioport.h>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 uart = serial8250_find_match_or_unused(&up->port);984 uart = serial8250_find_match_or_unused(&up->port);
984 if (uart && uart->port.type != PORT_8250_CIR) {985 if (uart && uart->port.type != PORT_8250_CIR) {
986 struct mctrl_gpios *gpios;
987
985 if (uart->port.dev)988 if (uart->port.dev)
986 uart_remove_one_port(&serial8250_reg, &uart->port);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 if (up->port.flags & UPF_FIXED_TYPE)1019 if (up->port.flags & UPF_FIXED_TYPE)
1017 uart->port.type = up->port.type;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 serial8250_set_defaults(uart);1036 serial8250_set_defaults(uart);
1020 1037
1021 /* Possibly override default I/O functions. */1038 /* Possibly override default I/O functions. */
drivers/tty/serial/8250/8250_omap.c+16−13
@@ -141,18 +141,20 @@ static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) · 140 unmodified lines
141 141
142 serial8250_do_set_mctrl(port, mctrl);142 serial8250_do_set_mctrl(port, mctrl);
143 143
144 /*144 if (!up->gpios) {
145 * Turn off autoRTS if RTS is lowered and restore autoRTS setting145 /*
146 * if RTS is raised146 * Turn off autoRTS if RTS is lowered and restore autoRTS
147 */147 * setting if RTS is raised
148 lcr = serial_in(up, UART_LCR);148 */
149 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);149 lcr = serial_in(up, UART_LCR);
150 if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))150 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
151 priv->efr |= UART_EFR_RTS;151 if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
152 else152 priv->efr |= UART_EFR_RTS;
153 priv->efr &= ~UART_EFR_RTS;153 else
154 serial_out(up, UART_EFR, priv->efr);154 priv->efr &= ~UART_EFR_RTS;
155 serial_out(up, UART_LCR, lcr);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 priv->efr = 0;455 priv->efr = 0;
454 up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);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 /* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */460 /* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */
458 up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;461 up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;
459 priv->efr |= UART_EFR_CTS;462 priv->efr |= UART_EFR_CTS;
drivers/tty/serial/8250/8250_port.c+10−1
@@ -1656,6 +1656,8 @@ static void serial8250_disable_ms(struct uart_port *port) · 1655 unmodified lines
1656 if (up->bugs & UART_BUG_NOMSR)1656 if (up->bugs & UART_BUG_NOMSR)
1657 return;1657 return;
1658 1658
1659 mctrl_gpio_disable_ms(up->gpios);
1660
1659 up->ier &= ~UART_IER_MSI;1661 up->ier &= ~UART_IER_MSI;
1660 serial_port_out(port, UART_IER, up->ier);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 if (up->bugs & UART_BUG_NOMSR)1670 if (up->bugs & UART_BUG_NOMSR)
1669 return;1671 return;
1670 1672
1673 mctrl_gpio_enable_ms(up->gpios);
1674
1671 up->ier |= UART_IER_MSI;1675 up->ier |= UART_IER_MSI;
1672 1676
1673 serial8250_rpm_get(up);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 struct uart_8250_port *up = up_to_u8250p(port);1944 struct uart_8250_port *up = up_to_u8250p(port);
1941 unsigned int status;1945 unsigned int status;
1946 unsigned int val;
1942 1947
1943 serial8250_rpm_get(up);1948 serial8250_rpm_get(up);
1944 status = serial8250_modem_status(up);1949 status = serial8250_modem_status(up);
1945 serial8250_rpm_put(up);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}
1949EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl);1958EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl);
1950 1959
drivers/tty/serial/8250/Kconfig+1−0
@@ -8,6 +8,7 @@ config SERIAL_8250 · 7 unmodified lines
8 tristate "8250/16550 and compatible serial support"8 tristate "8250/16550 and compatible serial support"
9 depends on !S3909 depends on !S390
10 select SERIAL_CORE10 select SERIAL_CORE
11 select SERIAL_MCTRL_GPIO if GPIOLIB
11 ---help---12 ---help---
12 This selects whether you want to include the driver for the standard13 This selects whether you want to include the driver for the standard
13 serial ports. The standard answer is Y. People who might say N14 serial ports. The standard answer is Y. People who might say N
include/linux/serial_8250.h+1−0
@@ -110,6 +110,7 @@ struct uart_8250_port { · 109 unmodified lines
110 * if no_console_suspend110 * if no_console_suspend
111 */111 */
112 unsigned char probe;112 unsigned char probe;
113 struct mctrl_gpios *gpios;
113#define UART_PROBE_RSA (1 << 0)114#define UART_PROBE_RSA (1 << 0)
114 115
115 /*116 /*

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t