Commit 4f1296a5169c13b2c1f76c1446aaf361e8519050
1 parent
7bcd4dae62
Exists in
master
and in
7 other branches
[SERIAL]: Fix 32-bit warnings in sunzilog.c and sunsu.c
resource_size_t can be either a u64 or a u32, and we can't really know for sure, so when printing such a value out always use long-long printf formatting and cast the argument to that type. Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 2 changed files with 11 additions and 8 deletions Inline Diff
drivers/serial/sunsu.c
1 | /* $Id: su.c,v 1.55 2002/01/08 16:00:16 davem Exp $ | 1 | /* $Id: su.c,v 1.55 2002/01/08 16:00:16 davem Exp $ |
2 | * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI | 2 | * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI |
3 | * | 3 | * |
4 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) | 4 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) |
5 | * Copyright (C) 1998-1999 Pete Zaitcev (zaitcev@yahoo.com) | 5 | * Copyright (C) 1998-1999 Pete Zaitcev (zaitcev@yahoo.com) |
6 | * | 6 | * |
7 | * This is mainly a variation of 8250.c, credits go to authors mentioned | 7 | * This is mainly a variation of 8250.c, credits go to authors mentioned |
8 | * therein. In fact this driver should be merged into the generic 8250.c | 8 | * therein. In fact this driver should be merged into the generic 8250.c |
9 | * infrastructure perhaps using a 8250_sparc.c module. | 9 | * infrastructure perhaps using a 8250_sparc.c module. |
10 | * | 10 | * |
11 | * Fixed to use tty_get_baud_rate(). | 11 | * Fixed to use tty_get_baud_rate(). |
12 | * Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12 | 12 | * Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12 |
13 | * | 13 | * |
14 | * Converted to new 2.5.x UART layer. | 14 | * Converted to new 2.5.x UART layer. |
15 | * David S. Miller (davem@davemloft.net), 2002-Jul-29 | 15 | * David S. Miller (davem@davemloft.net), 2002-Jul-29 |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
21 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
22 | #include <linux/tty.h> | 22 | #include <linux/tty.h> |
23 | #include <linux/tty_flip.h> | 23 | #include <linux/tty_flip.h> |
24 | #include <linux/major.h> | 24 | #include <linux/major.h> |
25 | #include <linux/string.h> | 25 | #include <linux/string.h> |
26 | #include <linux/ptrace.h> | 26 | #include <linux/ptrace.h> |
27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
28 | #include <linux/circ_buf.h> | 28 | #include <linux/circ_buf.h> |
29 | #include <linux/serial.h> | 29 | #include <linux/serial.h> |
30 | #include <linux/sysrq.h> | 30 | #include <linux/sysrq.h> |
31 | #include <linux/console.h> | 31 | #include <linux/console.h> |
32 | #ifdef CONFIG_SERIO | 32 | #ifdef CONFIG_SERIO |
33 | #include <linux/serio.h> | 33 | #include <linux/serio.h> |
34 | #endif | 34 | #endif |
35 | #include <linux/serial_reg.h> | 35 | #include <linux/serial_reg.h> |
36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
37 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
38 | 38 | ||
39 | #include <asm/io.h> | 39 | #include <asm/io.h> |
40 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
41 | #include <asm/prom.h> | 41 | #include <asm/prom.h> |
42 | #include <asm/of_device.h> | 42 | #include <asm/of_device.h> |
43 | 43 | ||
44 | #if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | 44 | #if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
45 | #define SUPPORT_SYSRQ | 45 | #define SUPPORT_SYSRQ |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #include <linux/serial_core.h> | 48 | #include <linux/serial_core.h> |
49 | 49 | ||
50 | #include "suncore.h" | 50 | #include "suncore.h" |
51 | 51 | ||
52 | /* We are on a NS PC87303 clocked with 24.0 MHz, which results | 52 | /* We are on a NS PC87303 clocked with 24.0 MHz, which results |
53 | * in a UART clock of 1.8462 MHz. | 53 | * in a UART clock of 1.8462 MHz. |
54 | */ | 54 | */ |
55 | #define SU_BASE_BAUD (1846200 / 16) | 55 | #define SU_BASE_BAUD (1846200 / 16) |
56 | 56 | ||
57 | enum su_type { SU_PORT_NONE, SU_PORT_MS, SU_PORT_KBD, SU_PORT_PORT }; | 57 | enum su_type { SU_PORT_NONE, SU_PORT_MS, SU_PORT_KBD, SU_PORT_PORT }; |
58 | static char *su_typev[] = { "su(???)", "su(mouse)", "su(kbd)", "su(serial)" }; | 58 | static char *su_typev[] = { "su(???)", "su(mouse)", "su(kbd)", "su(serial)" }; |
59 | 59 | ||
60 | /* | 60 | /* |
61 | * Here we define the default xmit fifo size used for each type of UART. | 61 | * Here we define the default xmit fifo size used for each type of UART. |
62 | */ | 62 | */ |
63 | static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = { | 63 | static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = { |
64 | { "unknown", 1, 0 }, | 64 | { "unknown", 1, 0 }, |
65 | { "8250", 1, 0 }, | 65 | { "8250", 1, 0 }, |
66 | { "16450", 1, 0 }, | 66 | { "16450", 1, 0 }, |
67 | { "16550", 1, 0 }, | 67 | { "16550", 1, 0 }, |
68 | { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, | 68 | { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, |
69 | { "Cirrus", 1, 0 }, | 69 | { "Cirrus", 1, 0 }, |
70 | { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, | 70 | { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, |
71 | { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, | 71 | { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, |
72 | { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO }, | 72 | { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO }, |
73 | { "Startech", 1, 0 }, | 73 | { "Startech", 1, 0 }, |
74 | { "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO }, | 74 | { "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO }, |
75 | { "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, | 75 | { "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, |
76 | { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, | 76 | { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, |
77 | { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO } | 77 | { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO } |
78 | }; | 78 | }; |
79 | 79 | ||
80 | struct uart_sunsu_port { | 80 | struct uart_sunsu_port { |
81 | struct uart_port port; | 81 | struct uart_port port; |
82 | unsigned char acr; | 82 | unsigned char acr; |
83 | unsigned char ier; | 83 | unsigned char ier; |
84 | unsigned short rev; | 84 | unsigned short rev; |
85 | unsigned char lcr; | 85 | unsigned char lcr; |
86 | unsigned int lsr_break_flag; | 86 | unsigned int lsr_break_flag; |
87 | unsigned int cflag; | 87 | unsigned int cflag; |
88 | 88 | ||
89 | /* Probing information. */ | 89 | /* Probing information. */ |
90 | enum su_type su_type; | 90 | enum su_type su_type; |
91 | unsigned int type_probed; /* XXX Stupid */ | 91 | unsigned int type_probed; /* XXX Stupid */ |
92 | unsigned long reg_size; | 92 | unsigned long reg_size; |
93 | 93 | ||
94 | #ifdef CONFIG_SERIO | 94 | #ifdef CONFIG_SERIO |
95 | struct serio serio; | 95 | struct serio serio; |
96 | int serio_open; | 96 | int serio_open; |
97 | #endif | 97 | #endif |
98 | }; | 98 | }; |
99 | 99 | ||
100 | static unsigned int serial_in(struct uart_sunsu_port *up, int offset) | 100 | static unsigned int serial_in(struct uart_sunsu_port *up, int offset) |
101 | { | 101 | { |
102 | offset <<= up->port.regshift; | 102 | offset <<= up->port.regshift; |
103 | 103 | ||
104 | switch (up->port.iotype) { | 104 | switch (up->port.iotype) { |
105 | case UPIO_HUB6: | 105 | case UPIO_HUB6: |
106 | outb(up->port.hub6 - 1 + offset, up->port.iobase); | 106 | outb(up->port.hub6 - 1 + offset, up->port.iobase); |
107 | return inb(up->port.iobase + 1); | 107 | return inb(up->port.iobase + 1); |
108 | 108 | ||
109 | case UPIO_MEM: | 109 | case UPIO_MEM: |
110 | return readb(up->port.membase + offset); | 110 | return readb(up->port.membase + offset); |
111 | 111 | ||
112 | default: | 112 | default: |
113 | return inb(up->port.iobase + offset); | 113 | return inb(up->port.iobase + offset); |
114 | } | 114 | } |
115 | } | 115 | } |
116 | 116 | ||
117 | static void serial_out(struct uart_sunsu_port *up, int offset, int value) | 117 | static void serial_out(struct uart_sunsu_port *up, int offset, int value) |
118 | { | 118 | { |
119 | #ifndef CONFIG_SPARC64 | 119 | #ifndef CONFIG_SPARC64 |
120 | /* | 120 | /* |
121 | * MrCoffee has weird schematics: IRQ4 & P10(?) pins of SuperIO are | 121 | * MrCoffee has weird schematics: IRQ4 & P10(?) pins of SuperIO are |
122 | * connected with a gate then go to SlavIO. When IRQ4 goes tristated | 122 | * connected with a gate then go to SlavIO. When IRQ4 goes tristated |
123 | * gate outputs a logical one. Since we use level triggered interrupts | 123 | * gate outputs a logical one. Since we use level triggered interrupts |
124 | * we have lockup and watchdog reset. We cannot mask IRQ because | 124 | * we have lockup and watchdog reset. We cannot mask IRQ because |
125 | * keyboard shares IRQ with us (Word has it as Bob Smelik's design). | 125 | * keyboard shares IRQ with us (Word has it as Bob Smelik's design). |
126 | * This problem is similar to what Alpha people suffer, see serial.c. | 126 | * This problem is similar to what Alpha people suffer, see serial.c. |
127 | */ | 127 | */ |
128 | if (offset == UART_MCR) | 128 | if (offset == UART_MCR) |
129 | value |= UART_MCR_OUT2; | 129 | value |= UART_MCR_OUT2; |
130 | #endif | 130 | #endif |
131 | offset <<= up->port.regshift; | 131 | offset <<= up->port.regshift; |
132 | 132 | ||
133 | switch (up->port.iotype) { | 133 | switch (up->port.iotype) { |
134 | case UPIO_HUB6: | 134 | case UPIO_HUB6: |
135 | outb(up->port.hub6 - 1 + offset, up->port.iobase); | 135 | outb(up->port.hub6 - 1 + offset, up->port.iobase); |
136 | outb(value, up->port.iobase + 1); | 136 | outb(value, up->port.iobase + 1); |
137 | break; | 137 | break; |
138 | 138 | ||
139 | case UPIO_MEM: | 139 | case UPIO_MEM: |
140 | writeb(value, up->port.membase + offset); | 140 | writeb(value, up->port.membase + offset); |
141 | break; | 141 | break; |
142 | 142 | ||
143 | default: | 143 | default: |
144 | outb(value, up->port.iobase + offset); | 144 | outb(value, up->port.iobase + offset); |
145 | } | 145 | } |
146 | } | 146 | } |
147 | 147 | ||
148 | /* | 148 | /* |
149 | * We used to support using pause I/O for certain machines. We | 149 | * We used to support using pause I/O for certain machines. We |
150 | * haven't supported this for a while, but just in case it's badly | 150 | * haven't supported this for a while, but just in case it's badly |
151 | * needed for certain old 386 machines, I've left these #define's | 151 | * needed for certain old 386 machines, I've left these #define's |
152 | * in.... | 152 | * in.... |
153 | */ | 153 | */ |
154 | #define serial_inp(up, offset) serial_in(up, offset) | 154 | #define serial_inp(up, offset) serial_in(up, offset) |
155 | #define serial_outp(up, offset, value) serial_out(up, offset, value) | 155 | #define serial_outp(up, offset, value) serial_out(up, offset, value) |
156 | 156 | ||
157 | 157 | ||
158 | /* | 158 | /* |
159 | * For the 16C950 | 159 | * For the 16C950 |
160 | */ | 160 | */ |
161 | static void serial_icr_write(struct uart_sunsu_port *up, int offset, int value) | 161 | static void serial_icr_write(struct uart_sunsu_port *up, int offset, int value) |
162 | { | 162 | { |
163 | serial_out(up, UART_SCR, offset); | 163 | serial_out(up, UART_SCR, offset); |
164 | serial_out(up, UART_ICR, value); | 164 | serial_out(up, UART_ICR, value); |
165 | } | 165 | } |
166 | 166 | ||
167 | #if 0 /* Unused currently */ | 167 | #if 0 /* Unused currently */ |
168 | static unsigned int serial_icr_read(struct uart_sunsu_port *up, int offset) | 168 | static unsigned int serial_icr_read(struct uart_sunsu_port *up, int offset) |
169 | { | 169 | { |
170 | unsigned int value; | 170 | unsigned int value; |
171 | 171 | ||
172 | serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD); | 172 | serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD); |
173 | serial_out(up, UART_SCR, offset); | 173 | serial_out(up, UART_SCR, offset); |
174 | value = serial_in(up, UART_ICR); | 174 | value = serial_in(up, UART_ICR); |
175 | serial_icr_write(up, UART_ACR, up->acr); | 175 | serial_icr_write(up, UART_ACR, up->acr); |
176 | 176 | ||
177 | return value; | 177 | return value; |
178 | } | 178 | } |
179 | #endif | 179 | #endif |
180 | 180 | ||
181 | #ifdef CONFIG_SERIAL_8250_RSA | 181 | #ifdef CONFIG_SERIAL_8250_RSA |
182 | /* | 182 | /* |
183 | * Attempts to turn on the RSA FIFO. Returns zero on failure. | 183 | * Attempts to turn on the RSA FIFO. Returns zero on failure. |
184 | * We set the port uart clock rate if we succeed. | 184 | * We set the port uart clock rate if we succeed. |
185 | */ | 185 | */ |
186 | static int __enable_rsa(struct uart_sunsu_port *up) | 186 | static int __enable_rsa(struct uart_sunsu_port *up) |
187 | { | 187 | { |
188 | unsigned char mode; | 188 | unsigned char mode; |
189 | int result; | 189 | int result; |
190 | 190 | ||
191 | mode = serial_inp(up, UART_RSA_MSR); | 191 | mode = serial_inp(up, UART_RSA_MSR); |
192 | result = mode & UART_RSA_MSR_FIFO; | 192 | result = mode & UART_RSA_MSR_FIFO; |
193 | 193 | ||
194 | if (!result) { | 194 | if (!result) { |
195 | serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); | 195 | serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); |
196 | mode = serial_inp(up, UART_RSA_MSR); | 196 | mode = serial_inp(up, UART_RSA_MSR); |
197 | result = mode & UART_RSA_MSR_FIFO; | 197 | result = mode & UART_RSA_MSR_FIFO; |
198 | } | 198 | } |
199 | 199 | ||
200 | if (result) | 200 | if (result) |
201 | up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16; | 201 | up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16; |
202 | 202 | ||
203 | return result; | 203 | return result; |
204 | } | 204 | } |
205 | 205 | ||
206 | static void enable_rsa(struct uart_sunsu_port *up) | 206 | static void enable_rsa(struct uart_sunsu_port *up) |
207 | { | 207 | { |
208 | if (up->port.type == PORT_RSA) { | 208 | if (up->port.type == PORT_RSA) { |
209 | if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) { | 209 | if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) { |
210 | spin_lock_irq(&up->port.lock); | 210 | spin_lock_irq(&up->port.lock); |
211 | __enable_rsa(up); | 211 | __enable_rsa(up); |
212 | spin_unlock_irq(&up->port.lock); | 212 | spin_unlock_irq(&up->port.lock); |
213 | } | 213 | } |
214 | if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) | 214 | if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) |
215 | serial_outp(up, UART_RSA_FRR, 0); | 215 | serial_outp(up, UART_RSA_FRR, 0); |
216 | } | 216 | } |
217 | } | 217 | } |
218 | 218 | ||
219 | /* | 219 | /* |
220 | * Attempts to turn off the RSA FIFO. Returns zero on failure. | 220 | * Attempts to turn off the RSA FIFO. Returns zero on failure. |
221 | * It is unknown why interrupts were disabled in here. However, | 221 | * It is unknown why interrupts were disabled in here. However, |
222 | * the caller is expected to preserve this behaviour by grabbing | 222 | * the caller is expected to preserve this behaviour by grabbing |
223 | * the spinlock before calling this function. | 223 | * the spinlock before calling this function. |
224 | */ | 224 | */ |
225 | static void disable_rsa(struct uart_sunsu_port *up) | 225 | static void disable_rsa(struct uart_sunsu_port *up) |
226 | { | 226 | { |
227 | unsigned char mode; | 227 | unsigned char mode; |
228 | int result; | 228 | int result; |
229 | 229 | ||
230 | if (up->port.type == PORT_RSA && | 230 | if (up->port.type == PORT_RSA && |
231 | up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) { | 231 | up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) { |
232 | spin_lock_irq(&up->port.lock); | 232 | spin_lock_irq(&up->port.lock); |
233 | 233 | ||
234 | mode = serial_inp(up, UART_RSA_MSR); | 234 | mode = serial_inp(up, UART_RSA_MSR); |
235 | result = !(mode & UART_RSA_MSR_FIFO); | 235 | result = !(mode & UART_RSA_MSR_FIFO); |
236 | 236 | ||
237 | if (!result) { | 237 | if (!result) { |
238 | serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); | 238 | serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); |
239 | mode = serial_inp(up, UART_RSA_MSR); | 239 | mode = serial_inp(up, UART_RSA_MSR); |
240 | result = !(mode & UART_RSA_MSR_FIFO); | 240 | result = !(mode & UART_RSA_MSR_FIFO); |
241 | } | 241 | } |
242 | 242 | ||
243 | if (result) | 243 | if (result) |
244 | up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16; | 244 | up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16; |
245 | spin_unlock_irq(&up->port.lock); | 245 | spin_unlock_irq(&up->port.lock); |
246 | } | 246 | } |
247 | } | 247 | } |
248 | #endif /* CONFIG_SERIAL_8250_RSA */ | 248 | #endif /* CONFIG_SERIAL_8250_RSA */ |
249 | 249 | ||
250 | static inline void __stop_tx(struct uart_sunsu_port *p) | 250 | static inline void __stop_tx(struct uart_sunsu_port *p) |
251 | { | 251 | { |
252 | if (p->ier & UART_IER_THRI) { | 252 | if (p->ier & UART_IER_THRI) { |
253 | p->ier &= ~UART_IER_THRI; | 253 | p->ier &= ~UART_IER_THRI; |
254 | serial_out(p, UART_IER, p->ier); | 254 | serial_out(p, UART_IER, p->ier); |
255 | } | 255 | } |
256 | } | 256 | } |
257 | 257 | ||
258 | static void sunsu_stop_tx(struct uart_port *port) | 258 | static void sunsu_stop_tx(struct uart_port *port) |
259 | { | 259 | { |
260 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 260 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
261 | 261 | ||
262 | __stop_tx(up); | 262 | __stop_tx(up); |
263 | 263 | ||
264 | /* | 264 | /* |
265 | * We really want to stop the transmitter from sending. | 265 | * We really want to stop the transmitter from sending. |
266 | */ | 266 | */ |
267 | if (up->port.type == PORT_16C950) { | 267 | if (up->port.type == PORT_16C950) { |
268 | up->acr |= UART_ACR_TXDIS; | 268 | up->acr |= UART_ACR_TXDIS; |
269 | serial_icr_write(up, UART_ACR, up->acr); | 269 | serial_icr_write(up, UART_ACR, up->acr); |
270 | } | 270 | } |
271 | } | 271 | } |
272 | 272 | ||
273 | static void sunsu_start_tx(struct uart_port *port) | 273 | static void sunsu_start_tx(struct uart_port *port) |
274 | { | 274 | { |
275 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 275 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
276 | 276 | ||
277 | if (!(up->ier & UART_IER_THRI)) { | 277 | if (!(up->ier & UART_IER_THRI)) { |
278 | up->ier |= UART_IER_THRI; | 278 | up->ier |= UART_IER_THRI; |
279 | serial_out(up, UART_IER, up->ier); | 279 | serial_out(up, UART_IER, up->ier); |
280 | } | 280 | } |
281 | 281 | ||
282 | /* | 282 | /* |
283 | * Re-enable the transmitter if we disabled it. | 283 | * Re-enable the transmitter if we disabled it. |
284 | */ | 284 | */ |
285 | if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) { | 285 | if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) { |
286 | up->acr &= ~UART_ACR_TXDIS; | 286 | up->acr &= ~UART_ACR_TXDIS; |
287 | serial_icr_write(up, UART_ACR, up->acr); | 287 | serial_icr_write(up, UART_ACR, up->acr); |
288 | } | 288 | } |
289 | } | 289 | } |
290 | 290 | ||
291 | static void sunsu_stop_rx(struct uart_port *port) | 291 | static void sunsu_stop_rx(struct uart_port *port) |
292 | { | 292 | { |
293 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 293 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
294 | 294 | ||
295 | up->ier &= ~UART_IER_RLSI; | 295 | up->ier &= ~UART_IER_RLSI; |
296 | up->port.read_status_mask &= ~UART_LSR_DR; | 296 | up->port.read_status_mask &= ~UART_LSR_DR; |
297 | serial_out(up, UART_IER, up->ier); | 297 | serial_out(up, UART_IER, up->ier); |
298 | } | 298 | } |
299 | 299 | ||
300 | static void sunsu_enable_ms(struct uart_port *port) | 300 | static void sunsu_enable_ms(struct uart_port *port) |
301 | { | 301 | { |
302 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 302 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
303 | unsigned long flags; | 303 | unsigned long flags; |
304 | 304 | ||
305 | spin_lock_irqsave(&up->port.lock, flags); | 305 | spin_lock_irqsave(&up->port.lock, flags); |
306 | up->ier |= UART_IER_MSI; | 306 | up->ier |= UART_IER_MSI; |
307 | serial_out(up, UART_IER, up->ier); | 307 | serial_out(up, UART_IER, up->ier); |
308 | spin_unlock_irqrestore(&up->port.lock, flags); | 308 | spin_unlock_irqrestore(&up->port.lock, flags); |
309 | } | 309 | } |
310 | 310 | ||
311 | static struct tty_struct * | 311 | static struct tty_struct * |
312 | receive_chars(struct uart_sunsu_port *up, unsigned char *status) | 312 | receive_chars(struct uart_sunsu_port *up, unsigned char *status) |
313 | { | 313 | { |
314 | struct tty_struct *tty = up->port.info->tty; | 314 | struct tty_struct *tty = up->port.info->tty; |
315 | unsigned char ch, flag; | 315 | unsigned char ch, flag; |
316 | int max_count = 256; | 316 | int max_count = 256; |
317 | int saw_console_brk = 0; | 317 | int saw_console_brk = 0; |
318 | 318 | ||
319 | do { | 319 | do { |
320 | ch = serial_inp(up, UART_RX); | 320 | ch = serial_inp(up, UART_RX); |
321 | flag = TTY_NORMAL; | 321 | flag = TTY_NORMAL; |
322 | up->port.icount.rx++; | 322 | up->port.icount.rx++; |
323 | 323 | ||
324 | if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | | 324 | if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | |
325 | UART_LSR_FE | UART_LSR_OE))) { | 325 | UART_LSR_FE | UART_LSR_OE))) { |
326 | /* | 326 | /* |
327 | * For statistics only | 327 | * For statistics only |
328 | */ | 328 | */ |
329 | if (*status & UART_LSR_BI) { | 329 | if (*status & UART_LSR_BI) { |
330 | *status &= ~(UART_LSR_FE | UART_LSR_PE); | 330 | *status &= ~(UART_LSR_FE | UART_LSR_PE); |
331 | up->port.icount.brk++; | 331 | up->port.icount.brk++; |
332 | if (up->port.cons != NULL && | 332 | if (up->port.cons != NULL && |
333 | up->port.line == up->port.cons->index) | 333 | up->port.line == up->port.cons->index) |
334 | saw_console_brk = 1; | 334 | saw_console_brk = 1; |
335 | /* | 335 | /* |
336 | * We do the SysRQ and SAK checking | 336 | * We do the SysRQ and SAK checking |
337 | * here because otherwise the break | 337 | * here because otherwise the break |
338 | * may get masked by ignore_status_mask | 338 | * may get masked by ignore_status_mask |
339 | * or read_status_mask. | 339 | * or read_status_mask. |
340 | */ | 340 | */ |
341 | if (uart_handle_break(&up->port)) | 341 | if (uart_handle_break(&up->port)) |
342 | goto ignore_char; | 342 | goto ignore_char; |
343 | } else if (*status & UART_LSR_PE) | 343 | } else if (*status & UART_LSR_PE) |
344 | up->port.icount.parity++; | 344 | up->port.icount.parity++; |
345 | else if (*status & UART_LSR_FE) | 345 | else if (*status & UART_LSR_FE) |
346 | up->port.icount.frame++; | 346 | up->port.icount.frame++; |
347 | if (*status & UART_LSR_OE) | 347 | if (*status & UART_LSR_OE) |
348 | up->port.icount.overrun++; | 348 | up->port.icount.overrun++; |
349 | 349 | ||
350 | /* | 350 | /* |
351 | * Mask off conditions which should be ingored. | 351 | * Mask off conditions which should be ingored. |
352 | */ | 352 | */ |
353 | *status &= up->port.read_status_mask; | 353 | *status &= up->port.read_status_mask; |
354 | 354 | ||
355 | if (up->port.cons != NULL && | 355 | if (up->port.cons != NULL && |
356 | up->port.line == up->port.cons->index) { | 356 | up->port.line == up->port.cons->index) { |
357 | /* Recover the break flag from console xmit */ | 357 | /* Recover the break flag from console xmit */ |
358 | *status |= up->lsr_break_flag; | 358 | *status |= up->lsr_break_flag; |
359 | up->lsr_break_flag = 0; | 359 | up->lsr_break_flag = 0; |
360 | } | 360 | } |
361 | 361 | ||
362 | if (*status & UART_LSR_BI) { | 362 | if (*status & UART_LSR_BI) { |
363 | flag = TTY_BREAK; | 363 | flag = TTY_BREAK; |
364 | } else if (*status & UART_LSR_PE) | 364 | } else if (*status & UART_LSR_PE) |
365 | flag = TTY_PARITY; | 365 | flag = TTY_PARITY; |
366 | else if (*status & UART_LSR_FE) | 366 | else if (*status & UART_LSR_FE) |
367 | flag = TTY_FRAME; | 367 | flag = TTY_FRAME; |
368 | } | 368 | } |
369 | if (uart_handle_sysrq_char(&up->port, ch)) | 369 | if (uart_handle_sysrq_char(&up->port, ch)) |
370 | goto ignore_char; | 370 | goto ignore_char; |
371 | if ((*status & up->port.ignore_status_mask) == 0) | 371 | if ((*status & up->port.ignore_status_mask) == 0) |
372 | tty_insert_flip_char(tty, ch, flag); | 372 | tty_insert_flip_char(tty, ch, flag); |
373 | if (*status & UART_LSR_OE) | 373 | if (*status & UART_LSR_OE) |
374 | /* | 374 | /* |
375 | * Overrun is special, since it's reported | 375 | * Overrun is special, since it's reported |
376 | * immediately, and doesn't affect the current | 376 | * immediately, and doesn't affect the current |
377 | * character. | 377 | * character. |
378 | */ | 378 | */ |
379 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 379 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
380 | ignore_char: | 380 | ignore_char: |
381 | *status = serial_inp(up, UART_LSR); | 381 | *status = serial_inp(up, UART_LSR); |
382 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); | 382 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); |
383 | 383 | ||
384 | if (saw_console_brk) | 384 | if (saw_console_brk) |
385 | sun_do_break(); | 385 | sun_do_break(); |
386 | 386 | ||
387 | return tty; | 387 | return tty; |
388 | } | 388 | } |
389 | 389 | ||
390 | static void transmit_chars(struct uart_sunsu_port *up) | 390 | static void transmit_chars(struct uart_sunsu_port *up) |
391 | { | 391 | { |
392 | struct circ_buf *xmit = &up->port.info->xmit; | 392 | struct circ_buf *xmit = &up->port.info->xmit; |
393 | int count; | 393 | int count; |
394 | 394 | ||
395 | if (up->port.x_char) { | 395 | if (up->port.x_char) { |
396 | serial_outp(up, UART_TX, up->port.x_char); | 396 | serial_outp(up, UART_TX, up->port.x_char); |
397 | up->port.icount.tx++; | 397 | up->port.icount.tx++; |
398 | up->port.x_char = 0; | 398 | up->port.x_char = 0; |
399 | return; | 399 | return; |
400 | } | 400 | } |
401 | if (uart_tx_stopped(&up->port)) { | 401 | if (uart_tx_stopped(&up->port)) { |
402 | sunsu_stop_tx(&up->port); | 402 | sunsu_stop_tx(&up->port); |
403 | return; | 403 | return; |
404 | } | 404 | } |
405 | if (uart_circ_empty(xmit)) { | 405 | if (uart_circ_empty(xmit)) { |
406 | __stop_tx(up); | 406 | __stop_tx(up); |
407 | return; | 407 | return; |
408 | } | 408 | } |
409 | 409 | ||
410 | count = up->port.fifosize; | 410 | count = up->port.fifosize; |
411 | do { | 411 | do { |
412 | serial_out(up, UART_TX, xmit->buf[xmit->tail]); | 412 | serial_out(up, UART_TX, xmit->buf[xmit->tail]); |
413 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 413 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
414 | up->port.icount.tx++; | 414 | up->port.icount.tx++; |
415 | if (uart_circ_empty(xmit)) | 415 | if (uart_circ_empty(xmit)) |
416 | break; | 416 | break; |
417 | } while (--count > 0); | 417 | } while (--count > 0); |
418 | 418 | ||
419 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 419 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
420 | uart_write_wakeup(&up->port); | 420 | uart_write_wakeup(&up->port); |
421 | 421 | ||
422 | if (uart_circ_empty(xmit)) | 422 | if (uart_circ_empty(xmit)) |
423 | __stop_tx(up); | 423 | __stop_tx(up); |
424 | } | 424 | } |
425 | 425 | ||
426 | static void check_modem_status(struct uart_sunsu_port *up) | 426 | static void check_modem_status(struct uart_sunsu_port *up) |
427 | { | 427 | { |
428 | int status; | 428 | int status; |
429 | 429 | ||
430 | status = serial_in(up, UART_MSR); | 430 | status = serial_in(up, UART_MSR); |
431 | 431 | ||
432 | if ((status & UART_MSR_ANY_DELTA) == 0) | 432 | if ((status & UART_MSR_ANY_DELTA) == 0) |
433 | return; | 433 | return; |
434 | 434 | ||
435 | if (status & UART_MSR_TERI) | 435 | if (status & UART_MSR_TERI) |
436 | up->port.icount.rng++; | 436 | up->port.icount.rng++; |
437 | if (status & UART_MSR_DDSR) | 437 | if (status & UART_MSR_DDSR) |
438 | up->port.icount.dsr++; | 438 | up->port.icount.dsr++; |
439 | if (status & UART_MSR_DDCD) | 439 | if (status & UART_MSR_DDCD) |
440 | uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); | 440 | uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); |
441 | if (status & UART_MSR_DCTS) | 441 | if (status & UART_MSR_DCTS) |
442 | uart_handle_cts_change(&up->port, status & UART_MSR_CTS); | 442 | uart_handle_cts_change(&up->port, status & UART_MSR_CTS); |
443 | 443 | ||
444 | wake_up_interruptible(&up->port.info->delta_msr_wait); | 444 | wake_up_interruptible(&up->port.info->delta_msr_wait); |
445 | } | 445 | } |
446 | 446 | ||
447 | static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id) | 447 | static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id) |
448 | { | 448 | { |
449 | struct uart_sunsu_port *up = dev_id; | 449 | struct uart_sunsu_port *up = dev_id; |
450 | unsigned long flags; | 450 | unsigned long flags; |
451 | unsigned char status; | 451 | unsigned char status; |
452 | 452 | ||
453 | spin_lock_irqsave(&up->port.lock, flags); | 453 | spin_lock_irqsave(&up->port.lock, flags); |
454 | 454 | ||
455 | do { | 455 | do { |
456 | struct tty_struct *tty; | 456 | struct tty_struct *tty; |
457 | 457 | ||
458 | status = serial_inp(up, UART_LSR); | 458 | status = serial_inp(up, UART_LSR); |
459 | tty = NULL; | 459 | tty = NULL; |
460 | if (status & UART_LSR_DR) | 460 | if (status & UART_LSR_DR) |
461 | tty = receive_chars(up, &status); | 461 | tty = receive_chars(up, &status); |
462 | check_modem_status(up); | 462 | check_modem_status(up); |
463 | if (status & UART_LSR_THRE) | 463 | if (status & UART_LSR_THRE) |
464 | transmit_chars(up); | 464 | transmit_chars(up); |
465 | 465 | ||
466 | spin_unlock_irqrestore(&up->port.lock, flags); | 466 | spin_unlock_irqrestore(&up->port.lock, flags); |
467 | 467 | ||
468 | if (tty) | 468 | if (tty) |
469 | tty_flip_buffer_push(tty); | 469 | tty_flip_buffer_push(tty); |
470 | 470 | ||
471 | spin_lock_irqsave(&up->port.lock, flags); | 471 | spin_lock_irqsave(&up->port.lock, flags); |
472 | 472 | ||
473 | } while (!(serial_in(up, UART_IIR) & UART_IIR_NO_INT)); | 473 | } while (!(serial_in(up, UART_IIR) & UART_IIR_NO_INT)); |
474 | 474 | ||
475 | spin_unlock_irqrestore(&up->port.lock, flags); | 475 | spin_unlock_irqrestore(&up->port.lock, flags); |
476 | 476 | ||
477 | return IRQ_HANDLED; | 477 | return IRQ_HANDLED; |
478 | } | 478 | } |
479 | 479 | ||
480 | /* Separate interrupt handling path for keyboard/mouse ports. */ | 480 | /* Separate interrupt handling path for keyboard/mouse ports. */ |
481 | 481 | ||
482 | static void | 482 | static void |
483 | sunsu_change_speed(struct uart_port *port, unsigned int cflag, | 483 | sunsu_change_speed(struct uart_port *port, unsigned int cflag, |
484 | unsigned int iflag, unsigned int quot); | 484 | unsigned int iflag, unsigned int quot); |
485 | 485 | ||
486 | static void sunsu_change_mouse_baud(struct uart_sunsu_port *up) | 486 | static void sunsu_change_mouse_baud(struct uart_sunsu_port *up) |
487 | { | 487 | { |
488 | unsigned int cur_cflag = up->cflag; | 488 | unsigned int cur_cflag = up->cflag; |
489 | int quot, new_baud; | 489 | int quot, new_baud; |
490 | 490 | ||
491 | up->cflag &= ~CBAUD; | 491 | up->cflag &= ~CBAUD; |
492 | up->cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud); | 492 | up->cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud); |
493 | 493 | ||
494 | quot = up->port.uartclk / (16 * new_baud); | 494 | quot = up->port.uartclk / (16 * new_baud); |
495 | 495 | ||
496 | sunsu_change_speed(&up->port, up->cflag, 0, quot); | 496 | sunsu_change_speed(&up->port, up->cflag, 0, quot); |
497 | } | 497 | } |
498 | 498 | ||
499 | static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break) | 499 | static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break) |
500 | { | 500 | { |
501 | do { | 501 | do { |
502 | unsigned char ch = serial_inp(up, UART_RX); | 502 | unsigned char ch = serial_inp(up, UART_RX); |
503 | 503 | ||
504 | /* Stop-A is handled by drivers/char/keyboard.c now. */ | 504 | /* Stop-A is handled by drivers/char/keyboard.c now. */ |
505 | if (up->su_type == SU_PORT_KBD) { | 505 | if (up->su_type == SU_PORT_KBD) { |
506 | #ifdef CONFIG_SERIO | 506 | #ifdef CONFIG_SERIO |
507 | serio_interrupt(&up->serio, ch, 0); | 507 | serio_interrupt(&up->serio, ch, 0); |
508 | #endif | 508 | #endif |
509 | } else if (up->su_type == SU_PORT_MS) { | 509 | } else if (up->su_type == SU_PORT_MS) { |
510 | int ret = suncore_mouse_baud_detection(ch, is_break); | 510 | int ret = suncore_mouse_baud_detection(ch, is_break); |
511 | 511 | ||
512 | switch (ret) { | 512 | switch (ret) { |
513 | case 2: | 513 | case 2: |
514 | sunsu_change_mouse_baud(up); | 514 | sunsu_change_mouse_baud(up); |
515 | /* fallthru */ | 515 | /* fallthru */ |
516 | case 1: | 516 | case 1: |
517 | break; | 517 | break; |
518 | 518 | ||
519 | case 0: | 519 | case 0: |
520 | #ifdef CONFIG_SERIO | 520 | #ifdef CONFIG_SERIO |
521 | serio_interrupt(&up->serio, ch, 0); | 521 | serio_interrupt(&up->serio, ch, 0); |
522 | #endif | 522 | #endif |
523 | break; | 523 | break; |
524 | }; | 524 | }; |
525 | } | 525 | } |
526 | } while (serial_in(up, UART_LSR) & UART_LSR_DR); | 526 | } while (serial_in(up, UART_LSR) & UART_LSR_DR); |
527 | } | 527 | } |
528 | 528 | ||
529 | static irqreturn_t sunsu_kbd_ms_interrupt(int irq, void *dev_id) | 529 | static irqreturn_t sunsu_kbd_ms_interrupt(int irq, void *dev_id) |
530 | { | 530 | { |
531 | struct uart_sunsu_port *up = dev_id; | 531 | struct uart_sunsu_port *up = dev_id; |
532 | 532 | ||
533 | if (!(serial_in(up, UART_IIR) & UART_IIR_NO_INT)) { | 533 | if (!(serial_in(up, UART_IIR) & UART_IIR_NO_INT)) { |
534 | unsigned char status = serial_inp(up, UART_LSR); | 534 | unsigned char status = serial_inp(up, UART_LSR); |
535 | 535 | ||
536 | if ((status & UART_LSR_DR) || (status & UART_LSR_BI)) | 536 | if ((status & UART_LSR_DR) || (status & UART_LSR_BI)) |
537 | receive_kbd_ms_chars(up, (status & UART_LSR_BI) != 0); | 537 | receive_kbd_ms_chars(up, (status & UART_LSR_BI) != 0); |
538 | } | 538 | } |
539 | 539 | ||
540 | return IRQ_HANDLED; | 540 | return IRQ_HANDLED; |
541 | } | 541 | } |
542 | 542 | ||
543 | static unsigned int sunsu_tx_empty(struct uart_port *port) | 543 | static unsigned int sunsu_tx_empty(struct uart_port *port) |
544 | { | 544 | { |
545 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 545 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
546 | unsigned long flags; | 546 | unsigned long flags; |
547 | unsigned int ret; | 547 | unsigned int ret; |
548 | 548 | ||
549 | spin_lock_irqsave(&up->port.lock, flags); | 549 | spin_lock_irqsave(&up->port.lock, flags); |
550 | ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; | 550 | ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; |
551 | spin_unlock_irqrestore(&up->port.lock, flags); | 551 | spin_unlock_irqrestore(&up->port.lock, flags); |
552 | 552 | ||
553 | return ret; | 553 | return ret; |
554 | } | 554 | } |
555 | 555 | ||
556 | static unsigned int sunsu_get_mctrl(struct uart_port *port) | 556 | static unsigned int sunsu_get_mctrl(struct uart_port *port) |
557 | { | 557 | { |
558 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 558 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
559 | unsigned char status; | 559 | unsigned char status; |
560 | unsigned int ret; | 560 | unsigned int ret; |
561 | 561 | ||
562 | status = serial_in(up, UART_MSR); | 562 | status = serial_in(up, UART_MSR); |
563 | 563 | ||
564 | ret = 0; | 564 | ret = 0; |
565 | if (status & UART_MSR_DCD) | 565 | if (status & UART_MSR_DCD) |
566 | ret |= TIOCM_CAR; | 566 | ret |= TIOCM_CAR; |
567 | if (status & UART_MSR_RI) | 567 | if (status & UART_MSR_RI) |
568 | ret |= TIOCM_RNG; | 568 | ret |= TIOCM_RNG; |
569 | if (status & UART_MSR_DSR) | 569 | if (status & UART_MSR_DSR) |
570 | ret |= TIOCM_DSR; | 570 | ret |= TIOCM_DSR; |
571 | if (status & UART_MSR_CTS) | 571 | if (status & UART_MSR_CTS) |
572 | ret |= TIOCM_CTS; | 572 | ret |= TIOCM_CTS; |
573 | return ret; | 573 | return ret; |
574 | } | 574 | } |
575 | 575 | ||
576 | static void sunsu_set_mctrl(struct uart_port *port, unsigned int mctrl) | 576 | static void sunsu_set_mctrl(struct uart_port *port, unsigned int mctrl) |
577 | { | 577 | { |
578 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 578 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
579 | unsigned char mcr = 0; | 579 | unsigned char mcr = 0; |
580 | 580 | ||
581 | if (mctrl & TIOCM_RTS) | 581 | if (mctrl & TIOCM_RTS) |
582 | mcr |= UART_MCR_RTS; | 582 | mcr |= UART_MCR_RTS; |
583 | if (mctrl & TIOCM_DTR) | 583 | if (mctrl & TIOCM_DTR) |
584 | mcr |= UART_MCR_DTR; | 584 | mcr |= UART_MCR_DTR; |
585 | if (mctrl & TIOCM_OUT1) | 585 | if (mctrl & TIOCM_OUT1) |
586 | mcr |= UART_MCR_OUT1; | 586 | mcr |= UART_MCR_OUT1; |
587 | if (mctrl & TIOCM_OUT2) | 587 | if (mctrl & TIOCM_OUT2) |
588 | mcr |= UART_MCR_OUT2; | 588 | mcr |= UART_MCR_OUT2; |
589 | if (mctrl & TIOCM_LOOP) | 589 | if (mctrl & TIOCM_LOOP) |
590 | mcr |= UART_MCR_LOOP; | 590 | mcr |= UART_MCR_LOOP; |
591 | 591 | ||
592 | serial_out(up, UART_MCR, mcr); | 592 | serial_out(up, UART_MCR, mcr); |
593 | } | 593 | } |
594 | 594 | ||
595 | static void sunsu_break_ctl(struct uart_port *port, int break_state) | 595 | static void sunsu_break_ctl(struct uart_port *port, int break_state) |
596 | { | 596 | { |
597 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 597 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
598 | unsigned long flags; | 598 | unsigned long flags; |
599 | 599 | ||
600 | spin_lock_irqsave(&up->port.lock, flags); | 600 | spin_lock_irqsave(&up->port.lock, flags); |
601 | if (break_state == -1) | 601 | if (break_state == -1) |
602 | up->lcr |= UART_LCR_SBC; | 602 | up->lcr |= UART_LCR_SBC; |
603 | else | 603 | else |
604 | up->lcr &= ~UART_LCR_SBC; | 604 | up->lcr &= ~UART_LCR_SBC; |
605 | serial_out(up, UART_LCR, up->lcr); | 605 | serial_out(up, UART_LCR, up->lcr); |
606 | spin_unlock_irqrestore(&up->port.lock, flags); | 606 | spin_unlock_irqrestore(&up->port.lock, flags); |
607 | } | 607 | } |
608 | 608 | ||
609 | static int sunsu_startup(struct uart_port *port) | 609 | static int sunsu_startup(struct uart_port *port) |
610 | { | 610 | { |
611 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 611 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
612 | unsigned long flags; | 612 | unsigned long flags; |
613 | int retval; | 613 | int retval; |
614 | 614 | ||
615 | if (up->port.type == PORT_16C950) { | 615 | if (up->port.type == PORT_16C950) { |
616 | /* Wake up and initialize UART */ | 616 | /* Wake up and initialize UART */ |
617 | up->acr = 0; | 617 | up->acr = 0; |
618 | serial_outp(up, UART_LCR, 0xBF); | 618 | serial_outp(up, UART_LCR, 0xBF); |
619 | serial_outp(up, UART_EFR, UART_EFR_ECB); | 619 | serial_outp(up, UART_EFR, UART_EFR_ECB); |
620 | serial_outp(up, UART_IER, 0); | 620 | serial_outp(up, UART_IER, 0); |
621 | serial_outp(up, UART_LCR, 0); | 621 | serial_outp(up, UART_LCR, 0); |
622 | serial_icr_write(up, UART_CSR, 0); /* Reset the UART */ | 622 | serial_icr_write(up, UART_CSR, 0); /* Reset the UART */ |
623 | serial_outp(up, UART_LCR, 0xBF); | 623 | serial_outp(up, UART_LCR, 0xBF); |
624 | serial_outp(up, UART_EFR, UART_EFR_ECB); | 624 | serial_outp(up, UART_EFR, UART_EFR_ECB); |
625 | serial_outp(up, UART_LCR, 0); | 625 | serial_outp(up, UART_LCR, 0); |
626 | } | 626 | } |
627 | 627 | ||
628 | #ifdef CONFIG_SERIAL_8250_RSA | 628 | #ifdef CONFIG_SERIAL_8250_RSA |
629 | /* | 629 | /* |
630 | * If this is an RSA port, see if we can kick it up to the | 630 | * If this is an RSA port, see if we can kick it up to the |
631 | * higher speed clock. | 631 | * higher speed clock. |
632 | */ | 632 | */ |
633 | enable_rsa(up); | 633 | enable_rsa(up); |
634 | #endif | 634 | #endif |
635 | 635 | ||
636 | /* | 636 | /* |
637 | * Clear the FIFO buffers and disable them. | 637 | * Clear the FIFO buffers and disable them. |
638 | * (they will be reenabled in set_termios()) | 638 | * (they will be reenabled in set_termios()) |
639 | */ | 639 | */ |
640 | if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) { | 640 | if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) { |
641 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); | 641 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); |
642 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | | 642 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | |
643 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); | 643 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); |
644 | serial_outp(up, UART_FCR, 0); | 644 | serial_outp(up, UART_FCR, 0); |
645 | } | 645 | } |
646 | 646 | ||
647 | /* | 647 | /* |
648 | * Clear the interrupt registers. | 648 | * Clear the interrupt registers. |
649 | */ | 649 | */ |
650 | (void) serial_inp(up, UART_LSR); | 650 | (void) serial_inp(up, UART_LSR); |
651 | (void) serial_inp(up, UART_RX); | 651 | (void) serial_inp(up, UART_RX); |
652 | (void) serial_inp(up, UART_IIR); | 652 | (void) serial_inp(up, UART_IIR); |
653 | (void) serial_inp(up, UART_MSR); | 653 | (void) serial_inp(up, UART_MSR); |
654 | 654 | ||
655 | /* | 655 | /* |
656 | * At this point, there's no way the LSR could still be 0xff; | 656 | * At this point, there's no way the LSR could still be 0xff; |
657 | * if it is, then bail out, because there's likely no UART | 657 | * if it is, then bail out, because there's likely no UART |
658 | * here. | 658 | * here. |
659 | */ | 659 | */ |
660 | if (!(up->port.flags & UPF_BUGGY_UART) && | 660 | if (!(up->port.flags & UPF_BUGGY_UART) && |
661 | (serial_inp(up, UART_LSR) == 0xff)) { | 661 | (serial_inp(up, UART_LSR) == 0xff)) { |
662 | printk("ttyS%d: LSR safety check engaged!\n", up->port.line); | 662 | printk("ttyS%d: LSR safety check engaged!\n", up->port.line); |
663 | return -ENODEV; | 663 | return -ENODEV; |
664 | } | 664 | } |
665 | 665 | ||
666 | if (up->su_type != SU_PORT_PORT) { | 666 | if (up->su_type != SU_PORT_PORT) { |
667 | retval = request_irq(up->port.irq, sunsu_kbd_ms_interrupt, | 667 | retval = request_irq(up->port.irq, sunsu_kbd_ms_interrupt, |
668 | IRQF_SHARED, su_typev[up->su_type], up); | 668 | IRQF_SHARED, su_typev[up->su_type], up); |
669 | } else { | 669 | } else { |
670 | retval = request_irq(up->port.irq, sunsu_serial_interrupt, | 670 | retval = request_irq(up->port.irq, sunsu_serial_interrupt, |
671 | IRQF_SHARED, su_typev[up->su_type], up); | 671 | IRQF_SHARED, su_typev[up->su_type], up); |
672 | } | 672 | } |
673 | if (retval) { | 673 | if (retval) { |
674 | printk("su: Cannot register IRQ %d\n", up->port.irq); | 674 | printk("su: Cannot register IRQ %d\n", up->port.irq); |
675 | return retval; | 675 | return retval; |
676 | } | 676 | } |
677 | 677 | ||
678 | /* | 678 | /* |
679 | * Now, initialize the UART | 679 | * Now, initialize the UART |
680 | */ | 680 | */ |
681 | serial_outp(up, UART_LCR, UART_LCR_WLEN8); | 681 | serial_outp(up, UART_LCR, UART_LCR_WLEN8); |
682 | 682 | ||
683 | spin_lock_irqsave(&up->port.lock, flags); | 683 | spin_lock_irqsave(&up->port.lock, flags); |
684 | 684 | ||
685 | up->port.mctrl |= TIOCM_OUT2; | 685 | up->port.mctrl |= TIOCM_OUT2; |
686 | 686 | ||
687 | sunsu_set_mctrl(&up->port, up->port.mctrl); | 687 | sunsu_set_mctrl(&up->port, up->port.mctrl); |
688 | spin_unlock_irqrestore(&up->port.lock, flags); | 688 | spin_unlock_irqrestore(&up->port.lock, flags); |
689 | 689 | ||
690 | /* | 690 | /* |
691 | * Finally, enable interrupts. Note: Modem status interrupts | 691 | * Finally, enable interrupts. Note: Modem status interrupts |
692 | * are set via set_termios(), which will be occurring imminently | 692 | * are set via set_termios(), which will be occurring imminently |
693 | * anyway, so we don't enable them here. | 693 | * anyway, so we don't enable them here. |
694 | */ | 694 | */ |
695 | up->ier = UART_IER_RLSI | UART_IER_RDI; | 695 | up->ier = UART_IER_RLSI | UART_IER_RDI; |
696 | serial_outp(up, UART_IER, up->ier); | 696 | serial_outp(up, UART_IER, up->ier); |
697 | 697 | ||
698 | if (up->port.flags & UPF_FOURPORT) { | 698 | if (up->port.flags & UPF_FOURPORT) { |
699 | unsigned int icp; | 699 | unsigned int icp; |
700 | /* | 700 | /* |
701 | * Enable interrupts on the AST Fourport board | 701 | * Enable interrupts on the AST Fourport board |
702 | */ | 702 | */ |
703 | icp = (up->port.iobase & 0xfe0) | 0x01f; | 703 | icp = (up->port.iobase & 0xfe0) | 0x01f; |
704 | outb_p(0x80, icp); | 704 | outb_p(0x80, icp); |
705 | (void) inb_p(icp); | 705 | (void) inb_p(icp); |
706 | } | 706 | } |
707 | 707 | ||
708 | /* | 708 | /* |
709 | * And clear the interrupt registers again for luck. | 709 | * And clear the interrupt registers again for luck. |
710 | */ | 710 | */ |
711 | (void) serial_inp(up, UART_LSR); | 711 | (void) serial_inp(up, UART_LSR); |
712 | (void) serial_inp(up, UART_RX); | 712 | (void) serial_inp(up, UART_RX); |
713 | (void) serial_inp(up, UART_IIR); | 713 | (void) serial_inp(up, UART_IIR); |
714 | (void) serial_inp(up, UART_MSR); | 714 | (void) serial_inp(up, UART_MSR); |
715 | 715 | ||
716 | return 0; | 716 | return 0; |
717 | } | 717 | } |
718 | 718 | ||
719 | static void sunsu_shutdown(struct uart_port *port) | 719 | static void sunsu_shutdown(struct uart_port *port) |
720 | { | 720 | { |
721 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 721 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
722 | unsigned long flags; | 722 | unsigned long flags; |
723 | 723 | ||
724 | /* | 724 | /* |
725 | * Disable interrupts from this port | 725 | * Disable interrupts from this port |
726 | */ | 726 | */ |
727 | up->ier = 0; | 727 | up->ier = 0; |
728 | serial_outp(up, UART_IER, 0); | 728 | serial_outp(up, UART_IER, 0); |
729 | 729 | ||
730 | spin_lock_irqsave(&up->port.lock, flags); | 730 | spin_lock_irqsave(&up->port.lock, flags); |
731 | if (up->port.flags & UPF_FOURPORT) { | 731 | if (up->port.flags & UPF_FOURPORT) { |
732 | /* reset interrupts on the AST Fourport board */ | 732 | /* reset interrupts on the AST Fourport board */ |
733 | inb((up->port.iobase & 0xfe0) | 0x1f); | 733 | inb((up->port.iobase & 0xfe0) | 0x1f); |
734 | up->port.mctrl |= TIOCM_OUT1; | 734 | up->port.mctrl |= TIOCM_OUT1; |
735 | } else | 735 | } else |
736 | up->port.mctrl &= ~TIOCM_OUT2; | 736 | up->port.mctrl &= ~TIOCM_OUT2; |
737 | 737 | ||
738 | sunsu_set_mctrl(&up->port, up->port.mctrl); | 738 | sunsu_set_mctrl(&up->port, up->port.mctrl); |
739 | spin_unlock_irqrestore(&up->port.lock, flags); | 739 | spin_unlock_irqrestore(&up->port.lock, flags); |
740 | 740 | ||
741 | /* | 741 | /* |
742 | * Disable break condition and FIFOs | 742 | * Disable break condition and FIFOs |
743 | */ | 743 | */ |
744 | serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC); | 744 | serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC); |
745 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | | 745 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | |
746 | UART_FCR_CLEAR_RCVR | | 746 | UART_FCR_CLEAR_RCVR | |
747 | UART_FCR_CLEAR_XMIT); | 747 | UART_FCR_CLEAR_XMIT); |
748 | serial_outp(up, UART_FCR, 0); | 748 | serial_outp(up, UART_FCR, 0); |
749 | 749 | ||
750 | #ifdef CONFIG_SERIAL_8250_RSA | 750 | #ifdef CONFIG_SERIAL_8250_RSA |
751 | /* | 751 | /* |
752 | * Reset the RSA board back to 115kbps compat mode. | 752 | * Reset the RSA board back to 115kbps compat mode. |
753 | */ | 753 | */ |
754 | disable_rsa(up); | 754 | disable_rsa(up); |
755 | #endif | 755 | #endif |
756 | 756 | ||
757 | /* | 757 | /* |
758 | * Read data port to reset things. | 758 | * Read data port to reset things. |
759 | */ | 759 | */ |
760 | (void) serial_in(up, UART_RX); | 760 | (void) serial_in(up, UART_RX); |
761 | 761 | ||
762 | free_irq(up->port.irq, up); | 762 | free_irq(up->port.irq, up); |
763 | } | 763 | } |
764 | 764 | ||
765 | static void | 765 | static void |
766 | sunsu_change_speed(struct uart_port *port, unsigned int cflag, | 766 | sunsu_change_speed(struct uart_port *port, unsigned int cflag, |
767 | unsigned int iflag, unsigned int quot) | 767 | unsigned int iflag, unsigned int quot) |
768 | { | 768 | { |
769 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 769 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
770 | unsigned char cval, fcr = 0; | 770 | unsigned char cval, fcr = 0; |
771 | unsigned long flags; | 771 | unsigned long flags; |
772 | 772 | ||
773 | switch (cflag & CSIZE) { | 773 | switch (cflag & CSIZE) { |
774 | case CS5: | 774 | case CS5: |
775 | cval = 0x00; | 775 | cval = 0x00; |
776 | break; | 776 | break; |
777 | case CS6: | 777 | case CS6: |
778 | cval = 0x01; | 778 | cval = 0x01; |
779 | break; | 779 | break; |
780 | case CS7: | 780 | case CS7: |
781 | cval = 0x02; | 781 | cval = 0x02; |
782 | break; | 782 | break; |
783 | default: | 783 | default: |
784 | case CS8: | 784 | case CS8: |
785 | cval = 0x03; | 785 | cval = 0x03; |
786 | break; | 786 | break; |
787 | } | 787 | } |
788 | 788 | ||
789 | if (cflag & CSTOPB) | 789 | if (cflag & CSTOPB) |
790 | cval |= 0x04; | 790 | cval |= 0x04; |
791 | if (cflag & PARENB) | 791 | if (cflag & PARENB) |
792 | cval |= UART_LCR_PARITY; | 792 | cval |= UART_LCR_PARITY; |
793 | if (!(cflag & PARODD)) | 793 | if (!(cflag & PARODD)) |
794 | cval |= UART_LCR_EPAR; | 794 | cval |= UART_LCR_EPAR; |
795 | #ifdef CMSPAR | 795 | #ifdef CMSPAR |
796 | if (cflag & CMSPAR) | 796 | if (cflag & CMSPAR) |
797 | cval |= UART_LCR_SPAR; | 797 | cval |= UART_LCR_SPAR; |
798 | #endif | 798 | #endif |
799 | 799 | ||
800 | /* | 800 | /* |
801 | * Work around a bug in the Oxford Semiconductor 952 rev B | 801 | * Work around a bug in the Oxford Semiconductor 952 rev B |
802 | * chip which causes it to seriously miscalculate baud rates | 802 | * chip which causes it to seriously miscalculate baud rates |
803 | * when DLL is 0. | 803 | * when DLL is 0. |
804 | */ | 804 | */ |
805 | if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 && | 805 | if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 && |
806 | up->rev == 0x5201) | 806 | up->rev == 0x5201) |
807 | quot ++; | 807 | quot ++; |
808 | 808 | ||
809 | if (uart_config[up->port.type].flags & UART_USE_FIFO) { | 809 | if (uart_config[up->port.type].flags & UART_USE_FIFO) { |
810 | if ((up->port.uartclk / quot) < (2400 * 16)) | 810 | if ((up->port.uartclk / quot) < (2400 * 16)) |
811 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; | 811 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; |
812 | #ifdef CONFIG_SERIAL_8250_RSA | 812 | #ifdef CONFIG_SERIAL_8250_RSA |
813 | else if (up->port.type == PORT_RSA) | 813 | else if (up->port.type == PORT_RSA) |
814 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14; | 814 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14; |
815 | #endif | 815 | #endif |
816 | else | 816 | else |
817 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; | 817 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; |
818 | } | 818 | } |
819 | if (up->port.type == PORT_16750) | 819 | if (up->port.type == PORT_16750) |
820 | fcr |= UART_FCR7_64BYTE; | 820 | fcr |= UART_FCR7_64BYTE; |
821 | 821 | ||
822 | /* | 822 | /* |
823 | * Ok, we're now changing the port state. Do it with | 823 | * Ok, we're now changing the port state. Do it with |
824 | * interrupts disabled. | 824 | * interrupts disabled. |
825 | */ | 825 | */ |
826 | spin_lock_irqsave(&up->port.lock, flags); | 826 | spin_lock_irqsave(&up->port.lock, flags); |
827 | 827 | ||
828 | /* | 828 | /* |
829 | * Update the per-port timeout. | 829 | * Update the per-port timeout. |
830 | */ | 830 | */ |
831 | uart_update_timeout(port, cflag, (port->uartclk / (16 * quot))); | 831 | uart_update_timeout(port, cflag, (port->uartclk / (16 * quot))); |
832 | 832 | ||
833 | up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; | 833 | up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; |
834 | if (iflag & INPCK) | 834 | if (iflag & INPCK) |
835 | up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; | 835 | up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; |
836 | if (iflag & (BRKINT | PARMRK)) | 836 | if (iflag & (BRKINT | PARMRK)) |
837 | up->port.read_status_mask |= UART_LSR_BI; | 837 | up->port.read_status_mask |= UART_LSR_BI; |
838 | 838 | ||
839 | /* | 839 | /* |
840 | * Characteres to ignore | 840 | * Characteres to ignore |
841 | */ | 841 | */ |
842 | up->port.ignore_status_mask = 0; | 842 | up->port.ignore_status_mask = 0; |
843 | if (iflag & IGNPAR) | 843 | if (iflag & IGNPAR) |
844 | up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; | 844 | up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; |
845 | if (iflag & IGNBRK) { | 845 | if (iflag & IGNBRK) { |
846 | up->port.ignore_status_mask |= UART_LSR_BI; | 846 | up->port.ignore_status_mask |= UART_LSR_BI; |
847 | /* | 847 | /* |
848 | * If we're ignoring parity and break indicators, | 848 | * If we're ignoring parity and break indicators, |
849 | * ignore overruns too (for real raw support). | 849 | * ignore overruns too (for real raw support). |
850 | */ | 850 | */ |
851 | if (iflag & IGNPAR) | 851 | if (iflag & IGNPAR) |
852 | up->port.ignore_status_mask |= UART_LSR_OE; | 852 | up->port.ignore_status_mask |= UART_LSR_OE; |
853 | } | 853 | } |
854 | 854 | ||
855 | /* | 855 | /* |
856 | * ignore all characters if CREAD is not set | 856 | * ignore all characters if CREAD is not set |
857 | */ | 857 | */ |
858 | if ((cflag & CREAD) == 0) | 858 | if ((cflag & CREAD) == 0) |
859 | up->port.ignore_status_mask |= UART_LSR_DR; | 859 | up->port.ignore_status_mask |= UART_LSR_DR; |
860 | 860 | ||
861 | /* | 861 | /* |
862 | * CTS flow control flag and modem status interrupts | 862 | * CTS flow control flag and modem status interrupts |
863 | */ | 863 | */ |
864 | up->ier &= ~UART_IER_MSI; | 864 | up->ier &= ~UART_IER_MSI; |
865 | if (UART_ENABLE_MS(&up->port, cflag)) | 865 | if (UART_ENABLE_MS(&up->port, cflag)) |
866 | up->ier |= UART_IER_MSI; | 866 | up->ier |= UART_IER_MSI; |
867 | 867 | ||
868 | serial_out(up, UART_IER, up->ier); | 868 | serial_out(up, UART_IER, up->ier); |
869 | 869 | ||
870 | if (uart_config[up->port.type].flags & UART_STARTECH) { | 870 | if (uart_config[up->port.type].flags & UART_STARTECH) { |
871 | serial_outp(up, UART_LCR, 0xBF); | 871 | serial_outp(up, UART_LCR, 0xBF); |
872 | serial_outp(up, UART_EFR, cflag & CRTSCTS ? UART_EFR_CTS :0); | 872 | serial_outp(up, UART_EFR, cflag & CRTSCTS ? UART_EFR_CTS :0); |
873 | } | 873 | } |
874 | serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ | 874 | serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ |
875 | serial_outp(up, UART_DLL, quot & 0xff); /* LS of divisor */ | 875 | serial_outp(up, UART_DLL, quot & 0xff); /* LS of divisor */ |
876 | serial_outp(up, UART_DLM, quot >> 8); /* MS of divisor */ | 876 | serial_outp(up, UART_DLM, quot >> 8); /* MS of divisor */ |
877 | if (up->port.type == PORT_16750) | 877 | if (up->port.type == PORT_16750) |
878 | serial_outp(up, UART_FCR, fcr); /* set fcr */ | 878 | serial_outp(up, UART_FCR, fcr); /* set fcr */ |
879 | serial_outp(up, UART_LCR, cval); /* reset DLAB */ | 879 | serial_outp(up, UART_LCR, cval); /* reset DLAB */ |
880 | up->lcr = cval; /* Save LCR */ | 880 | up->lcr = cval; /* Save LCR */ |
881 | if (up->port.type != PORT_16750) { | 881 | if (up->port.type != PORT_16750) { |
882 | if (fcr & UART_FCR_ENABLE_FIFO) { | 882 | if (fcr & UART_FCR_ENABLE_FIFO) { |
883 | /* emulated UARTs (Lucent Venus 167x) need two steps */ | 883 | /* emulated UARTs (Lucent Venus 167x) need two steps */ |
884 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); | 884 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); |
885 | } | 885 | } |
886 | serial_outp(up, UART_FCR, fcr); /* set fcr */ | 886 | serial_outp(up, UART_FCR, fcr); /* set fcr */ |
887 | } | 887 | } |
888 | 888 | ||
889 | up->cflag = cflag; | 889 | up->cflag = cflag; |
890 | 890 | ||
891 | spin_unlock_irqrestore(&up->port.lock, flags); | 891 | spin_unlock_irqrestore(&up->port.lock, flags); |
892 | } | 892 | } |
893 | 893 | ||
894 | static void | 894 | static void |
895 | sunsu_set_termios(struct uart_port *port, struct ktermios *termios, | 895 | sunsu_set_termios(struct uart_port *port, struct ktermios *termios, |
896 | struct ktermios *old) | 896 | struct ktermios *old) |
897 | { | 897 | { |
898 | unsigned int baud, quot; | 898 | unsigned int baud, quot; |
899 | 899 | ||
900 | /* | 900 | /* |
901 | * Ask the core to calculate the divisor for us. | 901 | * Ask the core to calculate the divisor for us. |
902 | */ | 902 | */ |
903 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); | 903 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); |
904 | quot = uart_get_divisor(port, baud); | 904 | quot = uart_get_divisor(port, baud); |
905 | 905 | ||
906 | sunsu_change_speed(port, termios->c_cflag, termios->c_iflag, quot); | 906 | sunsu_change_speed(port, termios->c_cflag, termios->c_iflag, quot); |
907 | } | 907 | } |
908 | 908 | ||
909 | static void sunsu_release_port(struct uart_port *port) | 909 | static void sunsu_release_port(struct uart_port *port) |
910 | { | 910 | { |
911 | } | 911 | } |
912 | 912 | ||
913 | static int sunsu_request_port(struct uart_port *port) | 913 | static int sunsu_request_port(struct uart_port *port) |
914 | { | 914 | { |
915 | return 0; | 915 | return 0; |
916 | } | 916 | } |
917 | 917 | ||
918 | static void sunsu_config_port(struct uart_port *port, int flags) | 918 | static void sunsu_config_port(struct uart_port *port, int flags) |
919 | { | 919 | { |
920 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 920 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
921 | 921 | ||
922 | if (flags & UART_CONFIG_TYPE) { | 922 | if (flags & UART_CONFIG_TYPE) { |
923 | /* | 923 | /* |
924 | * We are supposed to call autoconfig here, but this requires | 924 | * We are supposed to call autoconfig here, but this requires |
925 | * splitting all the OBP probing crap from the UART probing. | 925 | * splitting all the OBP probing crap from the UART probing. |
926 | * We'll do it when we kill sunsu.c altogether. | 926 | * We'll do it when we kill sunsu.c altogether. |
927 | */ | 927 | */ |
928 | port->type = up->type_probed; /* XXX */ | 928 | port->type = up->type_probed; /* XXX */ |
929 | } | 929 | } |
930 | } | 930 | } |
931 | 931 | ||
932 | static int | 932 | static int |
933 | sunsu_verify_port(struct uart_port *port, struct serial_struct *ser) | 933 | sunsu_verify_port(struct uart_port *port, struct serial_struct *ser) |
934 | { | 934 | { |
935 | return -EINVAL; | 935 | return -EINVAL; |
936 | } | 936 | } |
937 | 937 | ||
938 | static const char * | 938 | static const char * |
939 | sunsu_type(struct uart_port *port) | 939 | sunsu_type(struct uart_port *port) |
940 | { | 940 | { |
941 | int type = port->type; | 941 | int type = port->type; |
942 | 942 | ||
943 | if (type >= ARRAY_SIZE(uart_config)) | 943 | if (type >= ARRAY_SIZE(uart_config)) |
944 | type = 0; | 944 | type = 0; |
945 | return uart_config[type].name; | 945 | return uart_config[type].name; |
946 | } | 946 | } |
947 | 947 | ||
948 | static struct uart_ops sunsu_pops = { | 948 | static struct uart_ops sunsu_pops = { |
949 | .tx_empty = sunsu_tx_empty, | 949 | .tx_empty = sunsu_tx_empty, |
950 | .set_mctrl = sunsu_set_mctrl, | 950 | .set_mctrl = sunsu_set_mctrl, |
951 | .get_mctrl = sunsu_get_mctrl, | 951 | .get_mctrl = sunsu_get_mctrl, |
952 | .stop_tx = sunsu_stop_tx, | 952 | .stop_tx = sunsu_stop_tx, |
953 | .start_tx = sunsu_start_tx, | 953 | .start_tx = sunsu_start_tx, |
954 | .stop_rx = sunsu_stop_rx, | 954 | .stop_rx = sunsu_stop_rx, |
955 | .enable_ms = sunsu_enable_ms, | 955 | .enable_ms = sunsu_enable_ms, |
956 | .break_ctl = sunsu_break_ctl, | 956 | .break_ctl = sunsu_break_ctl, |
957 | .startup = sunsu_startup, | 957 | .startup = sunsu_startup, |
958 | .shutdown = sunsu_shutdown, | 958 | .shutdown = sunsu_shutdown, |
959 | .set_termios = sunsu_set_termios, | 959 | .set_termios = sunsu_set_termios, |
960 | .type = sunsu_type, | 960 | .type = sunsu_type, |
961 | .release_port = sunsu_release_port, | 961 | .release_port = sunsu_release_port, |
962 | .request_port = sunsu_request_port, | 962 | .request_port = sunsu_request_port, |
963 | .config_port = sunsu_config_port, | 963 | .config_port = sunsu_config_port, |
964 | .verify_port = sunsu_verify_port, | 964 | .verify_port = sunsu_verify_port, |
965 | }; | 965 | }; |
966 | 966 | ||
967 | #define UART_NR 4 | 967 | #define UART_NR 4 |
968 | 968 | ||
969 | static struct uart_sunsu_port sunsu_ports[UART_NR]; | 969 | static struct uart_sunsu_port sunsu_ports[UART_NR]; |
970 | 970 | ||
971 | #ifdef CONFIG_SERIO | 971 | #ifdef CONFIG_SERIO |
972 | 972 | ||
973 | static DEFINE_SPINLOCK(sunsu_serio_lock); | 973 | static DEFINE_SPINLOCK(sunsu_serio_lock); |
974 | 974 | ||
975 | static int sunsu_serio_write(struct serio *serio, unsigned char ch) | 975 | static int sunsu_serio_write(struct serio *serio, unsigned char ch) |
976 | { | 976 | { |
977 | struct uart_sunsu_port *up = serio->port_data; | 977 | struct uart_sunsu_port *up = serio->port_data; |
978 | unsigned long flags; | 978 | unsigned long flags; |
979 | int lsr; | 979 | int lsr; |
980 | 980 | ||
981 | spin_lock_irqsave(&sunsu_serio_lock, flags); | 981 | spin_lock_irqsave(&sunsu_serio_lock, flags); |
982 | 982 | ||
983 | do { | 983 | do { |
984 | lsr = serial_in(up, UART_LSR); | 984 | lsr = serial_in(up, UART_LSR); |
985 | } while (!(lsr & UART_LSR_THRE)); | 985 | } while (!(lsr & UART_LSR_THRE)); |
986 | 986 | ||
987 | /* Send the character out. */ | 987 | /* Send the character out. */ |
988 | serial_out(up, UART_TX, ch); | 988 | serial_out(up, UART_TX, ch); |
989 | 989 | ||
990 | spin_unlock_irqrestore(&sunsu_serio_lock, flags); | 990 | spin_unlock_irqrestore(&sunsu_serio_lock, flags); |
991 | 991 | ||
992 | return 0; | 992 | return 0; |
993 | } | 993 | } |
994 | 994 | ||
995 | static int sunsu_serio_open(struct serio *serio) | 995 | static int sunsu_serio_open(struct serio *serio) |
996 | { | 996 | { |
997 | struct uart_sunsu_port *up = serio->port_data; | 997 | struct uart_sunsu_port *up = serio->port_data; |
998 | unsigned long flags; | 998 | unsigned long flags; |
999 | int ret; | 999 | int ret; |
1000 | 1000 | ||
1001 | spin_lock_irqsave(&sunsu_serio_lock, flags); | 1001 | spin_lock_irqsave(&sunsu_serio_lock, flags); |
1002 | if (!up->serio_open) { | 1002 | if (!up->serio_open) { |
1003 | up->serio_open = 1; | 1003 | up->serio_open = 1; |
1004 | ret = 0; | 1004 | ret = 0; |
1005 | } else | 1005 | } else |
1006 | ret = -EBUSY; | 1006 | ret = -EBUSY; |
1007 | spin_unlock_irqrestore(&sunsu_serio_lock, flags); | 1007 | spin_unlock_irqrestore(&sunsu_serio_lock, flags); |
1008 | 1008 | ||
1009 | return ret; | 1009 | return ret; |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | static void sunsu_serio_close(struct serio *serio) | 1012 | static void sunsu_serio_close(struct serio *serio) |
1013 | { | 1013 | { |
1014 | struct uart_sunsu_port *up = serio->port_data; | 1014 | struct uart_sunsu_port *up = serio->port_data; |
1015 | unsigned long flags; | 1015 | unsigned long flags; |
1016 | 1016 | ||
1017 | spin_lock_irqsave(&sunsu_serio_lock, flags); | 1017 | spin_lock_irqsave(&sunsu_serio_lock, flags); |
1018 | up->serio_open = 0; | 1018 | up->serio_open = 0; |
1019 | spin_unlock_irqrestore(&sunsu_serio_lock, flags); | 1019 | spin_unlock_irqrestore(&sunsu_serio_lock, flags); |
1020 | } | 1020 | } |
1021 | 1021 | ||
1022 | #endif /* CONFIG_SERIO */ | 1022 | #endif /* CONFIG_SERIO */ |
1023 | 1023 | ||
1024 | static void sunsu_autoconfig(struct uart_sunsu_port *up) | 1024 | static void sunsu_autoconfig(struct uart_sunsu_port *up) |
1025 | { | 1025 | { |
1026 | unsigned char status1, status2, scratch, scratch2, scratch3; | 1026 | unsigned char status1, status2, scratch, scratch2, scratch3; |
1027 | unsigned char save_lcr, save_mcr; | 1027 | unsigned char save_lcr, save_mcr; |
1028 | unsigned long flags; | 1028 | unsigned long flags; |
1029 | 1029 | ||
1030 | if (up->su_type == SU_PORT_NONE) | 1030 | if (up->su_type == SU_PORT_NONE) |
1031 | return; | 1031 | return; |
1032 | 1032 | ||
1033 | up->type_probed = PORT_UNKNOWN; | 1033 | up->type_probed = PORT_UNKNOWN; |
1034 | up->port.iotype = UPIO_MEM; | 1034 | up->port.iotype = UPIO_MEM; |
1035 | 1035 | ||
1036 | spin_lock_irqsave(&up->port.lock, flags); | 1036 | spin_lock_irqsave(&up->port.lock, flags); |
1037 | 1037 | ||
1038 | if (!(up->port.flags & UPF_BUGGY_UART)) { | 1038 | if (!(up->port.flags & UPF_BUGGY_UART)) { |
1039 | /* | 1039 | /* |
1040 | * Do a simple existence test first; if we fail this, there's | 1040 | * Do a simple existence test first; if we fail this, there's |
1041 | * no point trying anything else. | 1041 | * no point trying anything else. |
1042 | * | 1042 | * |
1043 | * 0x80 is used as a nonsense port to prevent against false | 1043 | * 0x80 is used as a nonsense port to prevent against false |
1044 | * positives due to ISA bus float. The assumption is that | 1044 | * positives due to ISA bus float. The assumption is that |
1045 | * 0x80 is a non-existent port; which should be safe since | 1045 | * 0x80 is a non-existent port; which should be safe since |
1046 | * include/asm/io.h also makes this assumption. | 1046 | * include/asm/io.h also makes this assumption. |
1047 | */ | 1047 | */ |
1048 | scratch = serial_inp(up, UART_IER); | 1048 | scratch = serial_inp(up, UART_IER); |
1049 | serial_outp(up, UART_IER, 0); | 1049 | serial_outp(up, UART_IER, 0); |
1050 | #ifdef __i386__ | 1050 | #ifdef __i386__ |
1051 | outb(0xff, 0x080); | 1051 | outb(0xff, 0x080); |
1052 | #endif | 1052 | #endif |
1053 | scratch2 = serial_inp(up, UART_IER); | 1053 | scratch2 = serial_inp(up, UART_IER); |
1054 | serial_outp(up, UART_IER, 0x0f); | 1054 | serial_outp(up, UART_IER, 0x0f); |
1055 | #ifdef __i386__ | 1055 | #ifdef __i386__ |
1056 | outb(0, 0x080); | 1056 | outb(0, 0x080); |
1057 | #endif | 1057 | #endif |
1058 | scratch3 = serial_inp(up, UART_IER); | 1058 | scratch3 = serial_inp(up, UART_IER); |
1059 | serial_outp(up, UART_IER, scratch); | 1059 | serial_outp(up, UART_IER, scratch); |
1060 | if (scratch2 != 0 || scratch3 != 0x0F) | 1060 | if (scratch2 != 0 || scratch3 != 0x0F) |
1061 | goto out; /* We failed; there's nothing here */ | 1061 | goto out; /* We failed; there's nothing here */ |
1062 | } | 1062 | } |
1063 | 1063 | ||
1064 | save_mcr = serial_in(up, UART_MCR); | 1064 | save_mcr = serial_in(up, UART_MCR); |
1065 | save_lcr = serial_in(up, UART_LCR); | 1065 | save_lcr = serial_in(up, UART_LCR); |
1066 | 1066 | ||
1067 | /* | 1067 | /* |
1068 | * Check to see if a UART is really there. Certain broken | 1068 | * Check to see if a UART is really there. Certain broken |
1069 | * internal modems based on the Rockwell chipset fail this | 1069 | * internal modems based on the Rockwell chipset fail this |
1070 | * test, because they apparently don't implement the loopback | 1070 | * test, because they apparently don't implement the loopback |
1071 | * test mode. So this test is skipped on the COM 1 through | 1071 | * test mode. So this test is skipped on the COM 1 through |
1072 | * COM 4 ports. This *should* be safe, since no board | 1072 | * COM 4 ports. This *should* be safe, since no board |
1073 | * manufacturer would be stupid enough to design a board | 1073 | * manufacturer would be stupid enough to design a board |
1074 | * that conflicts with COM 1-4 --- we hope! | 1074 | * that conflicts with COM 1-4 --- we hope! |
1075 | */ | 1075 | */ |
1076 | if (!(up->port.flags & UPF_SKIP_TEST)) { | 1076 | if (!(up->port.flags & UPF_SKIP_TEST)) { |
1077 | serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A); | 1077 | serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A); |
1078 | status1 = serial_inp(up, UART_MSR) & 0xF0; | 1078 | status1 = serial_inp(up, UART_MSR) & 0xF0; |
1079 | serial_outp(up, UART_MCR, save_mcr); | 1079 | serial_outp(up, UART_MCR, save_mcr); |
1080 | if (status1 != 0x90) | 1080 | if (status1 != 0x90) |
1081 | goto out; /* We failed loopback test */ | 1081 | goto out; /* We failed loopback test */ |
1082 | } | 1082 | } |
1083 | serial_outp(up, UART_LCR, 0xBF); /* set up for StarTech test */ | 1083 | serial_outp(up, UART_LCR, 0xBF); /* set up for StarTech test */ |
1084 | serial_outp(up, UART_EFR, 0); /* EFR is the same as FCR */ | 1084 | serial_outp(up, UART_EFR, 0); /* EFR is the same as FCR */ |
1085 | serial_outp(up, UART_LCR, 0); | 1085 | serial_outp(up, UART_LCR, 0); |
1086 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); | 1086 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); |
1087 | scratch = serial_in(up, UART_IIR) >> 6; | 1087 | scratch = serial_in(up, UART_IIR) >> 6; |
1088 | switch (scratch) { | 1088 | switch (scratch) { |
1089 | case 0: | 1089 | case 0: |
1090 | up->port.type = PORT_16450; | 1090 | up->port.type = PORT_16450; |
1091 | break; | 1091 | break; |
1092 | case 1: | 1092 | case 1: |
1093 | up->port.type = PORT_UNKNOWN; | 1093 | up->port.type = PORT_UNKNOWN; |
1094 | break; | 1094 | break; |
1095 | case 2: | 1095 | case 2: |
1096 | up->port.type = PORT_16550; | 1096 | up->port.type = PORT_16550; |
1097 | break; | 1097 | break; |
1098 | case 3: | 1098 | case 3: |
1099 | up->port.type = PORT_16550A; | 1099 | up->port.type = PORT_16550A; |
1100 | break; | 1100 | break; |
1101 | } | 1101 | } |
1102 | if (up->port.type == PORT_16550A) { | 1102 | if (up->port.type == PORT_16550A) { |
1103 | /* Check for Startech UART's */ | 1103 | /* Check for Startech UART's */ |
1104 | serial_outp(up, UART_LCR, UART_LCR_DLAB); | 1104 | serial_outp(up, UART_LCR, UART_LCR_DLAB); |
1105 | if (serial_in(up, UART_EFR) == 0) { | 1105 | if (serial_in(up, UART_EFR) == 0) { |
1106 | up->port.type = PORT_16650; | 1106 | up->port.type = PORT_16650; |
1107 | } else { | 1107 | } else { |
1108 | serial_outp(up, UART_LCR, 0xBF); | 1108 | serial_outp(up, UART_LCR, 0xBF); |
1109 | if (serial_in(up, UART_EFR) == 0) | 1109 | if (serial_in(up, UART_EFR) == 0) |
1110 | up->port.type = PORT_16650V2; | 1110 | up->port.type = PORT_16650V2; |
1111 | } | 1111 | } |
1112 | } | 1112 | } |
1113 | if (up->port.type == PORT_16550A) { | 1113 | if (up->port.type == PORT_16550A) { |
1114 | /* Check for TI 16750 */ | 1114 | /* Check for TI 16750 */ |
1115 | serial_outp(up, UART_LCR, save_lcr | UART_LCR_DLAB); | 1115 | serial_outp(up, UART_LCR, save_lcr | UART_LCR_DLAB); |
1116 | serial_outp(up, UART_FCR, | 1116 | serial_outp(up, UART_FCR, |
1117 | UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); | 1117 | UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); |
1118 | scratch = serial_in(up, UART_IIR) >> 5; | 1118 | scratch = serial_in(up, UART_IIR) >> 5; |
1119 | if (scratch == 7) { | 1119 | if (scratch == 7) { |
1120 | /* | 1120 | /* |
1121 | * If this is a 16750, and not a cheap UART | 1121 | * If this is a 16750, and not a cheap UART |
1122 | * clone, then it should only go into 64 byte | 1122 | * clone, then it should only go into 64 byte |
1123 | * mode if the UART_FCR7_64BYTE bit was set | 1123 | * mode if the UART_FCR7_64BYTE bit was set |
1124 | * while UART_LCR_DLAB was latched. | 1124 | * while UART_LCR_DLAB was latched. |
1125 | */ | 1125 | */ |
1126 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); | 1126 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); |
1127 | serial_outp(up, UART_LCR, 0); | 1127 | serial_outp(up, UART_LCR, 0); |
1128 | serial_outp(up, UART_FCR, | 1128 | serial_outp(up, UART_FCR, |
1129 | UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); | 1129 | UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); |
1130 | scratch = serial_in(up, UART_IIR) >> 5; | 1130 | scratch = serial_in(up, UART_IIR) >> 5; |
1131 | if (scratch == 6) | 1131 | if (scratch == 6) |
1132 | up->port.type = PORT_16750; | 1132 | up->port.type = PORT_16750; |
1133 | } | 1133 | } |
1134 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); | 1134 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); |
1135 | } | 1135 | } |
1136 | serial_outp(up, UART_LCR, save_lcr); | 1136 | serial_outp(up, UART_LCR, save_lcr); |
1137 | if (up->port.type == PORT_16450) { | 1137 | if (up->port.type == PORT_16450) { |
1138 | scratch = serial_in(up, UART_SCR); | 1138 | scratch = serial_in(up, UART_SCR); |
1139 | serial_outp(up, UART_SCR, 0xa5); | 1139 | serial_outp(up, UART_SCR, 0xa5); |
1140 | status1 = serial_in(up, UART_SCR); | 1140 | status1 = serial_in(up, UART_SCR); |
1141 | serial_outp(up, UART_SCR, 0x5a); | 1141 | serial_outp(up, UART_SCR, 0x5a); |
1142 | status2 = serial_in(up, UART_SCR); | 1142 | status2 = serial_in(up, UART_SCR); |
1143 | serial_outp(up, UART_SCR, scratch); | 1143 | serial_outp(up, UART_SCR, scratch); |
1144 | 1144 | ||
1145 | if ((status1 != 0xa5) || (status2 != 0x5a)) | 1145 | if ((status1 != 0xa5) || (status2 != 0x5a)) |
1146 | up->port.type = PORT_8250; | 1146 | up->port.type = PORT_8250; |
1147 | } | 1147 | } |
1148 | 1148 | ||
1149 | up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size; | 1149 | up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size; |
1150 | 1150 | ||
1151 | if (up->port.type == PORT_UNKNOWN) | 1151 | if (up->port.type == PORT_UNKNOWN) |
1152 | goto out; | 1152 | goto out; |
1153 | up->type_probed = up->port.type; /* XXX */ | 1153 | up->type_probed = up->port.type; /* XXX */ |
1154 | 1154 | ||
1155 | /* | 1155 | /* |
1156 | * Reset the UART. | 1156 | * Reset the UART. |
1157 | */ | 1157 | */ |
1158 | #ifdef CONFIG_SERIAL_8250_RSA | 1158 | #ifdef CONFIG_SERIAL_8250_RSA |
1159 | if (up->port.type == PORT_RSA) | 1159 | if (up->port.type == PORT_RSA) |
1160 | serial_outp(up, UART_RSA_FRR, 0); | 1160 | serial_outp(up, UART_RSA_FRR, 0); |
1161 | #endif | 1161 | #endif |
1162 | serial_outp(up, UART_MCR, save_mcr); | 1162 | serial_outp(up, UART_MCR, save_mcr); |
1163 | serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO | | 1163 | serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO | |
1164 | UART_FCR_CLEAR_RCVR | | 1164 | UART_FCR_CLEAR_RCVR | |
1165 | UART_FCR_CLEAR_XMIT)); | 1165 | UART_FCR_CLEAR_XMIT)); |
1166 | serial_outp(up, UART_FCR, 0); | 1166 | serial_outp(up, UART_FCR, 0); |
1167 | (void)serial_in(up, UART_RX); | 1167 | (void)serial_in(up, UART_RX); |
1168 | serial_outp(up, UART_IER, 0); | 1168 | serial_outp(up, UART_IER, 0); |
1169 | 1169 | ||
1170 | out: | 1170 | out: |
1171 | spin_unlock_irqrestore(&up->port.lock, flags); | 1171 | spin_unlock_irqrestore(&up->port.lock, flags); |
1172 | } | 1172 | } |
1173 | 1173 | ||
1174 | static struct uart_driver sunsu_reg = { | 1174 | static struct uart_driver sunsu_reg = { |
1175 | .owner = THIS_MODULE, | 1175 | .owner = THIS_MODULE, |
1176 | .driver_name = "serial", | 1176 | .driver_name = "serial", |
1177 | .dev_name = "ttyS", | 1177 | .dev_name = "ttyS", |
1178 | .major = TTY_MAJOR, | 1178 | .major = TTY_MAJOR, |
1179 | }; | 1179 | }; |
1180 | 1180 | ||
1181 | static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up) | 1181 | static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up) |
1182 | { | 1182 | { |
1183 | int quot, baud; | 1183 | int quot, baud; |
1184 | #ifdef CONFIG_SERIO | 1184 | #ifdef CONFIG_SERIO |
1185 | struct serio *serio; | 1185 | struct serio *serio; |
1186 | #endif | 1186 | #endif |
1187 | 1187 | ||
1188 | if (up->su_type == SU_PORT_KBD) { | 1188 | if (up->su_type == SU_PORT_KBD) { |
1189 | up->cflag = B1200 | CS8 | CLOCAL | CREAD; | 1189 | up->cflag = B1200 | CS8 | CLOCAL | CREAD; |
1190 | baud = 1200; | 1190 | baud = 1200; |
1191 | } else { | 1191 | } else { |
1192 | up->cflag = B4800 | CS8 | CLOCAL | CREAD; | 1192 | up->cflag = B4800 | CS8 | CLOCAL | CREAD; |
1193 | baud = 4800; | 1193 | baud = 4800; |
1194 | } | 1194 | } |
1195 | quot = up->port.uartclk / (16 * baud); | 1195 | quot = up->port.uartclk / (16 * baud); |
1196 | 1196 | ||
1197 | sunsu_autoconfig(up); | 1197 | sunsu_autoconfig(up); |
1198 | if (up->port.type == PORT_UNKNOWN) | 1198 | if (up->port.type == PORT_UNKNOWN) |
1199 | return -ENODEV; | 1199 | return -ENODEV; |
1200 | 1200 | ||
1201 | printk("%s: %s port at %lx, irq %u\n", | 1201 | printk("%s: %s port at %llx, irq %u\n", |
1202 | to_of_device(up->port.dev)->node->full_name, | 1202 | to_of_device(up->port.dev)->node->full_name, |
1203 | (up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse", | 1203 | (up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse", |
1204 | up->port.mapbase, up->port.irq); | 1204 | (unsigned long long) up->port.mapbase, |
1205 | up->port.irq); | ||
1205 | 1206 | ||
1206 | #ifdef CONFIG_SERIO | 1207 | #ifdef CONFIG_SERIO |
1207 | serio = &up->serio; | 1208 | serio = &up->serio; |
1208 | serio->port_data = up; | 1209 | serio->port_data = up; |
1209 | 1210 | ||
1210 | serio->id.type = SERIO_RS232; | 1211 | serio->id.type = SERIO_RS232; |
1211 | if (up->su_type == SU_PORT_KBD) { | 1212 | if (up->su_type == SU_PORT_KBD) { |
1212 | serio->id.proto = SERIO_SUNKBD; | 1213 | serio->id.proto = SERIO_SUNKBD; |
1213 | strlcpy(serio->name, "sukbd", sizeof(serio->name)); | 1214 | strlcpy(serio->name, "sukbd", sizeof(serio->name)); |
1214 | } else { | 1215 | } else { |
1215 | serio->id.proto = SERIO_SUN; | 1216 | serio->id.proto = SERIO_SUN; |
1216 | serio->id.extra = 1; | 1217 | serio->id.extra = 1; |
1217 | strlcpy(serio->name, "sums", sizeof(serio->name)); | 1218 | strlcpy(serio->name, "sums", sizeof(serio->name)); |
1218 | } | 1219 | } |
1219 | strlcpy(serio->phys, | 1220 | strlcpy(serio->phys, |
1220 | (!(up->port.line & 1) ? "su/serio0" : "su/serio1"), | 1221 | (!(up->port.line & 1) ? "su/serio0" : "su/serio1"), |
1221 | sizeof(serio->phys)); | 1222 | sizeof(serio->phys)); |
1222 | 1223 | ||
1223 | serio->write = sunsu_serio_write; | 1224 | serio->write = sunsu_serio_write; |
1224 | serio->open = sunsu_serio_open; | 1225 | serio->open = sunsu_serio_open; |
1225 | serio->close = sunsu_serio_close; | 1226 | serio->close = sunsu_serio_close; |
1226 | serio->dev.parent = up->port.dev; | 1227 | serio->dev.parent = up->port.dev; |
1227 | 1228 | ||
1228 | serio_register_port(serio); | 1229 | serio_register_port(serio); |
1229 | #endif | 1230 | #endif |
1230 | 1231 | ||
1231 | sunsu_change_speed(&up->port, up->cflag, 0, quot); | 1232 | sunsu_change_speed(&up->port, up->cflag, 0, quot); |
1232 | 1233 | ||
1233 | sunsu_startup(&up->port); | 1234 | sunsu_startup(&up->port); |
1234 | return 0; | 1235 | return 0; |
1235 | } | 1236 | } |
1236 | 1237 | ||
1237 | /* | 1238 | /* |
1238 | * ------------------------------------------------------------ | 1239 | * ------------------------------------------------------------ |
1239 | * Serial console driver | 1240 | * Serial console driver |
1240 | * ------------------------------------------------------------ | 1241 | * ------------------------------------------------------------ |
1241 | */ | 1242 | */ |
1242 | 1243 | ||
1243 | #ifdef CONFIG_SERIAL_SUNSU_CONSOLE | 1244 | #ifdef CONFIG_SERIAL_SUNSU_CONSOLE |
1244 | 1245 | ||
1245 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) | 1246 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) |
1246 | 1247 | ||
1247 | /* | 1248 | /* |
1248 | * Wait for transmitter & holding register to empty | 1249 | * Wait for transmitter & holding register to empty |
1249 | */ | 1250 | */ |
1250 | static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up) | 1251 | static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up) |
1251 | { | 1252 | { |
1252 | unsigned int status, tmout = 10000; | 1253 | unsigned int status, tmout = 10000; |
1253 | 1254 | ||
1254 | /* Wait up to 10ms for the character(s) to be sent. */ | 1255 | /* Wait up to 10ms for the character(s) to be sent. */ |
1255 | do { | 1256 | do { |
1256 | status = serial_in(up, UART_LSR); | 1257 | status = serial_in(up, UART_LSR); |
1257 | 1258 | ||
1258 | if (status & UART_LSR_BI) | 1259 | if (status & UART_LSR_BI) |
1259 | up->lsr_break_flag = UART_LSR_BI; | 1260 | up->lsr_break_flag = UART_LSR_BI; |
1260 | 1261 | ||
1261 | if (--tmout == 0) | 1262 | if (--tmout == 0) |
1262 | break; | 1263 | break; |
1263 | udelay(1); | 1264 | udelay(1); |
1264 | } while ((status & BOTH_EMPTY) != BOTH_EMPTY); | 1265 | } while ((status & BOTH_EMPTY) != BOTH_EMPTY); |
1265 | 1266 | ||
1266 | /* Wait up to 1s for flow control if necessary */ | 1267 | /* Wait up to 1s for flow control if necessary */ |
1267 | if (up->port.flags & UPF_CONS_FLOW) { | 1268 | if (up->port.flags & UPF_CONS_FLOW) { |
1268 | tmout = 1000000; | 1269 | tmout = 1000000; |
1269 | while (--tmout && | 1270 | while (--tmout && |
1270 | ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) | 1271 | ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) |
1271 | udelay(1); | 1272 | udelay(1); |
1272 | } | 1273 | } |
1273 | } | 1274 | } |
1274 | 1275 | ||
1275 | static void sunsu_console_putchar(struct uart_port *port, int ch) | 1276 | static void sunsu_console_putchar(struct uart_port *port, int ch) |
1276 | { | 1277 | { |
1277 | struct uart_sunsu_port *up = (struct uart_sunsu_port *)port; | 1278 | struct uart_sunsu_port *up = (struct uart_sunsu_port *)port; |
1278 | 1279 | ||
1279 | wait_for_xmitr(up); | 1280 | wait_for_xmitr(up); |
1280 | serial_out(up, UART_TX, ch); | 1281 | serial_out(up, UART_TX, ch); |
1281 | } | 1282 | } |
1282 | 1283 | ||
1283 | /* | 1284 | /* |
1284 | * Print a string to the serial port trying not to disturb | 1285 | * Print a string to the serial port trying not to disturb |
1285 | * any possible real use of the port... | 1286 | * any possible real use of the port... |
1286 | */ | 1287 | */ |
1287 | static void sunsu_console_write(struct console *co, const char *s, | 1288 | static void sunsu_console_write(struct console *co, const char *s, |
1288 | unsigned int count) | 1289 | unsigned int count) |
1289 | { | 1290 | { |
1290 | struct uart_sunsu_port *up = &sunsu_ports[co->index]; | 1291 | struct uart_sunsu_port *up = &sunsu_ports[co->index]; |
1291 | unsigned long flags; | 1292 | unsigned long flags; |
1292 | unsigned int ier; | 1293 | unsigned int ier; |
1293 | int locked = 1; | 1294 | int locked = 1; |
1294 | 1295 | ||
1295 | local_irq_save(flags); | 1296 | local_irq_save(flags); |
1296 | if (up->port.sysrq) { | 1297 | if (up->port.sysrq) { |
1297 | locked = 0; | 1298 | locked = 0; |
1298 | } else if (oops_in_progress) { | 1299 | } else if (oops_in_progress) { |
1299 | locked = spin_trylock(&up->port.lock); | 1300 | locked = spin_trylock(&up->port.lock); |
1300 | } else | 1301 | } else |
1301 | spin_lock(&up->port.lock); | 1302 | spin_lock(&up->port.lock); |
1302 | 1303 | ||
1303 | /* | 1304 | /* |
1304 | * First save the UER then disable the interrupts | 1305 | * First save the UER then disable the interrupts |
1305 | */ | 1306 | */ |
1306 | ier = serial_in(up, UART_IER); | 1307 | ier = serial_in(up, UART_IER); |
1307 | serial_out(up, UART_IER, 0); | 1308 | serial_out(up, UART_IER, 0); |
1308 | 1309 | ||
1309 | uart_console_write(&up->port, s, count, sunsu_console_putchar); | 1310 | uart_console_write(&up->port, s, count, sunsu_console_putchar); |
1310 | 1311 | ||
1311 | /* | 1312 | /* |
1312 | * Finally, wait for transmitter to become empty | 1313 | * Finally, wait for transmitter to become empty |
1313 | * and restore the IER | 1314 | * and restore the IER |
1314 | */ | 1315 | */ |
1315 | wait_for_xmitr(up); | 1316 | wait_for_xmitr(up); |
1316 | serial_out(up, UART_IER, ier); | 1317 | serial_out(up, UART_IER, ier); |
1317 | 1318 | ||
1318 | if (locked) | 1319 | if (locked) |
1319 | spin_unlock(&up->port.lock); | 1320 | spin_unlock(&up->port.lock); |
1320 | local_irq_restore(flags); | 1321 | local_irq_restore(flags); |
1321 | } | 1322 | } |
1322 | 1323 | ||
1323 | /* | 1324 | /* |
1324 | * Setup initial baud/bits/parity. We do two things here: | 1325 | * Setup initial baud/bits/parity. We do two things here: |
1325 | * - construct a cflag setting for the first su_open() | 1326 | * - construct a cflag setting for the first su_open() |
1326 | * - initialize the serial port | 1327 | * - initialize the serial port |
1327 | * Return non-zero if we didn't find a serial port. | 1328 | * Return non-zero if we didn't find a serial port. |
1328 | */ | 1329 | */ |
1329 | static int __init sunsu_console_setup(struct console *co, char *options) | 1330 | static int __init sunsu_console_setup(struct console *co, char *options) |
1330 | { | 1331 | { |
1331 | struct uart_port *port; | 1332 | struct uart_port *port; |
1332 | int baud = 9600; | 1333 | int baud = 9600; |
1333 | int bits = 8; | 1334 | int bits = 8; |
1334 | int parity = 'n'; | 1335 | int parity = 'n'; |
1335 | int flow = 'n'; | 1336 | int flow = 'n'; |
1336 | 1337 | ||
1337 | printk("Console: ttyS%d (SU)\n", | 1338 | printk("Console: ttyS%d (SU)\n", |
1338 | (sunsu_reg.minor - 64) + co->index); | 1339 | (sunsu_reg.minor - 64) + co->index); |
1339 | 1340 | ||
1340 | /* | 1341 | /* |
1341 | * Check whether an invalid uart number has been specified, and | 1342 | * Check whether an invalid uart number has been specified, and |
1342 | * if so, search for the first available port that does have | 1343 | * if so, search for the first available port that does have |
1343 | * console support. | 1344 | * console support. |
1344 | */ | 1345 | */ |
1345 | if (co->index >= UART_NR) | 1346 | if (co->index >= UART_NR) |
1346 | co->index = 0; | 1347 | co->index = 0; |
1347 | port = &sunsu_ports[co->index].port; | 1348 | port = &sunsu_ports[co->index].port; |
1348 | 1349 | ||
1349 | /* | 1350 | /* |
1350 | * Temporary fix. | 1351 | * Temporary fix. |
1351 | */ | 1352 | */ |
1352 | spin_lock_init(&port->lock); | 1353 | spin_lock_init(&port->lock); |
1353 | 1354 | ||
1354 | if (options) | 1355 | if (options) |
1355 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 1356 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
1356 | 1357 | ||
1357 | return uart_set_options(port, co, baud, parity, bits, flow); | 1358 | return uart_set_options(port, co, baud, parity, bits, flow); |
1358 | } | 1359 | } |
1359 | 1360 | ||
1360 | static struct console sunsu_console = { | 1361 | static struct console sunsu_console = { |
1361 | .name = "ttyS", | 1362 | .name = "ttyS", |
1362 | .write = sunsu_console_write, | 1363 | .write = sunsu_console_write, |
1363 | .device = uart_console_device, | 1364 | .device = uart_console_device, |
1364 | .setup = sunsu_console_setup, | 1365 | .setup = sunsu_console_setup, |
1365 | .flags = CON_PRINTBUFFER, | 1366 | .flags = CON_PRINTBUFFER, |
1366 | .index = -1, | 1367 | .index = -1, |
1367 | .data = &sunsu_reg, | 1368 | .data = &sunsu_reg, |
1368 | }; | 1369 | }; |
1369 | 1370 | ||
1370 | /* | 1371 | /* |
1371 | * Register console. | 1372 | * Register console. |
1372 | */ | 1373 | */ |
1373 | 1374 | ||
1374 | static inline struct console *SUNSU_CONSOLE(void) | 1375 | static inline struct console *SUNSU_CONSOLE(void) |
1375 | { | 1376 | { |
1376 | return &sunsu_console; | 1377 | return &sunsu_console; |
1377 | } | 1378 | } |
1378 | #else | 1379 | #else |
1379 | #define SUNSU_CONSOLE() (NULL) | 1380 | #define SUNSU_CONSOLE() (NULL) |
1380 | #define sunsu_serial_console_init() do { } while (0) | 1381 | #define sunsu_serial_console_init() do { } while (0) |
1381 | #endif | 1382 | #endif |
1382 | 1383 | ||
1383 | static enum su_type __devinit su_get_type(struct device_node *dp) | 1384 | static enum su_type __devinit su_get_type(struct device_node *dp) |
1384 | { | 1385 | { |
1385 | struct device_node *ap = of_find_node_by_path("/aliases"); | 1386 | struct device_node *ap = of_find_node_by_path("/aliases"); |
1386 | 1387 | ||
1387 | if (ap) { | 1388 | if (ap) { |
1388 | const char *keyb = of_get_property(ap, "keyboard", NULL); | 1389 | const char *keyb = of_get_property(ap, "keyboard", NULL); |
1389 | const char *ms = of_get_property(ap, "mouse", NULL); | 1390 | const char *ms = of_get_property(ap, "mouse", NULL); |
1390 | 1391 | ||
1391 | if (keyb) { | 1392 | if (keyb) { |
1392 | if (dp == of_find_node_by_path(keyb)) | 1393 | if (dp == of_find_node_by_path(keyb)) |
1393 | return SU_PORT_KBD; | 1394 | return SU_PORT_KBD; |
1394 | } | 1395 | } |
1395 | if (ms) { | 1396 | if (ms) { |
1396 | if (dp == of_find_node_by_path(ms)) | 1397 | if (dp == of_find_node_by_path(ms)) |
1397 | return SU_PORT_MS; | 1398 | return SU_PORT_MS; |
1398 | } | 1399 | } |
1399 | } | 1400 | } |
1400 | 1401 | ||
1401 | return SU_PORT_PORT; | 1402 | return SU_PORT_PORT; |
1402 | } | 1403 | } |
1403 | 1404 | ||
1404 | static int __devinit su_probe(struct of_device *op, const struct of_device_id *match) | 1405 | static int __devinit su_probe(struct of_device *op, const struct of_device_id *match) |
1405 | { | 1406 | { |
1406 | static int inst; | 1407 | static int inst; |
1407 | struct device_node *dp = op->node; | 1408 | struct device_node *dp = op->node; |
1408 | struct uart_sunsu_port *up; | 1409 | struct uart_sunsu_port *up; |
1409 | struct resource *rp; | 1410 | struct resource *rp; |
1410 | enum su_type type; | 1411 | enum su_type type; |
1411 | int err; | 1412 | int err; |
1412 | 1413 | ||
1413 | type = su_get_type(dp); | 1414 | type = su_get_type(dp); |
1414 | if (type == SU_PORT_PORT) { | 1415 | if (type == SU_PORT_PORT) { |
1415 | if (inst >= UART_NR) | 1416 | if (inst >= UART_NR) |
1416 | return -EINVAL; | 1417 | return -EINVAL; |
1417 | up = &sunsu_ports[inst]; | 1418 | up = &sunsu_ports[inst]; |
1418 | } else { | 1419 | } else { |
1419 | up = kzalloc(sizeof(*up), GFP_KERNEL); | 1420 | up = kzalloc(sizeof(*up), GFP_KERNEL); |
1420 | if (!up) | 1421 | if (!up) |
1421 | return -ENOMEM; | 1422 | return -ENOMEM; |
1422 | } | 1423 | } |
1423 | 1424 | ||
1424 | up->port.line = inst; | 1425 | up->port.line = inst; |
1425 | 1426 | ||
1426 | spin_lock_init(&up->port.lock); | 1427 | spin_lock_init(&up->port.lock); |
1427 | 1428 | ||
1428 | up->su_type = type; | 1429 | up->su_type = type; |
1429 | 1430 | ||
1430 | rp = &op->resource[0]; | 1431 | rp = &op->resource[0]; |
1431 | up->port.mapbase = rp->start; | 1432 | up->port.mapbase = rp->start; |
1432 | up->reg_size = (rp->end - rp->start) + 1; | 1433 | up->reg_size = (rp->end - rp->start) + 1; |
1433 | up->port.membase = of_ioremap(rp, 0, up->reg_size, "su"); | 1434 | up->port.membase = of_ioremap(rp, 0, up->reg_size, "su"); |
1434 | if (!up->port.membase) { | 1435 | if (!up->port.membase) { |
1435 | if (type != SU_PORT_PORT) | 1436 | if (type != SU_PORT_PORT) |
1436 | kfree(up); | 1437 | kfree(up); |
1437 | return -ENOMEM; | 1438 | return -ENOMEM; |
1438 | } | 1439 | } |
1439 | 1440 | ||
1440 | up->port.irq = op->irqs[0]; | 1441 | up->port.irq = op->irqs[0]; |
1441 | 1442 | ||
1442 | up->port.dev = &op->dev; | 1443 | up->port.dev = &op->dev; |
1443 | 1444 | ||
1444 | up->port.type = PORT_UNKNOWN; | 1445 | up->port.type = PORT_UNKNOWN; |
1445 | up->port.uartclk = (SU_BASE_BAUD * 16); | 1446 | up->port.uartclk = (SU_BASE_BAUD * 16); |
1446 | 1447 | ||
1447 | err = 0; | 1448 | err = 0; |
1448 | if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) { | 1449 | if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) { |
1449 | err = sunsu_kbd_ms_init(up); | 1450 | err = sunsu_kbd_ms_init(up); |
1450 | if (err) { | 1451 | if (err) { |
1451 | kfree(up); | 1452 | kfree(up); |
1452 | goto out_unmap; | 1453 | goto out_unmap; |
1453 | } | 1454 | } |
1454 | dev_set_drvdata(&op->dev, up); | 1455 | dev_set_drvdata(&op->dev, up); |
1455 | 1456 | ||
1456 | return 0; | 1457 | return 0; |
1457 | } | 1458 | } |
1458 | 1459 | ||
1459 | up->port.flags |= UPF_BOOT_AUTOCONF; | 1460 | up->port.flags |= UPF_BOOT_AUTOCONF; |
1460 | 1461 | ||
1461 | sunsu_autoconfig(up); | 1462 | sunsu_autoconfig(up); |
1462 | 1463 | ||
1463 | err = -ENODEV; | 1464 | err = -ENODEV; |
1464 | if (up->port.type == PORT_UNKNOWN) | 1465 | if (up->port.type == PORT_UNKNOWN) |
1465 | goto out_unmap; | 1466 | goto out_unmap; |
1466 | 1467 | ||
1467 | up->port.ops = &sunsu_pops; | 1468 | up->port.ops = &sunsu_pops; |
1468 | 1469 | ||
1469 | sunserial_console_match(SUNSU_CONSOLE(), dp, | 1470 | sunserial_console_match(SUNSU_CONSOLE(), dp, |
1470 | &sunsu_reg, up->port.line); | 1471 | &sunsu_reg, up->port.line); |
1471 | err = uart_add_one_port(&sunsu_reg, &up->port); | 1472 | err = uart_add_one_port(&sunsu_reg, &up->port); |
1472 | if (err) | 1473 | if (err) |
1473 | goto out_unmap; | 1474 | goto out_unmap; |
1474 | 1475 | ||
1475 | dev_set_drvdata(&op->dev, up); | 1476 | dev_set_drvdata(&op->dev, up); |
1476 | 1477 | ||
1477 | inst++; | 1478 | inst++; |
1478 | 1479 | ||
1479 | return 0; | 1480 | return 0; |
1480 | 1481 | ||
1481 | out_unmap: | 1482 | out_unmap: |
1482 | of_iounmap(&op->resource[0], up->port.membase, up->reg_size); | 1483 | of_iounmap(&op->resource[0], up->port.membase, up->reg_size); |
1483 | return err; | 1484 | return err; |
1484 | } | 1485 | } |
1485 | 1486 | ||
1486 | static int __devexit su_remove(struct of_device *op) | 1487 | static int __devexit su_remove(struct of_device *op) |
1487 | { | 1488 | { |
1488 | struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); | 1489 | struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); |
1489 | 1490 | ||
1490 | if (up->su_type == SU_PORT_MS || | 1491 | if (up->su_type == SU_PORT_MS || |
1491 | up->su_type == SU_PORT_KBD) { | 1492 | up->su_type == SU_PORT_KBD) { |
1492 | #ifdef CONFIG_SERIO | 1493 | #ifdef CONFIG_SERIO |
1493 | serio_unregister_port(&up->serio); | 1494 | serio_unregister_port(&up->serio); |
1494 | #endif | 1495 | #endif |
1495 | kfree(up); | 1496 | kfree(up); |
1496 | } else if (up->port.type != PORT_UNKNOWN) { | 1497 | } else if (up->port.type != PORT_UNKNOWN) { |
1497 | uart_remove_one_port(&sunsu_reg, &up->port); | 1498 | uart_remove_one_port(&sunsu_reg, &up->port); |
1498 | } | 1499 | } |
1499 | 1500 | ||
1500 | if (up->port.membase) | 1501 | if (up->port.membase) |
1501 | of_iounmap(&op->resource[0], up->port.membase, up->reg_size); | 1502 | of_iounmap(&op->resource[0], up->port.membase, up->reg_size); |
1502 | 1503 | ||
1503 | dev_set_drvdata(&op->dev, NULL); | 1504 | dev_set_drvdata(&op->dev, NULL); |
1504 | 1505 | ||
1505 | return 0; | 1506 | return 0; |
1506 | } | 1507 | } |
1507 | 1508 | ||
1508 | static struct of_device_id su_match[] = { | 1509 | static struct of_device_id su_match[] = { |
1509 | { | 1510 | { |
1510 | .name = "su", | 1511 | .name = "su", |
1511 | }, | 1512 | }, |
1512 | { | 1513 | { |
1513 | .name = "su_pnp", | 1514 | .name = "su_pnp", |
1514 | }, | 1515 | }, |
1515 | { | 1516 | { |
1516 | .name = "serial", | 1517 | .name = "serial", |
1517 | .compatible = "su", | 1518 | .compatible = "su", |
1518 | }, | 1519 | }, |
1519 | {}, | 1520 | {}, |
1520 | }; | 1521 | }; |
1521 | MODULE_DEVICE_TABLE(of, su_match); | 1522 | MODULE_DEVICE_TABLE(of, su_match); |
1522 | 1523 | ||
1523 | static struct of_platform_driver su_driver = { | 1524 | static struct of_platform_driver su_driver = { |
1524 | .name = "su", | 1525 | .name = "su", |
1525 | .match_table = su_match, | 1526 | .match_table = su_match, |
1526 | .probe = su_probe, | 1527 | .probe = su_probe, |
1527 | .remove = __devexit_p(su_remove), | 1528 | .remove = __devexit_p(su_remove), |
1528 | }; | 1529 | }; |
1529 | 1530 | ||
1530 | static int num_uart; | 1531 | static int num_uart; |
1531 | 1532 | ||
1532 | static int __init sunsu_init(void) | 1533 | static int __init sunsu_init(void) |
1533 | { | 1534 | { |
1534 | struct device_node *dp; | 1535 | struct device_node *dp; |
1535 | int err; | 1536 | int err; |
1536 | 1537 | ||
1537 | num_uart = 0; | 1538 | num_uart = 0; |
1538 | for_each_node_by_name(dp, "su") { | 1539 | for_each_node_by_name(dp, "su") { |
1539 | if (su_get_type(dp) == SU_PORT_PORT) | 1540 | if (su_get_type(dp) == SU_PORT_PORT) |
1540 | num_uart++; | 1541 | num_uart++; |
1541 | } | 1542 | } |
1542 | for_each_node_by_name(dp, "su_pnp") { | 1543 | for_each_node_by_name(dp, "su_pnp") { |
1543 | if (su_get_type(dp) == SU_PORT_PORT) | 1544 | if (su_get_type(dp) == SU_PORT_PORT) |
1544 | num_uart++; | 1545 | num_uart++; |
1545 | } | 1546 | } |
1546 | for_each_node_by_name(dp, "serial") { | 1547 | for_each_node_by_name(dp, "serial") { |
1547 | if (of_device_is_compatible(dp, "su")) { | 1548 | if (of_device_is_compatible(dp, "su")) { |
1548 | if (su_get_type(dp) == SU_PORT_PORT) | 1549 | if (su_get_type(dp) == SU_PORT_PORT) |
1549 | num_uart++; | 1550 | num_uart++; |
1550 | } | 1551 | } |
1551 | } | 1552 | } |
1552 | 1553 | ||
1553 | if (num_uart) { | 1554 | if (num_uart) { |
1554 | sunsu_reg.minor = sunserial_current_minor; | 1555 | sunsu_reg.minor = sunserial_current_minor; |
1555 | sunsu_reg.nr = num_uart; | 1556 | sunsu_reg.nr = num_uart; |
1556 | err = uart_register_driver(&sunsu_reg); | 1557 | err = uart_register_driver(&sunsu_reg); |
1557 | if (err) | 1558 | if (err) |
1558 | return err; | 1559 | return err; |
1559 | sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64; | 1560 | sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64; |
1560 | sunserial_current_minor += num_uart; | 1561 | sunserial_current_minor += num_uart; |
1561 | } | 1562 | } |
1562 | 1563 | ||
1563 | err = of_register_driver(&su_driver, &of_bus_type); | 1564 | err = of_register_driver(&su_driver, &of_bus_type); |
1564 | if (err && num_uart) | 1565 | if (err && num_uart) |
1565 | uart_unregister_driver(&sunsu_reg); | 1566 | uart_unregister_driver(&sunsu_reg); |
1566 | 1567 | ||
1567 | return err; | 1568 | return err; |
1568 | } | 1569 | } |
1569 | 1570 | ||
1570 | static void __exit sunsu_exit(void) | 1571 | static void __exit sunsu_exit(void) |
1571 | { | 1572 | { |
1572 | if (num_uart) | 1573 | if (num_uart) |
1573 | uart_unregister_driver(&sunsu_reg); | 1574 | uart_unregister_driver(&sunsu_reg); |
1574 | } | 1575 | } |
1575 | 1576 | ||
1576 | module_init(sunsu_init); | 1577 | module_init(sunsu_init); |
1577 | module_exit(sunsu_exit); | 1578 | module_exit(sunsu_exit); |
1578 | 1579 | ||
1579 | MODULE_AUTHOR("Eddie C. Dost, Peter Zaitcev, and David S. Miller"); | 1580 | MODULE_AUTHOR("Eddie C. Dost, Peter Zaitcev, and David S. Miller"); |
1580 | MODULE_DESCRIPTION("Sun SU serial port driver"); | 1581 | MODULE_DESCRIPTION("Sun SU serial port driver"); |
1581 | MODULE_VERSION("2.0"); | 1582 | MODULE_VERSION("2.0"); |
1582 | MODULE_LICENSE("GPL"); | 1583 | MODULE_LICENSE("GPL"); |
1583 | 1584 |
drivers/serial/sunzilog.c
1 | /* sunzilog.c: Zilog serial driver for Sparc systems. | 1 | /* sunzilog.c: Zilog serial driver for Sparc systems. |
2 | * | 2 | * |
3 | * Driver for Zilog serial chips found on Sun workstations and | 3 | * Driver for Zilog serial chips found on Sun workstations and |
4 | * servers. This driver could actually be made more generic. | 4 | * servers. This driver could actually be made more generic. |
5 | * | 5 | * |
6 | * This is based on the old drivers/sbus/char/zs.c code. A lot | 6 | * This is based on the old drivers/sbus/char/zs.c code. A lot |
7 | * of code has been simply moved over directly from there but | 7 | * of code has been simply moved over directly from there but |
8 | * much has been rewritten. Credits therefore go out to Eddie | 8 | * much has been rewritten. Credits therefore go out to Eddie |
9 | * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their | 9 | * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their |
10 | * work there. | 10 | * work there. |
11 | * | 11 | * |
12 | * Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net) | 12 | * Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net) |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/tty.h> | 19 | #include <linux/tty.h> |
20 | #include <linux/tty_flip.h> | 20 | #include <linux/tty_flip.h> |
21 | #include <linux/major.h> | 21 | #include <linux/major.h> |
22 | #include <linux/string.h> | 22 | #include <linux/string.h> |
23 | #include <linux/ptrace.h> | 23 | #include <linux/ptrace.h> |
24 | #include <linux/ioport.h> | 24 | #include <linux/ioport.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/circ_buf.h> | 26 | #include <linux/circ_buf.h> |
27 | #include <linux/serial.h> | 27 | #include <linux/serial.h> |
28 | #include <linux/sysrq.h> | 28 | #include <linux/sysrq.h> |
29 | #include <linux/console.h> | 29 | #include <linux/console.h> |
30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
31 | #ifdef CONFIG_SERIO | 31 | #ifdef CONFIG_SERIO |
32 | #include <linux/serio.h> | 32 | #include <linux/serio.h> |
33 | #endif | 33 | #endif |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | 35 | ||
36 | #include <asm/io.h> | 36 | #include <asm/io.h> |
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
38 | #include <asm/prom.h> | 38 | #include <asm/prom.h> |
39 | #include <asm/of_device.h> | 39 | #include <asm/of_device.h> |
40 | 40 | ||
41 | #if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | 41 | #if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
42 | #define SUPPORT_SYSRQ | 42 | #define SUPPORT_SYSRQ |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | #include <linux/serial_core.h> | 45 | #include <linux/serial_core.h> |
46 | 46 | ||
47 | #include "suncore.h" | 47 | #include "suncore.h" |
48 | #include "sunzilog.h" | 48 | #include "sunzilog.h" |
49 | 49 | ||
50 | /* On 32-bit sparcs we need to delay after register accesses | 50 | /* On 32-bit sparcs we need to delay after register accesses |
51 | * to accommodate sun4 systems, but we do not need to flush writes. | 51 | * to accommodate sun4 systems, but we do not need to flush writes. |
52 | * On 64-bit sparc we only need to flush single writes to ensure | 52 | * On 64-bit sparc we only need to flush single writes to ensure |
53 | * completion. | 53 | * completion. |
54 | */ | 54 | */ |
55 | #ifndef CONFIG_SPARC64 | 55 | #ifndef CONFIG_SPARC64 |
56 | #define ZSDELAY() udelay(5) | 56 | #define ZSDELAY() udelay(5) |
57 | #define ZSDELAY_LONG() udelay(20) | 57 | #define ZSDELAY_LONG() udelay(20) |
58 | #define ZS_WSYNC(channel) do { } while (0) | 58 | #define ZS_WSYNC(channel) do { } while (0) |
59 | #else | 59 | #else |
60 | #define ZSDELAY() | 60 | #define ZSDELAY() |
61 | #define ZSDELAY_LONG() | 61 | #define ZSDELAY_LONG() |
62 | #define ZS_WSYNC(__channel) \ | 62 | #define ZS_WSYNC(__channel) \ |
63 | readb(&((__channel)->control)) | 63 | readb(&((__channel)->control)) |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | static int num_sunzilog; | 66 | static int num_sunzilog; |
67 | #define NUM_SUNZILOG num_sunzilog | 67 | #define NUM_SUNZILOG num_sunzilog |
68 | #define NUM_CHANNELS (NUM_SUNZILOG * 2) | 68 | #define NUM_CHANNELS (NUM_SUNZILOG * 2) |
69 | 69 | ||
70 | #define ZS_CLOCK 4915200 /* Zilog input clock rate. */ | 70 | #define ZS_CLOCK 4915200 /* Zilog input clock rate. */ |
71 | #define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */ | 71 | #define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */ |
72 | 72 | ||
73 | /* | 73 | /* |
74 | * We wrap our port structure around the generic uart_port. | 74 | * We wrap our port structure around the generic uart_port. |
75 | */ | 75 | */ |
76 | struct uart_sunzilog_port { | 76 | struct uart_sunzilog_port { |
77 | struct uart_port port; | 77 | struct uart_port port; |
78 | 78 | ||
79 | /* IRQ servicing chain. */ | 79 | /* IRQ servicing chain. */ |
80 | struct uart_sunzilog_port *next; | 80 | struct uart_sunzilog_port *next; |
81 | 81 | ||
82 | /* Current values of Zilog write registers. */ | 82 | /* Current values of Zilog write registers. */ |
83 | unsigned char curregs[NUM_ZSREGS]; | 83 | unsigned char curregs[NUM_ZSREGS]; |
84 | 84 | ||
85 | unsigned int flags; | 85 | unsigned int flags; |
86 | #define SUNZILOG_FLAG_CONS_KEYB 0x00000001 | 86 | #define SUNZILOG_FLAG_CONS_KEYB 0x00000001 |
87 | #define SUNZILOG_FLAG_CONS_MOUSE 0x00000002 | 87 | #define SUNZILOG_FLAG_CONS_MOUSE 0x00000002 |
88 | #define SUNZILOG_FLAG_IS_CONS 0x00000004 | 88 | #define SUNZILOG_FLAG_IS_CONS 0x00000004 |
89 | #define SUNZILOG_FLAG_IS_KGDB 0x00000008 | 89 | #define SUNZILOG_FLAG_IS_KGDB 0x00000008 |
90 | #define SUNZILOG_FLAG_MODEM_STATUS 0x00000010 | 90 | #define SUNZILOG_FLAG_MODEM_STATUS 0x00000010 |
91 | #define SUNZILOG_FLAG_IS_CHANNEL_A 0x00000020 | 91 | #define SUNZILOG_FLAG_IS_CHANNEL_A 0x00000020 |
92 | #define SUNZILOG_FLAG_REGS_HELD 0x00000040 | 92 | #define SUNZILOG_FLAG_REGS_HELD 0x00000040 |
93 | #define SUNZILOG_FLAG_TX_STOPPED 0x00000080 | 93 | #define SUNZILOG_FLAG_TX_STOPPED 0x00000080 |
94 | #define SUNZILOG_FLAG_TX_ACTIVE 0x00000100 | 94 | #define SUNZILOG_FLAG_TX_ACTIVE 0x00000100 |
95 | #define SUNZILOG_FLAG_ESCC 0x00000200 | 95 | #define SUNZILOG_FLAG_ESCC 0x00000200 |
96 | #define SUNZILOG_FLAG_ISR_HANDLER 0x00000400 | 96 | #define SUNZILOG_FLAG_ISR_HANDLER 0x00000400 |
97 | 97 | ||
98 | unsigned int cflag; | 98 | unsigned int cflag; |
99 | 99 | ||
100 | unsigned char parity_mask; | 100 | unsigned char parity_mask; |
101 | unsigned char prev_status; | 101 | unsigned char prev_status; |
102 | 102 | ||
103 | #ifdef CONFIG_SERIO | 103 | #ifdef CONFIG_SERIO |
104 | struct serio serio; | 104 | struct serio serio; |
105 | int serio_open; | 105 | int serio_open; |
106 | #endif | 106 | #endif |
107 | }; | 107 | }; |
108 | 108 | ||
109 | #define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel __iomem *)((PORT)->membase)) | 109 | #define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel __iomem *)((PORT)->membase)) |
110 | #define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT)) | 110 | #define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT)) |
111 | 111 | ||
112 | #define ZS_IS_KEYB(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_KEYB) | 112 | #define ZS_IS_KEYB(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_KEYB) |
113 | #define ZS_IS_MOUSE(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_MOUSE) | 113 | #define ZS_IS_MOUSE(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_MOUSE) |
114 | #define ZS_IS_CONS(UP) ((UP)->flags & SUNZILOG_FLAG_IS_CONS) | 114 | #define ZS_IS_CONS(UP) ((UP)->flags & SUNZILOG_FLAG_IS_CONS) |
115 | #define ZS_IS_KGDB(UP) ((UP)->flags & SUNZILOG_FLAG_IS_KGDB) | 115 | #define ZS_IS_KGDB(UP) ((UP)->flags & SUNZILOG_FLAG_IS_KGDB) |
116 | #define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags & SUNZILOG_FLAG_MODEM_STATUS) | 116 | #define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags & SUNZILOG_FLAG_MODEM_STATUS) |
117 | #define ZS_IS_CHANNEL_A(UP) ((UP)->flags & SUNZILOG_FLAG_IS_CHANNEL_A) | 117 | #define ZS_IS_CHANNEL_A(UP) ((UP)->flags & SUNZILOG_FLAG_IS_CHANNEL_A) |
118 | #define ZS_REGS_HELD(UP) ((UP)->flags & SUNZILOG_FLAG_REGS_HELD) | 118 | #define ZS_REGS_HELD(UP) ((UP)->flags & SUNZILOG_FLAG_REGS_HELD) |
119 | #define ZS_TX_STOPPED(UP) ((UP)->flags & SUNZILOG_FLAG_TX_STOPPED) | 119 | #define ZS_TX_STOPPED(UP) ((UP)->flags & SUNZILOG_FLAG_TX_STOPPED) |
120 | #define ZS_TX_ACTIVE(UP) ((UP)->flags & SUNZILOG_FLAG_TX_ACTIVE) | 120 | #define ZS_TX_ACTIVE(UP) ((UP)->flags & SUNZILOG_FLAG_TX_ACTIVE) |
121 | 121 | ||
122 | /* Reading and writing Zilog8530 registers. The delays are to make this | 122 | /* Reading and writing Zilog8530 registers. The delays are to make this |
123 | * driver work on the Sun4 which needs a settling delay after each chip | 123 | * driver work on the Sun4 which needs a settling delay after each chip |
124 | * register access, other machines handle this in hardware via auxiliary | 124 | * register access, other machines handle this in hardware via auxiliary |
125 | * flip-flops which implement the settle time we do in software. | 125 | * flip-flops which implement the settle time we do in software. |
126 | * | 126 | * |
127 | * The port lock must be held and local IRQs must be disabled | 127 | * The port lock must be held and local IRQs must be disabled |
128 | * when {read,write}_zsreg is invoked. | 128 | * when {read,write}_zsreg is invoked. |
129 | */ | 129 | */ |
130 | static unsigned char read_zsreg(struct zilog_channel __iomem *channel, | 130 | static unsigned char read_zsreg(struct zilog_channel __iomem *channel, |
131 | unsigned char reg) | 131 | unsigned char reg) |
132 | { | 132 | { |
133 | unsigned char retval; | 133 | unsigned char retval; |
134 | 134 | ||
135 | writeb(reg, &channel->control); | 135 | writeb(reg, &channel->control); |
136 | ZSDELAY(); | 136 | ZSDELAY(); |
137 | retval = readb(&channel->control); | 137 | retval = readb(&channel->control); |
138 | ZSDELAY(); | 138 | ZSDELAY(); |
139 | 139 | ||
140 | return retval; | 140 | return retval; |
141 | } | 141 | } |
142 | 142 | ||
143 | static void write_zsreg(struct zilog_channel __iomem *channel, | 143 | static void write_zsreg(struct zilog_channel __iomem *channel, |
144 | unsigned char reg, unsigned char value) | 144 | unsigned char reg, unsigned char value) |
145 | { | 145 | { |
146 | writeb(reg, &channel->control); | 146 | writeb(reg, &channel->control); |
147 | ZSDELAY(); | 147 | ZSDELAY(); |
148 | writeb(value, &channel->control); | 148 | writeb(value, &channel->control); |
149 | ZSDELAY(); | 149 | ZSDELAY(); |
150 | } | 150 | } |
151 | 151 | ||
152 | static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel) | 152 | static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel) |
153 | { | 153 | { |
154 | int i; | 154 | int i; |
155 | 155 | ||
156 | for (i = 0; i < 32; i++) { | 156 | for (i = 0; i < 32; i++) { |
157 | unsigned char regval; | 157 | unsigned char regval; |
158 | 158 | ||
159 | regval = readb(&channel->control); | 159 | regval = readb(&channel->control); |
160 | ZSDELAY(); | 160 | ZSDELAY(); |
161 | if (regval & Rx_CH_AV) | 161 | if (regval & Rx_CH_AV) |
162 | break; | 162 | break; |
163 | 163 | ||
164 | regval = read_zsreg(channel, R1); | 164 | regval = read_zsreg(channel, R1); |
165 | readb(&channel->data); | 165 | readb(&channel->data); |
166 | ZSDELAY(); | 166 | ZSDELAY(); |
167 | 167 | ||
168 | if (regval & (PAR_ERR | Rx_OVR | CRC_ERR)) { | 168 | if (regval & (PAR_ERR | Rx_OVR | CRC_ERR)) { |
169 | writeb(ERR_RES, &channel->control); | 169 | writeb(ERR_RES, &channel->control); |
170 | ZSDELAY(); | 170 | ZSDELAY(); |
171 | ZS_WSYNC(channel); | 171 | ZS_WSYNC(channel); |
172 | } | 172 | } |
173 | } | 173 | } |
174 | } | 174 | } |
175 | 175 | ||
176 | /* This function must only be called when the TX is not busy. The UART | 176 | /* This function must only be called when the TX is not busy. The UART |
177 | * port lock must be held and local interrupts disabled. | 177 | * port lock must be held and local interrupts disabled. |
178 | */ | 178 | */ |
179 | static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs) | 179 | static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs) |
180 | { | 180 | { |
181 | int i; | 181 | int i; |
182 | int escc; | 182 | int escc; |
183 | unsigned char r15; | 183 | unsigned char r15; |
184 | 184 | ||
185 | /* Let pending transmits finish. */ | 185 | /* Let pending transmits finish. */ |
186 | for (i = 0; i < 1000; i++) { | 186 | for (i = 0; i < 1000; i++) { |
187 | unsigned char stat = read_zsreg(channel, R1); | 187 | unsigned char stat = read_zsreg(channel, R1); |
188 | if (stat & ALL_SNT) | 188 | if (stat & ALL_SNT) |
189 | break; | 189 | break; |
190 | udelay(100); | 190 | udelay(100); |
191 | } | 191 | } |
192 | 192 | ||
193 | writeb(ERR_RES, &channel->control); | 193 | writeb(ERR_RES, &channel->control); |
194 | ZSDELAY(); | 194 | ZSDELAY(); |
195 | ZS_WSYNC(channel); | 195 | ZS_WSYNC(channel); |
196 | 196 | ||
197 | sunzilog_clear_fifo(channel); | 197 | sunzilog_clear_fifo(channel); |
198 | 198 | ||
199 | /* Disable all interrupts. */ | 199 | /* Disable all interrupts. */ |
200 | write_zsreg(channel, R1, | 200 | write_zsreg(channel, R1, |
201 | regs[R1] & ~(RxINT_MASK | TxINT_ENAB | EXT_INT_ENAB)); | 201 | regs[R1] & ~(RxINT_MASK | TxINT_ENAB | EXT_INT_ENAB)); |
202 | 202 | ||
203 | /* Set parity, sync config, stop bits, and clock divisor. */ | 203 | /* Set parity, sync config, stop bits, and clock divisor. */ |
204 | write_zsreg(channel, R4, regs[R4]); | 204 | write_zsreg(channel, R4, regs[R4]); |
205 | 205 | ||
206 | /* Set misc. TX/RX control bits. */ | 206 | /* Set misc. TX/RX control bits. */ |
207 | write_zsreg(channel, R10, regs[R10]); | 207 | write_zsreg(channel, R10, regs[R10]); |
208 | 208 | ||
209 | /* Set TX/RX controls sans the enable bits. */ | 209 | /* Set TX/RX controls sans the enable bits. */ |
210 | write_zsreg(channel, R3, regs[R3] & ~RxENAB); | 210 | write_zsreg(channel, R3, regs[R3] & ~RxENAB); |
211 | write_zsreg(channel, R5, regs[R5] & ~TxENAB); | 211 | write_zsreg(channel, R5, regs[R5] & ~TxENAB); |
212 | 212 | ||
213 | /* Synchronous mode config. */ | 213 | /* Synchronous mode config. */ |
214 | write_zsreg(channel, R6, regs[R6]); | 214 | write_zsreg(channel, R6, regs[R6]); |
215 | write_zsreg(channel, R7, regs[R7]); | 215 | write_zsreg(channel, R7, regs[R7]); |
216 | 216 | ||
217 | /* Don't mess with the interrupt vector (R2, unused by us) and | 217 | /* Don't mess with the interrupt vector (R2, unused by us) and |
218 | * master interrupt control (R9). We make sure this is setup | 218 | * master interrupt control (R9). We make sure this is setup |
219 | * properly at probe time then never touch it again. | 219 | * properly at probe time then never touch it again. |
220 | */ | 220 | */ |
221 | 221 | ||
222 | /* Disable baud generator. */ | 222 | /* Disable baud generator. */ |
223 | write_zsreg(channel, R14, regs[R14] & ~BRENAB); | 223 | write_zsreg(channel, R14, regs[R14] & ~BRENAB); |
224 | 224 | ||
225 | /* Clock mode control. */ | 225 | /* Clock mode control. */ |
226 | write_zsreg(channel, R11, regs[R11]); | 226 | write_zsreg(channel, R11, regs[R11]); |
227 | 227 | ||
228 | /* Lower and upper byte of baud rate generator divisor. */ | 228 | /* Lower and upper byte of baud rate generator divisor. */ |
229 | write_zsreg(channel, R12, regs[R12]); | 229 | write_zsreg(channel, R12, regs[R12]); |
230 | write_zsreg(channel, R13, regs[R13]); | 230 | write_zsreg(channel, R13, regs[R13]); |
231 | 231 | ||
232 | /* Now rewrite R14, with BRENAB (if set). */ | 232 | /* Now rewrite R14, with BRENAB (if set). */ |
233 | write_zsreg(channel, R14, regs[R14]); | 233 | write_zsreg(channel, R14, regs[R14]); |
234 | 234 | ||
235 | /* External status interrupt control. */ | 235 | /* External status interrupt control. */ |
236 | write_zsreg(channel, R15, (regs[R15] | WR7pEN) & ~FIFOEN); | 236 | write_zsreg(channel, R15, (regs[R15] | WR7pEN) & ~FIFOEN); |
237 | 237 | ||
238 | /* ESCC Extension Register */ | 238 | /* ESCC Extension Register */ |
239 | r15 = read_zsreg(channel, R15); | 239 | r15 = read_zsreg(channel, R15); |
240 | if (r15 & 0x01) { | 240 | if (r15 & 0x01) { |
241 | write_zsreg(channel, R7, regs[R7p]); | 241 | write_zsreg(channel, R7, regs[R7p]); |
242 | 242 | ||
243 | /* External status interrupt and FIFO control. */ | 243 | /* External status interrupt and FIFO control. */ |
244 | write_zsreg(channel, R15, regs[R15] & ~WR7pEN); | 244 | write_zsreg(channel, R15, regs[R15] & ~WR7pEN); |
245 | escc = 1; | 245 | escc = 1; |
246 | } else { | 246 | } else { |
247 | /* Clear FIFO bit case it is an issue */ | 247 | /* Clear FIFO bit case it is an issue */ |
248 | regs[R15] &= ~FIFOEN; | 248 | regs[R15] &= ~FIFOEN; |
249 | escc = 0; | 249 | escc = 0; |
250 | } | 250 | } |
251 | 251 | ||
252 | /* Reset external status interrupts. */ | 252 | /* Reset external status interrupts. */ |
253 | write_zsreg(channel, R0, RES_EXT_INT); /* First Latch */ | 253 | write_zsreg(channel, R0, RES_EXT_INT); /* First Latch */ |
254 | write_zsreg(channel, R0, RES_EXT_INT); /* Second Latch */ | 254 | write_zsreg(channel, R0, RES_EXT_INT); /* Second Latch */ |
255 | 255 | ||
256 | /* Rewrite R3/R5, this time without enables masked. */ | 256 | /* Rewrite R3/R5, this time without enables masked. */ |
257 | write_zsreg(channel, R3, regs[R3]); | 257 | write_zsreg(channel, R3, regs[R3]); |
258 | write_zsreg(channel, R5, regs[R5]); | 258 | write_zsreg(channel, R5, regs[R5]); |
259 | 259 | ||
260 | /* Rewrite R1, this time without IRQ enabled masked. */ | 260 | /* Rewrite R1, this time without IRQ enabled masked. */ |
261 | write_zsreg(channel, R1, regs[R1]); | 261 | write_zsreg(channel, R1, regs[R1]); |
262 | 262 | ||
263 | return escc; | 263 | return escc; |
264 | } | 264 | } |
265 | 265 | ||
266 | /* Reprogram the Zilog channel HW registers with the copies found in the | 266 | /* Reprogram the Zilog channel HW registers with the copies found in the |
267 | * software state struct. If the transmitter is busy, we defer this update | 267 | * software state struct. If the transmitter is busy, we defer this update |
268 | * until the next TX complete interrupt. Else, we do it right now. | 268 | * until the next TX complete interrupt. Else, we do it right now. |
269 | * | 269 | * |
270 | * The UART port lock must be held and local interrupts disabled. | 270 | * The UART port lock must be held and local interrupts disabled. |
271 | */ | 271 | */ |
272 | static void sunzilog_maybe_update_regs(struct uart_sunzilog_port *up, | 272 | static void sunzilog_maybe_update_regs(struct uart_sunzilog_port *up, |
273 | struct zilog_channel __iomem *channel) | 273 | struct zilog_channel __iomem *channel) |
274 | { | 274 | { |
275 | if (!ZS_REGS_HELD(up)) { | 275 | if (!ZS_REGS_HELD(up)) { |
276 | if (ZS_TX_ACTIVE(up)) { | 276 | if (ZS_TX_ACTIVE(up)) { |
277 | up->flags |= SUNZILOG_FLAG_REGS_HELD; | 277 | up->flags |= SUNZILOG_FLAG_REGS_HELD; |
278 | } else { | 278 | } else { |
279 | __load_zsregs(channel, up->curregs); | 279 | __load_zsregs(channel, up->curregs); |
280 | } | 280 | } |
281 | } | 281 | } |
282 | } | 282 | } |
283 | 283 | ||
284 | static void sunzilog_change_mouse_baud(struct uart_sunzilog_port *up) | 284 | static void sunzilog_change_mouse_baud(struct uart_sunzilog_port *up) |
285 | { | 285 | { |
286 | unsigned int cur_cflag = up->cflag; | 286 | unsigned int cur_cflag = up->cflag; |
287 | int brg, new_baud; | 287 | int brg, new_baud; |
288 | 288 | ||
289 | up->cflag &= ~CBAUD; | 289 | up->cflag &= ~CBAUD; |
290 | up->cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud); | 290 | up->cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud); |
291 | 291 | ||
292 | brg = BPS_TO_BRG(new_baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); | 292 | brg = BPS_TO_BRG(new_baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); |
293 | up->curregs[R12] = (brg & 0xff); | 293 | up->curregs[R12] = (brg & 0xff); |
294 | up->curregs[R13] = (brg >> 8) & 0xff; | 294 | up->curregs[R13] = (brg >> 8) & 0xff; |
295 | sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(&up->port)); | 295 | sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(&up->port)); |
296 | } | 296 | } |
297 | 297 | ||
298 | static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, | 298 | static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, |
299 | unsigned char ch, int is_break) | 299 | unsigned char ch, int is_break) |
300 | { | 300 | { |
301 | if (ZS_IS_KEYB(up)) { | 301 | if (ZS_IS_KEYB(up)) { |
302 | /* Stop-A is handled by drivers/char/keyboard.c now. */ | 302 | /* Stop-A is handled by drivers/char/keyboard.c now. */ |
303 | #ifdef CONFIG_SERIO | 303 | #ifdef CONFIG_SERIO |
304 | if (up->serio_open) | 304 | if (up->serio_open) |
305 | serio_interrupt(&up->serio, ch, 0); | 305 | serio_interrupt(&up->serio, ch, 0); |
306 | #endif | 306 | #endif |
307 | } else if (ZS_IS_MOUSE(up)) { | 307 | } else if (ZS_IS_MOUSE(up)) { |
308 | int ret = suncore_mouse_baud_detection(ch, is_break); | 308 | int ret = suncore_mouse_baud_detection(ch, is_break); |
309 | 309 | ||
310 | switch (ret) { | 310 | switch (ret) { |
311 | case 2: | 311 | case 2: |
312 | sunzilog_change_mouse_baud(up); | 312 | sunzilog_change_mouse_baud(up); |
313 | /* fallthru */ | 313 | /* fallthru */ |
314 | case 1: | 314 | case 1: |
315 | break; | 315 | break; |
316 | 316 | ||
317 | case 0: | 317 | case 0: |
318 | #ifdef CONFIG_SERIO | 318 | #ifdef CONFIG_SERIO |
319 | if (up->serio_open) | 319 | if (up->serio_open) |
320 | serio_interrupt(&up->serio, ch, 0); | 320 | serio_interrupt(&up->serio, ch, 0); |
321 | #endif | 321 | #endif |
322 | break; | 322 | break; |
323 | }; | 323 | }; |
324 | } | 324 | } |
325 | } | 325 | } |
326 | 326 | ||
327 | static struct tty_struct * | 327 | static struct tty_struct * |
328 | sunzilog_receive_chars(struct uart_sunzilog_port *up, | 328 | sunzilog_receive_chars(struct uart_sunzilog_port *up, |
329 | struct zilog_channel __iomem *channel) | 329 | struct zilog_channel __iomem *channel) |
330 | { | 330 | { |
331 | struct tty_struct *tty; | 331 | struct tty_struct *tty; |
332 | unsigned char ch, r1, flag; | 332 | unsigned char ch, r1, flag; |
333 | 333 | ||
334 | tty = NULL; | 334 | tty = NULL; |
335 | if (up->port.info != NULL && /* Unopened serial console */ | 335 | if (up->port.info != NULL && /* Unopened serial console */ |
336 | up->port.info->tty != NULL) /* Keyboard || mouse */ | 336 | up->port.info->tty != NULL) /* Keyboard || mouse */ |
337 | tty = up->port.info->tty; | 337 | tty = up->port.info->tty; |
338 | 338 | ||
339 | for (;;) { | 339 | for (;;) { |
340 | 340 | ||
341 | r1 = read_zsreg(channel, R1); | 341 | r1 = read_zsreg(channel, R1); |
342 | if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { | 342 | if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { |
343 | writeb(ERR_RES, &channel->control); | 343 | writeb(ERR_RES, &channel->control); |
344 | ZSDELAY(); | 344 | ZSDELAY(); |
345 | ZS_WSYNC(channel); | 345 | ZS_WSYNC(channel); |
346 | } | 346 | } |
347 | 347 | ||
348 | ch = readb(&channel->control); | 348 | ch = readb(&channel->control); |
349 | ZSDELAY(); | 349 | ZSDELAY(); |
350 | 350 | ||
351 | /* This funny hack depends upon BRK_ABRT not interfering | 351 | /* This funny hack depends upon BRK_ABRT not interfering |
352 | * with the other bits we care about in R1. | 352 | * with the other bits we care about in R1. |
353 | */ | 353 | */ |
354 | if (ch & BRK_ABRT) | 354 | if (ch & BRK_ABRT) |
355 | r1 |= BRK_ABRT; | 355 | r1 |= BRK_ABRT; |
356 | 356 | ||
357 | if (!(ch & Rx_CH_AV)) | 357 | if (!(ch & Rx_CH_AV)) |
358 | break; | 358 | break; |
359 | 359 | ||
360 | ch = readb(&channel->data); | 360 | ch = readb(&channel->data); |
361 | ZSDELAY(); | 361 | ZSDELAY(); |
362 | 362 | ||
363 | ch &= up->parity_mask; | 363 | ch &= up->parity_mask; |
364 | 364 | ||
365 | if (unlikely(ZS_IS_KEYB(up)) || unlikely(ZS_IS_MOUSE(up))) { | 365 | if (unlikely(ZS_IS_KEYB(up)) || unlikely(ZS_IS_MOUSE(up))) { |
366 | sunzilog_kbdms_receive_chars(up, ch, 0); | 366 | sunzilog_kbdms_receive_chars(up, ch, 0); |
367 | continue; | 367 | continue; |
368 | } | 368 | } |
369 | 369 | ||
370 | if (tty == NULL) { | 370 | if (tty == NULL) { |
371 | uart_handle_sysrq_char(&up->port, ch); | 371 | uart_handle_sysrq_char(&up->port, ch); |
372 | continue; | 372 | continue; |
373 | } | 373 | } |
374 | 374 | ||
375 | /* A real serial line, record the character and status. */ | 375 | /* A real serial line, record the character and status. */ |
376 | flag = TTY_NORMAL; | 376 | flag = TTY_NORMAL; |
377 | up->port.icount.rx++; | 377 | up->port.icount.rx++; |
378 | if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) { | 378 | if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) { |
379 | if (r1 & BRK_ABRT) { | 379 | if (r1 & BRK_ABRT) { |
380 | r1 &= ~(PAR_ERR | CRC_ERR); | 380 | r1 &= ~(PAR_ERR | CRC_ERR); |
381 | up->port.icount.brk++; | 381 | up->port.icount.brk++; |
382 | if (uart_handle_break(&up->port)) | 382 | if (uart_handle_break(&up->port)) |
383 | continue; | 383 | continue; |
384 | } | 384 | } |
385 | else if (r1 & PAR_ERR) | 385 | else if (r1 & PAR_ERR) |
386 | up->port.icount.parity++; | 386 | up->port.icount.parity++; |
387 | else if (r1 & CRC_ERR) | 387 | else if (r1 & CRC_ERR) |
388 | up->port.icount.frame++; | 388 | up->port.icount.frame++; |
389 | if (r1 & Rx_OVR) | 389 | if (r1 & Rx_OVR) |
390 | up->port.icount.overrun++; | 390 | up->port.icount.overrun++; |
391 | r1 &= up->port.read_status_mask; | 391 | r1 &= up->port.read_status_mask; |
392 | if (r1 & BRK_ABRT) | 392 | if (r1 & BRK_ABRT) |
393 | flag = TTY_BREAK; | 393 | flag = TTY_BREAK; |
394 | else if (r1 & PAR_ERR) | 394 | else if (r1 & PAR_ERR) |
395 | flag = TTY_PARITY; | 395 | flag = TTY_PARITY; |
396 | else if (r1 & CRC_ERR) | 396 | else if (r1 & CRC_ERR) |
397 | flag = TTY_FRAME; | 397 | flag = TTY_FRAME; |
398 | } | 398 | } |
399 | if (uart_handle_sysrq_char(&up->port, ch)) | 399 | if (uart_handle_sysrq_char(&up->port, ch)) |
400 | continue; | 400 | continue; |
401 | 401 | ||
402 | if (up->port.ignore_status_mask == 0xff || | 402 | if (up->port.ignore_status_mask == 0xff || |
403 | (r1 & up->port.ignore_status_mask) == 0) { | 403 | (r1 & up->port.ignore_status_mask) == 0) { |
404 | tty_insert_flip_char(tty, ch, flag); | 404 | tty_insert_flip_char(tty, ch, flag); |
405 | } | 405 | } |
406 | if (r1 & Rx_OVR) | 406 | if (r1 & Rx_OVR) |
407 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 407 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
408 | } | 408 | } |
409 | 409 | ||
410 | return tty; | 410 | return tty; |
411 | } | 411 | } |
412 | 412 | ||
413 | static void sunzilog_status_handle(struct uart_sunzilog_port *up, | 413 | static void sunzilog_status_handle(struct uart_sunzilog_port *up, |
414 | struct zilog_channel __iomem *channel) | 414 | struct zilog_channel __iomem *channel) |
415 | { | 415 | { |
416 | unsigned char status; | 416 | unsigned char status; |
417 | 417 | ||
418 | status = readb(&channel->control); | 418 | status = readb(&channel->control); |
419 | ZSDELAY(); | 419 | ZSDELAY(); |
420 | 420 | ||
421 | writeb(RES_EXT_INT, &channel->control); | 421 | writeb(RES_EXT_INT, &channel->control); |
422 | ZSDELAY(); | 422 | ZSDELAY(); |
423 | ZS_WSYNC(channel); | 423 | ZS_WSYNC(channel); |
424 | 424 | ||
425 | if (status & BRK_ABRT) { | 425 | if (status & BRK_ABRT) { |
426 | if (ZS_IS_MOUSE(up)) | 426 | if (ZS_IS_MOUSE(up)) |
427 | sunzilog_kbdms_receive_chars(up, 0, 1); | 427 | sunzilog_kbdms_receive_chars(up, 0, 1); |
428 | if (ZS_IS_CONS(up)) { | 428 | if (ZS_IS_CONS(up)) { |
429 | /* Wait for BREAK to deassert to avoid potentially | 429 | /* Wait for BREAK to deassert to avoid potentially |
430 | * confusing the PROM. | 430 | * confusing the PROM. |
431 | */ | 431 | */ |
432 | while (1) { | 432 | while (1) { |
433 | status = readb(&channel->control); | 433 | status = readb(&channel->control); |
434 | ZSDELAY(); | 434 | ZSDELAY(); |
435 | if (!(status & BRK_ABRT)) | 435 | if (!(status & BRK_ABRT)) |
436 | break; | 436 | break; |
437 | } | 437 | } |
438 | sun_do_break(); | 438 | sun_do_break(); |
439 | return; | 439 | return; |
440 | } | 440 | } |
441 | } | 441 | } |
442 | 442 | ||
443 | if (ZS_WANTS_MODEM_STATUS(up)) { | 443 | if (ZS_WANTS_MODEM_STATUS(up)) { |
444 | if (status & SYNC) | 444 | if (status & SYNC) |
445 | up->port.icount.dsr++; | 445 | up->port.icount.dsr++; |
446 | 446 | ||
447 | /* The Zilog just gives us an interrupt when DCD/CTS/etc. change. | 447 | /* The Zilog just gives us an interrupt when DCD/CTS/etc. change. |
448 | * But it does not tell us which bit has changed, we have to keep | 448 | * But it does not tell us which bit has changed, we have to keep |
449 | * track of this ourselves. | 449 | * track of this ourselves. |
450 | */ | 450 | */ |
451 | if ((status ^ up->prev_status) ^ DCD) | 451 | if ((status ^ up->prev_status) ^ DCD) |
452 | uart_handle_dcd_change(&up->port, | 452 | uart_handle_dcd_change(&up->port, |
453 | (status & DCD)); | 453 | (status & DCD)); |
454 | if ((status ^ up->prev_status) ^ CTS) | 454 | if ((status ^ up->prev_status) ^ CTS) |
455 | uart_handle_cts_change(&up->port, | 455 | uart_handle_cts_change(&up->port, |
456 | (status & CTS)); | 456 | (status & CTS)); |
457 | 457 | ||
458 | wake_up_interruptible(&up->port.info->delta_msr_wait); | 458 | wake_up_interruptible(&up->port.info->delta_msr_wait); |
459 | } | 459 | } |
460 | 460 | ||
461 | up->prev_status = status; | 461 | up->prev_status = status; |
462 | } | 462 | } |
463 | 463 | ||
464 | static void sunzilog_transmit_chars(struct uart_sunzilog_port *up, | 464 | static void sunzilog_transmit_chars(struct uart_sunzilog_port *up, |
465 | struct zilog_channel __iomem *channel) | 465 | struct zilog_channel __iomem *channel) |
466 | { | 466 | { |
467 | struct circ_buf *xmit; | 467 | struct circ_buf *xmit; |
468 | 468 | ||
469 | if (ZS_IS_CONS(up)) { | 469 | if (ZS_IS_CONS(up)) { |
470 | unsigned char status = readb(&channel->control); | 470 | unsigned char status = readb(&channel->control); |
471 | ZSDELAY(); | 471 | ZSDELAY(); |
472 | 472 | ||
473 | /* TX still busy? Just wait for the next TX done interrupt. | 473 | /* TX still busy? Just wait for the next TX done interrupt. |
474 | * | 474 | * |
475 | * It can occur because of how we do serial console writes. It would | 475 | * It can occur because of how we do serial console writes. It would |
476 | * be nice to transmit console writes just like we normally would for | 476 | * be nice to transmit console writes just like we normally would for |
477 | * a TTY line. (ie. buffered and TX interrupt driven). That is not | 477 | * a TTY line. (ie. buffered and TX interrupt driven). That is not |
478 | * easy because console writes cannot sleep. One solution might be | 478 | * easy because console writes cannot sleep. One solution might be |
479 | * to poll on enough port->xmit space becomming free. -DaveM | 479 | * to poll on enough port->xmit space becomming free. -DaveM |
480 | */ | 480 | */ |
481 | if (!(status & Tx_BUF_EMP)) | 481 | if (!(status & Tx_BUF_EMP)) |
482 | return; | 482 | return; |
483 | } | 483 | } |
484 | 484 | ||
485 | up->flags &= ~SUNZILOG_FLAG_TX_ACTIVE; | 485 | up->flags &= ~SUNZILOG_FLAG_TX_ACTIVE; |
486 | 486 | ||
487 | if (ZS_REGS_HELD(up)) { | 487 | if (ZS_REGS_HELD(up)) { |
488 | __load_zsregs(channel, up->curregs); | 488 | __load_zsregs(channel, up->curregs); |
489 | up->flags &= ~SUNZILOG_FLAG_REGS_HELD; | 489 | up->flags &= ~SUNZILOG_FLAG_REGS_HELD; |
490 | } | 490 | } |
491 | 491 | ||
492 | if (ZS_TX_STOPPED(up)) { | 492 | if (ZS_TX_STOPPED(up)) { |
493 | up->flags &= ~SUNZILOG_FLAG_TX_STOPPED; | 493 | up->flags &= ~SUNZILOG_FLAG_TX_STOPPED; |
494 | goto ack_tx_int; | 494 | goto ack_tx_int; |
495 | } | 495 | } |
496 | 496 | ||
497 | if (up->port.x_char) { | 497 | if (up->port.x_char) { |
498 | up->flags |= SUNZILOG_FLAG_TX_ACTIVE; | 498 | up->flags |= SUNZILOG_FLAG_TX_ACTIVE; |
499 | writeb(up->port.x_char, &channel->data); | 499 | writeb(up->port.x_char, &channel->data); |
500 | ZSDELAY(); | 500 | ZSDELAY(); |
501 | ZS_WSYNC(channel); | 501 | ZS_WSYNC(channel); |
502 | 502 | ||
503 | up->port.icount.tx++; | 503 | up->port.icount.tx++; |
504 | up->port.x_char = 0; | 504 | up->port.x_char = 0; |
505 | return; | 505 | return; |
506 | } | 506 | } |
507 | 507 | ||
508 | if (up->port.info == NULL) | 508 | if (up->port.info == NULL) |
509 | goto ack_tx_int; | 509 | goto ack_tx_int; |
510 | xmit = &up->port.info->xmit; | 510 | xmit = &up->port.info->xmit; |
511 | if (uart_circ_empty(xmit)) | 511 | if (uart_circ_empty(xmit)) |
512 | goto ack_tx_int; | 512 | goto ack_tx_int; |
513 | 513 | ||
514 | if (uart_tx_stopped(&up->port)) | 514 | if (uart_tx_stopped(&up->port)) |
515 | goto ack_tx_int; | 515 | goto ack_tx_int; |
516 | 516 | ||
517 | up->flags |= SUNZILOG_FLAG_TX_ACTIVE; | 517 | up->flags |= SUNZILOG_FLAG_TX_ACTIVE; |
518 | writeb(xmit->buf[xmit->tail], &channel->data); | 518 | writeb(xmit->buf[xmit->tail], &channel->data); |
519 | ZSDELAY(); | 519 | ZSDELAY(); |
520 | ZS_WSYNC(channel); | 520 | ZS_WSYNC(channel); |
521 | 521 | ||
522 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 522 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
523 | up->port.icount.tx++; | 523 | up->port.icount.tx++; |
524 | 524 | ||
525 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 525 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
526 | uart_write_wakeup(&up->port); | 526 | uart_write_wakeup(&up->port); |
527 | 527 | ||
528 | return; | 528 | return; |
529 | 529 | ||
530 | ack_tx_int: | 530 | ack_tx_int: |
531 | writeb(RES_Tx_P, &channel->control); | 531 | writeb(RES_Tx_P, &channel->control); |
532 | ZSDELAY(); | 532 | ZSDELAY(); |
533 | ZS_WSYNC(channel); | 533 | ZS_WSYNC(channel); |
534 | } | 534 | } |
535 | 535 | ||
536 | static irqreturn_t sunzilog_interrupt(int irq, void *dev_id) | 536 | static irqreturn_t sunzilog_interrupt(int irq, void *dev_id) |
537 | { | 537 | { |
538 | struct uart_sunzilog_port *up = dev_id; | 538 | struct uart_sunzilog_port *up = dev_id; |
539 | 539 | ||
540 | while (up) { | 540 | while (up) { |
541 | struct zilog_channel __iomem *channel | 541 | struct zilog_channel __iomem *channel |
542 | = ZILOG_CHANNEL_FROM_PORT(&up->port); | 542 | = ZILOG_CHANNEL_FROM_PORT(&up->port); |
543 | struct tty_struct *tty; | 543 | struct tty_struct *tty; |
544 | unsigned char r3; | 544 | unsigned char r3; |
545 | 545 | ||
546 | spin_lock(&up->port.lock); | 546 | spin_lock(&up->port.lock); |
547 | r3 = read_zsreg(channel, R3); | 547 | r3 = read_zsreg(channel, R3); |
548 | 548 | ||
549 | /* Channel A */ | 549 | /* Channel A */ |
550 | tty = NULL; | 550 | tty = NULL; |
551 | if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { | 551 | if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { |
552 | writeb(RES_H_IUS, &channel->control); | 552 | writeb(RES_H_IUS, &channel->control); |
553 | ZSDELAY(); | 553 | ZSDELAY(); |
554 | ZS_WSYNC(channel); | 554 | ZS_WSYNC(channel); |
555 | 555 | ||
556 | if (r3 & CHARxIP) | 556 | if (r3 & CHARxIP) |
557 | tty = sunzilog_receive_chars(up, channel); | 557 | tty = sunzilog_receive_chars(up, channel); |
558 | if (r3 & CHAEXT) | 558 | if (r3 & CHAEXT) |
559 | sunzilog_status_handle(up, channel); | 559 | sunzilog_status_handle(up, channel); |
560 | if (r3 & CHATxIP) | 560 | if (r3 & CHATxIP) |
561 | sunzilog_transmit_chars(up, channel); | 561 | sunzilog_transmit_chars(up, channel); |
562 | } | 562 | } |
563 | spin_unlock(&up->port.lock); | 563 | spin_unlock(&up->port.lock); |
564 | 564 | ||
565 | if (tty) | 565 | if (tty) |
566 | tty_flip_buffer_push(tty); | 566 | tty_flip_buffer_push(tty); |
567 | 567 | ||
568 | /* Channel B */ | 568 | /* Channel B */ |
569 | up = up->next; | 569 | up = up->next; |
570 | channel = ZILOG_CHANNEL_FROM_PORT(&up->port); | 570 | channel = ZILOG_CHANNEL_FROM_PORT(&up->port); |
571 | 571 | ||
572 | spin_lock(&up->port.lock); | 572 | spin_lock(&up->port.lock); |
573 | tty = NULL; | 573 | tty = NULL; |
574 | if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { | 574 | if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { |
575 | writeb(RES_H_IUS, &channel->control); | 575 | writeb(RES_H_IUS, &channel->control); |
576 | ZSDELAY(); | 576 | ZSDELAY(); |
577 | ZS_WSYNC(channel); | 577 | ZS_WSYNC(channel); |
578 | 578 | ||
579 | if (r3 & CHBRxIP) | 579 | if (r3 & CHBRxIP) |
580 | tty = sunzilog_receive_chars(up, channel); | 580 | tty = sunzilog_receive_chars(up, channel); |
581 | if (r3 & CHBEXT) | 581 | if (r3 & CHBEXT) |
582 | sunzilog_status_handle(up, channel); | 582 | sunzilog_status_handle(up, channel); |
583 | if (r3 & CHBTxIP) | 583 | if (r3 & CHBTxIP) |
584 | sunzilog_transmit_chars(up, channel); | 584 | sunzilog_transmit_chars(up, channel); |
585 | } | 585 | } |
586 | spin_unlock(&up->port.lock); | 586 | spin_unlock(&up->port.lock); |
587 | 587 | ||
588 | if (tty) | 588 | if (tty) |
589 | tty_flip_buffer_push(tty); | 589 | tty_flip_buffer_push(tty); |
590 | 590 | ||
591 | up = up->next; | 591 | up = up->next; |
592 | } | 592 | } |
593 | 593 | ||
594 | return IRQ_HANDLED; | 594 | return IRQ_HANDLED; |
595 | } | 595 | } |
596 | 596 | ||
597 | /* A convenient way to quickly get R0 status. The caller must _not_ hold the | 597 | /* A convenient way to quickly get R0 status. The caller must _not_ hold the |
598 | * port lock, it is acquired here. | 598 | * port lock, it is acquired here. |
599 | */ | 599 | */ |
600 | static __inline__ unsigned char sunzilog_read_channel_status(struct uart_port *port) | 600 | static __inline__ unsigned char sunzilog_read_channel_status(struct uart_port *port) |
601 | { | 601 | { |
602 | struct zilog_channel __iomem *channel; | 602 | struct zilog_channel __iomem *channel; |
603 | unsigned char status; | 603 | unsigned char status; |
604 | 604 | ||
605 | channel = ZILOG_CHANNEL_FROM_PORT(port); | 605 | channel = ZILOG_CHANNEL_FROM_PORT(port); |
606 | status = readb(&channel->control); | 606 | status = readb(&channel->control); |
607 | ZSDELAY(); | 607 | ZSDELAY(); |
608 | 608 | ||
609 | return status; | 609 | return status; |
610 | } | 610 | } |
611 | 611 | ||
612 | /* The port lock is not held. */ | 612 | /* The port lock is not held. */ |
613 | static unsigned int sunzilog_tx_empty(struct uart_port *port) | 613 | static unsigned int sunzilog_tx_empty(struct uart_port *port) |
614 | { | 614 | { |
615 | unsigned long flags; | 615 | unsigned long flags; |
616 | unsigned char status; | 616 | unsigned char status; |
617 | unsigned int ret; | 617 | unsigned int ret; |
618 | 618 | ||
619 | spin_lock_irqsave(&port->lock, flags); | 619 | spin_lock_irqsave(&port->lock, flags); |
620 | 620 | ||
621 | status = sunzilog_read_channel_status(port); | 621 | status = sunzilog_read_channel_status(port); |
622 | 622 | ||
623 | spin_unlock_irqrestore(&port->lock, flags); | 623 | spin_unlock_irqrestore(&port->lock, flags); |
624 | 624 | ||
625 | if (status & Tx_BUF_EMP) | 625 | if (status & Tx_BUF_EMP) |
626 | ret = TIOCSER_TEMT; | 626 | ret = TIOCSER_TEMT; |
627 | else | 627 | else |
628 | ret = 0; | 628 | ret = 0; |
629 | 629 | ||
630 | return ret; | 630 | return ret; |
631 | } | 631 | } |
632 | 632 | ||
633 | /* The port lock is held and interrupts are disabled. */ | 633 | /* The port lock is held and interrupts are disabled. */ |
634 | static unsigned int sunzilog_get_mctrl(struct uart_port *port) | 634 | static unsigned int sunzilog_get_mctrl(struct uart_port *port) |
635 | { | 635 | { |
636 | unsigned char status; | 636 | unsigned char status; |
637 | unsigned int ret; | 637 | unsigned int ret; |
638 | 638 | ||
639 | status = sunzilog_read_channel_status(port); | 639 | status = sunzilog_read_channel_status(port); |
640 | 640 | ||
641 | ret = 0; | 641 | ret = 0; |
642 | if (status & DCD) | 642 | if (status & DCD) |
643 | ret |= TIOCM_CAR; | 643 | ret |= TIOCM_CAR; |
644 | if (status & SYNC) | 644 | if (status & SYNC) |
645 | ret |= TIOCM_DSR; | 645 | ret |= TIOCM_DSR; |
646 | if (status & CTS) | 646 | if (status & CTS) |
647 | ret |= TIOCM_CTS; | 647 | ret |= TIOCM_CTS; |
648 | 648 | ||
649 | return ret; | 649 | return ret; |
650 | } | 650 | } |
651 | 651 | ||
652 | /* The port lock is held and interrupts are disabled. */ | 652 | /* The port lock is held and interrupts are disabled. */ |
653 | static void sunzilog_set_mctrl(struct uart_port *port, unsigned int mctrl) | 653 | static void sunzilog_set_mctrl(struct uart_port *port, unsigned int mctrl) |
654 | { | 654 | { |
655 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; | 655 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; |
656 | struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); | 656 | struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); |
657 | unsigned char set_bits, clear_bits; | 657 | unsigned char set_bits, clear_bits; |
658 | 658 | ||
659 | set_bits = clear_bits = 0; | 659 | set_bits = clear_bits = 0; |
660 | 660 | ||
661 | if (mctrl & TIOCM_RTS) | 661 | if (mctrl & TIOCM_RTS) |
662 | set_bits |= RTS; | 662 | set_bits |= RTS; |
663 | else | 663 | else |
664 | clear_bits |= RTS; | 664 | clear_bits |= RTS; |
665 | if (mctrl & TIOCM_DTR) | 665 | if (mctrl & TIOCM_DTR) |
666 | set_bits |= DTR; | 666 | set_bits |= DTR; |
667 | else | 667 | else |
668 | clear_bits |= DTR; | 668 | clear_bits |= DTR; |
669 | 669 | ||
670 | /* NOTE: Not subject to 'transmitter active' rule. */ | 670 | /* NOTE: Not subject to 'transmitter active' rule. */ |
671 | up->curregs[R5] |= set_bits; | 671 | up->curregs[R5] |= set_bits; |
672 | up->curregs[R5] &= ~clear_bits; | 672 | up->curregs[R5] &= ~clear_bits; |
673 | write_zsreg(channel, R5, up->curregs[R5]); | 673 | write_zsreg(channel, R5, up->curregs[R5]); |
674 | } | 674 | } |
675 | 675 | ||
676 | /* The port lock is held and interrupts are disabled. */ | 676 | /* The port lock is held and interrupts are disabled. */ |
677 | static void sunzilog_stop_tx(struct uart_port *port) | 677 | static void sunzilog_stop_tx(struct uart_port *port) |
678 | { | 678 | { |
679 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; | 679 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; |
680 | 680 | ||
681 | up->flags |= SUNZILOG_FLAG_TX_STOPPED; | 681 | up->flags |= SUNZILOG_FLAG_TX_STOPPED; |
682 | } | 682 | } |
683 | 683 | ||
684 | /* The port lock is held and interrupts are disabled. */ | 684 | /* The port lock is held and interrupts are disabled. */ |
685 | static void sunzilog_start_tx(struct uart_port *port) | 685 | static void sunzilog_start_tx(struct uart_port *port) |
686 | { | 686 | { |
687 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; | 687 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; |
688 | struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); | 688 | struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); |
689 | unsigned char status; | 689 | unsigned char status; |
690 | 690 | ||
691 | up->flags |= SUNZILOG_FLAG_TX_ACTIVE; | 691 | up->flags |= SUNZILOG_FLAG_TX_ACTIVE; |
692 | up->flags &= ~SUNZILOG_FLAG_TX_STOPPED; | 692 | up->flags &= ~SUNZILOG_FLAG_TX_STOPPED; |
693 | 693 | ||
694 | status = readb(&channel->control); | 694 | status = readb(&channel->control); |
695 | ZSDELAY(); | 695 | ZSDELAY(); |
696 | 696 | ||
697 | /* TX busy? Just wait for the TX done interrupt. */ | 697 | /* TX busy? Just wait for the TX done interrupt. */ |
698 | if (!(status & Tx_BUF_EMP)) | 698 | if (!(status & Tx_BUF_EMP)) |
699 | return; | 699 | return; |
700 | 700 | ||
701 | /* Send the first character to jump-start the TX done | 701 | /* Send the first character to jump-start the TX done |
702 | * IRQ sending engine. | 702 | * IRQ sending engine. |
703 | */ | 703 | */ |
704 | if (port->x_char) { | 704 | if (port->x_char) { |
705 | writeb(port->x_char, &channel->data); | 705 | writeb(port->x_char, &channel->data); |
706 | ZSDELAY(); | 706 | ZSDELAY(); |
707 | ZS_WSYNC(channel); | 707 | ZS_WSYNC(channel); |
708 | 708 | ||
709 | port->icount.tx++; | 709 | port->icount.tx++; |
710 | port->x_char = 0; | 710 | port->x_char = 0; |
711 | } else { | 711 | } else { |
712 | struct circ_buf *xmit = &port->info->xmit; | 712 | struct circ_buf *xmit = &port->info->xmit; |
713 | 713 | ||
714 | writeb(xmit->buf[xmit->tail], &channel->data); | 714 | writeb(xmit->buf[xmit->tail], &channel->data); |
715 | ZSDELAY(); | 715 | ZSDELAY(); |
716 | ZS_WSYNC(channel); | 716 | ZS_WSYNC(channel); |
717 | 717 | ||
718 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 718 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
719 | port->icount.tx++; | 719 | port->icount.tx++; |
720 | 720 | ||
721 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 721 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
722 | uart_write_wakeup(&up->port); | 722 | uart_write_wakeup(&up->port); |
723 | } | 723 | } |
724 | } | 724 | } |
725 | 725 | ||
726 | /* The port lock is held. */ | 726 | /* The port lock is held. */ |
727 | static void sunzilog_stop_rx(struct uart_port *port) | 727 | static void sunzilog_stop_rx(struct uart_port *port) |
728 | { | 728 | { |
729 | struct uart_sunzilog_port *up = UART_ZILOG(port); | 729 | struct uart_sunzilog_port *up = UART_ZILOG(port); |
730 | struct zilog_channel __iomem *channel; | 730 | struct zilog_channel __iomem *channel; |
731 | 731 | ||
732 | if (ZS_IS_CONS(up)) | 732 | if (ZS_IS_CONS(up)) |
733 | return; | 733 | return; |
734 | 734 | ||
735 | channel = ZILOG_CHANNEL_FROM_PORT(port); | 735 | channel = ZILOG_CHANNEL_FROM_PORT(port); |
736 | 736 | ||
737 | /* Disable all RX interrupts. */ | 737 | /* Disable all RX interrupts. */ |
738 | up->curregs[R1] &= ~RxINT_MASK; | 738 | up->curregs[R1] &= ~RxINT_MASK; |
739 | sunzilog_maybe_update_regs(up, channel); | 739 | sunzilog_maybe_update_regs(up, channel); |
740 | } | 740 | } |
741 | 741 | ||
742 | /* The port lock is held. */ | 742 | /* The port lock is held. */ |
743 | static void sunzilog_enable_ms(struct uart_port *port) | 743 | static void sunzilog_enable_ms(struct uart_port *port) |
744 | { | 744 | { |
745 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; | 745 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; |
746 | struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); | 746 | struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); |
747 | unsigned char new_reg; | 747 | unsigned char new_reg; |
748 | 748 | ||
749 | new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE); | 749 | new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE); |
750 | if (new_reg != up->curregs[R15]) { | 750 | if (new_reg != up->curregs[R15]) { |
751 | up->curregs[R15] = new_reg; | 751 | up->curregs[R15] = new_reg; |
752 | 752 | ||
753 | /* NOTE: Not subject to 'transmitter active' rule. */ | 753 | /* NOTE: Not subject to 'transmitter active' rule. */ |
754 | write_zsreg(channel, R15, up->curregs[R15] & ~WR7pEN); | 754 | write_zsreg(channel, R15, up->curregs[R15] & ~WR7pEN); |
755 | } | 755 | } |
756 | } | 756 | } |
757 | 757 | ||
758 | /* The port lock is not held. */ | 758 | /* The port lock is not held. */ |
759 | static void sunzilog_break_ctl(struct uart_port *port, int break_state) | 759 | static void sunzilog_break_ctl(struct uart_port *port, int break_state) |
760 | { | 760 | { |
761 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; | 761 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; |
762 | struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); | 762 | struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); |
763 | unsigned char set_bits, clear_bits, new_reg; | 763 | unsigned char set_bits, clear_bits, new_reg; |
764 | unsigned long flags; | 764 | unsigned long flags; |
765 | 765 | ||
766 | set_bits = clear_bits = 0; | 766 | set_bits = clear_bits = 0; |
767 | 767 | ||
768 | if (break_state) | 768 | if (break_state) |
769 | set_bits |= SND_BRK; | 769 | set_bits |= SND_BRK; |
770 | else | 770 | else |
771 | clear_bits |= SND_BRK; | 771 | clear_bits |= SND_BRK; |
772 | 772 | ||
773 | spin_lock_irqsave(&port->lock, flags); | 773 | spin_lock_irqsave(&port->lock, flags); |
774 | 774 | ||
775 | new_reg = (up->curregs[R5] | set_bits) & ~clear_bits; | 775 | new_reg = (up->curregs[R5] | set_bits) & ~clear_bits; |
776 | if (new_reg != up->curregs[R5]) { | 776 | if (new_reg != up->curregs[R5]) { |
777 | up->curregs[R5] = new_reg; | 777 | up->curregs[R5] = new_reg; |
778 | 778 | ||
779 | /* NOTE: Not subject to 'transmitter active' rule. */ | 779 | /* NOTE: Not subject to 'transmitter active' rule. */ |
780 | write_zsreg(channel, R5, up->curregs[R5]); | 780 | write_zsreg(channel, R5, up->curregs[R5]); |
781 | } | 781 | } |
782 | 782 | ||
783 | spin_unlock_irqrestore(&port->lock, flags); | 783 | spin_unlock_irqrestore(&port->lock, flags); |
784 | } | 784 | } |
785 | 785 | ||
786 | static void __sunzilog_startup(struct uart_sunzilog_port *up) | 786 | static void __sunzilog_startup(struct uart_sunzilog_port *up) |
787 | { | 787 | { |
788 | struct zilog_channel __iomem *channel; | 788 | struct zilog_channel __iomem *channel; |
789 | 789 | ||
790 | channel = ZILOG_CHANNEL_FROM_PORT(&up->port); | 790 | channel = ZILOG_CHANNEL_FROM_PORT(&up->port); |
791 | up->prev_status = readb(&channel->control); | 791 | up->prev_status = readb(&channel->control); |
792 | 792 | ||
793 | /* Enable receiver and transmitter. */ | 793 | /* Enable receiver and transmitter. */ |
794 | up->curregs[R3] |= RxENAB; | 794 | up->curregs[R3] |= RxENAB; |
795 | up->curregs[R5] |= TxENAB; | 795 | up->curregs[R5] |= TxENAB; |
796 | 796 | ||
797 | up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; | 797 | up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; |
798 | sunzilog_maybe_update_regs(up, channel); | 798 | sunzilog_maybe_update_regs(up, channel); |
799 | } | 799 | } |
800 | 800 | ||
801 | static int sunzilog_startup(struct uart_port *port) | 801 | static int sunzilog_startup(struct uart_port *port) |
802 | { | 802 | { |
803 | struct uart_sunzilog_port *up = UART_ZILOG(port); | 803 | struct uart_sunzilog_port *up = UART_ZILOG(port); |
804 | unsigned long flags; | 804 | unsigned long flags; |
805 | 805 | ||
806 | if (ZS_IS_CONS(up)) | 806 | if (ZS_IS_CONS(up)) |
807 | return 0; | 807 | return 0; |
808 | 808 | ||
809 | spin_lock_irqsave(&port->lock, flags); | 809 | spin_lock_irqsave(&port->lock, flags); |
810 | __sunzilog_startup(up); | 810 | __sunzilog_startup(up); |
811 | spin_unlock_irqrestore(&port->lock, flags); | 811 | spin_unlock_irqrestore(&port->lock, flags); |
812 | return 0; | 812 | return 0; |
813 | } | 813 | } |
814 | 814 | ||
815 | /* | 815 | /* |
816 | * The test for ZS_IS_CONS is explained by the following e-mail: | 816 | * The test for ZS_IS_CONS is explained by the following e-mail: |
817 | ***** | 817 | ***** |
818 | * From: Russell King <rmk@arm.linux.org.uk> | 818 | * From: Russell King <rmk@arm.linux.org.uk> |
819 | * Date: Sun, 8 Dec 2002 10:18:38 +0000 | 819 | * Date: Sun, 8 Dec 2002 10:18:38 +0000 |
820 | * | 820 | * |
821 | * On Sun, Dec 08, 2002 at 02:43:36AM -0500, Pete Zaitcev wrote: | 821 | * On Sun, Dec 08, 2002 at 02:43:36AM -0500, Pete Zaitcev wrote: |
822 | * > I boot my 2.5 boxes using "console=ttyS0,9600" argument, | 822 | * > I boot my 2.5 boxes using "console=ttyS0,9600" argument, |
823 | * > and I noticed that something is not right with reference | 823 | * > and I noticed that something is not right with reference |
824 | * > counting in this case. It seems that when the console | 824 | * > counting in this case. It seems that when the console |
825 | * > is open by kernel initially, this is not accounted | 825 | * > is open by kernel initially, this is not accounted |
826 | * > as an open, and uart_startup is not called. | 826 | * > as an open, and uart_startup is not called. |
827 | * | 827 | * |
828 | * That is correct. We are unable to call uart_startup when the serial | 828 | * That is correct. We are unable to call uart_startup when the serial |
829 | * console is initialised because it may need to allocate memory (as | 829 | * console is initialised because it may need to allocate memory (as |
830 | * request_irq does) and the memory allocators may not have been | 830 | * request_irq does) and the memory allocators may not have been |
831 | * initialised. | 831 | * initialised. |
832 | * | 832 | * |
833 | * 1. initialise the port into a state where it can send characters in the | 833 | * 1. initialise the port into a state where it can send characters in the |
834 | * console write method. | 834 | * console write method. |
835 | * | 835 | * |
836 | * 2. don't do the actual hardware shutdown in your shutdown() method (but | 836 | * 2. don't do the actual hardware shutdown in your shutdown() method (but |
837 | * do the normal software shutdown - ie, free irqs etc) | 837 | * do the normal software shutdown - ie, free irqs etc) |
838 | ***** | 838 | ***** |
839 | */ | 839 | */ |
840 | static void sunzilog_shutdown(struct uart_port *port) | 840 | static void sunzilog_shutdown(struct uart_port *port) |
841 | { | 841 | { |
842 | struct uart_sunzilog_port *up = UART_ZILOG(port); | 842 | struct uart_sunzilog_port *up = UART_ZILOG(port); |
843 | struct zilog_channel __iomem *channel; | 843 | struct zilog_channel __iomem *channel; |
844 | unsigned long flags; | 844 | unsigned long flags; |
845 | 845 | ||
846 | if (ZS_IS_CONS(up)) | 846 | if (ZS_IS_CONS(up)) |
847 | return; | 847 | return; |
848 | 848 | ||
849 | spin_lock_irqsave(&port->lock, flags); | 849 | spin_lock_irqsave(&port->lock, flags); |
850 | 850 | ||
851 | channel = ZILOG_CHANNEL_FROM_PORT(port); | 851 | channel = ZILOG_CHANNEL_FROM_PORT(port); |
852 | 852 | ||
853 | /* Disable receiver and transmitter. */ | 853 | /* Disable receiver and transmitter. */ |
854 | up->curregs[R3] &= ~RxENAB; | 854 | up->curregs[R3] &= ~RxENAB; |
855 | up->curregs[R5] &= ~TxENAB; | 855 | up->curregs[R5] &= ~TxENAB; |
856 | 856 | ||
857 | /* Disable all interrupts and BRK assertion. */ | 857 | /* Disable all interrupts and BRK assertion. */ |
858 | up->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); | 858 | up->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); |
859 | up->curregs[R5] &= ~SND_BRK; | 859 | up->curregs[R5] &= ~SND_BRK; |
860 | sunzilog_maybe_update_regs(up, channel); | 860 | sunzilog_maybe_update_regs(up, channel); |
861 | 861 | ||
862 | spin_unlock_irqrestore(&port->lock, flags); | 862 | spin_unlock_irqrestore(&port->lock, flags); |
863 | } | 863 | } |
864 | 864 | ||
865 | /* Shared by TTY driver and serial console setup. The port lock is held | 865 | /* Shared by TTY driver and serial console setup. The port lock is held |
866 | * and local interrupts are disabled. | 866 | * and local interrupts are disabled. |
867 | */ | 867 | */ |
868 | static void | 868 | static void |
869 | sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag, | 869 | sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag, |
870 | unsigned int iflag, int brg) | 870 | unsigned int iflag, int brg) |
871 | { | 871 | { |
872 | 872 | ||
873 | up->curregs[R10] = NRZ; | 873 | up->curregs[R10] = NRZ; |
874 | up->curregs[R11] = TCBR | RCBR; | 874 | up->curregs[R11] = TCBR | RCBR; |
875 | 875 | ||
876 | /* Program BAUD and clock source. */ | 876 | /* Program BAUD and clock source. */ |
877 | up->curregs[R4] &= ~XCLK_MASK; | 877 | up->curregs[R4] &= ~XCLK_MASK; |
878 | up->curregs[R4] |= X16CLK; | 878 | up->curregs[R4] |= X16CLK; |
879 | up->curregs[R12] = brg & 0xff; | 879 | up->curregs[R12] = brg & 0xff; |
880 | up->curregs[R13] = (brg >> 8) & 0xff; | 880 | up->curregs[R13] = (brg >> 8) & 0xff; |
881 | up->curregs[R14] = BRSRC | BRENAB; | 881 | up->curregs[R14] = BRSRC | BRENAB; |
882 | 882 | ||
883 | /* Character size, stop bits, and parity. */ | 883 | /* Character size, stop bits, and parity. */ |
884 | up->curregs[R3] &= ~RxN_MASK; | 884 | up->curregs[R3] &= ~RxN_MASK; |
885 | up->curregs[R5] &= ~TxN_MASK; | 885 | up->curregs[R5] &= ~TxN_MASK; |
886 | switch (cflag & CSIZE) { | 886 | switch (cflag & CSIZE) { |
887 | case CS5: | 887 | case CS5: |
888 | up->curregs[R3] |= Rx5; | 888 | up->curregs[R3] |= Rx5; |
889 | up->curregs[R5] |= Tx5; | 889 | up->curregs[R5] |= Tx5; |
890 | up->parity_mask = 0x1f; | 890 | up->parity_mask = 0x1f; |
891 | break; | 891 | break; |
892 | case CS6: | 892 | case CS6: |
893 | up->curregs[R3] |= Rx6; | 893 | up->curregs[R3] |= Rx6; |
894 | up->curregs[R5] |= Tx6; | 894 | up->curregs[R5] |= Tx6; |
895 | up->parity_mask = 0x3f; | 895 | up->parity_mask = 0x3f; |
896 | break; | 896 | break; |
897 | case CS7: | 897 | case CS7: |
898 | up->curregs[R3] |= Rx7; | 898 | up->curregs[R3] |= Rx7; |
899 | up->curregs[R5] |= Tx7; | 899 | up->curregs[R5] |= Tx7; |
900 | up->parity_mask = 0x7f; | 900 | up->parity_mask = 0x7f; |
901 | break; | 901 | break; |
902 | case CS8: | 902 | case CS8: |
903 | default: | 903 | default: |
904 | up->curregs[R3] |= Rx8; | 904 | up->curregs[R3] |= Rx8; |
905 | up->curregs[R5] |= Tx8; | 905 | up->curregs[R5] |= Tx8; |
906 | up->parity_mask = 0xff; | 906 | up->parity_mask = 0xff; |
907 | break; | 907 | break; |
908 | }; | 908 | }; |
909 | up->curregs[R4] &= ~0x0c; | 909 | up->curregs[R4] &= ~0x0c; |
910 | if (cflag & CSTOPB) | 910 | if (cflag & CSTOPB) |
911 | up->curregs[R4] |= SB2; | 911 | up->curregs[R4] |= SB2; |
912 | else | 912 | else |
913 | up->curregs[R4] |= SB1; | 913 | up->curregs[R4] |= SB1; |
914 | if (cflag & PARENB) | 914 | if (cflag & PARENB) |
915 | up->curregs[R4] |= PAR_ENAB; | 915 | up->curregs[R4] |= PAR_ENAB; |
916 | else | 916 | else |
917 | up->curregs[R4] &= ~PAR_ENAB; | 917 | up->curregs[R4] &= ~PAR_ENAB; |
918 | if (!(cflag & PARODD)) | 918 | if (!(cflag & PARODD)) |
919 | up->curregs[R4] |= PAR_EVEN; | 919 | up->curregs[R4] |= PAR_EVEN; |
920 | else | 920 | else |
921 | up->curregs[R4] &= ~PAR_EVEN; | 921 | up->curregs[R4] &= ~PAR_EVEN; |
922 | 922 | ||
923 | up->port.read_status_mask = Rx_OVR; | 923 | up->port.read_status_mask = Rx_OVR; |
924 | if (iflag & INPCK) | 924 | if (iflag & INPCK) |
925 | up->port.read_status_mask |= CRC_ERR | PAR_ERR; | 925 | up->port.read_status_mask |= CRC_ERR | PAR_ERR; |
926 | if (iflag & (BRKINT | PARMRK)) | 926 | if (iflag & (BRKINT | PARMRK)) |
927 | up->port.read_status_mask |= BRK_ABRT; | 927 | up->port.read_status_mask |= BRK_ABRT; |
928 | 928 | ||
929 | up->port.ignore_status_mask = 0; | 929 | up->port.ignore_status_mask = 0; |
930 | if (iflag & IGNPAR) | 930 | if (iflag & IGNPAR) |
931 | up->port.ignore_status_mask |= CRC_ERR | PAR_ERR; | 931 | up->port.ignore_status_mask |= CRC_ERR | PAR_ERR; |
932 | if (iflag & IGNBRK) { | 932 | if (iflag & IGNBRK) { |
933 | up->port.ignore_status_mask |= BRK_ABRT; | 933 | up->port.ignore_status_mask |= BRK_ABRT; |
934 | if (iflag & IGNPAR) | 934 | if (iflag & IGNPAR) |
935 | up->port.ignore_status_mask |= Rx_OVR; | 935 | up->port.ignore_status_mask |= Rx_OVR; |
936 | } | 936 | } |
937 | 937 | ||
938 | if ((cflag & CREAD) == 0) | 938 | if ((cflag & CREAD) == 0) |
939 | up->port.ignore_status_mask = 0xff; | 939 | up->port.ignore_status_mask = 0xff; |
940 | } | 940 | } |
941 | 941 | ||
942 | /* The port lock is not held. */ | 942 | /* The port lock is not held. */ |
943 | static void | 943 | static void |
944 | sunzilog_set_termios(struct uart_port *port, struct ktermios *termios, | 944 | sunzilog_set_termios(struct uart_port *port, struct ktermios *termios, |
945 | struct ktermios *old) | 945 | struct ktermios *old) |
946 | { | 946 | { |
947 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; | 947 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; |
948 | unsigned long flags; | 948 | unsigned long flags; |
949 | int baud, brg; | 949 | int baud, brg; |
950 | 950 | ||
951 | baud = uart_get_baud_rate(port, termios, old, 1200, 76800); | 951 | baud = uart_get_baud_rate(port, termios, old, 1200, 76800); |
952 | 952 | ||
953 | spin_lock_irqsave(&up->port.lock, flags); | 953 | spin_lock_irqsave(&up->port.lock, flags); |
954 | 954 | ||
955 | brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); | 955 | brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); |
956 | 956 | ||
957 | sunzilog_convert_to_zs(up, termios->c_cflag, termios->c_iflag, brg); | 957 | sunzilog_convert_to_zs(up, termios->c_cflag, termios->c_iflag, brg); |
958 | 958 | ||
959 | if (UART_ENABLE_MS(&up->port, termios->c_cflag)) | 959 | if (UART_ENABLE_MS(&up->port, termios->c_cflag)) |
960 | up->flags |= SUNZILOG_FLAG_MODEM_STATUS; | 960 | up->flags |= SUNZILOG_FLAG_MODEM_STATUS; |
961 | else | 961 | else |
962 | up->flags &= ~SUNZILOG_FLAG_MODEM_STATUS; | 962 | up->flags &= ~SUNZILOG_FLAG_MODEM_STATUS; |
963 | 963 | ||
964 | up->cflag = termios->c_cflag; | 964 | up->cflag = termios->c_cflag; |
965 | 965 | ||
966 | sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port)); | 966 | sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port)); |
967 | 967 | ||
968 | uart_update_timeout(port, termios->c_cflag, baud); | 968 | uart_update_timeout(port, termios->c_cflag, baud); |
969 | 969 | ||
970 | spin_unlock_irqrestore(&up->port.lock, flags); | 970 | spin_unlock_irqrestore(&up->port.lock, flags); |
971 | } | 971 | } |
972 | 972 | ||
973 | static const char *sunzilog_type(struct uart_port *port) | 973 | static const char *sunzilog_type(struct uart_port *port) |
974 | { | 974 | { |
975 | struct uart_sunzilog_port *up = UART_ZILOG(port); | 975 | struct uart_sunzilog_port *up = UART_ZILOG(port); |
976 | 976 | ||
977 | return (up->flags & SUNZILOG_FLAG_ESCC) ? "zs (ESCC)" : "zs"; | 977 | return (up->flags & SUNZILOG_FLAG_ESCC) ? "zs (ESCC)" : "zs"; |
978 | } | 978 | } |
979 | 979 | ||
980 | /* We do not request/release mappings of the registers here, this | 980 | /* We do not request/release mappings of the registers here, this |
981 | * happens at early serial probe time. | 981 | * happens at early serial probe time. |
982 | */ | 982 | */ |
983 | static void sunzilog_release_port(struct uart_port *port) | 983 | static void sunzilog_release_port(struct uart_port *port) |
984 | { | 984 | { |
985 | } | 985 | } |
986 | 986 | ||
987 | static int sunzilog_request_port(struct uart_port *port) | 987 | static int sunzilog_request_port(struct uart_port *port) |
988 | { | 988 | { |
989 | return 0; | 989 | return 0; |
990 | } | 990 | } |
991 | 991 | ||
992 | /* These do not need to do anything interesting either. */ | 992 | /* These do not need to do anything interesting either. */ |
993 | static void sunzilog_config_port(struct uart_port *port, int flags) | 993 | static void sunzilog_config_port(struct uart_port *port, int flags) |
994 | { | 994 | { |
995 | } | 995 | } |
996 | 996 | ||
997 | /* We do not support letting the user mess with the divisor, IRQ, etc. */ | 997 | /* We do not support letting the user mess with the divisor, IRQ, etc. */ |
998 | static int sunzilog_verify_port(struct uart_port *port, struct serial_struct *ser) | 998 | static int sunzilog_verify_port(struct uart_port *port, struct serial_struct *ser) |
999 | { | 999 | { |
1000 | return -EINVAL; | 1000 | return -EINVAL; |
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | static struct uart_ops sunzilog_pops = { | 1003 | static struct uart_ops sunzilog_pops = { |
1004 | .tx_empty = sunzilog_tx_empty, | 1004 | .tx_empty = sunzilog_tx_empty, |
1005 | .set_mctrl = sunzilog_set_mctrl, | 1005 | .set_mctrl = sunzilog_set_mctrl, |
1006 | .get_mctrl = sunzilog_get_mctrl, | 1006 | .get_mctrl = sunzilog_get_mctrl, |
1007 | .stop_tx = sunzilog_stop_tx, | 1007 | .stop_tx = sunzilog_stop_tx, |
1008 | .start_tx = sunzilog_start_tx, | 1008 | .start_tx = sunzilog_start_tx, |
1009 | .stop_rx = sunzilog_stop_rx, | 1009 | .stop_rx = sunzilog_stop_rx, |
1010 | .enable_ms = sunzilog_enable_ms, | 1010 | .enable_ms = sunzilog_enable_ms, |
1011 | .break_ctl = sunzilog_break_ctl, | 1011 | .break_ctl = sunzilog_break_ctl, |
1012 | .startup = sunzilog_startup, | 1012 | .startup = sunzilog_startup, |
1013 | .shutdown = sunzilog_shutdown, | 1013 | .shutdown = sunzilog_shutdown, |
1014 | .set_termios = sunzilog_set_termios, | 1014 | .set_termios = sunzilog_set_termios, |
1015 | .type = sunzilog_type, | 1015 | .type = sunzilog_type, |
1016 | .release_port = sunzilog_release_port, | 1016 | .release_port = sunzilog_release_port, |
1017 | .request_port = sunzilog_request_port, | 1017 | .request_port = sunzilog_request_port, |
1018 | .config_port = sunzilog_config_port, | 1018 | .config_port = sunzilog_config_port, |
1019 | .verify_port = sunzilog_verify_port, | 1019 | .verify_port = sunzilog_verify_port, |
1020 | }; | 1020 | }; |
1021 | 1021 | ||
1022 | static struct uart_sunzilog_port *sunzilog_port_table; | 1022 | static struct uart_sunzilog_port *sunzilog_port_table; |
1023 | static struct zilog_layout __iomem **sunzilog_chip_regs; | 1023 | static struct zilog_layout __iomem **sunzilog_chip_regs; |
1024 | 1024 | ||
1025 | static struct uart_sunzilog_port *sunzilog_irq_chain; | 1025 | static struct uart_sunzilog_port *sunzilog_irq_chain; |
1026 | 1026 | ||
1027 | static struct uart_driver sunzilog_reg = { | 1027 | static struct uart_driver sunzilog_reg = { |
1028 | .owner = THIS_MODULE, | 1028 | .owner = THIS_MODULE, |
1029 | .driver_name = "ttyS", | 1029 | .driver_name = "ttyS", |
1030 | .dev_name = "ttyS", | 1030 | .dev_name = "ttyS", |
1031 | .major = TTY_MAJOR, | 1031 | .major = TTY_MAJOR, |
1032 | }; | 1032 | }; |
1033 | 1033 | ||
1034 | static int __init sunzilog_alloc_tables(void) | 1034 | static int __init sunzilog_alloc_tables(void) |
1035 | { | 1035 | { |
1036 | struct uart_sunzilog_port *up; | 1036 | struct uart_sunzilog_port *up; |
1037 | unsigned long size; | 1037 | unsigned long size; |
1038 | int i; | 1038 | int i; |
1039 | 1039 | ||
1040 | size = NUM_CHANNELS * sizeof(struct uart_sunzilog_port); | 1040 | size = NUM_CHANNELS * sizeof(struct uart_sunzilog_port); |
1041 | sunzilog_port_table = kzalloc(size, GFP_KERNEL); | 1041 | sunzilog_port_table = kzalloc(size, GFP_KERNEL); |
1042 | if (!sunzilog_port_table) | 1042 | if (!sunzilog_port_table) |
1043 | return -ENOMEM; | 1043 | return -ENOMEM; |
1044 | 1044 | ||
1045 | for (i = 0; i < NUM_CHANNELS; i++) { | 1045 | for (i = 0; i < NUM_CHANNELS; i++) { |
1046 | up = &sunzilog_port_table[i]; | 1046 | up = &sunzilog_port_table[i]; |
1047 | 1047 | ||
1048 | spin_lock_init(&up->port.lock); | 1048 | spin_lock_init(&up->port.lock); |
1049 | 1049 | ||
1050 | if (i == 0) | 1050 | if (i == 0) |
1051 | sunzilog_irq_chain = up; | 1051 | sunzilog_irq_chain = up; |
1052 | 1052 | ||
1053 | if (i < NUM_CHANNELS - 1) | 1053 | if (i < NUM_CHANNELS - 1) |
1054 | up->next = up + 1; | 1054 | up->next = up + 1; |
1055 | else | 1055 | else |
1056 | up->next = NULL; | 1056 | up->next = NULL; |
1057 | } | 1057 | } |
1058 | 1058 | ||
1059 | size = NUM_SUNZILOG * sizeof(struct zilog_layout __iomem *); | 1059 | size = NUM_SUNZILOG * sizeof(struct zilog_layout __iomem *); |
1060 | sunzilog_chip_regs = kzalloc(size, GFP_KERNEL); | 1060 | sunzilog_chip_regs = kzalloc(size, GFP_KERNEL); |
1061 | if (!sunzilog_chip_regs) { | 1061 | if (!sunzilog_chip_regs) { |
1062 | kfree(sunzilog_port_table); | 1062 | kfree(sunzilog_port_table); |
1063 | sunzilog_irq_chain = NULL; | 1063 | sunzilog_irq_chain = NULL; |
1064 | return -ENOMEM; | 1064 | return -ENOMEM; |
1065 | } | 1065 | } |
1066 | 1066 | ||
1067 | return 0; | 1067 | return 0; |
1068 | } | 1068 | } |
1069 | 1069 | ||
1070 | static void sunzilog_free_tables(void) | 1070 | static void sunzilog_free_tables(void) |
1071 | { | 1071 | { |
1072 | kfree(sunzilog_port_table); | 1072 | kfree(sunzilog_port_table); |
1073 | sunzilog_irq_chain = NULL; | 1073 | sunzilog_irq_chain = NULL; |
1074 | kfree(sunzilog_chip_regs); | 1074 | kfree(sunzilog_chip_regs); |
1075 | } | 1075 | } |
1076 | 1076 | ||
1077 | #define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ | 1077 | #define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ |
1078 | 1078 | ||
1079 | static void sunzilog_putchar(struct uart_port *port, int ch) | 1079 | static void sunzilog_putchar(struct uart_port *port, int ch) |
1080 | { | 1080 | { |
1081 | struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); | 1081 | struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); |
1082 | int loops = ZS_PUT_CHAR_MAX_DELAY; | 1082 | int loops = ZS_PUT_CHAR_MAX_DELAY; |
1083 | 1083 | ||
1084 | /* This is a timed polling loop so do not switch the explicit | 1084 | /* This is a timed polling loop so do not switch the explicit |
1085 | * udelay with ZSDELAY as that is a NOP on some platforms. -DaveM | 1085 | * udelay with ZSDELAY as that is a NOP on some platforms. -DaveM |
1086 | */ | 1086 | */ |
1087 | do { | 1087 | do { |
1088 | unsigned char val = readb(&channel->control); | 1088 | unsigned char val = readb(&channel->control); |
1089 | if (val & Tx_BUF_EMP) { | 1089 | if (val & Tx_BUF_EMP) { |
1090 | ZSDELAY(); | 1090 | ZSDELAY(); |
1091 | break; | 1091 | break; |
1092 | } | 1092 | } |
1093 | udelay(5); | 1093 | udelay(5); |
1094 | } while (--loops); | 1094 | } while (--loops); |
1095 | 1095 | ||
1096 | writeb(ch, &channel->data); | 1096 | writeb(ch, &channel->data); |
1097 | ZSDELAY(); | 1097 | ZSDELAY(); |
1098 | ZS_WSYNC(channel); | 1098 | ZS_WSYNC(channel); |
1099 | } | 1099 | } |
1100 | 1100 | ||
1101 | #ifdef CONFIG_SERIO | 1101 | #ifdef CONFIG_SERIO |
1102 | 1102 | ||
1103 | static DEFINE_SPINLOCK(sunzilog_serio_lock); | 1103 | static DEFINE_SPINLOCK(sunzilog_serio_lock); |
1104 | 1104 | ||
1105 | static int sunzilog_serio_write(struct serio *serio, unsigned char ch) | 1105 | static int sunzilog_serio_write(struct serio *serio, unsigned char ch) |
1106 | { | 1106 | { |
1107 | struct uart_sunzilog_port *up = serio->port_data; | 1107 | struct uart_sunzilog_port *up = serio->port_data; |
1108 | unsigned long flags; | 1108 | unsigned long flags; |
1109 | 1109 | ||
1110 | spin_lock_irqsave(&sunzilog_serio_lock, flags); | 1110 | spin_lock_irqsave(&sunzilog_serio_lock, flags); |
1111 | 1111 | ||
1112 | sunzilog_putchar(&up->port, ch); | 1112 | sunzilog_putchar(&up->port, ch); |
1113 | 1113 | ||
1114 | spin_unlock_irqrestore(&sunzilog_serio_lock, flags); | 1114 | spin_unlock_irqrestore(&sunzilog_serio_lock, flags); |
1115 | 1115 | ||
1116 | return 0; | 1116 | return 0; |
1117 | } | 1117 | } |
1118 | 1118 | ||
1119 | static int sunzilog_serio_open(struct serio *serio) | 1119 | static int sunzilog_serio_open(struct serio *serio) |
1120 | { | 1120 | { |
1121 | struct uart_sunzilog_port *up = serio->port_data; | 1121 | struct uart_sunzilog_port *up = serio->port_data; |
1122 | unsigned long flags; | 1122 | unsigned long flags; |
1123 | int ret; | 1123 | int ret; |
1124 | 1124 | ||
1125 | spin_lock_irqsave(&sunzilog_serio_lock, flags); | 1125 | spin_lock_irqsave(&sunzilog_serio_lock, flags); |
1126 | if (!up->serio_open) { | 1126 | if (!up->serio_open) { |
1127 | up->serio_open = 1; | 1127 | up->serio_open = 1; |
1128 | ret = 0; | 1128 | ret = 0; |
1129 | } else | 1129 | } else |
1130 | ret = -EBUSY; | 1130 | ret = -EBUSY; |
1131 | spin_unlock_irqrestore(&sunzilog_serio_lock, flags); | 1131 | spin_unlock_irqrestore(&sunzilog_serio_lock, flags); |
1132 | 1132 | ||
1133 | return ret; | 1133 | return ret; |
1134 | } | 1134 | } |
1135 | 1135 | ||
1136 | static void sunzilog_serio_close(struct serio *serio) | 1136 | static void sunzilog_serio_close(struct serio *serio) |
1137 | { | 1137 | { |
1138 | struct uart_sunzilog_port *up = serio->port_data; | 1138 | struct uart_sunzilog_port *up = serio->port_data; |
1139 | unsigned long flags; | 1139 | unsigned long flags; |
1140 | 1140 | ||
1141 | spin_lock_irqsave(&sunzilog_serio_lock, flags); | 1141 | spin_lock_irqsave(&sunzilog_serio_lock, flags); |
1142 | up->serio_open = 0; | 1142 | up->serio_open = 0; |
1143 | spin_unlock_irqrestore(&sunzilog_serio_lock, flags); | 1143 | spin_unlock_irqrestore(&sunzilog_serio_lock, flags); |
1144 | } | 1144 | } |
1145 | 1145 | ||
1146 | #endif /* CONFIG_SERIO */ | 1146 | #endif /* CONFIG_SERIO */ |
1147 | 1147 | ||
1148 | #ifdef CONFIG_SERIAL_SUNZILOG_CONSOLE | 1148 | #ifdef CONFIG_SERIAL_SUNZILOG_CONSOLE |
1149 | static void | 1149 | static void |
1150 | sunzilog_console_write(struct console *con, const char *s, unsigned int count) | 1150 | sunzilog_console_write(struct console *con, const char *s, unsigned int count) |
1151 | { | 1151 | { |
1152 | struct uart_sunzilog_port *up = &sunzilog_port_table[con->index]; | 1152 | struct uart_sunzilog_port *up = &sunzilog_port_table[con->index]; |
1153 | unsigned long flags; | 1153 | unsigned long flags; |
1154 | int locked = 1; | 1154 | int locked = 1; |
1155 | 1155 | ||
1156 | local_irq_save(flags); | 1156 | local_irq_save(flags); |
1157 | if (up->port.sysrq) { | 1157 | if (up->port.sysrq) { |
1158 | locked = 0; | 1158 | locked = 0; |
1159 | } else if (oops_in_progress) { | 1159 | } else if (oops_in_progress) { |
1160 | locked = spin_trylock(&up->port.lock); | 1160 | locked = spin_trylock(&up->port.lock); |
1161 | } else | 1161 | } else |
1162 | spin_lock(&up->port.lock); | 1162 | spin_lock(&up->port.lock); |
1163 | 1163 | ||
1164 | uart_console_write(&up->port, s, count, sunzilog_putchar); | 1164 | uart_console_write(&up->port, s, count, sunzilog_putchar); |
1165 | udelay(2); | 1165 | udelay(2); |
1166 | 1166 | ||
1167 | if (locked) | 1167 | if (locked) |
1168 | spin_unlock(&up->port.lock); | 1168 | spin_unlock(&up->port.lock); |
1169 | local_irq_restore(flags); | 1169 | local_irq_restore(flags); |
1170 | } | 1170 | } |
1171 | 1171 | ||
1172 | static int __init sunzilog_console_setup(struct console *con, char *options) | 1172 | static int __init sunzilog_console_setup(struct console *con, char *options) |
1173 | { | 1173 | { |
1174 | struct uart_sunzilog_port *up = &sunzilog_port_table[con->index]; | 1174 | struct uart_sunzilog_port *up = &sunzilog_port_table[con->index]; |
1175 | unsigned long flags; | 1175 | unsigned long flags; |
1176 | int baud, brg; | 1176 | int baud, brg; |
1177 | 1177 | ||
1178 | if (up->port.type != PORT_SUNZILOG) | 1178 | if (up->port.type != PORT_SUNZILOG) |
1179 | return -1; | 1179 | return -1; |
1180 | 1180 | ||
1181 | printk(KERN_INFO "Console: ttyS%d (SunZilog zs%d)\n", | 1181 | printk(KERN_INFO "Console: ttyS%d (SunZilog zs%d)\n", |
1182 | (sunzilog_reg.minor - 64) + con->index, con->index); | 1182 | (sunzilog_reg.minor - 64) + con->index, con->index); |
1183 | 1183 | ||
1184 | /* Get firmware console settings. */ | 1184 | /* Get firmware console settings. */ |
1185 | sunserial_console_termios(con); | 1185 | sunserial_console_termios(con); |
1186 | 1186 | ||
1187 | /* Firmware console speed is limited to 150-->38400 baud so | 1187 | /* Firmware console speed is limited to 150-->38400 baud so |
1188 | * this hackish cflag thing is OK. | 1188 | * this hackish cflag thing is OK. |
1189 | */ | 1189 | */ |
1190 | switch (con->cflag & CBAUD) { | 1190 | switch (con->cflag & CBAUD) { |
1191 | case B150: baud = 150; break; | 1191 | case B150: baud = 150; break; |
1192 | case B300: baud = 300; break; | 1192 | case B300: baud = 300; break; |
1193 | case B600: baud = 600; break; | 1193 | case B600: baud = 600; break; |
1194 | case B1200: baud = 1200; break; | 1194 | case B1200: baud = 1200; break; |
1195 | case B2400: baud = 2400; break; | 1195 | case B2400: baud = 2400; break; |
1196 | case B4800: baud = 4800; break; | 1196 | case B4800: baud = 4800; break; |
1197 | default: case B9600: baud = 9600; break; | 1197 | default: case B9600: baud = 9600; break; |
1198 | case B19200: baud = 19200; break; | 1198 | case B19200: baud = 19200; break; |
1199 | case B38400: baud = 38400; break; | 1199 | case B38400: baud = 38400; break; |
1200 | }; | 1200 | }; |
1201 | 1201 | ||
1202 | brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); | 1202 | brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); |
1203 | 1203 | ||
1204 | spin_lock_irqsave(&up->port.lock, flags); | 1204 | spin_lock_irqsave(&up->port.lock, flags); |
1205 | 1205 | ||
1206 | up->curregs[R15] |= BRKIE; | 1206 | up->curregs[R15] |= BRKIE; |
1207 | sunzilog_convert_to_zs(up, con->cflag, 0, brg); | 1207 | sunzilog_convert_to_zs(up, con->cflag, 0, brg); |
1208 | 1208 | ||
1209 | sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); | 1209 | sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); |
1210 | __sunzilog_startup(up); | 1210 | __sunzilog_startup(up); |
1211 | 1211 | ||
1212 | spin_unlock_irqrestore(&up->port.lock, flags); | 1212 | spin_unlock_irqrestore(&up->port.lock, flags); |
1213 | 1213 | ||
1214 | return 0; | 1214 | return 0; |
1215 | } | 1215 | } |
1216 | 1216 | ||
1217 | static struct console sunzilog_console_ops = { | 1217 | static struct console sunzilog_console_ops = { |
1218 | .name = "ttyS", | 1218 | .name = "ttyS", |
1219 | .write = sunzilog_console_write, | 1219 | .write = sunzilog_console_write, |
1220 | .device = uart_console_device, | 1220 | .device = uart_console_device, |
1221 | .setup = sunzilog_console_setup, | 1221 | .setup = sunzilog_console_setup, |
1222 | .flags = CON_PRINTBUFFER, | 1222 | .flags = CON_PRINTBUFFER, |
1223 | .index = -1, | 1223 | .index = -1, |
1224 | .data = &sunzilog_reg, | 1224 | .data = &sunzilog_reg, |
1225 | }; | 1225 | }; |
1226 | 1226 | ||
1227 | static inline struct console *SUNZILOG_CONSOLE(void) | 1227 | static inline struct console *SUNZILOG_CONSOLE(void) |
1228 | { | 1228 | { |
1229 | return &sunzilog_console_ops; | 1229 | return &sunzilog_console_ops; |
1230 | } | 1230 | } |
1231 | 1231 | ||
1232 | #else | 1232 | #else |
1233 | #define SUNZILOG_CONSOLE() (NULL) | 1233 | #define SUNZILOG_CONSOLE() (NULL) |
1234 | #endif | 1234 | #endif |
1235 | 1235 | ||
1236 | static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channel) | 1236 | static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channel) |
1237 | { | 1237 | { |
1238 | int baud, brg; | 1238 | int baud, brg; |
1239 | 1239 | ||
1240 | if (up->flags & SUNZILOG_FLAG_CONS_KEYB) { | 1240 | if (up->flags & SUNZILOG_FLAG_CONS_KEYB) { |
1241 | up->cflag = B1200 | CS8 | CLOCAL | CREAD; | 1241 | up->cflag = B1200 | CS8 | CLOCAL | CREAD; |
1242 | baud = 1200; | 1242 | baud = 1200; |
1243 | } else { | 1243 | } else { |
1244 | up->cflag = B4800 | CS8 | CLOCAL | CREAD; | 1244 | up->cflag = B4800 | CS8 | CLOCAL | CREAD; |
1245 | baud = 4800; | 1245 | baud = 4800; |
1246 | } | 1246 | } |
1247 | 1247 | ||
1248 | up->curregs[R15] |= BRKIE; | 1248 | up->curregs[R15] |= BRKIE; |
1249 | brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); | 1249 | brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); |
1250 | sunzilog_convert_to_zs(up, up->cflag, 0, brg); | 1250 | sunzilog_convert_to_zs(up, up->cflag, 0, brg); |
1251 | sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); | 1251 | sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); |
1252 | __sunzilog_startup(up); | 1252 | __sunzilog_startup(up); |
1253 | } | 1253 | } |
1254 | 1254 | ||
1255 | #ifdef CONFIG_SERIO | 1255 | #ifdef CONFIG_SERIO |
1256 | static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up) | 1256 | static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up) |
1257 | { | 1257 | { |
1258 | struct serio *serio = &up->serio; | 1258 | struct serio *serio = &up->serio; |
1259 | 1259 | ||
1260 | serio->port_data = up; | 1260 | serio->port_data = up; |
1261 | 1261 | ||
1262 | serio->id.type = SERIO_RS232; | 1262 | serio->id.type = SERIO_RS232; |
1263 | if (up->flags & SUNZILOG_FLAG_CONS_KEYB) { | 1263 | if (up->flags & SUNZILOG_FLAG_CONS_KEYB) { |
1264 | serio->id.proto = SERIO_SUNKBD; | 1264 | serio->id.proto = SERIO_SUNKBD; |
1265 | strlcpy(serio->name, "zskbd", sizeof(serio->name)); | 1265 | strlcpy(serio->name, "zskbd", sizeof(serio->name)); |
1266 | } else { | 1266 | } else { |
1267 | serio->id.proto = SERIO_SUN; | 1267 | serio->id.proto = SERIO_SUN; |
1268 | serio->id.extra = 1; | 1268 | serio->id.extra = 1; |
1269 | strlcpy(serio->name, "zsms", sizeof(serio->name)); | 1269 | strlcpy(serio->name, "zsms", sizeof(serio->name)); |
1270 | } | 1270 | } |
1271 | strlcpy(serio->phys, | 1271 | strlcpy(serio->phys, |
1272 | ((up->flags & SUNZILOG_FLAG_CONS_KEYB) ? | 1272 | ((up->flags & SUNZILOG_FLAG_CONS_KEYB) ? |
1273 | "zs/serio0" : "zs/serio1"), | 1273 | "zs/serio0" : "zs/serio1"), |
1274 | sizeof(serio->phys)); | 1274 | sizeof(serio->phys)); |
1275 | 1275 | ||
1276 | serio->write = sunzilog_serio_write; | 1276 | serio->write = sunzilog_serio_write; |
1277 | serio->open = sunzilog_serio_open; | 1277 | serio->open = sunzilog_serio_open; |
1278 | serio->close = sunzilog_serio_close; | 1278 | serio->close = sunzilog_serio_close; |
1279 | serio->dev.parent = up->port.dev; | 1279 | serio->dev.parent = up->port.dev; |
1280 | 1280 | ||
1281 | serio_register_port(serio); | 1281 | serio_register_port(serio); |
1282 | } | 1282 | } |
1283 | #endif | 1283 | #endif |
1284 | 1284 | ||
1285 | static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) | 1285 | static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) |
1286 | { | 1286 | { |
1287 | struct zilog_channel __iomem *channel; | 1287 | struct zilog_channel __iomem *channel; |
1288 | unsigned long flags; | 1288 | unsigned long flags; |
1289 | int baud, brg; | 1289 | int baud, brg; |
1290 | 1290 | ||
1291 | channel = ZILOG_CHANNEL_FROM_PORT(&up->port); | 1291 | channel = ZILOG_CHANNEL_FROM_PORT(&up->port); |
1292 | 1292 | ||
1293 | spin_lock_irqsave(&up->port.lock, flags); | 1293 | spin_lock_irqsave(&up->port.lock, flags); |
1294 | if (ZS_IS_CHANNEL_A(up)) { | 1294 | if (ZS_IS_CHANNEL_A(up)) { |
1295 | write_zsreg(channel, R9, FHWRES); | 1295 | write_zsreg(channel, R9, FHWRES); |
1296 | ZSDELAY_LONG(); | 1296 | ZSDELAY_LONG(); |
1297 | (void) read_zsreg(channel, R0); | 1297 | (void) read_zsreg(channel, R0); |
1298 | } | 1298 | } |
1299 | 1299 | ||
1300 | if (up->flags & (SUNZILOG_FLAG_CONS_KEYB | | 1300 | if (up->flags & (SUNZILOG_FLAG_CONS_KEYB | |
1301 | SUNZILOG_FLAG_CONS_MOUSE)) { | 1301 | SUNZILOG_FLAG_CONS_MOUSE)) { |
1302 | up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; | 1302 | up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; |
1303 | up->curregs[R4] = PAR_EVEN | X16CLK | SB1; | 1303 | up->curregs[R4] = PAR_EVEN | X16CLK | SB1; |
1304 | up->curregs[R3] = RxENAB | Rx8; | 1304 | up->curregs[R3] = RxENAB | Rx8; |
1305 | up->curregs[R5] = TxENAB | Tx8; | 1305 | up->curregs[R5] = TxENAB | Tx8; |
1306 | up->curregs[R6] = 0x00; /* SDLC Address */ | 1306 | up->curregs[R6] = 0x00; /* SDLC Address */ |
1307 | up->curregs[R7] = 0x7E; /* SDLC Flag */ | 1307 | up->curregs[R7] = 0x7E; /* SDLC Flag */ |
1308 | up->curregs[R9] = NV; | 1308 | up->curregs[R9] = NV; |
1309 | up->curregs[R7p] = 0x00; | 1309 | up->curregs[R7p] = 0x00; |
1310 | sunzilog_init_kbdms(up, up->port.line); | 1310 | sunzilog_init_kbdms(up, up->port.line); |
1311 | /* Only enable interrupts if an ISR handler available */ | 1311 | /* Only enable interrupts if an ISR handler available */ |
1312 | if (up->flags & SUNZILOG_FLAG_ISR_HANDLER) | 1312 | if (up->flags & SUNZILOG_FLAG_ISR_HANDLER) |
1313 | up->curregs[R9] |= MIE; | 1313 | up->curregs[R9] |= MIE; |
1314 | write_zsreg(channel, R9, up->curregs[R9]); | 1314 | write_zsreg(channel, R9, up->curregs[R9]); |
1315 | } else { | 1315 | } else { |
1316 | /* Normal serial TTY. */ | 1316 | /* Normal serial TTY. */ |
1317 | up->parity_mask = 0xff; | 1317 | up->parity_mask = 0xff; |
1318 | up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; | 1318 | up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; |
1319 | up->curregs[R4] = PAR_EVEN | X16CLK | SB1; | 1319 | up->curregs[R4] = PAR_EVEN | X16CLK | SB1; |
1320 | up->curregs[R3] = RxENAB | Rx8; | 1320 | up->curregs[R3] = RxENAB | Rx8; |
1321 | up->curregs[R5] = TxENAB | Tx8; | 1321 | up->curregs[R5] = TxENAB | Tx8; |
1322 | up->curregs[R6] = 0x00; /* SDLC Address */ | 1322 | up->curregs[R6] = 0x00; /* SDLC Address */ |
1323 | up->curregs[R7] = 0x7E; /* SDLC Flag */ | 1323 | up->curregs[R7] = 0x7E; /* SDLC Flag */ |
1324 | up->curregs[R9] = NV; | 1324 | up->curregs[R9] = NV; |
1325 | up->curregs[R10] = NRZ; | 1325 | up->curregs[R10] = NRZ; |
1326 | up->curregs[R11] = TCBR | RCBR; | 1326 | up->curregs[R11] = TCBR | RCBR; |
1327 | baud = 9600; | 1327 | baud = 9600; |
1328 | brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); | 1328 | brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); |
1329 | up->curregs[R12] = (brg & 0xff); | 1329 | up->curregs[R12] = (brg & 0xff); |
1330 | up->curregs[R13] = (brg >> 8) & 0xff; | 1330 | up->curregs[R13] = (brg >> 8) & 0xff; |
1331 | up->curregs[R14] = BRSRC | BRENAB; | 1331 | up->curregs[R14] = BRSRC | BRENAB; |
1332 | up->curregs[R15] = FIFOEN; /* Use FIFO if on ESCC */ | 1332 | up->curregs[R15] = FIFOEN; /* Use FIFO if on ESCC */ |
1333 | up->curregs[R7p] = TxFIFO_LVL | RxFIFO_LVL; | 1333 | up->curregs[R7p] = TxFIFO_LVL | RxFIFO_LVL; |
1334 | if (__load_zsregs(channel, up->curregs)) { | 1334 | if (__load_zsregs(channel, up->curregs)) { |
1335 | up->flags |= SUNZILOG_FLAG_ESCC; | 1335 | up->flags |= SUNZILOG_FLAG_ESCC; |
1336 | } | 1336 | } |
1337 | /* Only enable interrupts if an ISR handler available */ | 1337 | /* Only enable interrupts if an ISR handler available */ |
1338 | if (up->flags & SUNZILOG_FLAG_ISR_HANDLER) | 1338 | if (up->flags & SUNZILOG_FLAG_ISR_HANDLER) |
1339 | up->curregs[R9] |= MIE; | 1339 | up->curregs[R9] |= MIE; |
1340 | write_zsreg(channel, R9, up->curregs[R9]); | 1340 | write_zsreg(channel, R9, up->curregs[R9]); |
1341 | } | 1341 | } |
1342 | 1342 | ||
1343 | spin_unlock_irqrestore(&up->port.lock, flags); | 1343 | spin_unlock_irqrestore(&up->port.lock, flags); |
1344 | 1344 | ||
1345 | #ifdef CONFIG_SERIO | 1345 | #ifdef CONFIG_SERIO |
1346 | if (up->flags & (SUNZILOG_FLAG_CONS_KEYB | | 1346 | if (up->flags & (SUNZILOG_FLAG_CONS_KEYB | |
1347 | SUNZILOG_FLAG_CONS_MOUSE)) | 1347 | SUNZILOG_FLAG_CONS_MOUSE)) |
1348 | sunzilog_register_serio(up); | 1348 | sunzilog_register_serio(up); |
1349 | #endif | 1349 | #endif |
1350 | } | 1350 | } |
1351 | 1351 | ||
1352 | static int zilog_irq = -1; | 1352 | static int zilog_irq = -1; |
1353 | 1353 | ||
1354 | static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match) | 1354 | static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match) |
1355 | { | 1355 | { |
1356 | static int inst; | 1356 | static int inst; |
1357 | struct uart_sunzilog_port *up; | 1357 | struct uart_sunzilog_port *up; |
1358 | struct zilog_layout __iomem *rp; | 1358 | struct zilog_layout __iomem *rp; |
1359 | int keyboard_mouse; | 1359 | int keyboard_mouse; |
1360 | int err; | 1360 | int err; |
1361 | 1361 | ||
1362 | keyboard_mouse = 0; | 1362 | keyboard_mouse = 0; |
1363 | if (of_find_property(op->node, "keyboard", NULL)) | 1363 | if (of_find_property(op->node, "keyboard", NULL)) |
1364 | keyboard_mouse = 1; | 1364 | keyboard_mouse = 1; |
1365 | 1365 | ||
1366 | sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0, | 1366 | sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0, |
1367 | sizeof(struct zilog_layout), | 1367 | sizeof(struct zilog_layout), |
1368 | "zs"); | 1368 | "zs"); |
1369 | if (!sunzilog_chip_regs[inst]) | 1369 | if (!sunzilog_chip_regs[inst]) |
1370 | return -ENOMEM; | 1370 | return -ENOMEM; |
1371 | 1371 | ||
1372 | rp = sunzilog_chip_regs[inst]; | 1372 | rp = sunzilog_chip_regs[inst]; |
1373 | 1373 | ||
1374 | if (zilog_irq == -1) | 1374 | if (zilog_irq == -1) |
1375 | zilog_irq = op->irqs[0]; | 1375 | zilog_irq = op->irqs[0]; |
1376 | 1376 | ||
1377 | up = &sunzilog_port_table[inst * 2]; | 1377 | up = &sunzilog_port_table[inst * 2]; |
1378 | 1378 | ||
1379 | /* Channel A */ | 1379 | /* Channel A */ |
1380 | up[0].port.mapbase = op->resource[0].start + 0x00; | 1380 | up[0].port.mapbase = op->resource[0].start + 0x00; |
1381 | up[0].port.membase = (void __iomem *) &rp->channelA; | 1381 | up[0].port.membase = (void __iomem *) &rp->channelA; |
1382 | up[0].port.iotype = UPIO_MEM; | 1382 | up[0].port.iotype = UPIO_MEM; |
1383 | up[0].port.irq = op->irqs[0]; | 1383 | up[0].port.irq = op->irqs[0]; |
1384 | up[0].port.uartclk = ZS_CLOCK; | 1384 | up[0].port.uartclk = ZS_CLOCK; |
1385 | up[0].port.fifosize = 1; | 1385 | up[0].port.fifosize = 1; |
1386 | up[0].port.ops = &sunzilog_pops; | 1386 | up[0].port.ops = &sunzilog_pops; |
1387 | up[0].port.type = PORT_SUNZILOG; | 1387 | up[0].port.type = PORT_SUNZILOG; |
1388 | up[0].port.flags = 0; | 1388 | up[0].port.flags = 0; |
1389 | up[0].port.line = (inst * 2) + 0; | 1389 | up[0].port.line = (inst * 2) + 0; |
1390 | up[0].port.dev = &op->dev; | 1390 | up[0].port.dev = &op->dev; |
1391 | up[0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A; | 1391 | up[0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A; |
1392 | if (keyboard_mouse) | 1392 | if (keyboard_mouse) |
1393 | up[0].flags |= SUNZILOG_FLAG_CONS_KEYB; | 1393 | up[0].flags |= SUNZILOG_FLAG_CONS_KEYB; |
1394 | sunzilog_init_hw(&up[0]); | 1394 | sunzilog_init_hw(&up[0]); |
1395 | 1395 | ||
1396 | /* Channel B */ | 1396 | /* Channel B */ |
1397 | up[1].port.mapbase = op->resource[0].start + 0x04; | 1397 | up[1].port.mapbase = op->resource[0].start + 0x04; |
1398 | up[1].port.membase = (void __iomem *) &rp->channelB; | 1398 | up[1].port.membase = (void __iomem *) &rp->channelB; |
1399 | up[1].port.iotype = UPIO_MEM; | 1399 | up[1].port.iotype = UPIO_MEM; |
1400 | up[1].port.irq = op->irqs[0]; | 1400 | up[1].port.irq = op->irqs[0]; |
1401 | up[1].port.uartclk = ZS_CLOCK; | 1401 | up[1].port.uartclk = ZS_CLOCK; |
1402 | up[1].port.fifosize = 1; | 1402 | up[1].port.fifosize = 1; |
1403 | up[1].port.ops = &sunzilog_pops; | 1403 | up[1].port.ops = &sunzilog_pops; |
1404 | up[1].port.type = PORT_SUNZILOG; | 1404 | up[1].port.type = PORT_SUNZILOG; |
1405 | up[1].port.flags = 0; | 1405 | up[1].port.flags = 0; |
1406 | up[1].port.line = (inst * 2) + 1; | 1406 | up[1].port.line = (inst * 2) + 1; |
1407 | up[1].port.dev = &op->dev; | 1407 | up[1].port.dev = &op->dev; |
1408 | up[1].flags |= 0; | 1408 | up[1].flags |= 0; |
1409 | if (keyboard_mouse) | 1409 | if (keyboard_mouse) |
1410 | up[1].flags |= SUNZILOG_FLAG_CONS_MOUSE; | 1410 | up[1].flags |= SUNZILOG_FLAG_CONS_MOUSE; |
1411 | sunzilog_init_hw(&up[1]); | 1411 | sunzilog_init_hw(&up[1]); |
1412 | 1412 | ||
1413 | if (!keyboard_mouse) { | 1413 | if (!keyboard_mouse) { |
1414 | if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node, | 1414 | if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node, |
1415 | &sunzilog_reg, up[0].port.line)) | 1415 | &sunzilog_reg, up[0].port.line)) |
1416 | up->flags |= SUNZILOG_FLAG_IS_CONS; | 1416 | up->flags |= SUNZILOG_FLAG_IS_CONS; |
1417 | err = uart_add_one_port(&sunzilog_reg, &up[0].port); | 1417 | err = uart_add_one_port(&sunzilog_reg, &up[0].port); |
1418 | if (err) { | 1418 | if (err) { |
1419 | of_iounmap(&op->resource[0], | 1419 | of_iounmap(&op->resource[0], |
1420 | rp, sizeof(struct zilog_layout)); | 1420 | rp, sizeof(struct zilog_layout)); |
1421 | return err; | 1421 | return err; |
1422 | } | 1422 | } |
1423 | if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node, | 1423 | if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node, |
1424 | &sunzilog_reg, up[1].port.line)) | 1424 | &sunzilog_reg, up[1].port.line)) |
1425 | up->flags |= SUNZILOG_FLAG_IS_CONS; | 1425 | up->flags |= SUNZILOG_FLAG_IS_CONS; |
1426 | err = uart_add_one_port(&sunzilog_reg, &up[1].port); | 1426 | err = uart_add_one_port(&sunzilog_reg, &up[1].port); |
1427 | if (err) { | 1427 | if (err) { |
1428 | uart_remove_one_port(&sunzilog_reg, &up[0].port); | 1428 | uart_remove_one_port(&sunzilog_reg, &up[0].port); |
1429 | of_iounmap(&op->resource[0], | 1429 | of_iounmap(&op->resource[0], |
1430 | rp, sizeof(struct zilog_layout)); | 1430 | rp, sizeof(struct zilog_layout)); |
1431 | return err; | 1431 | return err; |
1432 | } | 1432 | } |
1433 | } else { | 1433 | } else { |
1434 | printk(KERN_INFO "%s: Keyboard at MMIO 0x%lx (irq = %d) " | 1434 | printk(KERN_INFO "%s: Keyboard at MMIO 0x%llx (irq = %d) " |
1435 | "is a %s\n", | 1435 | "is a %s\n", |
1436 | op->dev.bus_id, up[0].port.mapbase, op->irqs[0], | 1436 | op->dev.bus_id, |
1437 | sunzilog_type (&up[0].port)); | 1437 | (unsigned long long) up[0].port.mapbase, |
1438 | printk(KERN_INFO "%s: Mouse at MMIO 0x%lx (irq = %d) " | 1438 | op->irqs[0], sunzilog_type(&up[0].port)); |
1439 | printk(KERN_INFO "%s: Mouse at MMIO 0x%llx (irq = %d) " | ||
1439 | "is a %s\n", | 1440 | "is a %s\n", |
1440 | op->dev.bus_id, up[1].port.mapbase, op->irqs[0], | 1441 | op->dev.bus_id, |
1441 | sunzilog_type (&up[1].port)); | 1442 | (unsigned long long) up[1].port.mapbase, |
1443 | op->irqs[0], sunzilog_type(&up[1].port)); | ||
1442 | } | 1444 | } |
1443 | 1445 | ||
1444 | dev_set_drvdata(&op->dev, &up[0]); | 1446 | dev_set_drvdata(&op->dev, &up[0]); |
1445 | 1447 | ||
1446 | inst++; | 1448 | inst++; |
1447 | 1449 | ||
1448 | return 0; | 1450 | return 0; |
1449 | } | 1451 | } |
1450 | 1452 | ||
1451 | static void __devexit zs_remove_one(struct uart_sunzilog_port *up) | 1453 | static void __devexit zs_remove_one(struct uart_sunzilog_port *up) |
1452 | { | 1454 | { |
1453 | if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) { | 1455 | if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) { |
1454 | #ifdef CONFIG_SERIO | 1456 | #ifdef CONFIG_SERIO |
1455 | serio_unregister_port(&up->serio); | 1457 | serio_unregister_port(&up->serio); |
1456 | #endif | 1458 | #endif |
1457 | } else | 1459 | } else |
1458 | uart_remove_one_port(&sunzilog_reg, &up->port); | 1460 | uart_remove_one_port(&sunzilog_reg, &up->port); |
1459 | } | 1461 | } |
1460 | 1462 | ||
1461 | static int __devexit zs_remove(struct of_device *op) | 1463 | static int __devexit zs_remove(struct of_device *op) |
1462 | { | 1464 | { |
1463 | struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev); | 1465 | struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev); |
1464 | struct zilog_layout __iomem *regs; | 1466 | struct zilog_layout __iomem *regs; |
1465 | 1467 | ||
1466 | zs_remove_one(&up[0]); | 1468 | zs_remove_one(&up[0]); |
1467 | zs_remove_one(&up[1]); | 1469 | zs_remove_one(&up[1]); |
1468 | 1470 | ||
1469 | regs = sunzilog_chip_regs[up[0].port.line / 2]; | 1471 | regs = sunzilog_chip_regs[up[0].port.line / 2]; |
1470 | of_iounmap(&op->resource[0], regs, sizeof(struct zilog_layout)); | 1472 | of_iounmap(&op->resource[0], regs, sizeof(struct zilog_layout)); |
1471 | 1473 | ||
1472 | dev_set_drvdata(&op->dev, NULL); | 1474 | dev_set_drvdata(&op->dev, NULL); |
1473 | 1475 | ||
1474 | return 0; | 1476 | return 0; |
1475 | } | 1477 | } |
1476 | 1478 | ||
1477 | static struct of_device_id zs_match[] = { | 1479 | static struct of_device_id zs_match[] = { |
1478 | { | 1480 | { |
1479 | .name = "zs", | 1481 | .name = "zs", |
1480 | }, | 1482 | }, |
1481 | {}, | 1483 | {}, |
1482 | }; | 1484 | }; |
1483 | MODULE_DEVICE_TABLE(of, zs_match); | 1485 | MODULE_DEVICE_TABLE(of, zs_match); |
1484 | 1486 | ||
1485 | static struct of_platform_driver zs_driver = { | 1487 | static struct of_platform_driver zs_driver = { |
1486 | .name = "zs", | 1488 | .name = "zs", |
1487 | .match_table = zs_match, | 1489 | .match_table = zs_match, |
1488 | .probe = zs_probe, | 1490 | .probe = zs_probe, |
1489 | .remove = __devexit_p(zs_remove), | 1491 | .remove = __devexit_p(zs_remove), |
1490 | }; | 1492 | }; |
1491 | 1493 | ||
1492 | static int __init sunzilog_init(void) | 1494 | static int __init sunzilog_init(void) |
1493 | { | 1495 | { |
1494 | struct device_node *dp; | 1496 | struct device_node *dp; |
1495 | int err, uart_count; | 1497 | int err, uart_count; |
1496 | int num_keybms; | 1498 | int num_keybms; |
1497 | 1499 | ||
1498 | NUM_SUNZILOG = 0; | 1500 | NUM_SUNZILOG = 0; |
1499 | num_keybms = 0; | 1501 | num_keybms = 0; |
1500 | for_each_node_by_name(dp, "zs") { | 1502 | for_each_node_by_name(dp, "zs") { |
1501 | NUM_SUNZILOG++; | 1503 | NUM_SUNZILOG++; |
1502 | if (of_find_property(dp, "keyboard", NULL)) | 1504 | if (of_find_property(dp, "keyboard", NULL)) |
1503 | num_keybms++; | 1505 | num_keybms++; |
1504 | } | 1506 | } |
1505 | 1507 | ||
1506 | uart_count = 0; | 1508 | uart_count = 0; |
1507 | if (NUM_SUNZILOG) { | 1509 | if (NUM_SUNZILOG) { |
1508 | int uart_count; | 1510 | int uart_count; |
1509 | 1511 | ||
1510 | err = sunzilog_alloc_tables(); | 1512 | err = sunzilog_alloc_tables(); |
1511 | if (err) | 1513 | if (err) |
1512 | goto out; | 1514 | goto out; |
1513 | 1515 | ||
1514 | uart_count = (NUM_SUNZILOG * 2) - (2 * num_keybms); | 1516 | uart_count = (NUM_SUNZILOG * 2) - (2 * num_keybms); |
1515 | 1517 | ||
1516 | sunzilog_reg.nr = uart_count; | 1518 | sunzilog_reg.nr = uart_count; |
1517 | sunzilog_reg.minor = sunserial_current_minor; | 1519 | sunzilog_reg.minor = sunserial_current_minor; |
1518 | err = uart_register_driver(&sunzilog_reg); | 1520 | err = uart_register_driver(&sunzilog_reg); |
1519 | if (err) | 1521 | if (err) |
1520 | goto out_free_tables; | 1522 | goto out_free_tables; |
1521 | 1523 | ||
1522 | sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64; | 1524 | sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64; |
1523 | 1525 | ||
1524 | sunserial_current_minor += uart_count; | 1526 | sunserial_current_minor += uart_count; |
1525 | } | 1527 | } |
1526 | 1528 | ||
1527 | err = of_register_driver(&zs_driver, &of_bus_type); | 1529 | err = of_register_driver(&zs_driver, &of_bus_type); |
1528 | if (err) | 1530 | if (err) |
1529 | goto out_unregister_uart; | 1531 | goto out_unregister_uart; |
1530 | 1532 | ||
1531 | if (zilog_irq != -1) { | 1533 | if (zilog_irq != -1) { |
1532 | struct uart_sunzilog_port *up = sunzilog_irq_chain; | 1534 | struct uart_sunzilog_port *up = sunzilog_irq_chain; |
1533 | err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, | 1535 | err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, |
1534 | "zs", sunzilog_irq_chain); | 1536 | "zs", sunzilog_irq_chain); |
1535 | if (err) | 1537 | if (err) |
1536 | goto out_unregister_driver; | 1538 | goto out_unregister_driver; |
1537 | 1539 | ||
1538 | /* Enable Interrupts */ | 1540 | /* Enable Interrupts */ |
1539 | while (up) { | 1541 | while (up) { |
1540 | struct zilog_channel __iomem *channel; | 1542 | struct zilog_channel __iomem *channel; |
1541 | 1543 | ||
1542 | /* printk (KERN_INFO "Enable IRQ for ZILOG Hardware %p\n", up); */ | 1544 | /* printk (KERN_INFO "Enable IRQ for ZILOG Hardware %p\n", up); */ |
1543 | channel = ZILOG_CHANNEL_FROM_PORT(&up->port); | 1545 | channel = ZILOG_CHANNEL_FROM_PORT(&up->port); |
1544 | up->flags |= SUNZILOG_FLAG_ISR_HANDLER; | 1546 | up->flags |= SUNZILOG_FLAG_ISR_HANDLER; |
1545 | up->curregs[R9] |= MIE; | 1547 | up->curregs[R9] |= MIE; |
1546 | write_zsreg(channel, R9, up->curregs[R9]); | 1548 | write_zsreg(channel, R9, up->curregs[R9]); |
1547 | up = up->next; | 1549 | up = up->next; |
1548 | } | 1550 | } |
1549 | } | 1551 | } |
1550 | 1552 | ||
1551 | out: | 1553 | out: |
1552 | return err; | 1554 | return err; |
1553 | 1555 | ||
1554 | out_unregister_driver: | 1556 | out_unregister_driver: |
1555 | of_unregister_driver(&zs_driver); | 1557 | of_unregister_driver(&zs_driver); |
1556 | 1558 | ||
1557 | out_unregister_uart: | 1559 | out_unregister_uart: |
1558 | if (NUM_SUNZILOG) { | 1560 | if (NUM_SUNZILOG) { |
1559 | uart_unregister_driver(&sunzilog_reg); | 1561 | uart_unregister_driver(&sunzilog_reg); |
1560 | sunzilog_reg.cons = NULL; | 1562 | sunzilog_reg.cons = NULL; |
1561 | } | 1563 | } |
1562 | 1564 | ||
1563 | out_free_tables: | 1565 | out_free_tables: |
1564 | sunzilog_free_tables(); | 1566 | sunzilog_free_tables(); |
1565 | goto out; | 1567 | goto out; |
1566 | } | 1568 | } |
1567 | 1569 | ||
1568 | static void __exit sunzilog_exit(void) | 1570 | static void __exit sunzilog_exit(void) |
1569 | { | 1571 | { |
1570 | of_unregister_driver(&zs_driver); | 1572 | of_unregister_driver(&zs_driver); |
1571 | 1573 | ||
1572 | if (zilog_irq != -1) { | 1574 | if (zilog_irq != -1) { |
1573 | struct uart_sunzilog_port *up = sunzilog_irq_chain; | 1575 | struct uart_sunzilog_port *up = sunzilog_irq_chain; |
1574 | 1576 | ||
1575 | /* Disable Interrupts */ | 1577 | /* Disable Interrupts */ |
1576 | while (up) { | 1578 | while (up) { |
1577 | struct zilog_channel __iomem *channel; | 1579 | struct zilog_channel __iomem *channel; |
1578 | 1580 | ||
1579 | /* printk (KERN_INFO "Disable IRQ for ZILOG Hardware %p\n", up); */ | 1581 | /* printk (KERN_INFO "Disable IRQ for ZILOG Hardware %p\n", up); */ |
1580 | channel = ZILOG_CHANNEL_FROM_PORT(&up->port); | 1582 | channel = ZILOG_CHANNEL_FROM_PORT(&up->port); |
1581 | up->flags &= ~SUNZILOG_FLAG_ISR_HANDLER; | 1583 | up->flags &= ~SUNZILOG_FLAG_ISR_HANDLER; |
1582 | up->curregs[R9] &= ~MIE; | 1584 | up->curregs[R9] &= ~MIE; |
1583 | write_zsreg(channel, R9, up->curregs[R9]); | 1585 | write_zsreg(channel, R9, up->curregs[R9]); |
1584 | up = up->next; | 1586 | up = up->next; |
1585 | } | 1587 | } |
1586 | 1588 | ||
1587 | free_irq(zilog_irq, sunzilog_irq_chain); | 1589 | free_irq(zilog_irq, sunzilog_irq_chain); |
1588 | zilog_irq = -1; | 1590 | zilog_irq = -1; |
1589 | } | 1591 | } |
1590 | 1592 | ||
1591 | if (NUM_SUNZILOG) { | 1593 | if (NUM_SUNZILOG) { |
1592 | uart_unregister_driver(&sunzilog_reg); | 1594 | uart_unregister_driver(&sunzilog_reg); |
1593 | sunzilog_free_tables(); | 1595 | sunzilog_free_tables(); |
1594 | } | 1596 | } |
1595 | } | 1597 | } |
1596 | 1598 | ||
1597 | module_init(sunzilog_init); | 1599 | module_init(sunzilog_init); |
1598 | module_exit(sunzilog_exit); | 1600 | module_exit(sunzilog_exit); |
1599 | 1601 | ||
1600 | MODULE_AUTHOR("David S. Miller"); | 1602 | MODULE_AUTHOR("David S. Miller"); |
1601 | MODULE_DESCRIPTION("Sun Zilog serial port driver"); | 1603 | MODULE_DESCRIPTION("Sun Zilog serial port driver"); |
1602 | MODULE_VERSION("2.0"); | 1604 | MODULE_VERSION("2.0"); |
1603 | MODULE_LICENSE("GPL"); | 1605 | MODULE_LICENSE("GPL"); |
1604 | 1606 |