OMAP: add RS485 support
PATCH v2 1/1 OMAP: add RS485 support
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.
---
Changes in v2:
- Fix incorrect logic in serial_omap_config_rs485()
drivers/tty/serial/omap-serial.c | 178 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+)
drivers/tty/serial/omap-serial.c +178 -0
@@ -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);
Signature · 1 line
1.7.9.5
Greg KH
maintainerRe: [PATCH v2] serial: OMAP: add RS485 support
Quoted 16 lines · Mark Jackson
This patch adds RS485 support to the OMAP serial driver, as defined in:-
Documentation/devicetree/bindings/serial/rs485.txtWhen 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.
Quoted 7 lines
Signed-off-by Mark Jackson <[email protected]>---
Changes in v2:
- Fix incorrect logic inserial_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
Re: [PATCH v2] serial: OMAP: add RS485 support
Quoted 38 lines · Greg KH
Quoted 16 lines · Mark Jackson
This patch adds RS485 support to the OMAP serial driver, as defined in:-
Documentation/devicetree/bindings/serial/rs485.txtWhen 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.
Quoted 7 lines
Signed-off-by Mark Jackson <[email protected]>---
Changes in v2:
- Fix incorrect logic inserial_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 filedrivers/tty/serial/omap-serial.cHunk #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
Quoted 1 line
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.
Re: [PATCH v2] serial: OMAP: add RS485 support
Quoted 39 lines · Mark Jackson
Quoted 38 lines · Greg KH
Quoted 16 lines · Mark Jackson
This patch adds RS485 support to the OMAP serial driver, as defined in:-
Documentation/devicetree/bindings/serial/rs485.txtWhen 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.
Quoted 7 lines
Signed-off-by Mark Jackson <[email protected]>---
Changes in v2:
- Fix incorrect logic inserial_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 filedrivers/tty/serial/omap-serial.cHunk #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
Quoted 6 lines
Quoted 1 line
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/
Re: [PATCH v2] serial: OMAP: add RS485 support
On 13/08/13 11:54, Javier Martinez Canillas wrote:
<snip>
Quoted 7 lines
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.
Re: [PATCH v2] serial: OMAP: add RS485 support
Quoted 7 lines · Mark Jackson
On 13/08/13 11:54, Javier Martinez Canillas wrote:
<snip>
Quoted 3 lines
Hi Mark,
Quoted 8 lines
Quoted 4 lines
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 :(
Quoted 1 line
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
Greg KH
maintainerRe: [PATCH v2] serial: OMAP: add RS485 support
In reply to Mark JacksonQuoted 7 lines · Mark Jackson
On 13/08/13 11:54, Javier Martinez Canillas wrote:
<snip>
Quoted 3 lines
Hi Mark,
Quoted 7 lines
Quoted 4 lines
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
Greg KH
maintainerRe: [PATCH v2] serial: OMAP: add RS485 support
In reply to Javier Martinez CanillasQuoted 47 lines · Javier Martinez Canillas
Quoted 39 lines · Mark Jackson
Quoted 38 lines · Greg KH
Quoted 16 lines · Mark Jackson
This patch adds RS485 support to the OMAP serial driver, as defined in:-
Documentation/devicetree/bindings/serial/rs485.txtWhen 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.
Quoted 7 lines
Signed-off-by Mark Jackson <[email protected]>---
Changes in v2:
- Fix incorrect logic inserial_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 filedrivers/tty/serial/omap-serial.cHunk #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 FAILEDQuoted 6 lines
Quoted 1 line
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.
--
Quoted 6 lines
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
Re: [PATCH v2] serial: OMAP: add RS485 support
Quoted 51 lines · Greg KH
Quoted 49 lines · Javier Martinez Canillas
Quoted 39 lines · Mark Jackson
Quoted 38 lines · Greg KH
Quoted 16 lines · Mark Jackson
This patch adds RS485 support to the OMAP serial driver, as defined in:-
Documentation/devicetree/bindings/serial/rs485.txtWhen 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.
Quoted 7 lines
Signed-off-by Mark Jackson <[email protected]>---
Changes in v2:
- Fix incorrect logic inserial_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 filedrivers/tty/serial/omap-serial.cHunk #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 FAILEDQuoted 6 lines
Quoted 1 line
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,
Quoted 9 lines
Quoted 4 lines
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.
Quoted 3 lines
thanks,
greg k-h
Thanks a lot and best regards,
Javier
Greg KH
maintainerRe: [PATCH v2] serial: OMAP: add RS485 support
In reply to Mark JacksonQuoted 39 lines · Mark Jackson
Quoted 38 lines · Greg KH
Quoted 16 lines · Mark Jackson
This patch adds RS485 support to the OMAP serial driver, as defined in:-
Documentation/devicetree/bindings/serial/rs485.txtWhen 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.
Quoted 7 lines
Signed-off-by Mark Jackson <[email protected]>---
Changes in v2:
- Fix incorrect logic inserial_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 filedrivers/tty/serial/omap-serial.cHunk #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
Quoted 3 lines
Quoted 1 line
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.
Quoted 1 line
I'll rebase onto yours and re-post the patch.
That would be great, please do.
thanks,
greg k-h