Skip to content

RTS-GPIO not working with imx tty driver #1

Description

@BrendanSimon

I'm trying to use the rts-gpio devicetree setting to emulate RTS modem control signals for an RS485 serial bus.

I can NOT use hardware RTS because the Advantech RSB-3430 does not have those signals exposed on the 40-pin connectors (CN1 and CN2).

I'm doing manual gpio sets for RTS from user space (using gpiod) but it is not reliable, especially under processor load. The timing is not reliable and clobbers responses from other devices on the RS485 bus.

The imx tty driver does support the rts-gpio devicetree setting. When I specify it I can see that the gpiod system reports that it is in use (by consumer "rts") and I cannot manually set it high/low anymore from user space.

HOWEVER, the gpio does not toggle when sending data. Looking at the imx tty driver, I can see that there are #ifdef CONFIG_ARCH_ADVANTECH blocks that skip the RS485 handling of RTS. i.e. the functions imx_port_rts_active() and imx_port_rts_inactive() are never called (see code example below).

Why is there special code for Advantech to disable this feature ??

Can it be fixed/patched please so I can use RS485 with my Advantech RSB-3430 board please.

I'm using the adv_4.14.98_2.0.0_ga kernel.

https://github.com/ADVANTECH-Corp/linux-imx/blob/adv_4.14.98_2.0.0_ga/drivers/tty/serial/imx.c

static void imx_stop_tx(struct uart_port *port)
{
	struct imx_port *sport = (struct imx_port *)port;
	unsigned long temp;

	/*
	 * We are maybe in the SMP context, so if the DMA TX thread is running
	 * on other cpu, we have to wait for it to finish.
	 */
	if (sport->dma_is_enabled && sport->dma_is_txing)
		return;

	temp = readl(port->membase + UCR1);
	writel(temp & ~UCR1_TXMPTYEN, port->membase + UCR1);

	/* in rs485 mode disable transmitter if shifter is empty */
	if (port->rs485.flags & SER_RS485_ENABLED &&
	    readl(port->membase + USR2) & USR2_TXDC) {
		temp = readl(port->membase + UCR2);
#ifdef CONFIG_ARCH_ADVANTECH
		temp &= ~UCR2_CTS;
#else
		if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
			imx_port_rts_active(sport, &temp);
		else
			imx_port_rts_inactive(sport, &temp);
		temp |= UCR2_RXEN;
#endif
		writel(temp, port->membase + UCR2);

		temp = readl(port->membase + UCR4);
		temp &= ~UCR4_TCEN;
		writel(temp, port->membase + UCR4);
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions