diff mbox

[v2] OMAP: add RS485 support

Message ID 52079822.9020103@newflow.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Mark Jackson Aug. 11, 2013, 1:56 p.m. UTC
This patch adds RS485 support to the OMAP serial driver, as
defined in:-

Documentation/devicetree/bindings/serial/rs485.txt

When a UART transmitter is connected to (eg) a RS485 driver, it is
necessary to turn the driver on/off as quickly as possible.  This is
best achieved in the serial driver itself (rather than in userspace
where the latency can be quite large).

This patch allows a GPIO pin to be defined (via DT) that controls
the enabling of the driver at the start of a message, and disables
the driver when the message has been completed.

When RS485 is disabled, the RTS pin is set to on.

Signed-off-by: Mark Jackson <mpfj@newflow.co.uk>
---
Changes in v2:
- Fix incorrect logic in serial_omap_config_rs485()

 drivers/tty/serial/omap-serial.c |  178 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 178 insertions(+)

Comments

Greg KH Aug. 12, 2013, 10:56 p.m. UTC | #1
On Sun, Aug 11, 2013 at 02:56:50PM +0100, Mark Jackson wrote:
> This patch adds RS485 support to the OMAP serial driver, as
> defined in:-
> 
> Documentation/devicetree/bindings/serial/rs485.txt
> 
> When a UART transmitter is connected to (eg) a RS485 driver, it is
> necessary to turn the driver on/off as quickly as possible.  This is
> best achieved in the serial driver itself (rather than in userspace
> where the latency can be quite large).
> 
> This patch allows a GPIO pin to be defined (via DT) that controls
> the enabling of the driver at the start of a message, and disables
> the driver when the message has been completed.
> 
> When RS485 is disabled, the RTS pin is set to on.
> 
> Signed-off-by: Mark Jackson <mpfj@newflow.co.uk>
> ---
> Changes in v2:
> - Fix incorrect logic in serial_omap_config_rs485()
> 
>  drivers/tty/serial/omap-serial.c |  178 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 178 insertions(+)

This doesn't apply to my tty-next branch:
	checking file drivers/tty/serial/omap-serial.c
	Hunk #1 FAILED at 40.
	Hunk #2 succeeded at 162 (offset 6 lines).
	Hunk #3 succeeded at 280 (offset 5 lines).
	Hunk #4 succeeded at 378 (offset 6 lines).
	Hunk #5 succeeded at 1312 (offset 8 lines).
	Hunk #6 succeeded at 1405 (offset 8 lines).
	Hunk #7 succeeded at 1528 (offset 10 lines).
	Hunk #8 FAILED at 1638.
	Hunk #9 succeeded at 1705 (offset 6 lines).
	2 out of 9 hunks FAILED

so I can't apply it, sorry.

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Jackson Aug. 13, 2013, 10:22 a.m. UTC | #2
On 12/08/13 23:56, Greg KH wrote:
> On Sun, Aug 11, 2013 at 02:56:50PM +0100, Mark Jackson wrote:
>> This patch adds RS485 support to the OMAP serial driver, as
>> defined in:-
>>
>> Documentation/devicetree/bindings/serial/rs485.txt
>>
>> When a UART transmitter is connected to (eg) a RS485 driver, it is
>> necessary to turn the driver on/off as quickly as possible.  This is
>> best achieved in the serial driver itself (rather than in userspace
>> where the latency can be quite large).
>>
>> This patch allows a GPIO pin to be defined (via DT) that controls
>> the enabling of the driver at the start of a message, and disables
>> the driver when the message has been completed.
>>
>> When RS485 is disabled, the RTS pin is set to on.
>>
>> Signed-off-by: Mark Jackson <mpfj@newflow.co.uk>
>> ---
>> Changes in v2:
>> - Fix incorrect logic in serial_omap_config_rs485()
>>
>>  drivers/tty/serial/omap-serial.c |  178 ++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 178 insertions(+)
> 
> This doesn't apply to my tty-next branch:
> 	checking file drivers/tty/serial/omap-serial.c
> 	Hunk #1 FAILED at 40.
> 	Hunk #2 succeeded at 162 (offset 6 lines).
> 	Hunk #3 succeeded at 280 (offset 5 lines).
> 	Hunk #4 succeeded at 378 (offset 6 lines).
> 	Hunk #5 succeeded at 1312 (offset 8 lines).
> 	Hunk #6 succeeded at 1405 (offset 8 lines).
> 	Hunk #7 succeeded at 1528 (offset 10 lines).
> 	Hunk #8 FAILED at 1638.
> 	Hunk #9 succeeded at 1705 (offset 6 lines).
> 	2 out of 9 hunks FAILED
> 
> so I can't apply it, sorry.

