[OpenWrt-Devel] [PATCH v2 1/2] ath79: ar9330-uart: add support for half-duplex using DTR signal

Karl Palsson karlp at tweak.net.au
Tue Feb 11 09:21:30 EST 2020


Is there any reason why we can't implement the required peices to
use upstreams rs485 support instead of just redoing it the way
that Teltonika bolted it in? From past attempts this sort of
change would never be allowed upstream as is. Your device using
DTR would just have a binding of "rts-gpios: dtr-gpio-pin-id" And
anyone else on ath79 who wants to use rs485 can then use their
own gpios, instead of hardcoded DTR like you have here.

Sincerely,
Karl Palsson

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/serial/rs485.yaml
and
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/serial/serial.txt

(Apologies if people are getting this a third time, I've been
attempting to coerce spamhaus into allowing me to send email, and
i've not seen any replies to my earlier posts anyway)

Daniel Golle <daniel at makrotopia.org> wrote:
> Add support for RS485 tranceiver with transmit/receive switch
> hooked to the DTR GPIO. This is how RS485 is implemented on the
> Teltonika RUT955 device and this patch immitates the behaviour
> of the driver found in their SDK[1].
> 
> [1]:
> https://wiki.teltonika.lt/gpl/RUT9XX_R_GPL_00.06.05.3.tar.gz
> Signed-off-by: Daniel Golle <daniel at makrotopia.org>
> ---
>  ...41-tty-serial-ar933x-uart-rs485-gpio.patch | 129 ++++++++++++++++++
>  1 file changed, 129 insertions(+)
>  create mode 100644 target/linux/ath79/patches-4.19/0041-tty-serial-ar933x-uart-rs485-gpio.patch
> 
> diff --git
> a/target/linux/ath79/patches-4.19/0041-tty-serial-ar933x-uart-rs485-gpio.patch
> b/target/linux/ath79/patches-4.19/0041-tty-serial-ar933x-uart-rs485-gpio.patch
> new file mode 100644 index 0000000000..2b6b32be26
> --- /dev/null
> +++ b/target/linux/ath79/patches-4.19/0041-tty-serial-ar933x-uart-rs485-gpio.patch
> @@ -0,0 +1,129 @@
> +--- 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,7 @@ struct ar933x_uart_port {
> + 	unsigned int		min_baud;
> + 	unsigned int		max_baud;
> + 	struct clk		*clk;
> ++	struct mctrl_gpios	*gpios;
> + };
> + 
> + static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
> +@@ -103,10 +107,48 @@ static inline void ar933x_uart_stop_tx_i
> + static inline void ar933x_uart_putc(struct ar933x_uart_port *up, int ch)
> + {
> + 	unsigned int rdata;
> ++	unsigned int timeout = 60000;
> ++	unsigned long flags;
> ++	unsigned int status;
> ++	struct serial_rs485 *rs485conf = &up->port.rs485;
> ++	struct gpio_desc *dtr_gpio = mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_DTR);
> + 
> + 	rdata = ch & AR933X_UART_DATA_TX_RX_MASK;
> + 	rdata |= AR933X_UART_DATA_TX_CSR;
> +-	ar933x_uart_write(up, AR933X_UART_DATA_REG, rdata);
> ++
> ++	if (rs485conf->flags & SER_RS485_ENABLED) {
> ++		/* Disable RX interrupt */
> ++		spin_lock_irqsave(&up->port.lock, flags);
> ++		up->ier &= ~AR933X_UART_INT_RX_VALID;
> ++		ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
> ++
> ++		if (!IS_ERR_OR_NULL(dtr_gpio))
> ++			gpiod_set_value(dtr_gpio, 0);
> ++
> ++		ar933x_uart_write(up, AR933X_UART_DATA_REG, rdata);
> ++
> ++		/* wait for transmission to end */
> ++		do {
> ++			status = ar933x_uart_read(up, AR933X_UART_CS_REG);
> ++			if (--timeout == 0)
> ++				break;
> ++			udelay(1);
> ++		} while ((status & AR933X_UART_CS_TX_BUSY) != 0);
> ++
> ++		ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_RX_VALID);
> ++		/* remove the character from the FIFO */
> ++		ar933x_uart_write(up, AR933X_UART_DATA_REG, AR933X_UART_DATA_RX_CSR);
> ++		/* Enable RX interrupt */
> ++		up->ier |= AR933X_UART_INT_RX_VALID;
> ++		ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
> ++
> ++		if (!IS_ERR_OR_NULL(dtr_gpio))
> ++			gpiod_set_value(dtr_gpio, 1);
> ++
> ++		spin_unlock_irqrestore(&up->port.lock, flags);
> ++	} else {
> ++		ar933x_uart_write(up, AR933X_UART_DATA_REG, rdata);
> ++	}
> + }
> + 
> + static unsigned int ar933x_uart_tx_empty(struct uart_port *port)
> +@@ -503,6 +545,13 @@ 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)
> ++{
> ++	port->rs485 = *rs485conf;
> ++	return 0;
> ++}
> ++
> + #ifdef CONFIG_SERIAL_AR933X_CONSOLE
> + static struct ar933x_uart_port *
> + ar933x_console_ports[CONFIG_SERIAL_AR933X_NR_UARTS];
> +@@ -672,6 +721,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;
> +@@ -682,6 +733,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);
> +@@ -689,6 +741,10 @@ 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);
> ++
> + #ifdef CONFIG_SERIAL_AR933X_CONSOLE
> + 	ar933x_console_ports[up->port.line] = up;
> + #endif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP-digital-signature.html
Type: application/pgp-signature
Size: 1175 bytes
Desc: OpenPGP Digital Signature
URL: <http://lists.infradead.org/pipermail/openwrt-devel/attachments/20200211/a96c9921/attachment.sig>
-------------- next part --------------
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel


More information about the openwrt-devel mailing list