This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Problem manually controlling RTS on /dev/ttyO3

Other Parts Discussed in Thread: AM3352

I have a custom AM3352 board and use all 6 uarts.  I am trying to test out RS-485 on uart 3.  With our hardware the cpu has to set RTS high to enable the RS-485 transmitter.  However when I run my test program below I never see the RTS output from the CPU change.  I'm pretty sure the pin is pinmixed correctly too.  How can I get RTS to work?

My RTS test program is attached and I've verified it works on an X86 platform.

I also cannot see how the RTS bit would ever be reset by the OMAP serial driver:

static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
        struct uart_omap_port *up = (struct uart_omap_port *)port;
        unsigned char mcr = 0;

        dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line);
        if (mctrl & TIOCM_RTS)
                mcr |= UART_MCR_RTS;
        if (mctrl & TIOCM_DTR)
                mcr |= UART_MCR_DTR;
        if (mctrl & TIOCM_OUT1)
                mcr |= UART_MCR_OUT1;
        if (mctrl & TIOCM_OUT2)
                mcr |= UART_MCR_OUT2;
        if (mctrl & TIOCM_LOOP)
                mcr |= UART_MCR_LOOP;

        pm_runtime_get_sync(&up->pdev->dev);
        up->mcr = serial_in(up, UART_MCR);
        up->mcr |= mcr;
        serial_out(up, UART_MCR, up->mcr);
        pm_runtime_put(&up->pdev->dev);
}

  • Well I found out the problem, the line

    up->mcr |= mcr;

    in the code above is obviously wrong.  It will set the bits but never clear them.  On replacing the line with:

    up->mcr = (up->mcr & ~(UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT1 | UART_MCR_OUT2 | UART_MCR_LOOP)) | mcr;

    it now all works.  Future serial port users beware.