It was applied on top of Linus' tree, if that makes any difference.

I'll rebase onto yours and re-post the patch.
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Javier Martinez Canillas Aug. 13, 2013, 10:54 a.m. UTC | #3
On Tue, Aug 13, 2013 at 12:22 PM, Mark Jackson <mpfj-list@newflow.co.uk> wrote:
> On 12/08/13 23:56, Greg KH wrote:
>> On Sun, Aug 11, 2013 at 02:56:50PM +0100, Mark Jackson wrote:
>>> This patch adds RS485 support to the OMAP serial driver, as
>>> defined in:-
>>>
>>> Documentation/devicetree/bindings/serial/rs485.txt
>>>
>>> When a UART transmitter is connected to (eg) a RS485 driver, it is
>>> necessary to turn the driver on/off as quickly as possible.  This is
>>> best achieved in the serial driver itself (rather than in userspace
>>> where the latency can be quite large).
>>>
>>> This patch allows a GPIO pin to be defined (via DT) that controls
>>> the enabling of the driver at the start of a message, and disables
>>> the driver when the message has been completed.
>>>
>>> When RS485 is disabled, the RTS pin is set to on.
>>>
>>> Signed-off-by: Mark Jackson <mpfj@newflow.co.uk>
>>> ---
>>> Changes in v2:
>>> - Fix incorrect logic in serial_omap_config_rs485()
>>>
>>>  drivers/tty/serial/omap-serial.c |  178 ++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 178 insertions(+)
>>
>> This doesn't apply to my tty-next branch:
>>       checking file drivers/tty/serial/omap-serial.c
>>       Hunk #1 FAILED at 40.
>>       Hunk #2 succeeded at 162 (offset 6 lines).
>>       Hunk #3 succeeded at 280 (offset 5 lines).
>>       Hunk #4 succeeded at 378 (offset 6 lines).
>>       Hunk #5 succeeded at 1312 (offset 8 lines).
>>       Hunk #6 succeeded at 1405 (offset 8 lines).
>>       Hunk #7 succeeded at 1528 (offset 10 lines).
>>       Hunk #8 FAILED at 1638.
>>       Hunk #9 succeeded at 1705 (offset 6 lines).
>>       2 out of 9 hunks FAILED
>>
>> so I can't apply it, sorry.
>
> It was applied on top of Linus' tree, if that makes any difference.
>
> I'll rebase onto yours and re-post the patch.
> --

Hi Mark,

I've seen several attempts to add RS485 support to the omap serial
driver and it is always nack-ed. There seems to be concerns about
controlling the RTS by software when RS485 is not supported by the
UART hardware. Please refer to [1] and [2] for more information.

Best regards,
Javier

[1]: http://comments.gmane.org/gmane.linux.serial/6770
[2]: http://article.gmane.org/gmane.linux.serial/3619/
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Jackson Aug. 13, 2013, 11:07 a.m. UTC | #4
On 13/08/13 11:54, Javier Martinez Canillas wrote:

<snip>

> 
> Hi Mark,
> 
> I've seen several attempts to add RS485 support to the omap serial
> driver and it is always nack-ed. There seems to be concerns about
> controlling the RTS by software when RS485 is not supported by the
> UART hardware. Please refer to [1] and [2] for more information.

