Re: [PATCH] omap-serial: add RS485 mode support

2011-11-10 Thread Kevin Hilman
Ilya Yanok  writes:

> Hi guys,
>
> any comments on this? Is anybody interested?

There's a major cleanup of the OMAP UART driver in progress[1].  I
suggest you rebase on top of that, or hold onto this until the cleanup
is merged.

Kevin

[1] http://marc.info/?l=linux-omap&m=131914563820506&w=2
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] omap-serial: add RS485 mode support

2011-11-08 Thread Ilya Yanok

Hi guys,

any comments on this? Is anybody interested?

Regards, Ilya.

03.10.2011 0:27, Ilya Yanok wrote:

Add support for asserting RTS line while TX is in progress. OMAP
hardware doesn't support auto-RS485 mode so we control the line from
software. We use TX_EMPTY_CTL_IT bit in SCR register to generate TX
empty interrupt.

We use SER_RS485_RTS_ON_SEND flag to control the polarity of RTS signal
(RTS is asserted high during transmition if this flag is set and low
otherwise) though I'm not sure if this is what this flag is for...

Signed-off-by: Ilya Yanok
---
  arch/arm/plat-omap/include/plat/omap-serial.h |3 +
  drivers/tty/serial/omap-serial.c  |  127 ++---
  include/linux/serial_reg.h|2 +
  3 files changed, 120 insertions(+), 12 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h 
b/arch/arm/plat-omap/include/plat/omap-serial.h
index 2682043..5003400 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -111,6 +111,9 @@ struct uart_omap_port {
unsigned char   msr_saved_flags;
charname[20];
unsigned long   port_activity;
+   struct serial_rs485 rs485;
+   unsigned inttx_in_progress:1,
+   tx_wait_end:1;
  };

  #endif /* __OMAP_SERIAL_H__ */
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 47cadf4..6526171 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -37,11 +37,14 @@
  #include
  #include
  #include
+#include

  #include
  #include
  #include

+#define OMAP_RS485_SUPPORTED   (SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND)
+
  static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];

  /* Forward declaration of functions */
@@ -114,6 +117,45 @@ static void serial_omap_enable_ms(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
  }

+static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
+{
+   if (!(up->ier&  UART_IER_THRI)) {
+   up->ier |= UART_IER_THRI;
+   serial_out(up, UART_IER, up->ier);
+   }
+}
+
+static inline void serial_omap_disable_ier_thri(struct uart_omap_port *up)
+{
+   if (up->ier&  UART_IER_THRI) {
+   up->ier&= ~UART_IER_THRI;
+   serial_out(up, UART_IER, up->ier);
+   }
+}
+
+static inline void serial_omap_thri_mode(struct uart_omap_port *up)
+{
+   unsigned char scr = serial_in(up, UART_OMAP_SCR);
+
+   if (up->tx_wait_end)
+   scr |= UART_OMAP_SCR_TX_EMPTY_CTL_IT;
+   else
+   scr&= ~UART_OMAP_SCR_TX_EMPTY_CTL_IT;
+   serial_out(up, UART_OMAP_SCR, scr);
+}
+
+static inline void serial_omap_update_rts(struct uart_omap_port *up)
+{
+   unsigned char mcr = up->mcr;
+   int rts_on_send = up->rs485.flags&  SER_RS485_RTS_ON_SEND;
+
+   if ((up->rs485.flags&  SER_RS485_ENABLED)&&
+   ((up->tx_in_progress&&  rts_on_send) ||
+!(up->tx_in_progress || rts_on_send)))
+   mcr |= UART_MCR_RTS;
+   serial_out(up, UART_MCR, mcr);
+}
+
  static void serial_omap_stop_tx(struct uart_port *port)
  {
struct uart_omap_port *up = (struct uart_omap_port *)port;
@@ -131,10 +173,14 @@ static void serial_omap_stop_tx(struct uart_port *port)
up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
}

-   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)) {
+   serial_omap_disable_ier_thri(up);
+   return;
}
+
+   up->tx_wait_end = 1;
+   serial_omap_thri_mode(up);
+   serial_omap_enable_ier_thri(up);
  }

  static void serial_omap_stop_rx(struct uart_port *port)
@@ -246,14 +292,6 @@ static void transmit_chars(struct uart_omap_port *up)
serial_omap_stop_tx(&up->port);
  }

