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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
|
#
# Patch managed by http://www.holgerschurig.de/patcher.html
#
--- linux-2.4.27/include/asm-arm/arch-sa1100/simpad.h~simpad-serial
+++ linux-2.4.27/include/asm-arm/arch-sa1100/simpad.h
@@ -16,7 +16,7 @@
#error "include <asm/hardware.h> instead"
#endif
-#define GPIO_UART1_RTS GPIO_GPIO14
+#define GPIO_UART1_RTS GPIO_GPIO9
#define GPIO_UART1_DTR GPIO_GPIO7
#define GPIO_UART1_CTS GPIO_GPIO8
#define GPIO_UART1_DCD GPIO_GPIO23
@@ -31,12 +31,12 @@
#define GPIO_POWER_BUTTON GPIO_GPIO0
#define GPIO_UCB1300_IRQ GPIO_GPIO (22) /* UCB GPIO and touchscreen */
-#define IRQ_UART1_CTS IRQ_GPIO15
-#define IRQ_UART1_DCD GPIO_GPIO23
-#define IRQ_UART1_DSR GPIO_GPIO6
-#define IRQ_UART3_CTS GPIO_GPIO13
-#define IRQ_UART3_DCD GPIO_GPIO18
-#define IRQ_UART3_DSR GPIO_GPIO17
+#define IRQ_GPIO_UART1_CTS IRQ_GPIO8
+#define IRQ_GPIO_UART1_DCD IRQ_GPIO23
+#define IRQ_GPIO_UART1_DSR IRQ_GPIO6
+#define IRQ_GPIO_UART3_CTS IRQ_GPIO13
+#define IRQ_GPIO_UART3_DCD IRQ_GPIO18
+#define IRQ_GPIO_UART3_DSR IRQ_GPIO17
#define IRQ_GPIO_UCB1300_IRQ IRQ_GPIO22
#define IRQ_GPIO_POWER_BUTTON IRQ_GPIO0
--- linux-2.4.27/arch/arm/mach-sa1100/simpad.c~simpad-serial
+++ linux-2.4.27/arch/arm/mach-sa1100/simpad.c
@@ -22,9 +22,11 @@
#include "generic.h"
+#undef SIMPAD_UART_USE_IRQ // irq handling on CTS/DCD doesn't work yet
+
long cs3_shadow;
-long get_cs3_shadow()
+long get_cs3_shadow(void)
{
return cs3_shadow;
}
@@ -107,18 +109,170 @@
LAST_DESC
};
+#define SER_INFO(fmt, arg...) printk(KERN_INFO fmt "\n" , ## arg)
+
+static void simpad_uart_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ if (port->mapbase == _Ser1UTCR0) {
+ /* internal serial port (ttySA1, DECT/Bluetooth) */
+ if (mctrl & TIOCM_RTS) GPCR = GPIO_UART1_RTS;
+ else GPSR = GPIO_UART1_RTS;
+
+ if (mctrl & TIOCM_DTR) GPCR = GPIO_UART1_DTR;
+ else GPSR = GPIO_UART1_DTR;
+ }
+
+ else if (port->mapbase == _Ser3UTCR0) {
+ /* external serial port (ttySA0, RS232) */
+ if (mctrl & TIOCM_RTS) GPCR = GPIO_UART3_RTS;
+ else GPSR = GPIO_UART3_RTS;
+
+ if (mctrl & TIOCM_DTR) GPCR = GPIO_UART3_DTR;
+ else GPSR = GPIO_UART3_DTR;
+ }
+}
+
+static u_int simpad_uart_get_mctrl(struct uart_port *port)
+{
+ u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
+
+ if (port->mapbase == _Ser1UTCR0) {
+ /* internal serial port (ttySA1, DECT/Bluetooth) */
+ int gplr = GPLR;
+ if (gplr & GPIO_UART1_DCD) ret &= ~TIOCM_CD;
+ if (gplr & GPIO_UART1_CTS) ret &= ~TIOCM_CTS;
+ if (gplr & GPIO_UART1_DSR) ret &= ~TIOCM_DSR;
+ }
+
+ else if (port->mapbase == _Ser3UTCR0) {
+ /* external serial port (ttySA0, RS232) */
+ int gplr = GPLR;
+ if (gplr & GPIO_UART3_DCD) ret &= ~TIOCM_CD;
+ if (gplr & GPIO_UART3_CTS) ret &= ~TIOCM_CTS;
+ if (gplr & GPIO_UART3_DSR) ret &= ~TIOCM_DSR;
+ }
+ return ret;
+}
+
static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
{
- if (port->mapbase == (u_int)&Ser1UTCR0) {
+ if (port->mapbase == (u_int)&Ser3UTCR0) {
if (state)
clear_cs3_bit(RS232_ON);
else
set_cs3_bit(RS232_ON);
}
}
+/*
+ * Enable/Disable wake up events for this serial port.
+ * Obviously, we only support this on the normal COM port.
+ */
+static int simpad_uart_set_wake(struct uart_port *port, u_int enable)
+{
+ int err = -EINVAL;
+
+#if 0 // TODO: port management
+ if (port->mapbase == _Ser3UTCR0) {
+ if (enable)
+ PWER |= PWER_GPIO23 | PWER_GPIO25 ; /* DCD and CTS */
+ else
+ PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
+ err = 0;
+ }
+#endif
+
+ return err;
+}
+
+#ifdef SIMPAD_UART_USE_IRQ
+static void simpad_uart1_dcd_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct uart_port *port = dev_id;
+ /* Note: should only call this if something has changed */
+ uart_handle_dcd_change(port, !(GPLR & GPIO_UART1_DCD));
+}
+
+static void simpad_uart1_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct uart_port *port = dev_id;
+ /* Note: should only call this if something has changed */
+ uart_handle_cts_change(port, !(GPLR & GPIO_UART1_CTS));
+}
+
+static void simpad_uart3_dcd_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct uart_port *port = dev_id;
+ /* Note: should only call this if something has changed */
+ uart_handle_dcd_change(port, !(GPLR & GPIO_UART3_DCD));
+}
+
+static void simpad_uart3_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct uart_port *port = dev_id;
+ /* Note: should only call this if something has changed */
+ uart_handle_cts_change(port, !(GPLR & GPIO_UART3_CTS));
+}
+#endif
+
+static int simpad_uart_open(struct uart_port *port)
+{
+ int ret = 0;
+#ifdef SIMPAD_UART_USE_IRQ
+ if (port->mapbase == _Ser1UTCR0) {
+ set_GPIO_IRQ_edge(GPIO_UART1_DCD|GPIO_UART1_CTS,
+ GPIO_BOTH_EDGES);
+
+ ret = request_irq(IRQ_GPIO_UART1_DCD, simpad_uart1_dcd_intr,
+ 0, "UART1 DCD", port);
+ if (ret)
+ return ret;
+
+ ret = request_irq(IRQ_GPIO_UART1_CTS, simpad_uart1_cts_intr,
+ 0, "UART1 CTS", port);
+ if (ret)
+ free_irq(IRQ_GPIO_UART1_DCD, port);
+ }
+
+ else if (port->mapbase == _Ser3UTCR0) {
+ set_GPIO_IRQ_edge(GPIO_UART3_DCD|GPIO_UART3_CTS,
+ GPIO_BOTH_EDGES);
+
+ ret = request_irq(IRQ_GPIO_UART3_DCD, simpad_uart3_dcd_intr,
+ 0, "UART3 DCD", port);
+ if (ret)
+ return ret;
+
+ ret = request_irq(IRQ_GPIO_UART3_CTS, simpad_uart3_cts_intr,
+ 0, "UART3 CTS", port);
+ if (ret)
+ free_irq(IRQ_GPIO_UART3_DCD, port);
+ }
+#endif
+ return ret;
+}
+
+static void simpad_uart_close(struct uart_port *port)
+{
+#ifdef SIMPAD_UART_USE_IRQ
+ if (port->mapbase == _Ser1UTCR0) {
+ free_irq(IRQ_GPIO_UART1_DCD, port);
+ free_irq(IRQ_GPIO_UART1_CTS, port);
+ }
+
+ else if (port->mapbase == _Ser3UTCR0) {
+ free_irq(IRQ_GPIO_UART3_DCD, port);
+ free_irq(IRQ_GPIO_UART3_CTS, port);
+ }
+#endif
+}
static struct sa1100_port_fns simpad_port_fns __initdata = {
- .pm = simpad_uart_pm,
+ .set_mctrl = simpad_uart_set_mctrl,
+ .get_mctrl = simpad_uart_get_mctrl,
+ .pm = simpad_uart_pm,
+ .set_wake = simpad_uart_set_wake,
+ .open = simpad_uart_open,
+ .close = simpad_uart_close,
};
static void __init simpad_map_io(void)
@@ -129,13 +283,32 @@
set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
ENABLE_5V | nRESET_SIMCARD);
+ sa1100_register_uart_fns(&simpad_port_fns);
+
//It is only possible to register 3 UART in serial_sa1100.c
sa1100_register_uart(0, 3);
sa1100_register_uart(1, 1);
+ // txd and rxd use their alternate function
GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD);
+
+ // the control lines are gpio
+ GAFR &= ~(GPIO_UART1_RTS | GPIO_UART1_CTS | GPIO_UART1_DCD);
+ GAFR &= ~(GPIO_UART1_DSR | GPIO_UART1_DTR);
+ GAFR &= ~(GPIO_UART3_RTS | GPIO_UART3_CTS | GPIO_UART3_DCD);
+ GAFR &= ~(GPIO_UART3_DSR | GPIO_UART3_DTR);
+
+ // txd, rts and dtr are outputs
GPDR |= GPIO_UART_TXD;
+ GPDR |= GPIO_UART1_RTS | GPIO_UART3_RTS;
+ GPDR |= GPIO_UART1_DTR | GPIO_UART3_DTR;
+
+ // cts, dcd, dsr and rxd are inputs
+ GPDR &= ~(GPIO_UART1_CTS | GPIO_UART3_CTS);
+ GPDR &= ~(GPIO_UART1_DCD | GPIO_UART3_DCD);
+ GPDR &= ~(GPIO_UART1_DSR | GPIO_UART3_DSR);
GPDR &= ~GPIO_UART_RXD;
+
PPAR |= PPAR_UPR;
set_GPIO_IRQ_edge(GPIO_UCB1300_IRQ, GPIO_RISING_EDGE);
--- linux-2.4.27/drivers/video/mq200fb.c~simpad-serial
+++ linux-2.4.27/drivers/video/mq200fb.c
@@ -672,7 +672,7 @@
#ifdef CONFIG_SA1100_SIMPAD
GPDR |= (1<<3);
- GAFR |= ~(1<<3);
+ GAFR &= ~(1<<3);
GPSR |= (1<<3);
#endif
|