Hmmmm ... okay, I guess I'll just have to maintain our own code (as
did the OP in [1]).

Thanks for the info.
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Javier Martinez Canillas Aug. 13, 2013, 11:14 a.m. UTC | #5
On Tue, Aug 13, 2013 at 1:07 PM, Mark Jackson <mpfj-list@newflow.co.uk> wrote:
> On 13/08/13 11:54, Javier Martinez Canillas wrote:
>
> <snip>
>
>>
>> Hi Mark,
>>
>> I've seen several attempts to add RS485 support to the omap serial
>> driver and it is always nack-ed. There seems to be concerns about
>> controlling the RTS by software when RS485 is not supported by the
>> UART hardware. Please refer to [1] and [2] for more information.
>
> Hmmmm ... okay, I guess I'll just have to maintain our own code (as
> did the OP in [1]).
>

Yes, back then we had to do the same using Ilya Yanok's OMAP RS485
patches [1] on a vendor tree :(

> Thanks for the info.

I just wanted to avoid you wasting more time on this, unless the
mindset has changed in which case it would be really great to have
RS485 support for OMAP serial.

Thanks a lot and best regards,
Javier

[1]: http://comments.gmane.org/gmane.linux.serial/6770
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Greg KH Aug. 13, 2013, 6:50 p.m. UTC | #6
On Tue, Aug 13, 2013 at 12:54:47PM +0200, Javier Martinez Canillas wrote:
> On Tue, Aug 13, 2013 at 12:22 PM, Mark Jackson <mpfj-list@newflow.co.uk> wrote:
> > On 12/08/13 23:56, Greg KH wrote:
> >> On Sun, Aug 11, 2013 at 02:56:50PM +0100, Mark Jackson wrote:
> >>> This patch adds RS485 support to the OMAP serial driver, as
> >>> defined in:-
> >>>
> >>> Documentation/devicetree/bindings/serial/rs485.txt
> >>>
> >>> When a UART transmitter is connected to (eg) a RS485 driver, it is
> >>> necessary to turn the driver on/off as quickly as possible.  This is
> >>> best achieved in the serial driver itself (rather than in userspace
> >>> where the latency can be quite large).
> >>>
> >>> This patch allows a GPIO pin to be defined (via DT) that controls
> >>> the enabling of the driver at the start of a message, and disables
> >>> the driver when the message has been completed.
> >>>
> >>> When RS485 is disabled, the RTS pin is set to on.
> >>>
> >>> Signed-off-by: Mark Jackson <mpfj@newflow.co.uk>
> >>> ---
> >>> Changes in v2:
> >>> - Fix incorrect logic in serial_omap_config_rs485()
> >>>
> >>>  drivers/tty/serial/omap-serial.c |  178 ++++++++++++++++++++++++++++++++++++++
> >>>  1 file changed, 178 insertions(+)
> >>
> >> This doesn't apply to my tty-next branch:
> >>       checking file drivers/tty/serial/omap-serial.c
> >>       Hunk #1 FAILED at 40.
> >>       Hunk #2 succeeded at 162 (offset 6 lines).
> >>       Hunk #3 succeeded at 280 (offset 5 lines).
> >>       Hunk #4 succeeded at 378 (offset 6 lines).
> >>       Hunk #5 succeeded at 1312 (offset 8 lines).
> >>       Hunk #6 succeeded at 1405 (offset 8 lines).
> >>       Hunk #7 succeeded at 1528 (offset 10 lines).
> >>       Hunk #8 FAILED at 1638.
> >>       Hunk #9 succeeded at 1705 (offset 6 lines).
> >>       2 out of 9 hunks FAILED
> >>
> >> so I can't apply it, sorry.
> >
> > It was applied on top of Linus' tree, if that makes any difference.
> >
> > I'll rebase onto yours and re-post the patch.
> > --
> 
> Hi Mark,
> 
> I've seen several attempts to add RS485 support to the omap serial
> driver and it is always nack-ed. There seems to be concerns about
> controlling the RTS by software when RS485 is not supported by the
> UART hardware. Please refer to [1] and [2] for more information.

Hm, but we do support RS485 now in the kernel, look at
Documentation/serial/serial-rs485.txt.  Why can't this driver support it
as well if the serial core already does?

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Greg KH Aug. 13, 2013, 6:51 p.m. UTC | #7
On Tue, Aug 13, 2013 at 12:07:01PM +0100, Mark Jackson wrote:
> On 13/08/13 11:54, Javier Martinez Canillas wrote:
> 
> <snip>
> 
> > 
> > Hi Mark,
> > 
> > I've seen several attempts to add RS485 support to the omap serial
> > driver and it is always nack-ed. There seems to be concerns about
> > controlling the RTS by software when RS485 is not supported by the
> > UART hardware. Please refer to [1] and [2] for more information.
> 
> Hmmmm ... okay, I guess I'll just have to maintain our own code (as
> did the OP in [1]).