-static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
-{
-   if (!(up->ier&  UART_IER_THRI)) {
-   up->ier |= UART_IER_THRI;
-   serial_out(up, UART_IER, up->ier);
-   }
-}
-
  static void serial_omap_start_tx(struct uart_port *port)
  {
struct uart_omap_port *up = (struct uart_omap_port *)port;
@@ -261,6 +299,18 @@ static void serial_omap_start_tx(struct uart_port *port)
unsigned int start;
int ret = 0;

+   if (up->rs485.flags&  SER_RS485_ENABLED) {
+   if (!up->tx_in_progress) {
+   up->tx_in_progress = 1;
+   serial_omap_update_rts(up);
+   }
+   if (up->tx_wait_end) {
+   up->tx_wait_end = 0;
+   serial_omap_thri_mode(up);
+   serial_omap_disable_ier_thri(up);
+   }

[PATCH] omap-serial: add RS485 mode support

2011-10-02 Thread Ilya Yanok
Add support for asserting RTS line while TX is in progress. OMAP
hardware doesn't support auto-RS485 mode so we control the line from
software. We use TX_EMPTY_CTL_IT bit in SCR register to generate TX
empty interrupt.

We use SER_RS485_RTS_ON_SEND flag to control the polarity of RTS signal
(RTS is asserted high during transmition if this flag is set and low
otherwise) though I'm not sure if this is what this flag is for...

Signed-off-by: Ilya Yanok 
---
 arch/arm/plat-omap/include/plat/omap-serial.h |3 +
 drivers/tty/serial/omap-serial.c  |  127 ++---
 include/linux/serial_reg.h|2 +
 3 files changed, 120 insertions(+), 12 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h 
b/arch/arm/plat-omap/include/plat/omap-serial.h
index 2682043..5003400 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -111,6 +111,9 @@ struct uart_omap_port {
unsigned char   msr_saved_flags;
charname[20];
unsigned long   port_activity;
+   struct serial_rs485 rs485;
+   unsigned inttx_in_progress:1,
+   tx_wait_end:1;
 };
 
 #endif /* __OMAP_SERIAL_H__ */
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 47cadf4..6526171 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -37,11 +37,14 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
 #include 
 
+#define OMAP_RS485_SUPPORTED   (SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND)
+
 static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
 
 /* Forward declaration of functions */
@@ -114,6 +117,45 @@ static void serial_omap_enable_ms(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
 }
 
+static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
+{
+   if (!(up->ier & UART_IER_THRI)) {
+   up->ier |= UART_IER_THRI;
+   serial_out(up, UART_IER, up->ier);
+   }
+}
+
+static inline void serial_omap_disable_ier_thri(struct uart_omap_port *up)
+{
+   if (up->ier & UART_IER_THRI) {
+   up->ier &= ~UART_IER_THRI;
+   serial_out(up, UART_IER, up->ier);
+   }
+}
+
+static inline void serial_omap_thri_mode(struct uart_omap_port *up)
+{
+   unsigned char scr = serial_in(up, UART_OMAP_SCR);
+
+   if (up->tx_wait_end)
+   scr |= UART_OMAP_SCR_TX_EMPTY_CTL_IT;
+   else
+   scr &= ~UART_OMAP_SCR_TX_EMPTY_CTL_IT;
+   serial_out(up, UART_OMAP_SCR, scr);
+}
+
+static inline void serial_omap_update_rts(struct uart_omap_port *up)
+{
+   unsigned char mcr = up->mcr;
+   int rts_on_send = up->rs485.flags & SER_RS485_RTS_ON_SEND;
+
+   if ((up->rs485.flags & SER_RS485_ENABLED) &&
+   ((up->tx_in_progress && rts_on_send) ||
+!(up->tx_in_progress || rts_on_send)))
+   mcr |= UART_MCR_RTS;
+   serial_out(up, UART_MCR, mcr);
+}
+
 static void serial_omap_stop_tx(struct uart_port *port)
 {
struct uart_omap_port *up = (struct uart_omap_port *)port;
@@ -131,10 +173,14 @@ static void serial_omap_stop_tx(struct uart_port *port)
up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
}
 
-   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)) {
+   serial_omap_disable_ier_thri(up);
+   return;
}
+
+   up->tx_wait_end = 1;
+   serial_omap_thri_mode(up);
+   serial_omap_enable_ier_thri(up);
 }
 
 static void serial_omap_stop_rx(struct uart_port *port)
@@ -246,14 +292,6 @@ static void transmit_chars(struct uart_omap_port *up)
serial_omap_stop_tx(&up->port);
 }
 
-static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
-{
-   if (!(up->ier & UART_IER_THRI)) {
-   up->ier |= UART_IER_THRI;
-   serial_out(up, UART_IER, up->ier);
-   }
-}
-
 static void serial_omap_start_tx(struct uart_port *port)
 {
struct uart_omap_port *up = (struct uart_omap_port *)port;
@@ -261,6 +299,18 @@ static void serial_omap_start_tx(struct uart_port *port)
unsigned int start;
int ret = 0;
 
+   if (up->rs485.flags & SER_RS485_ENABLED) {
+   if (!up->tx_in_progress) {
+   up->tx_in_progress = 1;
+   serial_omap_update_rts(up);
+   }
+   if (up->tx_wait_end) {
+   up->tx_wait_end = 0;
+   serial_omap_thri_mode(up);
+   serial_omap_disable_ier_thri(up);
+   }
+   }
+
if (!up->use_dma) {
serial_omap_enable_ier_thri(up);
retur