/
0011-omap-serial-Fix-bug-when-using-rs485-mode.patch
132 lines (112 loc) · 4.25 KB
/
0011-omap-serial-Fix-bug-when-using-rs485-mode.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
From 758829a338356549be29d43fb875985333b8f013 Mon Sep 17 00:00:00 2001
From: Enrico Butera <ebutera@users.berlios.de>
Date: Tue, 17 Jan 2012 15:10:11 +0100
Subject: [PATCH 11/12] omap-serial: Fix bug when using rs485 mode.
Rebased patch from Javier Martinez Canillas [1]:
After finishing to transmit in rs485 mode the UART_IER, UART_OMAP_SCR and
UART_MCR_RTS values weren't updated correctly.
This had the effect that once a transmission was made from a source node in
a semi-duplex communication, the transmitter didn't allow others nodes to
transmit anymore.
If the tty was closed after it finished the transmission and re-opened to
transmit again the bug wasn't spot. Only happened if the tty was kept opened.
Also, this patch make a few cleanups to the omap-serial driver.
We only have to update the Ready-to-Send control line if the user sets the
SER_RS485_RTS_ON_SEND flag and testing inside the function is redundant.
If the user didn't set the SER_RS485_RTS_ON_SEND flag, we don't have to
update the RTS line, since is the hardware who manages this.
[1]: http://git.igep.es/?p=pub/scm/linux-omap-2.6.git;a=commit;h=ecb1bc3e28d23144c4d2bdaa41bd8379e0a8de43
Signed-off-by: Enrico Butera <ebutera@users.berlios.de>
---
drivers/tty/serial/omap-serial.c | 44 +++++++++++++++++++-------------------
1 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index f42fc70..12049f2 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -142,25 +142,19 @@ static inline void serial_omap_thri_mode(struct uart_omap_port *up)
serial_out(up, UART_OMAP_SCR, scr);
}
+static inline int rts_on_send(struct uart_omap_port *up)
+{
+ return up->rs485.flags & SER_RS485_RTS_ON_SEND;
+}
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) {
- if (up->tx_in_progress) {
- if (rts_on_send)
- mcr |= UART_MCR_RTS;
- else
- mcr &= ~UART_MCR_RTS;
- } else {
- if (rts_on_send)
- mcr &= ~UART_MCR_RTS;
- else
- mcr |= ~UART_MCR_RTS;
- }
- }
+ if (up->tx_in_progress)
+ mcr |= UART_MCR_RTS;
+ else
+ mcr &= ~UART_MCR_RTS;
serial_out(up, UART_MCR, mcr);
}
@@ -186,7 +180,8 @@ static void serial_omap_stop_tx(struct uart_port *port)
serial_omap_disable_ier_thri(up);
else {
up->tx_in_progress = 0;
- serial_omap_update_rts(up);
+ if (rts_on_send(up))
+ serial_omap_update_rts(up);
up->tx_wait_end = 1;
serial_omap_thri_mode(up);
serial_omap_enable_ier_thri(up);
@@ -312,7 +307,8 @@ static void serial_omap_start_tx(struct uart_port *port)
if (up->rs485.flags & SER_RS485_ENABLED) {
if (!up->tx_in_progress) {
up->tx_in_progress = 1;
- serial_omap_update_rts(up);
+ if (rts_on_send(up))
+ serial_omap_update_rts(up);
}
if (up->tx_wait_end) {
up->tx_wait_end = 0;
@@ -425,12 +421,15 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
spin_lock_irqsave(&up->port.lock, flags);
if (up->tx_wait_end && (iir & UART_IIR_THRI) &&
- __serial_omap_tx_empty(up)) {
+ __serial_omap_tx_empty(up) &&
+ up->rs485.flags & SER_RS485_ENABLED) {
up->tx_wait_end = 0;
up->tx_in_progress = 0;
- serial_omap_thri_mode(up);
- serial_omap_update_rts(up);
- serial_omap_disable_ier_thri(up);
+ up->ier = UART_IER_RLSI | UART_IER_RDI;
+ serial_out(up, UART_IER, up->ier);
+ serial_out(up, UART_OMAP_SCR, 0);
+ if (rts_on_send(up))
+ serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
spin_unlock_irqrestore(&up->port.lock, flags);
return IRQ_HANDLED;
}
@@ -510,7 +509,7 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
mcr |= up->mcr;
- if (up->rs485.flags & SER_RS485_ENABLED)
+ if (up->rs485.flags & SER_RS485_ENABLED && rts_on_send(up))
serial_omap_update_rts(up);
serial_out(up, UART_MCR, mcr);
@@ -1126,7 +1125,8 @@ serial_omap_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
up->tx_wait_end = 0;
}
up->rs485 = rs485conf;
- serial_omap_update_rts(up);
+ if (rts_on_send(up))
+ serial_omap_update_rts(up);
serial_omap_thri_mode(up);
spin_unlock_irqrestore(&up->port.lock, flags);
--
1.7.5.4