I don't want to have that happen, that's just foolish.  I'd rather merge
it so that everyone can benifit, and so you don't have to spend extra
work maintaining this out-of-tree.

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Greg KH Aug. 13, 2013, 6:53 p.m. UTC | #8
On Tue, Aug 13, 2013 at 11:22:54AM +0100, Mark Jackson wrote:
> On 12/08/13 23:56, Greg KH wrote:
> > On Sun, Aug 11, 2013 at 02:56:50PM +0100, Mark Jackson wrote:
> >> This patch adds RS485 support to the OMAP serial driver, as
> >> defined in:-
> >>
> >> Documentation/devicetree/bindings/serial/rs485.txt
> >>
> >> When a UART transmitter is connected to (eg) a RS485 driver, it is
> >> necessary to turn the driver on/off as quickly as possible.  This is
> >> best achieved in the serial driver itself (rather than in userspace
> >> where the latency can be quite large).
> >>
> >> This patch allows a GPIO pin to be defined (via DT) that controls
> >> the enabling of the driver at the start of a message, and disables
> >> the driver when the message has been completed.
> >>
> >> When RS485 is disabled, the RTS pin is set to on.
> >>
> >> Signed-off-by: Mark Jackson <mpfj@newflow.co.uk>
> >> ---
> >> Changes in v2:
> >> - Fix incorrect logic in serial_omap_config_rs485()
> >>
> >>  drivers/tty/serial/omap-serial.c |  178 ++++++++++++++++++++++++++++++++++++++
> >>  1 file changed, 178 insertions(+)
> > 
> > This doesn't apply to my tty-next branch:
> > 	checking file drivers/tty/serial/omap-serial.c
> > 	Hunk #1 FAILED at 40.
> > 	Hunk #2 succeeded at 162 (offset 6 lines).
> > 	Hunk #3 succeeded at 280 (offset 5 lines).
> > 	Hunk #4 succeeded at 378 (offset 6 lines).
> > 	Hunk #5 succeeded at 1312 (offset 8 lines).
> > 	Hunk #6 succeeded at 1405 (offset 8 lines).
> > 	Hunk #7 succeeded at 1528 (offset 10 lines).
> > 	Hunk #8 FAILED at 1638.
> > 	Hunk #9 succeeded at 1705 (offset 6 lines).
> > 	2 out of 9 hunks FAILED
> > 
> > so I can't apply it, sorry.
> 
> It was applied on top of Linus' tree, if that makes any difference.

Ah, that makes sense.  I should have tried a --3way merge to see if it
worked, sorry about that.  Let me go try it again...

Nope, a few merge errors that I don't know how to resolve, sorry.

> I'll rebase onto yours and re-post the patch.

