Hi,
I am trying to add RS485 transceiver support to UART5 in AM335x processor . I already applied patch for RS485 support in linux kernel. And its working file if i configure GPIO other than RTS of serial ports (Ex : gpio3 20) as Transmission Direction Control (DE). But if i assigned RTS of UART5 as its DE, it is not working as intended. DE pin is not toggling along with transmission of bytes.
The linux code and dtb details are as follows.
In dtb, the serial port (ttys5) is configured as follows
uart5_pins: pinmux_uart5_pins {
pinctrl-single,pins = <
0xD8 (PIN_INPUT | MUX_MODE6) /* lcd_data14.uart5_ctsn */
0xDC (PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* lcd_data15.uart5_rtsn */
0xC4 (PIN_INPUT_PULLUP | MUX_MODE4) /* lcd_data9.uart5_rxd */
0xC0 (PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* lcd_data8.uart5_txd */
>;
};
uart5: serial@481aa000 {
pinctrl-names = "default";
pinctrl-0 = <&uart5_pins>;
status = "okay";
rts-gpio = <&gpio0 11 GPIO_ACTIVE_HIGH>;
rs485-rts-active-high;
rs485-rts-delay = <1 1>;
linux,rs485-enabled-at-boot-time;
};
And in omap-serial.c, modified 'serial_omap_config_rs485' function as follows
/* Enable or disable the rs485 support */
static void
serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
{
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags;
unsigned int mode;
int val;
int r = 0, gpioFlag = 1;
pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
/* Disable interrupts from this port */
mode = up->ier;
up->ier = 0;
serial_out(up, UART_IER, 0);
if(!(rs485conf->flags & SER_RS485_ENABLED))
{
if ((up->rs485.flags & SER_RS485_ENABLED) && (gpio_is_valid(up->rts_gpio)))
{
gpio_free(up->rts_gpio);
}
up->rs485 = *rs485conf;
gpioFlag = 0;
}
else if(!(up->rs485.flags & SER_RS485_ENABLED) ||
(up->rts_gpio != rs485conf->gpio_pin))
{
val = (rs485conf->flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0;
if (gpio_is_valid(rs485conf->gpio_pin))
{
r = gpio_request(rs485conf->gpio_pin, "RS485 TXE");
if (r) {
dev_warn(port->dev, "Could not request GPIO %d : %d\n",rs485conf->gpio_pin, r);
gpioFlag = 0;
}
r = gpio_direction_output(rs485conf->gpio_pin, val);
if (r) {
dev_warn(port->dev, "Could not drive GPIO %d : %d\n", rs485conf->gpio_pin, r);
gpio_free(rs485conf->gpio_pin);
gpioFlag = 0;
}
}
}
if (gpioFlag)
{
/* store new config */
up->rs485 = *rs485conf;
/*
* Just as a precaution, only allow rs485
* to be enabled if the gpio pin is valid
*/
up->rts_gpio = rs485conf->gpio_pin;
/* enable / disable rts */
val = (up->rs485.flags & SER_RS485_ENABLED) ?
SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;
val = (up->rs485.flags & val) ? 1 : 0;
gpio_set_value(up->rts_gpio, val);
}
/* Enable interrupts */
up->ier = mode;
serial_out(up, UART_IER, up->ier);
spin_unlock_irqrestore(&up->port.lock, flags);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
And ensured that this function is executing properly.
Modified serial_omap_set_mctrl function as following
static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned char mcr = 0, old_mcr;
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->dev);
old_mcr = serial_in(up, UART_MCR);
old_mcr &= ~(UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_OUT1 |
UART_MCR_DTR | UART_MCR_RTS);
up->mcr = old_mcr | mcr;
printk(KERN_INFO "serial_omap_set_mctrl - %d %x \n", up->port.line, up->mcr);
serial_out(up, UART_MCR, up->mcr);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
if (gpio_is_valid(up->DTR_gpio) &&
!!(mctrl & TIOCM_DTR) != up->DTR_active) {
up->DTR_active = !up->DTR_active;
if (gpio_cansleep(up->DTR_gpio))
schedule_work(&up->qos_work);
else
gpio_set_value(up->DTR_gpio,
up->DTR_active != up->DTR_inverted);
}
}
Still RS485 is not working if RTS pin is configured as UART5 DE.
Please let me know if any mistake is there in my code/dtb .