|
@@ -0,0 +1,143 @@
|
|
|
|
+--- a/drivers/tty/serial/omap-serial.c 2014-10-09 15:46:37.000000000 +0200
|
|
|
|
++++ b/drivers/tty/serial/omap-serial.c 2017-02-17 18:10:41.671674904 +0100
|
|
|
|
+@@ -283,21 +283,22 @@
|
|
|
|
+ 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 */
|
|
|
|
++ /* Handle RS-485 */
|
|
|
|
+ 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 */
|
|
|
|
++ if (up->scr & OMAP_UART_SCR_TX_EMPTY) {
|
|
|
|
++ /* THR interrupt is fired when both TX FIFO and TX
|
|
|
|
++ * shift register are empty. This means there's nothing
|
|
|
|
++ * left to transmit now, so make sure the THR interrupt
|
|
|
|
++ * is fired when TX FIFO is below the trigger level,
|
|
|
|
++ * disable THR interrupts and toggle the RS-485 GPIO
|
|
|
|
++ * data direction pin if needed.
|
|
|
|
++ */
|
|
|
|
++ up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
|
|
|
|
++ serial_out(up, UART_OMAP_SCR, up->scr);
|
|
|
|
+ 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) {
|
|
|
|
+@@ -305,6 +306,18 @@
|
|
|
|
+ }
|
|
|
|
+ gpio_set_value(up->rts_gpio, res);
|
|
|
|
+ }
|
|
|
|
++ } else {
|
|
|
|
++ /* We're asked to stop, but there's still stuff in the
|
|
|
|
++ * UART FIFO, so make sure the THR interrupt is fired
|
|
|
|
++ * when both TX FIFO and TX shift register are empty.
|
|
|
|
++ * The next THR interrupt (if no transmission is started
|
|
|
|
++ * in the meantime) will indicate the end of a
|
|
|
|
++ * transmission. Therefore we _don't_ disable THR
|
|
|
|
++ * interrupts in this situation.
|
|
|
|
++ */
|
|
|
|
++ up->scr |= OMAP_UART_SCR_TX_EMPTY;
|
|
|
|
++ serial_out(up, UART_OMAP_SCR, up->scr);
|
|
|
|
++ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+@@ -384,11 +397,17 @@
|
|
|
|
+
|
|
|
|
+ pm_runtime_get_sync(up->dev);
|
|
|
|
+
|
|
|
|
+- /* handle rs485 */
|
|
|
|
++ /* Handle RS-485 */
|
|
|
|
+ if (up->rs485.flags & SER_RS485_ENABLED) {
|
|
|
|
++ /* Fire THR interrupts when FIFO is below trigger level */
|
|
|
|
++ up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
|
|
|
|
++ serial_out(up, UART_OMAP_SCR, up->scr);
|
|
|
|
++
|
|
|
|
+ /* if rts not already enabled */
|
|
|
|
+ res = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0;
|
|
|
|
+ if (gpio_get_value(up->rts_gpio) != res) {
|
|
|
|
++ if(up->rs485.udelay_before_enable_tx)
|
|
|
|
++ udelay(up->rs485.udelay_before_enable_tx);
|
|
|
|
+ gpio_set_value(up->rts_gpio, res);
|
|
|
|
+ if (up->rs485.delay_rts_before_send > 0) {
|
|
|
|
+ mdelay(up->rs485.delay_rts_before_send);
|
|
|
|
+@@ -938,7 +957,7 @@
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ /* Set receive FIFO threshold to 16 characters and
|
|
|
|
+- * transmit FIFO threshold to 16 spaces
|
|
|
|
++ * transmit FIFO threshold to 32 spaces
|
|
|
|
+ */
|
|
|
|
+ up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK;
|
|
|
|
+ up->fcr &= ~OMAP_UART_FCR_TX_FIFO_TRIG_MASK;
|
|
|
|
+@@ -1353,6 +1372,15 @@
|
|
|
|
+ up->ier = mode;
|
|
|
|
+ serial_out(up, UART_IER, up->ier);
|
|
|
|
+
|
|
|
|
++ /* If RS-485 is disabled, make sure the THR interrupt is fired when
|
|
|
|
++ * TX FIFO is below the trigger level.
|
|
|
|
++ */
|
|
|
|
++ if (!(up->rs485.flags & SER_RS485_ENABLED) &&
|
|
|
|
++ (up->scr & OMAP_UART_SCR_TX_EMPTY)) {
|
|
|
|
++ up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
|
|
|
|
++ serial_out(up, UART_OMAP_SCR, up->scr);
|
|
|
|
++ }
|
|
|
|
++
|
|
|
|
+ spin_unlock_irqrestore(&up->port.lock, flags);
|
|
|
|
+ pm_runtime_mark_last_busy(up->dev);
|
|
|
|
+ pm_runtime_put_autosuspend(up->dev);
|
|
|
|
+@@ -1540,7 +1568,7 @@
|
|
|
|
+ struct device_node *np)
|
|
|
|
+ {
|
|
|
|
+ struct serial_rs485 *rs485conf = &up->rs485;
|
|
|
|
+- u32 rs485_delay[2];
|
|
|
|
++ u32 rs485_delay[3];
|
|
|
|
+ enum of_gpio_flags flags;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+@@ -1569,9 +1597,10 @@
|
|
|
|
+ up->rts_gpio = -EINVAL;
|
|
|
|
+
|
|
|
|
+ if (of_property_read_u32_array(np, "rs485-rts-delay",
|
|
|
|
+- rs485_delay, 2) == 0) {
|
|
|
|
++ rs485_delay, 3) == 0) {
|
|
|
|
+ rs485conf->delay_rts_before_send = rs485_delay[0];
|
|
|
|
+ rs485conf->delay_rts_after_send = rs485_delay[1];
|
|
|
|
++ rs485conf->udelay_before_enable_tx = rs485_delay[2];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (of_property_read_bool(np, "rs485-rx-during-tx"))
|
|
|
|
+--- a/Documentation/serial/serial-rs485.txt 2014-10-09 15:46:37.000000000 +0200
|
|
|
|
++++ b/Documentation/serial/serial-rs485.txt 2017-02-18 10:42:18.940765385 +0100
|
|
|
|
+@@ -116,6 +116,9 @@
|
|
|
|
+ /* Set rts delay after send, if needed: */
|
|
|
|
+ rs485conf.delay_rts_after_send = ...;
|
|
|
|
+
|
|
|
|
++ /* Set udelay_before_enable_tx, if needed: */
|
|
|
|
++ rs485conf.udelay_before_enable_tx = ...;
|
|
|
|
++
|
|
|
|
+ /* Set this flag if you want to receive data even whilst sending data */
|
|
|
|
+ rs485conf.flags |= SER_RS485_RX_DURING_TX;
|
|
|
|
+
|
|
|
|
+--- a/include/uapi/linux/serial.h 2014-10-09 15:46:37.000000000 +0200
|
|
|
|
++++ b/include/uapi/linux/serial.h 2017-02-18 14:55:50.717958730 +0100
|
|
|
|
+@@ -119,7 +119,8 @@ struct serial_rs485 {
|
|
|
|
+ #define SER_RS485_RX_DURING_TX (1 << 4)
|
|
|
|
+ __u32 delay_rts_before_send; /* Delay before send (milliseconds) */
|
|
|
|
+ __u32 delay_rts_after_send; /* Delay after send (milliseconds) */
|
|
|
|
+- __u32 padding[5]; /* Memory is cheap, new structs
|
|
|
|
++ __u32 udelay_before_enable_tx;/* Delay before switching to tx direction */
|
|
|
|
++ __u32 padding[4]; /* Memory is cheap, new structs
|
|
|
|
+ are a royal PITA .. */
|
|
|
|
+ };
|
|
|
|
+
|