That would be great, please do.

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Javier Martinez Canillas Aug. 13, 2013, 9:16 p.m. UTC | #9
On Tue, Aug 13, 2013 at 8:50 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
>
> On Tue, Aug 13, 2013 at 12:54:47PM +0200, Javier Martinez Canillas wrote:
> > On Tue, Aug 13, 2013 at 12:22 PM, Mark Jackson <mpfj-list@newflow.co.uk> wrote:
> > > On 12/08/13 23:56, Greg KH wrote:
> > >> On Sun, Aug 11, 2013 at 02:56:50PM +0100, Mark Jackson wrote:
> > >>> This patch adds RS485 support to the OMAP serial driver, as
> > >>> defined in:-
> > >>>
> > >>> Documentation/devicetree/bindings/serial/rs485.txt
> > >>>
> > >>> When a UART transmitter is connected to (eg) a RS485 driver, it is
> > >>> necessary to turn the driver on/off as quickly as possible.  This is
> > >>> best achieved in the serial driver itself (rather than in userspace
> > >>> where the latency can be quite large).
> > >>>
> > >>> This patch allows a GPIO pin to be defined (via DT) that controls
> > >>> the enabling of the driver at the start of a message, and disables
> > >>> the driver when the message has been completed.
> > >>>
> > >>> When RS485 is disabled, the RTS pin is set to on.
> > >>>
> > >>> Signed-off-by: Mark Jackson <mpfj@newflow.co.uk>
> > >>> ---
> > >>> Changes in v2:
> > >>> - Fix incorrect logic in serial_omap_config_rs485()
> > >>>
> > >>>  drivers/tty/serial/omap-serial.c |  178 ++++++++++++++++++++++++++++++++++++++
> > >>>  1 file changed, 178 insertions(+)
> > >>
> > >> This doesn't apply to my tty-next branch:
> > >>       checking file drivers/tty/serial/omap-serial.c
> > >>       Hunk #1 FAILED at 40.
> > >>       Hunk #2 succeeded at 162 (offset 6 lines).
> > >>       Hunk #3 succeeded at 280 (offset 5 lines).
> > >>       Hunk #4 succeeded at 378 (offset 6 lines).
> > >>       Hunk #5 succeeded at 1312 (offset 8 lines).
> > >>       Hunk #6 succeeded at 1405 (offset 8 lines).
> > >>       Hunk #7 succeeded at 1528 (offset 10 lines).
> > >>       Hunk #8 FAILED at 1638.
> > >>       Hunk #9 succeeded at 1705 (offset 6 lines).
> > >>       2 out of 9 hunks FAILED
> > >>
> > >> so I can't apply it, sorry.
> > >
> > > It was applied on top of Linus' tree, if that makes any difference.
> > >
> > > I'll rebase onto yours and re-post the patch.
> > > --
> >
> > Hi Mark,
> >
> > I've seen several attempts to add RS485 support to the omap serial
> > driver and it is always nack-ed. There seems to be concerns about
> > controlling the RTS by software when RS485 is not supported by the
> > UART hardware. Please refer to [1] and [2] for more information.
>
> Hm, but we do support RS485 now in the kernel, look at
> Documentation/serial/serial-rs485.txt.  Why can't this driver support it
> as well if the serial core already does?
>

Hi Greg,

Please don't shoot the messenger :-)

In fact I was one of those who needed RS485 support in the OMAP serial
driver a couple of years ago and we were told that "software RS485 is
not mainlinable" [1].

I just wanted to warn Mark that he could be losing time pushing this
but I'm glad to learn that this seems not to be true anymore.

> thanks,
>
> greg k-h

Thanks a lot and best regards,
Javier

[1]: http://comments.gmane.org/gmane.linux.serial/6770
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index b6d1728..d538329 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -40,9 +40,12 @@ 
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_data/serial-omap.h>
 
+#include <dt-bindings/gpio/gpio.h>
+
 #define OMAP_MAX_HSUART_PORTS	6
 
 #define UART_BUILD_REVISION(x, y)	(((x) << 8) | (y))
