Commit | Line | Data |
---|---|---|
b920de1b DH |
1 | /* MN10300 On-chip serial port UART driver |
2 | * | |
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | |
4 | * Written by David Howells (dhowells@redhat.com) | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public Licence | |
8 | * as published by the Free Software Foundation; either version | |
9 | * 2 of the Licence, or (at your option) any later version. | |
10 | */ | |
11 | ||
12 | static const char serial_name[] = "MN10300 Serial driver"; | |
13 | static const char serial_version[] = "mn10300_serial-1.0"; | |
14 | static const char serial_revdate[] = "2007-11-06"; | |
15 | ||
16 | #if defined(CONFIG_MN10300_TTYSM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | |
17 | #define SUPPORT_SYSRQ | |
18 | #endif | |
19 | ||
b920de1b DH |
20 | #include <linux/module.h> |
21 | #include <linux/serial.h> | |
22 | #include <linux/circ_buf.h> | |
23 | #include <linux/errno.h> | |
24 | #include <linux/signal.h> | |
25 | #include <linux/sched.h> | |
26 | #include <linux/timer.h> | |
27 | #include <linux/interrupt.h> | |
28 | #include <linux/tty.h> | |
29 | #include <linux/tty_flip.h> | |
30 | #include <linux/major.h> | |
31 | #include <linux/string.h> | |
32 | #include <linux/ioport.h> | |
33 | #include <linux/mm.h> | |
34 | #include <linux/slab.h> | |
35 | #include <linux/init.h> | |
36 | #include <linux/console.h> | |
37 | #include <linux/sysrq.h> | |
38 | ||
39 | #include <asm/system.h> | |
40 | #include <asm/io.h> | |
41 | #include <asm/irq.h> | |
42 | #include <asm/bitops.h> | |
43 | #include <asm/serial-regs.h> | |
2f2a2132 | 44 | #include <unit/timex.h> |
b920de1b DH |
45 | #include "mn10300-serial.h" |
46 | ||
368dd5ac AT |
47 | #ifdef CONFIG_SMP |
48 | #undef GxICR | |
49 | #define GxICR(X) CROSS_GxICR(X, 0) | |
50 | #endif /* CONFIG_SMP */ | |
51 | ||
b920de1b DH |
52 | #define kenter(FMT, ...) \ |
53 | printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__) | |
54 | #define _enter(FMT, ...) \ | |
55 | no_printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__) | |
56 | #define kdebug(FMT, ...) \ | |
57 | printk(KERN_DEBUG "--- " FMT "\n", ##__VA_ARGS__) | |
58 | #define _debug(FMT, ...) \ | |
59 | no_printk(KERN_DEBUG "--- " FMT "\n", ##__VA_ARGS__) | |
60 | #define kproto(FMT, ...) \ | |
61 | printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__) | |
62 | #define _proto(FMT, ...) \ | |
63 | no_printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__) | |
64 | ||
368dd5ac AT |
65 | #ifndef CODMSB |
66 | /* c_cflag bit meaning */ | |
67 | #define CODMSB 004000000000 /* change Transfer bit-order */ | |
68 | #endif | |
69 | ||
b920de1b DH |
70 | #define NR_UARTS 3 |
71 | ||
72 | #ifdef CONFIG_MN10300_TTYSM_CONSOLE | |
73 | static void mn10300_serial_console_write(struct console *co, | |
74 | const char *s, unsigned count); | |
75 | static int __init mn10300_serial_console_setup(struct console *co, | |
76 | char *options); | |
77 | ||
78 | static struct uart_driver mn10300_serial_driver; | |
79 | static struct console mn10300_serial_console = { | |
80 | .name = "ttySM", | |
81 | .write = mn10300_serial_console_write, | |
82 | .device = uart_console_device, | |
83 | .setup = mn10300_serial_console_setup, | |
84 | .flags = CON_PRINTBUFFER, | |
85 | .index = -1, | |
86 | .data = &mn10300_serial_driver, | |
87 | }; | |
88 | #endif | |
89 | ||
90 | static struct uart_driver mn10300_serial_driver = { | |
91 | .owner = NULL, | |
92 | .driver_name = "mn10300-serial", | |
93 | .dev_name = "ttySM", | |
94 | .major = TTY_MAJOR, | |
95 | .minor = 128, | |
96 | .nr = NR_UARTS, | |
97 | #ifdef CONFIG_MN10300_TTYSM_CONSOLE | |
98 | .cons = &mn10300_serial_console, | |
99 | #endif | |
100 | }; | |
101 | ||
102 | static unsigned int mn10300_serial_tx_empty(struct uart_port *); | |
103 | static void mn10300_serial_set_mctrl(struct uart_port *, unsigned int mctrl); | |
104 | static unsigned int mn10300_serial_get_mctrl(struct uart_port *); | |
105 | static void mn10300_serial_stop_tx(struct uart_port *); | |
106 | static void mn10300_serial_start_tx(struct uart_port *); | |
107 | static void mn10300_serial_send_xchar(struct uart_port *, char ch); | |
108 | static void mn10300_serial_stop_rx(struct uart_port *); | |
109 | static void mn10300_serial_enable_ms(struct uart_port *); | |
110 | static void mn10300_serial_break_ctl(struct uart_port *, int ctl); | |
111 | static int mn10300_serial_startup(struct uart_port *); | |
112 | static void mn10300_serial_shutdown(struct uart_port *); | |
113 | static void mn10300_serial_set_termios(struct uart_port *, | |
114 | struct ktermios *new, | |
115 | struct ktermios *old); | |
116 | static const char *mn10300_serial_type(struct uart_port *); | |
117 | static void mn10300_serial_release_port(struct uart_port *); | |
118 | static int mn10300_serial_request_port(struct uart_port *); | |
119 | static void mn10300_serial_config_port(struct uart_port *, int); | |
120 | static int mn10300_serial_verify_port(struct uart_port *, | |
121 | struct serial_struct *); | |
122 | ||
123 | static const struct uart_ops mn10300_serial_ops = { | |
124 | .tx_empty = mn10300_serial_tx_empty, | |
125 | .set_mctrl = mn10300_serial_set_mctrl, | |
126 | .get_mctrl = mn10300_serial_get_mctrl, | |
127 | .stop_tx = mn10300_serial_stop_tx, | |
128 | .start_tx = mn10300_serial_start_tx, | |
129 | .send_xchar = mn10300_serial_send_xchar, | |
130 | .stop_rx = mn10300_serial_stop_rx, | |
131 | .enable_ms = mn10300_serial_enable_ms, | |
132 | .break_ctl = mn10300_serial_break_ctl, | |
133 | .startup = mn10300_serial_startup, | |
134 | .shutdown = mn10300_serial_shutdown, | |
135 | .set_termios = mn10300_serial_set_termios, | |
136 | .type = mn10300_serial_type, | |
137 | .release_port = mn10300_serial_release_port, | |
138 | .request_port = mn10300_serial_request_port, | |
139 | .config_port = mn10300_serial_config_port, | |
140 | .verify_port = mn10300_serial_verify_port, | |
141 | }; | |
142 | ||
143 | static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id); | |
144 | ||
145 | /* | |
146 | * the first on-chip serial port: ttySM0 (aka SIF0) | |
147 | */ | |
148 | #ifdef CONFIG_MN10300_TTYSM0 | |
149 | struct mn10300_serial_port mn10300_serial_port_sif0 = { | |
150 | .uart.ops = &mn10300_serial_ops, | |
151 | .uart.membase = (void __iomem *) &SC0CTR, | |
152 | .uart.mapbase = (unsigned long) &SC0CTR, | |
153 | .uart.iotype = UPIO_MEM, | |
154 | .uart.irq = 0, | |
155 | .uart.uartclk = 0, /* MN10300_IOCLK, */ | |
156 | .uart.fifosize = 1, | |
157 | .uart.flags = UPF_BOOT_AUTOCONF, | |
158 | .uart.line = 0, | |
159 | .uart.type = PORT_MN10300, | |
160 | .uart.lock = | |
161 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif0.uart.lock), | |
162 | .name = "ttySM0", | |
163 | ._iobase = &SC0CTR, | |
164 | ._control = &SC0CTR, | |
368dd5ac | 165 | ._status = (volatile u8 *)&SC0STR, |
b920de1b DH |
166 | ._intr = &SC0ICR, |
167 | ._rxb = &SC0RXB, | |
168 | ._txb = &SC0TXB, | |
a4128b03 DH |
169 | .rx_name = "ttySM0:Rx", |
170 | .tx_name = "ttySM0:Tx", | |
368dd5ac | 171 | #if defined(CONFIG_MN10300_TTYSM0_TIMER8) |
a4128b03 | 172 | .tm_name = "ttySM0:Timer8", |
b920de1b DH |
173 | ._tmxmd = &TM8MD, |
174 | ._tmxbr = &TM8BR, | |
175 | ._tmicr = &TM8ICR, | |
176 | .tm_irq = TM8IRQ, | |
177 | .div_timer = MNSCx_DIV_TIMER_16BIT, | |
368dd5ac AT |
178 | #elif defined(CONFIG_MN10300_TTYSM0_TIMER0) |
179 | .tm_name = "ttySM0:Timer0", | |
180 | ._tmxmd = &TM0MD, | |
181 | ._tmxbr = (volatile u16 *)&TM0BR, | |
182 | ._tmicr = &TM0ICR, | |
183 | .tm_irq = TM0IRQ, | |
184 | .div_timer = MNSCx_DIV_TIMER_8BIT, | |
185 | #elif defined(CONFIG_MN10300_TTYSM0_TIMER2) | |
a4128b03 | 186 | .tm_name = "ttySM0:Timer2", |
b920de1b | 187 | ._tmxmd = &TM2MD, |
368dd5ac | 188 | ._tmxbr = (volatile u16 *)&TM2BR, |
b920de1b DH |
189 | ._tmicr = &TM2ICR, |
190 | .tm_irq = TM2IRQ, | |
191 | .div_timer = MNSCx_DIV_TIMER_8BIT, | |
368dd5ac AT |
192 | #else |
193 | #error "Unknown config for ttySM0" | |
b920de1b DH |
194 | #endif |
195 | .rx_irq = SC0RXIRQ, | |
196 | .tx_irq = SC0TXIRQ, | |
197 | .rx_icr = &GxICR(SC0RXIRQ), | |
198 | .tx_icr = &GxICR(SC0TXIRQ), | |
199 | .clock_src = MNSCx_CLOCK_SRC_IOCLK, | |
200 | .options = 0, | |
201 | #ifdef CONFIG_GDBSTUB_ON_TTYSM0 | |
202 | .gdbstub = 1, | |
203 | #endif | |
204 | }; | |
205 | #endif /* CONFIG_MN10300_TTYSM0 */ | |
206 | ||
207 | /* | |
208 | * the second on-chip serial port: ttySM1 (aka SIF1) | |
209 | */ | |
210 | #ifdef CONFIG_MN10300_TTYSM1 | |
211 | struct mn10300_serial_port mn10300_serial_port_sif1 = { | |
212 | .uart.ops = &mn10300_serial_ops, | |
213 | .uart.membase = (void __iomem *) &SC1CTR, | |
214 | .uart.mapbase = (unsigned long) &SC1CTR, | |
215 | .uart.iotype = UPIO_MEM, | |
216 | .uart.irq = 0, | |
217 | .uart.uartclk = 0, /* MN10300_IOCLK, */ | |
218 | .uart.fifosize = 1, | |
219 | .uart.flags = UPF_BOOT_AUTOCONF, | |
220 | .uart.line = 1, | |
221 | .uart.type = PORT_MN10300, | |
222 | .uart.lock = | |
223 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif1.uart.lock), | |
224 | .name = "ttySM1", | |
225 | ._iobase = &SC1CTR, | |
226 | ._control = &SC1CTR, | |
368dd5ac | 227 | ._status = (volatile u8 *)&SC1STR, |
b920de1b DH |
228 | ._intr = &SC1ICR, |
229 | ._rxb = &SC1RXB, | |
230 | ._txb = &SC1TXB, | |
a4128b03 DH |
231 | .rx_name = "ttySM1:Rx", |
232 | .tx_name = "ttySM1:Tx", | |
368dd5ac | 233 | #if defined(CONFIG_MN10300_TTYSM1_TIMER9) |
a4128b03 | 234 | .tm_name = "ttySM1:Timer9", |
b920de1b DH |
235 | ._tmxmd = &TM9MD, |
236 | ._tmxbr = &TM9BR, | |
237 | ._tmicr = &TM9ICR, | |
238 | .tm_irq = TM9IRQ, | |
239 | .div_timer = MNSCx_DIV_TIMER_16BIT, | |
368dd5ac | 240 | #elif defined(CONFIG_MN10300_TTYSM1_TIMER3) |
a4128b03 | 241 | .tm_name = "ttySM1:Timer3", |
b920de1b | 242 | ._tmxmd = &TM3MD, |
368dd5ac | 243 | ._tmxbr = (volatile u16 *)&TM3BR, |
b920de1b DH |
244 | ._tmicr = &TM3ICR, |
245 | .tm_irq = TM3IRQ, | |
246 | .div_timer = MNSCx_DIV_TIMER_8BIT, | |
368dd5ac AT |
247 | #elif defined(CONFIG_MN10300_TTYSM1_TIMER12) |
248 | .tm_name = "ttySM1/Timer12", | |
249 | ._tmxmd = &TM12MD, | |
250 | ._tmxbr = &TM12BR, | |
251 | ._tmicr = &TM12ICR, | |
252 | .tm_irq = TM12IRQ, | |
253 | .div_timer = MNSCx_DIV_TIMER_16BIT, | |
254 | #else | |
255 | #error "Unknown config for ttySM1" | |
b920de1b DH |
256 | #endif |
257 | .rx_irq = SC1RXIRQ, | |
258 | .tx_irq = SC1TXIRQ, | |
259 | .rx_icr = &GxICR(SC1RXIRQ), | |
260 | .tx_icr = &GxICR(SC1TXIRQ), | |
261 | .clock_src = MNSCx_CLOCK_SRC_IOCLK, | |
262 | .options = 0, | |
263 | #ifdef CONFIG_GDBSTUB_ON_TTYSM1 | |
264 | .gdbstub = 1, | |
265 | #endif | |
266 | }; | |
267 | #endif /* CONFIG_MN10300_TTYSM1 */ | |
268 | ||
269 | /* | |
270 | * the third on-chip serial port: ttySM2 (aka SIF2) | |
271 | */ | |
272 | #ifdef CONFIG_MN10300_TTYSM2 | |
273 | struct mn10300_serial_port mn10300_serial_port_sif2 = { | |
274 | .uart.ops = &mn10300_serial_ops, | |
275 | .uart.membase = (void __iomem *) &SC2CTR, | |
276 | .uart.mapbase = (unsigned long) &SC2CTR, | |
277 | .uart.iotype = UPIO_MEM, | |
278 | .uart.irq = 0, | |
279 | .uart.uartclk = 0, /* MN10300_IOCLK, */ | |
280 | .uart.fifosize = 1, | |
281 | .uart.flags = UPF_BOOT_AUTOCONF, | |
282 | .uart.line = 2, | |
283 | #ifdef CONFIG_MN10300_TTYSM2_CTS | |
284 | .uart.type = PORT_MN10300_CTS, | |
285 | #else | |
286 | .uart.type = PORT_MN10300, | |
287 | #endif | |
288 | .uart.lock = | |
289 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), | |
290 | .name = "ttySM2", | |
b920de1b DH |
291 | ._iobase = &SC2CTR, |
292 | ._control = &SC2CTR, | |
368dd5ac | 293 | ._status = (volatile u8 *)&SC2STR, |
b920de1b DH |
294 | ._intr = &SC2ICR, |
295 | ._rxb = &SC2RXB, | |
296 | ._txb = &SC2TXB, | |
368dd5ac AT |
297 | .rx_name = "ttySM2:Rx", |
298 | .tx_name = "ttySM2:Tx", | |
299 | #if defined(CONFIG_MN10300_TTYSM2_TIMER10) | |
300 | .tm_name = "ttySM2/Timer10", | |
b920de1b DH |
301 | ._tmxmd = &TM10MD, |
302 | ._tmxbr = &TM10BR, | |
303 | ._tmicr = &TM10ICR, | |
304 | .tm_irq = TM10IRQ, | |
305 | .div_timer = MNSCx_DIV_TIMER_16BIT, | |
368dd5ac AT |
306 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER9) |
307 | .tm_name = "ttySM2/Timer9", | |
308 | ._tmxmd = &TM9MD, | |
309 | ._tmxbr = &TM9BR, | |
310 | ._tmicr = &TM9ICR, | |
311 | .tm_irq = TM9IRQ, | |
312 | .div_timer = MNSCx_DIV_TIMER_16BIT, | |
313 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER1) | |
314 | .tm_name = "ttySM2/Timer1", | |
315 | ._tmxmd = &TM1MD, | |
316 | ._tmxbr = (volatile u16 *)&TM1BR, | |
317 | ._tmicr = &TM1ICR, | |
318 | .tm_irq = TM1IRQ, | |
319 | .div_timer = MNSCx_DIV_TIMER_8BIT, | |
320 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER3) | |
321 | .tm_name = "ttySM2/Timer3", | |
322 | ._tmxmd = &TM3MD, | |
323 | ._tmxbr = (volatile u16 *)&TM3BR, | |
324 | ._tmicr = &TM3ICR, | |
325 | .tm_irq = TM3IRQ, | |
326 | .div_timer = MNSCx_DIV_TIMER_8BIT, | |
327 | #else | |
328 | #error "Unknown config for ttySM2" | |
329 | #endif | |
b920de1b DH |
330 | .rx_irq = SC2RXIRQ, |
331 | .tx_irq = SC2TXIRQ, | |
332 | .rx_icr = &GxICR(SC2RXIRQ), | |
333 | .tx_icr = &GxICR(SC2TXIRQ), | |
334 | .clock_src = MNSCx_CLOCK_SRC_IOCLK, | |
335 | #ifdef CONFIG_MN10300_TTYSM2_CTS | |
336 | .options = MNSCx_OPT_CTS, | |
337 | #else | |
338 | .options = 0, | |
339 | #endif | |
340 | #ifdef CONFIG_GDBSTUB_ON_TTYSM2 | |
341 | .gdbstub = 1, | |
342 | #endif | |
343 | }; | |
344 | #endif /* CONFIG_MN10300_TTYSM2 */ | |
345 | ||
346 | ||
347 | /* | |
348 | * list of available serial ports | |
349 | */ | |
350 | struct mn10300_serial_port *mn10300_serial_ports[NR_UARTS + 1] = { | |
351 | #ifdef CONFIG_MN10300_TTYSM0 | |
352 | [0] = &mn10300_serial_port_sif0, | |
353 | #endif | |
354 | #ifdef CONFIG_MN10300_TTYSM1 | |
355 | [1] = &mn10300_serial_port_sif1, | |
356 | #endif | |
357 | #ifdef CONFIG_MN10300_TTYSM2 | |
358 | [2] = &mn10300_serial_port_sif2, | |
359 | #endif | |
360 | [NR_UARTS] = NULL, | |
361 | }; | |
362 | ||
363 | ||
364 | /* | |
365 | * we abuse the serial ports' baud timers' interrupt lines to get the ability | |
366 | * to deliver interrupts to userspace as we use the ports' interrupt lines to | |
367 | * do virtual DMA on account of the ports having no hardware FIFOs | |
368 | * | |
369 | * we can generate an interrupt manually in the assembly stubs by writing to | |
370 | * the enable and detect bits in the interrupt control register, so all we need | |
371 | * to do here is disable the interrupt line | |
372 | * | |
373 | * note that we can't just leave the line enabled as the baud rate timer *also* | |
374 | * generates interrupts | |
375 | */ | |
376 | static void mn10300_serial_mask_ack(unsigned int irq) | |
377 | { | |
368dd5ac | 378 | unsigned long flags; |
b920de1b | 379 | u16 tmp; |
368dd5ac AT |
380 | |
381 | flags = arch_local_cli_save(); | |
b920de1b DH |
382 | GxICR(irq) = GxICR_LEVEL_6; |
383 | tmp = GxICR(irq); /* flush write buffer */ | |
368dd5ac | 384 | arch_local_irq_restore(flags); |
b920de1b DH |
385 | } |
386 | ||
387 | static void mn10300_serial_nop(unsigned int irq) | |
388 | { | |
389 | } | |
390 | ||
391 | static struct irq_chip mn10300_serial_pic = { | |
392 | .name = "mnserial", | |
393 | .ack = mn10300_serial_mask_ack, | |
394 | .mask = mn10300_serial_mask_ack, | |
395 | .mask_ack = mn10300_serial_mask_ack, | |
396 | .unmask = mn10300_serial_nop, | |
397 | .end = mn10300_serial_nop, | |
398 | }; | |
399 | ||
400 | ||
401 | /* | |
402 | * serial virtual DMA interrupt jump table | |
403 | */ | |
404 | struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS]; | |
405 | ||
406 | static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port) | |
407 | { | |
368dd5ac | 408 | unsigned long flags; |
b920de1b | 409 | u16 x; |
368dd5ac AT |
410 | |
411 | flags = arch_local_cli_save(); | |
412 | *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); | |
b920de1b | 413 | x = *port->tx_icr; |
368dd5ac | 414 | arch_local_irq_restore(flags); |
b920de1b DH |
415 | } |
416 | ||
417 | static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port) | |
418 | { | |
368dd5ac | 419 | unsigned long flags; |
b920de1b | 420 | u16 x; |
368dd5ac AT |
421 | |
422 | flags = arch_local_cli_save(); | |
423 | *port->tx_icr = | |
424 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | GxICR_ENABLE; | |
b920de1b | 425 | x = *port->tx_icr; |
368dd5ac | 426 | arch_local_irq_restore(flags); |
b920de1b DH |
427 | } |
428 | ||
429 | static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port) | |
430 | { | |
368dd5ac | 431 | unsigned long flags; |
b920de1b | 432 | u16 x; |
368dd5ac AT |
433 | |
434 | flags = arch_local_cli_save(); | |
435 | *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); | |
b920de1b | 436 | x = *port->rx_icr; |
368dd5ac | 437 | arch_local_irq_restore(flags); |
b920de1b DH |
438 | } |
439 | ||
440 | /* | |
441 | * multi-bit equivalent of test_and_clear_bit() | |
442 | */ | |
443 | static int mask_test_and_clear(volatile u8 *ptr, u8 mask) | |
444 | { | |
445 | u32 epsw; | |
446 | asm volatile(" bclr %1,(%2) \n" | |
447 | " mov epsw,%0 \n" | |
d6bb7a1a MS |
448 | : "=d"(epsw) : "d"(mask), "a"(ptr) |
449 | : "cc", "memory"); | |
b920de1b DH |
450 | return !(epsw & EPSW_FLAG_Z); |
451 | } | |
452 | ||
453 | /* | |
454 | * receive chars from the ring buffer for this serial port | |
455 | * - must do break detection here (not done in the UART) | |
456 | */ | |
457 | static void mn10300_serial_receive_interrupt(struct mn10300_serial_port *port) | |
458 | { | |
459 | struct uart_icount *icount = &port->uart.icount; | |
70430786 | 460 | struct tty_struct *tty = port->uart.state->port.tty; |
b920de1b DH |
461 | unsigned ix; |
462 | int count; | |
463 | u8 st, ch, push, status, overrun; | |
464 | ||
465 | _enter("%s", port->name); | |
466 | ||
467 | push = 0; | |
468 | ||
469 | count = CIRC_CNT(port->rx_inp, port->rx_outp, MNSC_BUFFER_SIZE); | |
470 | count = tty_buffer_request_room(tty, count); | |
471 | if (count == 0) { | |
472 | if (!tty->low_latency) | |
473 | tty_flip_buffer_push(tty); | |
474 | return; | |
475 | } | |
476 | ||
477 | try_again: | |
478 | /* pull chars out of the hat */ | |
479 | ix = port->rx_outp; | |
480 | if (ix == port->rx_inp) { | |
481 | if (push && !tty->low_latency) | |
482 | tty_flip_buffer_push(tty); | |
483 | return; | |
484 | } | |
485 | ||
486 | ch = port->rx_buffer[ix++]; | |
487 | st = port->rx_buffer[ix++]; | |
488 | smp_rmb(); | |
489 | port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1); | |
490 | port->uart.icount.rx++; | |
491 | ||
492 | st &= SC01STR_FEF | SC01STR_PEF | SC01STR_OEF; | |
493 | status = 0; | |
494 | overrun = 0; | |
495 | ||
496 | /* the UART doesn't detect BREAK, so we have to do that ourselves | |
497 | * - it starts as a framing error on a NUL character | |
498 | * - then we count another two NUL characters before issuing TTY_BREAK | |
499 | * - then we end on a normal char or one that has all the bottom bits | |
500 | * zero and the top bits set | |
501 | */ | |
502 | switch (port->rx_brk) { | |
503 | case 0: | |
504 | /* not breaking at the moment */ | |
505 | break; | |
506 | ||
507 | case 1: | |
508 | if (st & SC01STR_FEF && ch == 0) { | |
509 | port->rx_brk = 2; | |
510 | goto try_again; | |
511 | } | |
512 | goto not_break; | |
513 | ||
514 | case 2: | |
515 | if (st & SC01STR_FEF && ch == 0) { | |
516 | port->rx_brk = 3; | |
517 | _proto("Rx Break Detected"); | |
518 | icount->brk++; | |
519 | if (uart_handle_break(&port->uart)) | |
520 | goto ignore_char; | |
521 | status |= 1 << TTY_BREAK; | |
522 | goto insert; | |
523 | } | |
524 | goto not_break; | |
525 | ||
526 | default: | |
527 | if (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF)) | |
528 | goto try_again; /* still breaking */ | |
529 | ||
530 | port->rx_brk = 0; /* end of the break */ | |
531 | ||
532 | switch (ch) { | |
533 | case 0xFF: | |
534 | case 0xFE: | |
535 | case 0xFC: | |
536 | case 0xF8: | |
537 | case 0xF0: | |
538 | case 0xE0: | |
539 | case 0xC0: | |
540 | case 0x80: | |
541 | case 0x00: | |
542 | /* discard char at probable break end */ | |
543 | goto try_again; | |
544 | } | |
545 | break; | |
546 | } | |
547 | ||
548 | process_errors: | |
549 | /* handle framing error */ | |
550 | if (st & SC01STR_FEF) { | |
551 | if (ch == 0) { | |
552 | /* framing error with NUL char is probably a BREAK */ | |
553 | port->rx_brk = 1; | |
554 | goto try_again; | |
555 | } | |
556 | ||
557 | _proto("Rx Framing Error"); | |
558 | icount->frame++; | |
559 | status |= 1 << TTY_FRAME; | |
560 | } | |
561 | ||
562 | /* handle parity error */ | |
563 | if (st & SC01STR_PEF) { | |
564 | _proto("Rx Parity Error"); | |
565 | icount->parity++; | |
566 | status = TTY_PARITY; | |
567 | } | |
568 | ||
569 | /* handle normal char */ | |
570 | if (status == 0) { | |
571 | if (uart_handle_sysrq_char(&port->uart, ch)) | |
572 | goto ignore_char; | |
573 | status = (1 << TTY_NORMAL); | |
574 | } | |
575 | ||
576 | /* handle overrun error */ | |
577 | if (st & SC01STR_OEF) { | |
578 | if (port->rx_brk) | |
579 | goto try_again; | |
580 | ||
581 | _proto("Rx Overrun Error"); | |
582 | icount->overrun++; | |
583 | overrun = 1; | |
584 | } | |
585 | ||
586 | insert: | |
587 | status &= port->uart.read_status_mask; | |
588 | ||
589 | if (!overrun && !(status & port->uart.ignore_status_mask)) { | |
590 | int flag; | |
591 | ||
592 | if (status & (1 << TTY_BREAK)) | |
593 | flag = TTY_BREAK; | |
594 | else if (status & (1 << TTY_PARITY)) | |
595 | flag = TTY_PARITY; | |
596 | else if (status & (1 << TTY_FRAME)) | |
597 | flag = TTY_FRAME; | |
598 | else | |
599 | flag = TTY_NORMAL; | |
600 | ||
601 | tty_insert_flip_char(tty, ch, flag); | |
602 | } | |
603 | ||
604 | /* overrun is special, since it's reported immediately, and doesn't | |
605 | * affect the current character | |
606 | */ | |
607 | if (overrun) | |
608 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | |
609 | ||
610 | count--; | |
611 | if (count <= 0) { | |
612 | if (!tty->low_latency) | |
613 | tty_flip_buffer_push(tty); | |
614 | return; | |
615 | } | |
616 | ||
617 | ignore_char: | |
618 | push = 1; | |
619 | goto try_again; | |
620 | ||
621 | not_break: | |
622 | port->rx_brk = 0; | |
623 | goto process_errors; | |
624 | } | |
625 | ||
626 | /* | |
627 | * handle an interrupt from the serial transmission "virtual DMA" driver | |
628 | * - note: the interrupt routine will disable its own interrupts when the Tx | |
629 | * buffer is empty | |
630 | */ | |
631 | static void mn10300_serial_transmit_interrupt(struct mn10300_serial_port *port) | |
632 | { | |
633 | _enter("%s", port->name); | |
634 | ||
70430786 | 635 | if (!port->uart.state || !port->uart.state->port.tty) { |
a8893fb3 AT |
636 | mn10300_serial_dis_tx_intr(port); |
637 | return; | |
638 | } | |
639 | ||
b920de1b | 640 | if (uart_tx_stopped(&port->uart) || |
70430786 | 641 | uart_circ_empty(&port->uart.state->xmit)) |
b920de1b DH |
642 | mn10300_serial_dis_tx_intr(port); |
643 | ||
70430786 | 644 | if (uart_circ_chars_pending(&port->uart.state->xmit) < WAKEUP_CHARS) |
b920de1b DH |
645 | uart_write_wakeup(&port->uart); |
646 | } | |
647 | ||
648 | /* | |
649 | * deal with a change in the status of the CTS line | |
650 | */ | |
651 | static void mn10300_serial_cts_changed(struct mn10300_serial_port *port, u8 st) | |
652 | { | |
653 | u16 ctr; | |
654 | ||
655 | port->tx_cts = st; | |
656 | port->uart.icount.cts++; | |
657 | ||
658 | /* flip the CTS state selector flag to interrupt when it changes | |
659 | * back */ | |
660 | ctr = *port->_control; | |
661 | ctr ^= SC2CTR_TWS; | |
662 | *port->_control = ctr; | |
663 | ||
664 | uart_handle_cts_change(&port->uart, st & SC2STR_CTS); | |
70430786 | 665 | wake_up_interruptible(&port->uart.state->port.delta_msr_wait); |
b920de1b DH |
666 | } |
667 | ||
668 | /* | |
669 | * handle a virtual interrupt generated by the lower level "virtual DMA" | |
670 | * routines (irq is the baud timer interrupt) | |
671 | */ | |
672 | static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id) | |
673 | { | |
674 | struct mn10300_serial_port *port = dev_id; | |
675 | u8 st; | |
676 | ||
677 | spin_lock(&port->uart.lock); | |
678 | ||
679 | if (port->intr_flags) { | |
680 | _debug("INT %s: %x", port->name, port->intr_flags); | |
681 | ||
682 | if (mask_test_and_clear(&port->intr_flags, MNSCx_RX_AVAIL)) | |
683 | mn10300_serial_receive_interrupt(port); | |
684 | ||
685 | if (mask_test_and_clear(&port->intr_flags, | |
686 | MNSCx_TX_SPACE | MNSCx_TX_EMPTY)) | |
687 | mn10300_serial_transmit_interrupt(port); | |
688 | } | |
689 | ||
690 | /* the only modem control line amongst the whole lot is CTS on | |
691 | * serial port 2 */ | |
692 | if (port->type == PORT_MN10300_CTS) { | |
693 | st = *port->_status; | |
694 | if ((port->tx_cts ^ st) & SC2STR_CTS) | |
695 | mn10300_serial_cts_changed(port, st); | |
696 | } | |
697 | ||
698 | spin_unlock(&port->uart.lock); | |
699 | ||
700 | return IRQ_HANDLED; | |
701 | } | |
702 | ||
703 | /* | |
704 | * return indication of whether the hardware transmit buffer is empty | |
705 | */ | |
706 | static unsigned int mn10300_serial_tx_empty(struct uart_port *_port) | |
707 | { | |
708 | struct mn10300_serial_port *port = | |
709 | container_of(_port, struct mn10300_serial_port, uart); | |
710 | ||
711 | _enter("%s", port->name); | |
712 | ||
713 | return (*port->_status & (SC01STR_TXF | SC01STR_TBF)) ? | |
714 | 0 : TIOCSER_TEMT; | |
715 | } | |
716 | ||
717 | /* | |
718 | * set the modem control lines (we don't have any) | |
719 | */ | |
720 | static void mn10300_serial_set_mctrl(struct uart_port *_port, | |
721 | unsigned int mctrl) | |
722 | { | |
368dd5ac | 723 | struct mn10300_serial_port *port __attribute__ ((unused)) = |
b920de1b DH |
724 | container_of(_port, struct mn10300_serial_port, uart); |
725 | ||
726 | _enter("%s,%x", port->name, mctrl); | |
727 | } | |
728 | ||
729 | /* | |
730 | * get the modem control line statuses | |
731 | */ | |
732 | static unsigned int mn10300_serial_get_mctrl(struct uart_port *_port) | |
733 | { | |
734 | struct mn10300_serial_port *port = | |
735 | container_of(_port, struct mn10300_serial_port, uart); | |
736 | ||
737 | _enter("%s", port->name); | |
738 | ||
739 | if (port->type == PORT_MN10300_CTS && !(*port->_status & SC2STR_CTS)) | |
740 | return TIOCM_CAR | TIOCM_DSR; | |
741 | ||
742 | return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR; | |
743 | } | |
744 | ||
745 | /* | |
746 | * stop transmitting characters | |
747 | */ | |
748 | static void mn10300_serial_stop_tx(struct uart_port *_port) | |
749 | { | |
750 | struct mn10300_serial_port *port = | |
751 | container_of(_port, struct mn10300_serial_port, uart); | |
752 | ||
753 | _enter("%s", port->name); | |
754 | ||
755 | /* disable the virtual DMA */ | |
756 | mn10300_serial_dis_tx_intr(port); | |
757 | } | |
758 | ||
759 | /* | |
760 | * start transmitting characters | |
761 | * - jump-start transmission if it has stalled | |
762 | * - enable the serial Tx interrupt (used by the virtual DMA controller) | |
763 | * - force an interrupt to happen if necessary | |
764 | */ | |
765 | static void mn10300_serial_start_tx(struct uart_port *_port) | |
766 | { | |
767 | struct mn10300_serial_port *port = | |
768 | container_of(_port, struct mn10300_serial_port, uart); | |
769 | ||
770 | u16 x; | |
771 | ||
772 | _enter("%s{%lu}", | |
773 | port->name, | |
70430786 DH |
774 | CIRC_CNT(&port->uart.state->xmit.head, |
775 | &port->uart.state->xmit.tail, | |
b920de1b DH |
776 | UART_XMIT_SIZE)); |
777 | ||
778 | /* kick the virtual DMA controller */ | |
368dd5ac | 779 | arch_local_cli(); |
b920de1b DH |
780 | x = *port->tx_icr; |
781 | x |= GxICR_ENABLE; | |
782 | ||
783 | if (*port->_status & SC01STR_TBF) | |
784 | x &= ~(GxICR_REQUEST | GxICR_DETECT); | |
785 | else | |
786 | x |= GxICR_REQUEST | GxICR_DETECT; | |
787 | ||
788 | _debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx", | |
789 | *port->_control, *port->_intr, *port->_status, | |
368dd5ac AT |
790 | *port->_tmxmd, |
791 | (port->div_timer == MNSCx_DIV_TIMER_8BIT) ? | |
792 | *(volatile u8 *)port->_tmxbr : *port->_tmxbr, | |
793 | *port->tx_icr); | |
b920de1b DH |
794 | |
795 | *port->tx_icr = x; | |
796 | x = *port->tx_icr; | |
368dd5ac | 797 | arch_local_sti(); |
b920de1b DH |
798 | } |
799 | ||
800 | /* | |
801 | * transmit a high-priority XON/XOFF character | |
802 | */ | |
803 | static void mn10300_serial_send_xchar(struct uart_port *_port, char ch) | |
804 | { | |
805 | struct mn10300_serial_port *port = | |
806 | container_of(_port, struct mn10300_serial_port, uart); | |
807 | ||
808 | _enter("%s,%02x", port->name, ch); | |
809 | ||
810 | if (likely(port->gdbstub)) { | |
811 | port->tx_xchar = ch; | |
812 | if (ch) | |
813 | mn10300_serial_en_tx_intr(port); | |
814 | } | |
815 | } | |
816 | ||
817 | /* | |
818 | * stop receiving characters | |
819 | * - called whilst the port is being closed | |
820 | */ | |
821 | static void mn10300_serial_stop_rx(struct uart_port *_port) | |
822 | { | |
823 | struct mn10300_serial_port *port = | |
824 | container_of(_port, struct mn10300_serial_port, uart); | |
825 | ||
826 | u16 ctr; | |
827 | ||
828 | _enter("%s", port->name); | |
829 | ||
830 | ctr = *port->_control; | |
831 | ctr &= ~SC01CTR_RXE; | |
832 | *port->_control = ctr; | |
833 | ||
834 | mn10300_serial_dis_rx_intr(port); | |
835 | } | |
836 | ||
837 | /* | |
838 | * enable modem status interrupts | |
839 | */ | |
840 | static void mn10300_serial_enable_ms(struct uart_port *_port) | |
841 | { | |
842 | struct mn10300_serial_port *port = | |
843 | container_of(_port, struct mn10300_serial_port, uart); | |
844 | ||
845 | u16 ctr, cts; | |
846 | ||
847 | _enter("%s", port->name); | |
848 | ||
849 | if (port->type == PORT_MN10300_CTS) { | |
850 | /* want to interrupt when CTS goes low if CTS is now high and | |
851 | * vice versa | |
852 | */ | |
853 | port->tx_cts = *port->_status; | |
854 | ||
855 | cts = (port->tx_cts & SC2STR_CTS) ? | |
856 | SC2CTR_TWE : SC2CTR_TWE | SC2CTR_TWS; | |
857 | ||
858 | ctr = *port->_control; | |
859 | ctr &= ~SC2CTR_TWS; | |
860 | ctr |= cts; | |
861 | *port->_control = ctr; | |
862 | ||
863 | mn10300_serial_en_tx_intr(port); | |
864 | } | |
865 | } | |
866 | ||
867 | /* | |
868 | * transmit or cease transmitting a break signal | |
869 | */ | |
870 | static void mn10300_serial_break_ctl(struct uart_port *_port, int ctl) | |
871 | { | |
872 | struct mn10300_serial_port *port = | |
873 | container_of(_port, struct mn10300_serial_port, uart); | |
874 | ||
875 | _enter("%s,%d", port->name, ctl); | |
876 | ||
877 | if (ctl) { | |
878 | /* tell the virtual DMA handler to assert BREAK */ | |
879 | port->tx_break = 1; | |
880 | mn10300_serial_en_tx_intr(port); | |
881 | } else { | |
882 | port->tx_break = 0; | |
883 | *port->_control &= ~SC01CTR_BKE; | |
884 | mn10300_serial_en_tx_intr(port); | |
885 | } | |
886 | } | |
887 | ||
888 | /* | |
889 | * grab the interrupts and enable the port for reception | |
890 | */ | |
891 | static int mn10300_serial_startup(struct uart_port *_port) | |
892 | { | |
893 | struct mn10300_serial_port *port = | |
894 | container_of(_port, struct mn10300_serial_port, uart); | |
895 | struct mn10300_serial_int *pint; | |
896 | ||
897 | _enter("%s{%d}", port->name, port->gdbstub); | |
898 | ||
899 | if (unlikely(port->gdbstub)) | |
900 | return -EBUSY; | |
901 | ||
902 | /* allocate an Rx buffer for the virtual DMA handler */ | |
903 | port->rx_buffer = kmalloc(MNSC_BUFFER_SIZE, GFP_KERNEL); | |
904 | if (!port->rx_buffer) | |
905 | return -ENOMEM; | |
906 | ||
907 | port->rx_inp = port->rx_outp = 0; | |
908 | ||
909 | /* finally, enable the device */ | |
910 | *port->_intr = SC01ICR_TI; | |
911 | *port->_control |= SC01CTR_TXE | SC01CTR_RXE; | |
912 | ||
913 | pint = &mn10300_serial_int_tbl[port->rx_irq]; | |
914 | pint->port = port; | |
915 | pint->vdma = mn10300_serial_vdma_rx_handler; | |
916 | pint = &mn10300_serial_int_tbl[port->tx_irq]; | |
917 | pint->port = port; | |
918 | pint->vdma = mn10300_serial_vdma_tx_handler; | |
919 | ||
368dd5ac AT |
920 | set_intr_level(port->rx_irq, |
921 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)); | |
922 | set_intr_level(port->tx_irq, | |
923 | NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)); | |
b920de1b DH |
924 | set_irq_chip(port->tm_irq, &mn10300_serial_pic); |
925 | ||
926 | if (request_irq(port->rx_irq, mn10300_serial_interrupt, | |
927 | IRQF_DISABLED, port->rx_name, port) < 0) | |
928 | goto error; | |
929 | ||
930 | if (request_irq(port->tx_irq, mn10300_serial_interrupt, | |
931 | IRQF_DISABLED, port->tx_name, port) < 0) | |
932 | goto error2; | |
933 | ||
934 | if (request_irq(port->tm_irq, mn10300_serial_interrupt, | |
935 | IRQF_DISABLED, port->tm_name, port) < 0) | |
936 | goto error3; | |
937 | mn10300_serial_mask_ack(port->tm_irq); | |
938 | ||
939 | return 0; | |
940 | ||
941 | error3: | |
942 | free_irq(port->tx_irq, port); | |
943 | error2: | |
944 | free_irq(port->rx_irq, port); | |
945 | error: | |
946 | kfree(port->rx_buffer); | |
947 | port->rx_buffer = NULL; | |
948 | return -EBUSY; | |
949 | } | |
950 | ||
951 | /* | |
952 | * shutdown the port and release interrupts | |
953 | */ | |
954 | static void mn10300_serial_shutdown(struct uart_port *_port) | |
955 | { | |
368dd5ac | 956 | u16 x; |
b920de1b DH |
957 | struct mn10300_serial_port *port = |
958 | container_of(_port, struct mn10300_serial_port, uart); | |
959 | ||
960 | _enter("%s", port->name); | |
961 | ||
962 | /* disable the serial port and its baud rate timer */ | |
963 | port->tx_break = 0; | |
964 | *port->_control &= ~(SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE); | |
965 | *port->_tmxmd = 0; | |
966 | ||
967 | if (port->rx_buffer) { | |
968 | void *buf = port->rx_buffer; | |
969 | port->rx_buffer = NULL; | |
970 | kfree(buf); | |
971 | } | |
972 | ||
973 | /* disable all intrs */ | |
974 | free_irq(port->tm_irq, port); | |
975 | free_irq(port->rx_irq, port); | |
976 | free_irq(port->tx_irq, port); | |
977 | ||
368dd5ac AT |
978 | arch_local_cli(); |
979 | *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); | |
980 | x = *port->rx_icr; | |
981 | *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); | |
982 | x = *port->tx_icr; | |
983 | arch_local_sti(); | |
b920de1b DH |
984 | } |
985 | ||
986 | /* | |
987 | * this routine is called to set the UART divisor registers to match the | |
988 | * specified baud rate for a serial port. | |
989 | */ | |
990 | static void mn10300_serial_change_speed(struct mn10300_serial_port *port, | |
991 | struct ktermios *new, | |
992 | struct ktermios *old) | |
993 | { | |
994 | unsigned long flags; | |
995 | unsigned long ioclk = port->ioclk; | |
996 | unsigned cflag; | |
997 | int baud, bits, xdiv, tmp; | |
998 | u16 tmxbr, scxctr; | |
999 | u8 tmxmd, battempt; | |
1000 | u8 div_timer = port->div_timer; | |
1001 | ||
1002 | _enter("%s{%lu}", port->name, ioclk); | |
1003 | ||
1004 | /* byte size and parity */ | |
1005 | cflag = new->c_cflag; | |
1006 | switch (cflag & CSIZE) { | |
1007 | case CS7: scxctr = SC01CTR_CLN_7BIT; bits = 9; break; | |
1008 | case CS8: scxctr = SC01CTR_CLN_8BIT; bits = 10; break; | |
1009 | default: scxctr = SC01CTR_CLN_8BIT; bits = 10; break; | |
1010 | } | |
1011 | ||
1012 | if (cflag & CSTOPB) { | |
1013 | scxctr |= SC01CTR_STB_2BIT; | |
1014 | bits++; | |
1015 | } | |
1016 | ||
1017 | if (cflag & PARENB) { | |
1018 | bits++; | |
1019 | if (cflag & PARODD) | |
1020 | scxctr |= SC01CTR_PB_ODD; | |
1021 | #ifdef CMSPAR | |
1022 | else if (cflag & CMSPAR) | |
1023 | scxctr |= SC01CTR_PB_FIXED0; | |
1024 | #endif | |
1025 | else | |
1026 | scxctr |= SC01CTR_PB_EVEN; | |
1027 | } | |
1028 | ||
1029 | /* Determine divisor based on baud rate */ | |
1030 | battempt = 0; | |
1031 | ||
368dd5ac AT |
1032 | switch (port->uart.line) { |
1033 | #ifdef CONFIG_MN10300_TTYSM0 | |
1034 | case 0: /* ttySM0 */ | |
1035 | #if defined(CONFIG_MN10300_TTYSM0_TIMER8) | |
1036 | scxctr |= SC0CTR_CK_TM8UFLOW_8; | |
1037 | #elif defined(CONFIG_MN10300_TTYSM0_TIMER0) | |
1038 | scxctr |= SC0CTR_CK_TM0UFLOW_8; | |
1039 | #elif defined(CONFIG_MN10300_TTYSM0_TIMER2) | |
b920de1b | 1040 | scxctr |= SC0CTR_CK_TM2UFLOW_8; |
368dd5ac AT |
1041 | #else |
1042 | #error "Unknown config for ttySM0" | |
1043 | #endif | |
1044 | break; | |
1045 | #endif /* CONFIG_MN10300_TTYSM0 */ | |
1046 | ||
1047 | #ifdef CONFIG_MN10300_TTYSM1 | |
1048 | case 1: /* ttySM1 */ | |
1049 | #if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) | |
1050 | #if defined(CONFIG_MN10300_TTYSM1_TIMER9) | |
1051 | scxctr |= SC1CTR_CK_TM9UFLOW_8; | |
1052 | #elif defined(CONFIG_MN10300_TTYSM1_TIMER3) | |
1053 | scxctr |= SC1CTR_CK_TM3UFLOW_8; | |
1054 | #else | |
1055 | #error "Unknown config for ttySM1" | |
1056 | #endif | |
1057 | #else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ | |
1058 | #if defined(CONFIG_MN10300_TTYSM1_TIMER12) | |
1059 | scxctr |= SC1CTR_CK_TM12UFLOW_8; | |
1060 | #else | |
1061 | #error "Unknown config for ttySM1" | |
1062 | #endif | |
1063 | #endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ | |
1064 | break; | |
1065 | #endif /* CONFIG_MN10300_TTYSM1 */ | |
1066 | ||
1067 | #ifdef CONFIG_MN10300_TTYSM2 | |
1068 | case 2: /* ttySM2 */ | |
1069 | #if defined(CONFIG_AM33_2) | |
1070 | #if defined(CONFIG_MN10300_TTYSM2_TIMER10) | |
1071 | scxctr |= SC2CTR_CK_TM10UFLOW; | |
1072 | #else | |
1073 | #error "Unknown config for ttySM2" | |
1074 | #endif | |
1075 | #else /* CONFIG_AM33_2 */ | |
1076 | #if defined(CONFIG_MN10300_TTYSM2_TIMER9) | |
1077 | scxctr |= SC2CTR_CK_TM9UFLOW_8; | |
1078 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER1) | |
1079 | scxctr |= SC2CTR_CK_TM1UFLOW_8; | |
1080 | #elif defined(CONFIG_MN10300_TTYSM2_TIMER3) | |
1081 | scxctr |= SC2CTR_CK_TM3UFLOW_8; | |
1082 | #else | |
1083 | #error "Unknown config for ttySM2" | |
1084 | #endif | |
1085 | #endif /* CONFIG_AM33_2 */ | |
1086 | break; | |
1087 | #endif /* CONFIG_MN10300_TTYSM2 */ | |
1088 | ||
1089 | default: | |
1090 | break; | |
1091 | } | |
b920de1b DH |
1092 | |
1093 | try_alternative: | |
1094 | baud = uart_get_baud_rate(&port->uart, new, old, 0, | |
1095 | port->ioclk / 8); | |
1096 | ||
1097 | _debug("ALT %d [baud %d]", battempt, baud); | |
1098 | ||
1099 | if (!baud) | |
1100 | baud = 9600; /* B0 transition handled in rs_set_termios */ | |
1101 | xdiv = 1; | |
1102 | if (baud == 134) { | |
1103 | baud = 269; /* 134 is really 134.5 */ | |
1104 | xdiv = 2; | |
1105 | } | |
1106 | ||
1107 | if (baud == 38400 && | |
1108 | (port->uart.flags & UPF_SPD_MASK) == UPF_SPD_CUST | |
1109 | ) { | |
1110 | _debug("CUSTOM %u", port->uart.custom_divisor); | |
1111 | ||
1112 | if (div_timer == MNSCx_DIV_TIMER_16BIT) { | |
1113 | if (port->uart.custom_divisor <= 65535) { | |
1114 | tmxmd = TM8MD_SRC_IOCLK; | |
1115 | tmxbr = port->uart.custom_divisor; | |
1116 | port->uart.uartclk = ioclk; | |
1117 | goto timer_okay; | |
1118 | } | |
1119 | if (port->uart.custom_divisor / 8 <= 65535) { | |
1120 | tmxmd = TM8MD_SRC_IOCLK_8; | |
1121 | tmxbr = port->uart.custom_divisor / 8; | |
1122 | port->uart.custom_divisor = tmxbr * 8; | |
1123 | port->uart.uartclk = ioclk / 8; | |
1124 | goto timer_okay; | |
1125 | } | |
1126 | if (port->uart.custom_divisor / 32 <= 65535) { | |
1127 | tmxmd = TM8MD_SRC_IOCLK_32; | |
1128 | tmxbr = port->uart.custom_divisor / 32; | |
1129 | port->uart.custom_divisor = tmxbr * 32; | |
1130 | port->uart.uartclk = ioclk / 32; | |
1131 | goto timer_okay; | |
1132 | } | |
1133 | ||
1134 | } else if (div_timer == MNSCx_DIV_TIMER_8BIT) { | |
1135 | if (port->uart.custom_divisor <= 255) { | |
1136 | tmxmd = TM2MD_SRC_IOCLK; | |
1137 | tmxbr = port->uart.custom_divisor; | |
1138 | port->uart.uartclk = ioclk; | |
1139 | goto timer_okay; | |
1140 | } | |
1141 | if (port->uart.custom_divisor / 8 <= 255) { | |
1142 | tmxmd = TM2MD_SRC_IOCLK_8; | |
1143 | tmxbr = port->uart.custom_divisor / 8; | |
1144 | port->uart.custom_divisor = tmxbr * 8; | |
1145 | port->uart.uartclk = ioclk / 8; | |
1146 | goto timer_okay; | |
1147 | } | |
1148 | if (port->uart.custom_divisor / 32 <= 255) { | |
1149 | tmxmd = TM2MD_SRC_IOCLK_32; | |
1150 | tmxbr = port->uart.custom_divisor / 32; | |
1151 | port->uart.custom_divisor = tmxbr * 32; | |
1152 | port->uart.uartclk = ioclk / 32; | |
1153 | goto timer_okay; | |
1154 | } | |
1155 | } | |
1156 | } | |
1157 | ||
1158 | switch (div_timer) { | |
1159 | case MNSCx_DIV_TIMER_16BIT: | |
1160 | port->uart.uartclk = ioclk; | |
1161 | tmxmd = TM8MD_SRC_IOCLK; | |
1162 | tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1; | |
1163 | if (tmp > 0 && tmp <= 65535) | |
1164 | goto timer_okay; | |
1165 | ||
1166 | port->uart.uartclk = ioclk / 8; | |
1167 | tmxmd = TM8MD_SRC_IOCLK_8; | |
1168 | tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1; | |
1169 | if (tmp > 0 && tmp <= 65535) | |
1170 | goto timer_okay; | |
1171 | ||
1172 | port->uart.uartclk = ioclk / 32; | |
1173 | tmxmd = TM8MD_SRC_IOCLK_32; | |
1174 | tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1; | |
1175 | if (tmp > 0 && tmp <= 65535) | |
1176 | goto timer_okay; | |
1177 | break; | |
1178 | ||
1179 | case MNSCx_DIV_TIMER_8BIT: | |
1180 | port->uart.uartclk = ioclk; | |
1181 | tmxmd = TM2MD_SRC_IOCLK; | |
1182 | tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1; | |
1183 | if (tmp > 0 && tmp <= 255) | |
1184 | goto timer_okay; | |
1185 | ||
1186 | port->uart.uartclk = ioclk / 8; | |
1187 | tmxmd = TM2MD_SRC_IOCLK_8; | |
1188 | tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1; | |
1189 | if (tmp > 0 && tmp <= 255) | |
1190 | goto timer_okay; | |
1191 | ||
1192 | port->uart.uartclk = ioclk / 32; | |
1193 | tmxmd = TM2MD_SRC_IOCLK_32; | |
1194 | tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1; | |
1195 | if (tmp > 0 && tmp <= 255) | |
1196 | goto timer_okay; | |
1197 | break; | |
1198 | ||
1199 | default: | |
1200 | BUG(); | |
1201 | return; | |
1202 | } | |
1203 | ||
1204 | /* refuse to change to a baud rate we can't support */ | |
1205 | _debug("CAN'T SUPPORT"); | |
1206 | ||
1207 | switch (battempt) { | |
1208 | case 0: | |
1209 | if (old) { | |
1210 | new->c_cflag &= ~CBAUD; | |
1211 | new->c_cflag |= (old->c_cflag & CBAUD); | |
1212 | battempt = 1; | |
1213 | goto try_alternative; | |
1214 | } | |
1215 | ||
1216 | case 1: | |
1217 | /* as a last resort, if the quotient is zero, default to 9600 | |
1218 | * bps */ | |
1219 | new->c_cflag &= ~CBAUD; | |
1220 | new->c_cflag |= B9600; | |
1221 | battempt = 2; | |
1222 | goto try_alternative; | |
1223 | ||
1224 | default: | |
1225 | /* hmmm... can't seem to support 9600 either | |
1226 | * - we could try iterating through the speeds we know about to | |
1227 | * find the lowest | |
1228 | */ | |
1229 | new->c_cflag &= ~CBAUD; | |
1230 | new->c_cflag |= B0; | |
1231 | ||
1232 | if (div_timer == MNSCx_DIV_TIMER_16BIT) | |
1233 | tmxmd = TM8MD_SRC_IOCLK_32; | |
1234 | else if (div_timer == MNSCx_DIV_TIMER_8BIT) | |
1235 | tmxmd = TM2MD_SRC_IOCLK_32; | |
1236 | tmxbr = 1; | |
1237 | ||
1238 | port->uart.uartclk = ioclk / 32; | |
1239 | break; | |
1240 | } | |
1241 | timer_okay: | |
1242 | ||
1243 | _debug("UARTCLK: %u / %hu", port->uart.uartclk, tmxbr); | |
1244 | ||
1245 | /* make the changes */ | |
1246 | spin_lock_irqsave(&port->uart.lock, flags); | |
1247 | ||
1248 | uart_update_timeout(&port->uart, new->c_cflag, baud); | |
1249 | ||
1250 | /* set the timer to produce the required baud rate */ | |
1251 | switch (div_timer) { | |
1252 | case MNSCx_DIV_TIMER_16BIT: | |
1253 | *port->_tmxmd = 0; | |
1254 | *port->_tmxbr = tmxbr; | |
1255 | *port->_tmxmd = TM8MD_INIT_COUNTER; | |
1256 | *port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE; | |
1257 | break; | |
1258 | ||
1259 | case MNSCx_DIV_TIMER_8BIT: | |
1260 | *port->_tmxmd = 0; | |
1261 | *(volatile u8 *) port->_tmxbr = (u8) tmxbr; | |
1262 | *port->_tmxmd = TM2MD_INIT_COUNTER; | |
1263 | *port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE; | |
1264 | break; | |
1265 | } | |
1266 | ||
1267 | /* CTS flow control flag and modem status interrupts */ | |
1268 | scxctr &= ~(SC2CTR_TWE | SC2CTR_TWS); | |
1269 | ||
1270 | if (port->type == PORT_MN10300_CTS && cflag & CRTSCTS) { | |
1271 | /* want to interrupt when CTS goes low if CTS is now | |
1272 | * high and vice versa | |
1273 | */ | |
1274 | port->tx_cts = *port->_status; | |
1275 | ||
1276 | if (port->tx_cts & SC2STR_CTS) | |
1277 | scxctr |= SC2CTR_TWE; | |
1278 | else | |
1279 | scxctr |= SC2CTR_TWE | SC2CTR_TWS; | |
1280 | } | |
1281 | ||
1282 | /* set up parity check flag */ | |
1283 | port->uart.read_status_mask = (1 << TTY_NORMAL) | (1 << TTY_OVERRUN); | |
1284 | if (new->c_iflag & INPCK) | |
1285 | port->uart.read_status_mask |= | |
1286 | (1 << TTY_PARITY) | (1 << TTY_FRAME); | |
1287 | if (new->c_iflag & (BRKINT | PARMRK)) | |
1288 | port->uart.read_status_mask |= (1 << TTY_BREAK); | |
1289 | ||
1290 | /* characters to ignore */ | |
1291 | port->uart.ignore_status_mask = 0; | |
1292 | if (new->c_iflag & IGNPAR) | |
1293 | port->uart.ignore_status_mask |= | |
1294 | (1 << TTY_PARITY) | (1 << TTY_FRAME); | |
1295 | if (new->c_iflag & IGNBRK) { | |
1296 | port->uart.ignore_status_mask |= (1 << TTY_BREAK); | |
1297 | /* | |
1298 | * If we're ignoring parity and break indicators, | |
1299 | * ignore overruns to (for real raw support). | |
1300 | */ | |
1301 | if (new->c_iflag & IGNPAR) | |
1302 | port->uart.ignore_status_mask |= (1 << TTY_OVERRUN); | |
1303 | } | |
1304 | ||
1305 | /* Ignore all characters if CREAD is not set */ | |
1306 | if ((new->c_cflag & CREAD) == 0) | |
1307 | port->uart.ignore_status_mask |= (1 << TTY_NORMAL); | |
1308 | ||
1309 | scxctr |= *port->_control & (SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE); | |
1310 | *port->_control = scxctr; | |
1311 | ||
1312 | spin_unlock_irqrestore(&port->uart.lock, flags); | |
1313 | } | |
1314 | ||
1315 | /* | |
1316 | * set the terminal I/O parameters | |
1317 | */ | |
1318 | static void mn10300_serial_set_termios(struct uart_port *_port, | |
1319 | struct ktermios *new, | |
1320 | struct ktermios *old) | |
1321 | { | |
1322 | struct mn10300_serial_port *port = | |
1323 | container_of(_port, struct mn10300_serial_port, uart); | |
1324 | ||
1325 | _enter("%s,%p,%p", port->name, new, old); | |
1326 | ||
1327 | mn10300_serial_change_speed(port, new, old); | |
1328 | ||
1329 | /* handle turning off CRTSCTS */ | |
1330 | if (!(new->c_cflag & CRTSCTS)) { | |
1331 | u16 ctr = *port->_control; | |
1332 | ctr &= ~SC2CTR_TWE; | |
1333 | *port->_control = ctr; | |
1334 | } | |
368dd5ac AT |
1335 | |
1336 | /* change Transfer bit-order (LSB/MSB) */ | |
1337 | if (new->c_cflag & CODMSB) | |
1338 | *port->_control |= SC01CTR_OD_MSBFIRST; /* MSB MODE */ | |
1339 | else | |
1340 | *port->_control &= ~SC01CTR_OD_MSBFIRST; /* LSB MODE */ | |
b920de1b DH |
1341 | } |
1342 | ||
1343 | /* | |
1344 | * return description of port type | |
1345 | */ | |
1346 | static const char *mn10300_serial_type(struct uart_port *_port) | |
1347 | { | |
1348 | struct mn10300_serial_port *port = | |
1349 | container_of(_port, struct mn10300_serial_port, uart); | |
1350 | ||
1351 | if (port->uart.type == PORT_MN10300_CTS) | |
1352 | return "MN10300 SIF_CTS"; | |
1353 | ||
1354 | return "MN10300 SIF"; | |
1355 | } | |
1356 | ||
1357 | /* | |
1358 | * release I/O and memory regions in use by port | |
1359 | */ | |
1360 | static void mn10300_serial_release_port(struct uart_port *_port) | |
1361 | { | |
1362 | struct mn10300_serial_port *port = | |
1363 | container_of(_port, struct mn10300_serial_port, uart); | |
1364 | ||
1365 | _enter("%s", port->name); | |
1366 | ||
1367 | release_mem_region((unsigned long) port->_iobase, 16); | |
1368 | } | |
1369 | ||
1370 | /* | |
1371 | * request I/O and memory regions for port | |
1372 | */ | |
1373 | static int mn10300_serial_request_port(struct uart_port *_port) | |
1374 | { | |
1375 | struct mn10300_serial_port *port = | |
1376 | container_of(_port, struct mn10300_serial_port, uart); | |
1377 | ||
1378 | _enter("%s", port->name); | |
1379 | ||
1380 | request_mem_region((unsigned long) port->_iobase, 16, port->name); | |
1381 | return 0; | |
1382 | } | |
1383 | ||
1384 | /* | |
1385 | * configure the type and reserve the ports | |
1386 | */ | |
1387 | static void mn10300_serial_config_port(struct uart_port *_port, int type) | |
1388 | { | |
1389 | struct mn10300_serial_port *port = | |
1390 | container_of(_port, struct mn10300_serial_port, uart); | |
1391 | ||
1392 | _enter("%s", port->name); | |
1393 | ||
1394 | port->uart.type = PORT_MN10300; | |
1395 | ||
1396 | if (port->options & MNSCx_OPT_CTS) | |
1397 | port->uart.type = PORT_MN10300_CTS; | |
1398 | ||
1399 | mn10300_serial_request_port(_port); | |
1400 | } | |
1401 | ||
1402 | /* | |
1403 | * verify serial parameters are suitable for this port type | |
1404 | */ | |
1405 | static int mn10300_serial_verify_port(struct uart_port *_port, | |
1406 | struct serial_struct *ss) | |
1407 | { | |
1408 | struct mn10300_serial_port *port = | |
1409 | container_of(_port, struct mn10300_serial_port, uart); | |
1410 | void *mapbase = (void *) (unsigned long) port->uart.mapbase; | |
1411 | ||
1412 | _enter("%s", port->name); | |
1413 | ||
1414 | /* these things may not be changed */ | |
1415 | if (ss->irq != port->uart.irq || | |
1416 | ss->port != port->uart.iobase || | |
1417 | ss->io_type != port->uart.iotype || | |
1418 | ss->iomem_base != mapbase || | |
1419 | ss->iomem_reg_shift != port->uart.regshift || | |
1420 | ss->hub6 != port->uart.hub6 || | |
1421 | ss->xmit_fifo_size != port->uart.fifosize) | |
1422 | return -EINVAL; | |
1423 | ||
1424 | /* type may be changed on a port that supports CTS */ | |
1425 | if (ss->type != port->uart.type) { | |
1426 | if (!(port->options & MNSCx_OPT_CTS)) | |
1427 | return -EINVAL; | |
1428 | ||
1429 | if (ss->type != PORT_MN10300 && | |
1430 | ss->type != PORT_MN10300_CTS) | |
1431 | return -EINVAL; | |
1432 | } | |
1433 | ||
1434 | return 0; | |
1435 | } | |
1436 | ||
1437 | /* | |
1438 | * initialise the MN10300 on-chip UARTs | |
1439 | */ | |
1440 | static int __init mn10300_serial_init(void) | |
1441 | { | |
1442 | struct mn10300_serial_port *port; | |
1443 | int ret, i; | |
1444 | ||
1445 | printk(KERN_INFO "%s version %s (%s)\n", | |
1446 | serial_name, serial_version, serial_revdate); | |
1447 | ||
368dd5ac AT |
1448 | #if defined(CONFIG_MN10300_TTYSM2) && defined(CONFIG_AM33_2) |
1449 | { | |
1450 | int tmp; | |
1451 | SC2TIM = 8; /* make the baud base of timer 2 IOCLK/8 */ | |
1452 | tmp = SC2TIM; | |
1453 | } | |
b920de1b DH |
1454 | #endif |
1455 | ||
368dd5ac AT |
1456 | set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL), |
1457 | mn10300_serial_vdma_interrupt); | |
b920de1b DH |
1458 | |
1459 | ret = uart_register_driver(&mn10300_serial_driver); | |
1460 | if (!ret) { | |
1461 | for (i = 0 ; i < NR_PORTS ; i++) { | |
1462 | port = mn10300_serial_ports[i]; | |
1463 | if (!port || port->gdbstub) | |
1464 | continue; | |
1465 | ||
1466 | switch (port->clock_src) { | |
1467 | case MNSCx_CLOCK_SRC_IOCLK: | |
1468 | port->ioclk = MN10300_IOCLK; | |
1469 | break; | |
1470 | ||
1471 | #ifdef MN10300_IOBCLK | |
1472 | case MNSCx_CLOCK_SRC_IOBCLK: | |
1473 | port->ioclk = MN10300_IOBCLK; | |
1474 | break; | |
1475 | #endif | |
1476 | default: | |
1477 | BUG(); | |
1478 | } | |
1479 | ||
1480 | ret = uart_add_one_port(&mn10300_serial_driver, | |
1481 | &port->uart); | |
1482 | ||
1483 | if (ret < 0) { | |
1484 | _debug("ERROR %d", -ret); | |
1485 | break; | |
1486 | } | |
1487 | } | |
1488 | ||
1489 | if (ret) | |
1490 | uart_unregister_driver(&mn10300_serial_driver); | |
1491 | } | |
1492 | ||
1493 | return ret; | |
1494 | } | |
1495 | ||
1496 | __initcall(mn10300_serial_init); | |
1497 | ||
1498 | ||
1499 | #ifdef CONFIG_MN10300_TTYSM_CONSOLE | |
1500 | ||
1501 | /* | |
1502 | * print a string to the serial port without disturbing the real user of the | |
1503 | * port too much | |
1504 | * - the console must be locked by the caller | |
1505 | */ | |
1506 | static void mn10300_serial_console_write(struct console *co, | |
1507 | const char *s, unsigned count) | |
1508 | { | |
1509 | struct mn10300_serial_port *port; | |
1510 | unsigned i; | |
1511 | u16 scxctr, txicr, tmp; | |
1512 | u8 tmxmd; | |
1513 | ||
1514 | port = mn10300_serial_ports[co->index]; | |
1515 | ||
1516 | /* firstly hijack the serial port from the "virtual DMA" controller */ | |
368dd5ac | 1517 | arch_local_cli(); |
b920de1b | 1518 | txicr = *port->tx_icr; |
368dd5ac | 1519 | *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); |
b920de1b | 1520 | tmp = *port->tx_icr; |
368dd5ac | 1521 | arch_local_sti(); |
b920de1b DH |
1522 | |
1523 | /* the transmitter may be disabled */ | |
1524 | scxctr = *port->_control; | |
1525 | if (!(scxctr & SC01CTR_TXE)) { | |
1526 | /* restart the UART clock */ | |
1527 | tmxmd = *port->_tmxmd; | |
1528 | ||
1529 | switch (port->div_timer) { | |
1530 | case MNSCx_DIV_TIMER_16BIT: | |
1531 | *port->_tmxmd = 0; | |
1532 | *port->_tmxmd = TM8MD_INIT_COUNTER; | |
1533 | *port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE; | |
1534 | break; | |
1535 | ||
1536 | case MNSCx_DIV_TIMER_8BIT: | |
1537 | *port->_tmxmd = 0; | |
1538 | *port->_tmxmd = TM2MD_INIT_COUNTER; | |
1539 | *port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE; | |
1540 | break; | |
1541 | } | |
1542 | ||
1543 | /* enable the transmitter */ | |
1544 | *port->_control = (scxctr & ~SC01CTR_BKE) | SC01CTR_TXE; | |
1545 | ||
1546 | } else if (scxctr & SC01CTR_BKE) { | |
1547 | /* stop transmitting BREAK */ | |
1548 | *port->_control = (scxctr & ~SC01CTR_BKE); | |
1549 | } | |
1550 | ||
1551 | /* send the chars into the serial port (with LF -> LFCR conversion) */ | |
1552 | for (i = 0; i < count; i++) { | |
1553 | char ch = *s++; | |
1554 | ||
1555 | while (*port->_status & SC01STR_TBF) | |
1556 | continue; | |
1557 | *(u8 *) port->_txb = ch; | |
1558 | ||
1559 | if (ch == 0x0a) { | |
1560 | while (*port->_status & SC01STR_TBF) | |
1561 | continue; | |
1562 | *(u8 *) port->_txb = 0xd; | |
1563 | } | |
1564 | } | |
1565 | ||
1566 | /* can't let the transmitter be turned off if it's actually | |
1567 | * transmitting */ | |
1568 | while (*port->_status & (SC01STR_TXF | SC01STR_TBF)) | |
1569 | continue; | |
1570 | ||
1571 | /* disable the transmitter if we re-enabled it */ | |
1572 | if (!(scxctr & SC01CTR_TXE)) | |
1573 | *port->_control = scxctr; | |
1574 | ||
368dd5ac | 1575 | arch_local_cli(); |
b920de1b DH |
1576 | *port->tx_icr = txicr; |
1577 | tmp = *port->tx_icr; | |
368dd5ac | 1578 | arch_local_sti(); |
b920de1b DH |
1579 | } |
1580 | ||
1581 | /* | |
1582 | * set up a serial port as a console | |
1583 | * - construct a cflag setting for the first rs_open() | |
1584 | * - initialize the serial port | |
1585 | * - return non-zero if we didn't find a serial port. | |
1586 | */ | |
1587 | static int __init mn10300_serial_console_setup(struct console *co, | |
1588 | char *options) | |
1589 | { | |
1590 | struct mn10300_serial_port *port; | |
1591 | int i, parity = 'n', baud = 9600, bits = 8, flow = 0; | |
1592 | ||
1593 | for (i = 0 ; i < NR_PORTS ; i++) { | |
1594 | port = mn10300_serial_ports[i]; | |
1595 | if (port && !port->gdbstub && port->uart.line == co->index) | |
1596 | goto found_device; | |
1597 | } | |
1598 | ||
1599 | return -ENODEV; | |
1600 | ||
1601 | found_device: | |
1602 | switch (port->clock_src) { | |
1603 | case MNSCx_CLOCK_SRC_IOCLK: | |
1604 | port->ioclk = MN10300_IOCLK; | |
1605 | break; | |
1606 | ||
1607 | #ifdef MN10300_IOBCLK | |
1608 | case MNSCx_CLOCK_SRC_IOBCLK: | |
1609 | port->ioclk = MN10300_IOBCLK; | |
1610 | break; | |
1611 | #endif | |
1612 | default: | |
1613 | BUG(); | |
1614 | } | |
1615 | ||
1616 | if (options) | |
1617 | uart_parse_options(options, &baud, &parity, &bits, &flow); | |
1618 | ||
1619 | return uart_set_options(&port->uart, co, baud, parity, bits, flow); | |
1620 | } | |
1621 | ||
1622 | /* | |
1623 | * register console | |
1624 | */ | |
1625 | static int __init mn10300_serial_console_init(void) | |
1626 | { | |
1627 | register_console(&mn10300_serial_console); | |
1628 | return 0; | |
1629 | } | |
1630 | ||
1631 | console_initcall(mn10300_serial_console_init); | |
1632 | #endif |