aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ath79/patches-4.19/0061-tty-serial-ar933x-uart-rs485-gpio.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ath79/patches-4.19/0061-tty-serial-ar933x-uart-rs485-gpio.patch')
-rw-r--r--target/linux/ath79/patches-4.19/0061-tty-serial-ar933x-uart-rs485-gpio.patch267
1 files changed, 0 insertions, 267 deletions
diff --git a/target/linux/ath79/patches-4.19/0061-tty-serial-ar933x-uart-rs485-gpio.patch b/target/linux/ath79/patches-4.19/0061-tty-serial-ar933x-uart-rs485-gpio.patch
deleted file mode 100644
index b77cd2d574..0000000000
--- a/target/linux/ath79/patches-4.19/0061-tty-serial-ar933x-uart-rs485-gpio.patch
+++ /dev/null
@@ -1,267 +0,0 @@
-From patchwork Fri Feb 21 21:23:31 2020
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
-X-Patchwork-Id: 1198835
-Date: Fri, 21 Feb 2020 22:23:31 +0100
-From: Daniel Golle <daniel@makrotopia.org>
-To: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org
-Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
- Jiri Slaby <jslaby@suse.com>, Petr =?utf-8?q?=C5=A0tetiar?= <ynezz@true.cz>,
- Chuanhong Guo <gch981213@gmail.com>, Piotr Dymacz <pepe2k@gmail.com>
-Subject: [PATCH v2] serial: ar933x_uart: add RS485 support
-Message-ID: <20200221212331.GA21467@makrotopia.org>
-MIME-Version: 1.0
-Content-Disposition: inline
-Sender: linux-kernel-owner@vger.kernel.org
-Precedence: bulk
-List-ID: <linux-kernel.vger.kernel.org>
-X-Mailing-List: linux-kernel@vger.kernel.org
-
-Emulate half-duplex operation and use mctrl_gpio to add support for
-RS485 tranceiver with transmit/receive switch hooked to RTS GPIO line.
-This is needed to make use of the RS485 port found on Teltonika RUT955.
-
-Signed-off-by: Daniel Golle <daniel@makrotopia.org>
----
-v2: use bool to indicate ongoing half-duplex send, use it afterwards
- to decide whether we've just been in a send operation.
-
- drivers/tty/serial/Kconfig | 1 +
- drivers/tty/serial/ar933x_uart.c | 113 +++++++++++++++++++++++++++++--
- 2 files changed, 108 insertions(+), 6 deletions(-)
-
---- a/drivers/tty/serial/Kconfig
-+++ b/drivers/tty/serial/Kconfig
-@@ -1296,6 +1296,7 @@ config SERIAL_AR933X
- tristate "AR933X serial port support"
- depends on HAVE_CLK && ATH79
- select SERIAL_CORE
-+ select SERIAL_MCTRL_GPIO if GPIOLIB
- help
- If you have an Atheros AR933X SOC based board and want to use the
- built-in UART of the SoC, say Y to this option.
---- a/drivers/tty/serial/ar933x_uart.c
-+++ b/drivers/tty/serial/ar933x_uart.c
-@@ -13,6 +13,7 @@
- #include <linux/console.h>
- #include <linux/sysrq.h>
- #include <linux/delay.h>
-+#include <linux/gpio/consumer.h>
- #include <linux/platform_device.h>
- #include <linux/of.h>
- #include <linux/of_platform.h>
-@@ -29,6 +30,8 @@
-
- #include <asm/mach-ath79/ar933x_uart.h>
-
-+#include "serial_mctrl_gpio.h"
-+
- #define DRIVER_NAME "ar933x-uart"
-
- #define AR933X_UART_MAX_SCALE 0xff
-@@ -47,6 +50,8 @@ struct ar933x_uart_port {
- unsigned int min_baud;
- unsigned int max_baud;
- struct clk *clk;
-+ struct mctrl_gpios *gpios;
-+ struct gpio_desc *rts_gpiod;
- };
-
- static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
-@@ -100,6 +105,18 @@ static inline void ar933x_uart_stop_tx_i
- ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
- }
-
-+static inline void ar933x_uart_start_rx_interrupt(struct ar933x_uart_port *up)
-+{
-+ up->ier |= AR933X_UART_INT_RX_VALID;
-+ ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
-+}
-+
-+static inline void ar933x_uart_stop_rx_interrupt(struct ar933x_uart_port *up)
-+{
-+ up->ier &= ~AR933X_UART_INT_RX_VALID;
-+ ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
-+}
-+
- static inline void ar933x_uart_putc(struct ar933x_uart_port *up, int ch)
- {
- unsigned int rdata;
-@@ -125,11 +142,21 @@ static unsigned int ar933x_uart_tx_empty
-
- static unsigned int ar933x_uart_get_mctrl(struct uart_port *port)
- {
-- return TIOCM_CAR;
-+ struct ar933x_uart_port *up =
-+ container_of(port, struct ar933x_uart_port, port);
-+ int ret = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
-+
-+ mctrl_gpio_get(up->gpios, &ret);
-+
-+ return ret;
- }
-
- static void ar933x_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
- {
-+ struct ar933x_uart_port *up =
-+ container_of(port, struct ar933x_uart_port, port);
-+
-+ mctrl_gpio_set(up->gpios, mctrl);
- }
-
- static void ar933x_uart_start_tx(struct uart_port *port)
-@@ -140,6 +167,37 @@ static void ar933x_uart_start_tx(struct
- ar933x_uart_start_tx_interrupt(up);
- }
-
-+static void ar933x_uart_wait_tx_complete(struct ar933x_uart_port *up)
-+{
-+ unsigned int status;
-+ unsigned int timeout = 60000;
-+
-+ /* Wait up to 60ms for the character(s) to be sent. */
-+ do {
-+ status = ar933x_uart_read(up, AR933X_UART_CS_REG);
-+ if (--timeout == 0)
-+ break;
-+ udelay(1);
-+ } while (status & AR933X_UART_CS_TX_BUSY);
-+
-+ if (timeout == 0)
-+ dev_err(up->port.dev, "waiting for TX timed out\n");
-+}
-+
-+static void ar933x_uart_rx_flush(struct ar933x_uart_port *up)
-+{
-+ unsigned int status;
-+
-+ /* clear RX_VALID interrupt */
-+ ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_RX_VALID);
-+
-+ /* remove characters from the RX FIFO */
-+ do {
-+ ar933x_uart_write(up, AR933X_UART_DATA_REG, AR933X_UART_DATA_RX_CSR);
-+ status = ar933x_uart_read(up, AR933X_UART_DATA_REG);
-+ } while (status & AR933X_UART_DATA_RX_CSR);
-+}
-+
- static void ar933x_uart_stop_tx(struct uart_port *port)
- {
- struct ar933x_uart_port *up =
-@@ -153,8 +211,7 @@ static void ar933x_uart_stop_rx(struct u
- struct ar933x_uart_port *up =
- container_of(port, struct ar933x_uart_port, port);
-
-- up->ier &= ~AR933X_UART_INT_RX_VALID;
-- ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
-+ ar933x_uart_stop_rx_interrupt(up);
- }
-
- static void ar933x_uart_break_ctl(struct uart_port *port, int break_state)
-@@ -340,11 +397,20 @@ static void ar933x_uart_rx_chars(struct
- static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
- {
- struct circ_buf *xmit = &up->port.state->xmit;
-+ struct serial_rs485 *rs485conf = &up->port.rs485;
- int count;
-+ bool half_duplex_send = false;
-
- if (uart_tx_stopped(&up->port))
- return;
-
-+ if ((rs485conf->flags & SER_RS485_ENABLED) &&
-+ (up->port.x_char || !uart_circ_empty(xmit))) {
-+ ar933x_uart_stop_rx_interrupt(up);
-+ gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_ON_SEND));
-+ half_duplex_send = true;
-+ }
-+
- count = up->port.fifosize;
- do {
- unsigned int rdata;
-@@ -372,8 +438,14 @@ static void ar933x_uart_tx_chars(struct
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
-- if (!uart_circ_empty(xmit))
-+ if (!uart_circ_empty(xmit)) {
- ar933x_uart_start_tx_interrupt(up);
-+ } else if (half_duplex_send) {
-+ ar933x_uart_wait_tx_complete(up);
-+ ar933x_uart_rx_flush(up);
-+ ar933x_uart_start_rx_interrupt(up);
-+ gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_AFTER_SEND));
-+ }
- }
-
- static irqreturn_t ar933x_uart_interrupt(int irq, void *dev_id)
-@@ -435,8 +507,7 @@ static int ar933x_uart_startup(struct ua
- AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE);
-
- /* Enable RX interrupts */
-- up->ier = AR933X_UART_INT_RX_VALID;
-- ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
-+ ar933x_uart_start_rx_interrupt(up);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-
-@@ -519,6 +590,21 @@ static const struct uart_ops ar933x_uart
- .verify_port = ar933x_uart_verify_port,
- };
-
-+static int ar933x_config_rs485(struct uart_port *port,
-+ struct serial_rs485 *rs485conf)
-+{
-+ struct ar933x_uart_port *up =
-+ container_of(port, struct ar933x_uart_port, port);
-+
-+ if ((rs485conf->flags & SER_RS485_ENABLED) &&
-+ !up->rts_gpiod) {
-+ dev_err(port->dev, "RS485 needs rts-gpio\n");
-+ return 1;
-+ }
-+ port->rs485 = *rs485conf;
-+ return 0;
-+}
-+
- #ifdef CONFIG_SERIAL_AR933X_CONSOLE
- static struct ar933x_uart_port *
- ar933x_console_ports[CONFIG_SERIAL_AR933X_NR_UARTS];
-@@ -688,6 +774,8 @@ static int ar933x_uart_probe(struct plat
- goto err_disable_clk;
- }
-
-+ uart_get_rs485_mode(&pdev->dev, &port->rs485);
-+
- port->mapbase = mem_res->start;
- port->line = id;
- port->irq = irq_res->start;
-@@ -698,6 +786,7 @@ static int ar933x_uart_probe(struct plat
- port->regshift = 2;
- port->fifosize = AR933X_UART_FIFO_SIZE;
- port->ops = &ar933x_uart_ops;
-+ port->rs485_config = ar933x_config_rs485;
-
- baud = ar933x_uart_get_baud(port->uartclk, AR933X_UART_MAX_SCALE, 1);
- up->min_baud = max_t(unsigned int, baud, AR933X_UART_MIN_BAUD);
-@@ -705,6 +794,18 @@ static int ar933x_uart_probe(struct plat
- baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP);
- up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD);
-
-+ up->gpios = mctrl_gpio_init(port, 0);
-+ if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS)
-+ return PTR_ERR(up->gpios);
-+
-+ up->rts_gpiod = mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS);
-+
-+ if ((port->rs485.flags & SER_RS485_ENABLED) &&
-+ !up->rts_gpiod) {
-+ dev_err(&pdev->dev, "lacking rts-gpio, disabling RS485\n");
-+ port->rs485.flags &= ~SER_RS485_ENABLED;
-+ }
-+
- #ifdef CONFIG_SERIAL_AR933X_CONSOLE
- ar933x_console_ports[up->port.line] = up;
- #endif