@@ -156,6 +159,9 @@  struct uart_omap_port {
 	int			DTR_inverted;
 	int			DTR_active;
 
+	struct serial_rs485	rs485;
+	int			rts_gpio;
+
 	struct pm_qos_request	pm_qos_request;
 	u32			latency;
 	u32			calc_latency;
@@ -272,13 +278,42 @@  static void serial_omap_enable_ms(struct uart_port *port)
 static void serial_omap_stop_tx(struct uart_port *port)
 {
 	struct uart_omap_port *up = to_uart_omap_port(port);
+	struct circ_buf *xmit = &up->port.state->xmit;
+	int res;
 
 	pm_runtime_get_sync(up->dev);
+
+	/* handle rs485 */
+	if (up->rs485.flags & SER_RS485_ENABLED) {
+		/* do nothing if current tx not yet completed */
+		res = serial_in(up, UART_LSR) & UART_LSR_TEMT;
+		if (!res)
+			return;
+
+		/* if there's no more data to send, turn off rts */
+		if (uart_circ_empty(xmit)) {
+			/* if rts not already disabled */
+			res = (up->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0;
+			if (gpio_get_value(up->rts_gpio) != res) {
+				if (up->rs485.delay_rts_after_send > 0) {
+					mdelay(up->rs485.delay_rts_after_send);
+				}
+				gpio_set_value(up->rts_gpio, res);
+			}
+		}
+	}
+
 	if (up->ier & UART_IER_THRI) {
 		up->ier &= ~UART_IER_THRI;
 		serial_out(up, UART_IER, up->ier);
 	}
 
+	if ((up->rs485.flags & SER_RS485_ENABLED) &&
+	    !(up->rs485.flags & SER_RS485_RX_DURING_TX)) {
+		up->ier = UART_IER_RLSI | UART_IER_RDI;
+		serial_out(up, UART_IER, up->ier);
+	}
+
 	pm_runtime_mark_last_busy(up->dev);
 	pm_runtime_put_autosuspend(up->dev);
 }
@@ -340,8 +375,26 @@  static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
 static void serial_omap_start_tx(struct uart_port *port)
 {
 	struct uart_omap_port *up = to_uart_omap_port(port);
+	int res;
 
 	pm_runtime_get_sync(up->dev);
+
+	/* handle rs485 */
+	if (up->rs485.flags & SER_RS485_ENABLED) {
+		/* if rts not already enabled */
+		res = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0;
+		if (gpio_get_value(up->rts_gpio) != res) {
+			gpio_set_value(up->rts_gpio, res);
+			if (up->rs485.delay_rts_before_send > 0) {
+				mdelay(up->rs485.delay_rts_before_send);
+			}
+		}
+	}
+
+	if ((up->rs485.flags & SER_RS485_ENABLED) &&
+	    !(up->rs485.flags & SER_RS485_RX_DURING_TX))
+		serial_omap_stop_rx(port);
+
 	serial_omap_enable_ier_thri(up);
 	pm_runtime_mark_last_busy(up->dev);
 	pm_runtime_put_autosuspend(up->dev);
@@ -1254,6 +1307,78 @@  static inline void serial_omap_add_console_port(struct uart_omap_port *up)
 
 #endif
 
+/* 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;
+
+	pm_runtime_get_sync(up->dev);
+	spin_lock_irqsave(&up->port.lock, flags);
+
+	up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+	serial_out(up, UART_IER, up->ier);
+
+	/* Disable interrupts from this port */
+	mode = up->ier;
+	up->ier = 0;
+	serial_out(up, UART_IER, 0);
+
+	/* store new config */
+	up->rs485 = *rs485conf;
+
+	/*
+	 * Just as a precaution, only allow rs485
+	 * to be enabled if the gpio pin is valid
+	 */
+	if (gpio_is_valid(up->rts_gpio)) {
+		/* 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);
+	} else
+		up->rs485.flags &= ~SER_RS485_ENABLED;
+
+	/* 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);
+}
+
+static int
+serial_omap_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
+{
+	struct serial_rs485 rs485conf;
+
+	switch (cmd) {
+	case TIOCSRS485:
+		if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg,
+					sizeof(rs485conf)))
+			return -EFAULT;
+
+		serial_omap_config_rs485(port, &rs485conf);
+		break;
+
+	case TIOCGRS485:
+		if (copy_to_user((struct serial_rs485 *) arg,
+					&(to_uart_omap_port(port)->rs485),
+					sizeof(rs485conf)))
+			return -EFAULT;
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
 static struct uart_ops serial_omap_pops = {
 	.tx_empty	= serial_omap_tx_empty,
 	.set_mctrl	= serial_omap_set_mctrl,
@@ -1275,6 +1400,7 @@  static struct uart_ops serial_omap_pops = {
 	.request_port	= serial_omap_request_port,
 	.config_port	= serial_omap_config_port,
 	.verify_port	= serial_omap_verify_port,
+	.ioctl		= serial_omap_ioctl,
 #ifdef CONFIG_CONSOLE_POLL
 	.poll_put_char  = serial_omap_poll_put_char,
 	.poll_get_char  = serial_omap_poll_get_char,
@@ -1395,6 +1521,53 @@  static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
 	return omap_up_info;
 }
 
+static int serial_omap_probe_rs485(struct uart_omap_port *up,
+				   struct device_node *np)
+{
+	struct serial_rs485 *rs485conf = &up->rs485;
+	u32 rs485_delay[2];
+	enum of_gpio_flags flags;
+	int ret;
+
+	rs485conf->flags = 0;
+	up->rts_gpio = -EINVAL;
+
+	if (!np)
+		return 0;
+
+	if (of_property_read_bool(np, "rs485-rts-active-high"))
+		rs485conf->flags |= SER_RS485_RTS_ON_SEND;
+	else
+		rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
+
+	/* check for tx enable gpio */
+	up->rts_gpio = of_get_named_gpio_flags(np, "rts-gpio", 0, &flags);
+	if (gpio_is_valid(up->rts_gpio)) {
+		ret = gpio_request(up->rts_gpio, "omap-serial");
+		if (ret < 0)
+			return ret;
+		ret = gpio_direction_output(up->rts_gpio,
+					    flags & SER_RS485_RTS_AFTER_SEND);
+		if (ret < 0)
+			return ret;
+	} else
+		up->rts_gpio = -EINVAL;
+
+	if (of_property_read_u32_array(np, "rs485-rts-delay",
+				    rs485_delay, 2) == 0) {
+		rs485conf->delay_rts_before_send = rs485_delay[0];
+		rs485conf->delay_rts_after_send = rs485_delay[1];
+	}
+
+	if (of_property_read_bool(np, "rs485-rx-during-tx"))
+		rs485conf->flags |= SER_RS485_RX_DURING_TX;
+
+	if (of_property_read_bool(np, "linux,rs485-enabled-at-boot-time"))
+		rs485conf->flags |= SER_RS485_ENABLED;
+
+	return 0;
+}
+
 static int serial_omap_probe(struct platform_device *pdev)
 {
 	struct uart_omap_port	*up;
@@ -1468,6 +1641,10 @@  static int serial_omap_probe(struct platform_device *pdev)
 		goto err_port_line;
 	}
 
+	ret = serial_omap_probe_rs485(up, pdev->dev.of_node);
+	if (ret < 0)
+		goto err_rs485;
+
 	up->pins = devm_pinctrl_get_select_default(&pdev->dev);
 	if (IS_ERR(up->pins)) {
 		dev_warn(&pdev->dev, "did not get pins for uart%i error: %li\n",
@@ -1529,6 +1706,7 @@  err_add_port:
 	pm_runtime_put(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 err_ioremap:
+err_rs485:
 err_port_line:
 	dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
 				pdev->id, __func__, ret);