aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-03-20 14:57:50 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-20 14:57:50 -0500
commitc4a1745aa09fc110afdefea0e5d025043e348bae (patch)
tree6d28dc3a0c1bf18437b3d49f28e5c81b850cdb2f /drivers/serial
parent88dcb91177cfa5b26143a29074389a2aa259c7cf (diff)
parentac0eb3eb7e54b700386068be025a43d2a3958ee5 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: (230 commits) [SPARC64]: Update defconfig. [SPARC64]: Fix 2 bugs in huge page support. [SPARC64]: CONFIG_BLK_DEV_RAM fix [SPARC64]: Optimized TSB table initialization. [SPARC64]: Allow CONFIG_MEMORY_HOTPLUG to build. [SPARC64]: Use SLAB caches for TSB tables. [SPARC64]: Don't kill the page allocator when growing a TSB. [SPARC64]: Randomize mm->mmap_base when PF_RANDOMIZE is set. [SPARC64]: Increase top of 32-bit process stack. [SPARC64]: Top-down address space allocation for 32-bit tasks. [SPARC64] bbc_i2c: Fix cpu check and add missing module license. [SPARC64]: Fix and re-enable dynamic TSB sizing. [SUNSU]: Fix missing spinlock initialization. [TG3]: Do not try to access NIC_SRAM_DATA_SIG on Sun parts. [SPARC64]: First cut at VIS simulator for Niagara. [SPARC64]: Fix system type in /proc/cpuinfo and remove bogus OBP check. [SPARC64]: Add SMT scheduling support for Niagara. [SPARC64]: Fix 32-bit truncation which broke sparsemem. [SPARC64]: Move over to sparsemem. [SPARC64]: Fix new context version SMP handling. ...
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/Kconfig7
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/sunhv.c550
-rw-r--r--drivers/serial/sunsab.c19
-rw-r--r--drivers/serial/sunsu.c26
-rw-r--r--drivers/serial/sunzilog.c35
6 files changed, 612 insertions, 26 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index b3c561abe3f6..89e5413cc2a3 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -582,6 +582,13 @@ config SERIAL_SUNSAB_CONSOLE
582 on your Sparc system as the console, you can do so by answering 582 on your Sparc system as the console, you can do so by answering
583 Y to this option. 583 Y to this option.
584 584
585config SERIAL_SUNHV
586 bool "Sun4v Hypervisor Console support"
587 depends on SPARC64
588 help
589 This driver supports the console device found on SUN4V Sparc
590 systems. Say Y if you want to be able to use this device.
591
585config SERIAL_IP22_ZILOG 592config SERIAL_IP22_ZILOG
586 tristate "IP22 Zilog8530 serial support" 593 tristate "IP22 Zilog8530 serial support"
587 depends on SGI_IP22 594 depends on SGI_IP22
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index eaf8e01db198..50c221af9e6d 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_SERIAL_PXA) += pxa.o
30obj-$(CONFIG_SERIAL_SA1100) += sa1100.o 30obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
31obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o 31obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
32obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o 32obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
33obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o
33obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o 34obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
34obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o 35obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
35obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o 36obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
new file mode 100644
index 000000000000..f137804b3133
--- /dev/null
+++ b/drivers/serial/sunhv.c
@@ -0,0 +1,550 @@
1/* sunhv.c: Serial driver for SUN4V hypervisor console.
2 *
3 * Copyright (C) 2006 David S. Miller (davem@davemloft.net)
4 */
5
6#include <linux/module.h>
7#include <linux/kernel.h>
8#include <linux/errno.h>
9#include <linux/tty.h>
10#include <linux/tty_flip.h>
11#include <linux/major.h>
12#include <linux/circ_buf.h>
13#include <linux/serial.h>
14#include <linux/sysrq.h>
15#include <linux/console.h>
16#include <linux/spinlock.h>
17#include <linux/slab.h>
18#include <linux/delay.h>
19#include <linux/init.h>
20
21#include <asm/hypervisor.h>
22#include <asm/spitfire.h>
23#include <asm/vdev.h>
24#include <asm/oplib.h>
25#include <asm/irq.h>
26
27#if defined(CONFIG_MAGIC_SYSRQ)
28#define SUPPORT_SYSRQ
29#endif
30
31#include <linux/serial_core.h>
32
33#include "suncore.h"
34
35#define CON_BREAK ((long)-1)
36#define CON_HUP ((long)-2)
37
38static inline long hypervisor_con_getchar(long *status)
39{
40 register unsigned long func asm("%o5");
41 register unsigned long arg0 asm("%o0");
42 register unsigned long arg1 asm("%o1");
43
44 func = HV_FAST_CONS_GETCHAR;
45 arg0 = 0;
46 arg1 = 0;
47 __asm__ __volatile__("ta %6"
48 : "=&r" (func), "=&r" (arg0), "=&r" (arg1)
49 : "0" (func), "1" (arg0), "2" (arg1),
50 "i" (HV_FAST_TRAP));
51
52 *status = arg0;
53
54 return (long) arg1;
55}
56
57static inline long hypervisor_con_putchar(long ch)
58{
59 register unsigned long func asm("%o5");
60 register unsigned long arg0 asm("%o0");
61
62 func = HV_FAST_CONS_PUTCHAR;
63 arg0 = ch;
64 __asm__ __volatile__("ta %4"
65 : "=&r" (func), "=&r" (arg0)
66 : "0" (func), "1" (arg0), "i" (HV_FAST_TRAP));
67
68 return (long) arg0;
69}
70
71#define IGNORE_BREAK 0x1
72#define IGNORE_ALL 0x2
73
74static int hung_up = 0;
75
76static struct tty_struct *receive_chars(struct uart_port *port, struct pt_regs *regs)
77{
78 struct tty_struct *tty = NULL;
79 int saw_console_brk = 0;
80 int limit = 10000;
81
82 if (port->info != NULL) /* Unopened serial console */
83 tty = port->info->tty;
84
85 while (limit-- > 0) {
86 long status;
87 long c = hypervisor_con_getchar(&status);
88 unsigned char flag;
89
90 if (status == HV_EWOULDBLOCK)
91 break;
92
93 if (c == CON_BREAK) {
94 if (uart_handle_break(port))
95 continue;
96 saw_console_brk = 1;
97 c = 0;
98 }
99
100 if (c == CON_HUP) {
101 hung_up = 1;
102 uart_handle_dcd_change(port, 0);
103 } else if (hung_up) {
104 hung_up = 0;
105 uart_handle_dcd_change(port, 1);
106 }
107
108 if (tty == NULL) {
109 uart_handle_sysrq_char(port, c, regs);
110 continue;
111 }
112
113 flag = TTY_NORMAL;
114 port->icount.rx++;
115 if (c == CON_BREAK) {
116 port->icount.brk++;
117 if (uart_handle_break(port))
118 continue;
119 flag = TTY_BREAK;
120 }
121
122 if (uart_handle_sysrq_char(port, c, regs))
123 continue;
124
125 if ((port->ignore_status_mask & IGNORE_ALL) ||
126 ((port->ignore_status_mask & IGNORE_BREAK) &&
127 (c == CON_BREAK)))
128 continue;
129
130 tty_insert_flip_char(tty, c, flag);
131 }
132
133 if (saw_console_brk)
134 sun_do_break();
135
136 return tty;
137}
138
139static void transmit_chars(struct uart_port *port)
140{
141 struct circ_buf *xmit;
142
143 if (!port->info)
144 return;
145
146 xmit = &port->info->xmit;
147 if (uart_circ_empty(xmit) || uart_tx_stopped(port))
148 return;
149
150 while (!uart_circ_empty(xmit)) {
151 long status = hypervisor_con_putchar(xmit->buf[xmit->tail]);
152
153 if (status != HV_EOK)
154 break;
155
156 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
157 port->icount.tx++;
158 }
159
160 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
161 uart_write_wakeup(port);
162}
163
164static irqreturn_t sunhv_interrupt(int irq, void *dev_id, struct pt_regs *regs)
165{
166 struct uart_port *port = dev_id;
167 struct tty_struct *tty;
168 unsigned long flags;
169
170 spin_lock_irqsave(&port->lock, flags);
171 tty = receive_chars(port, regs);
172 transmit_chars(port);
173 spin_unlock_irqrestore(&port->lock, flags);
174
175 if (tty)
176 tty_flip_buffer_push(tty);
177
178 return IRQ_HANDLED;
179}
180
181/* port->lock is not held. */
182static unsigned int sunhv_tx_empty(struct uart_port *port)
183{
184 /* Transmitter is always empty for us. If the circ buffer
185 * is non-empty or there is an x_char pending, our caller
186 * will do the right thing and ignore what we return here.
187 */
188 return TIOCSER_TEMT;
189}
190
191/* port->lock held by caller. */
192static void sunhv_set_mctrl(struct uart_port *port, unsigned int mctrl)
193{
194 return;
195}
196
197/* port->lock is held by caller and interrupts are disabled. */
198static unsigned int sunhv_get_mctrl(struct uart_port *port)
199{
200 return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS;
201}
202
203/* port->lock held by caller. */
204static void sunhv_stop_tx(struct uart_port *port)
205{
206 return;
207}
208
209/* port->lock held by caller. */
210static void sunhv_start_tx(struct uart_port *port)
211{
212 struct circ_buf *xmit = &port->info->xmit;
213
214 while (!uart_circ_empty(xmit)) {
215 long status = hypervisor_con_putchar(xmit->buf[xmit->tail]);
216
217 if (status != HV_EOK)
218 break;
219
220 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
221 port->icount.tx++;
222 }
223}
224
225/* port->lock is not held. */
226static void sunhv_send_xchar(struct uart_port *port, char ch)
227{
228 unsigned long flags;
229 int limit = 10000;
230
231 spin_lock_irqsave(&port->lock, flags);
232
233 while (limit-- > 0) {
234 long status = hypervisor_con_putchar(ch);
235 if (status == HV_EOK)
236 break;
237 }
238
239 spin_unlock_irqrestore(&port->lock, flags);
240}
241
242/* port->lock held by caller. */
243static void sunhv_stop_rx(struct uart_port *port)
244{
245}
246
247/* port->lock held by caller. */
248static void sunhv_enable_ms(struct uart_port *port)
249{
250}
251
252/* port->lock is not held. */
253static void sunhv_break_ctl(struct uart_port *port, int break_state)
254{
255 if (break_state) {
256 unsigned long flags;
257 int limit = 1000000;
258
259 spin_lock_irqsave(&port->lock, flags);
260
261 while (limit-- > 0) {
262 long status = hypervisor_con_putchar(CON_BREAK);
263 if (status == HV_EOK)
264 break;
265 udelay(2);
266 }
267
268 spin_unlock_irqrestore(&port->lock, flags);
269 }
270}
271
272/* port->lock is not held. */
273static int sunhv_startup(struct uart_port *port)
274{
275 return 0;
276}
277
278/* port->lock is not held. */
279static void sunhv_shutdown(struct uart_port *port)
280{
281}
282
283/* port->lock is not held. */
284static void sunhv_set_termios(struct uart_port *port, struct termios *termios,
285 struct termios *old)
286{
287 unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
288 unsigned int quot = uart_get_divisor(port, baud);
289 unsigned int iflag, cflag;
290 unsigned long flags;
291
292 spin_lock_irqsave(&port->lock, flags);
293
294 iflag = termios->c_iflag;
295 cflag = termios->c_cflag;
296
297 port->ignore_status_mask = 0;
298 if (iflag & IGNBRK)
299 port->ignore_status_mask |= IGNORE_BREAK;
300 if ((cflag & CREAD) == 0)
301 port->ignore_status_mask |= IGNORE_ALL;
302
303 /* XXX */
304 uart_update_timeout(port, cflag,
305 (port->uartclk / (16 * quot)));
306
307 spin_unlock_irqrestore(&port->lock, flags);
308}
309
310static const char *sunhv_type(struct uart_port *port)
311{
312 return "SUN4V HCONS";
313}
314
315static void sunhv_release_port(struct uart_port *port)
316{
317}
318
319static int sunhv_request_port(struct uart_port *port)
320{
321 return 0;
322}
323
324static void sunhv_config_port(struct uart_port *port, int flags)
325{
326}
327
328static int sunhv_verify_port(struct uart_port *port, struct serial_struct *ser)
329{
330 return -EINVAL;
331}
332
333static struct uart_ops sunhv_pops = {
334 .tx_empty = sunhv_tx_empty,
335 .set_mctrl = sunhv_set_mctrl,
336 .get_mctrl = sunhv_get_mctrl,
337 .stop_tx = sunhv_stop_tx,
338 .start_tx = sunhv_start_tx,
339 .send_xchar = sunhv_send_xchar,
340 .stop_rx = sunhv_stop_rx,
341 .enable_ms = sunhv_enable_ms,
342 .break_ctl = sunhv_break_ctl,
343 .startup = sunhv_startup,
344 .shutdown = sunhv_shutdown,
345 .set_termios = sunhv_set_termios,
346 .type = sunhv_type,
347 .release_port = sunhv_release_port,
348 .request_port = sunhv_request_port,
349 .config_port = sunhv_config_port,
350 .verify_port = sunhv_verify_port,
351};
352
353static struct uart_driver sunhv_reg = {
354 .owner = THIS_MODULE,
355 .driver_name = "serial",
356 .devfs_name = "tts/",
357 .dev_name = "ttyS",
358 .major = TTY_MAJOR,
359};
360
361static struct uart_port *sunhv_port;
362
363static inline void sunhv_console_putchar(struct uart_port *port, char c)
364{
365 unsigned long flags;
366 int limit = 1000000;
367
368 spin_lock_irqsave(&port->lock, flags);
369
370 while (limit-- > 0) {
371 long status = hypervisor_con_putchar(c);
372 if (status == HV_EOK)
373 break;
374 udelay(2);
375 }
376
377 spin_unlock_irqrestore(&port->lock, flags);
378}
379
380static void sunhv_console_write(struct console *con, const char *s, unsigned n)
381{
382 struct uart_port *port = sunhv_port;
383 int i;
384
385 for (i = 0; i < n; i++) {
386 if (*s == '\n')
387 sunhv_console_putchar(port, '\r');
388 sunhv_console_putchar(port, *s++);
389 }
390}
391
392static struct console sunhv_console = {
393 .name = "ttyHV",
394 .write = sunhv_console_write,
395 .device = uart_console_device,
396 .flags = CON_PRINTBUFFER,
397 .index = -1,
398 .data = &sunhv_reg,
399};
400
401static inline struct console *SUNHV_CONSOLE(void)
402{
403 if (con_is_present())
404 return NULL;
405
406 sunhv_console.index = 0;
407
408 return &sunhv_console;
409}
410
411static int __init hv_console_compatible(char *buf, int len)
412{
413 while (len) {
414 int this_len;
415
416 if (!strcmp(buf, "qcn"))
417 return 1;
418
419 this_len = strlen(buf) + 1;
420
421 buf += this_len;
422 len -= this_len;
423 }
424
425 return 0;
426}
427
428static unsigned int __init get_interrupt(void)
429{
430 const char *cons_str = "console";
431 const char *compat_str = "compatible";
432 int node = prom_getchild(sun4v_vdev_root);
433 char buf[64];
434 int err, len;
435
436 node = prom_searchsiblings(node, cons_str);
437 if (!node)
438 return 0;
439
440 len = prom_getproplen(node, compat_str);
441 if (len == 0 || len == -1)
442 return 0;
443
444 err = prom_getproperty(node, compat_str, buf, 64);
445 if (err == -1)
446 return 0;
447
448 if (!hv_console_compatible(buf, len))
449 return 0;
450
451 /* Ok, the this is the OBP node for the sun4v hypervisor
452 * console device. Decode the interrupt.
453 */
454 return sun4v_vdev_device_interrupt(node);
455}
456
457static int __init sunhv_init(void)
458{
459 struct uart_port *port;
460 int ret;
461
462 if (tlb_type != hypervisor)
463 return -ENODEV;
464
465 port = kmalloc(sizeof(struct uart_port), GFP_KERNEL);
466 if (unlikely(!port))
467 return -ENOMEM;
468
469 memset(port, 0, sizeof(struct uart_port));
470
471 port->line = 0;
472 port->ops = &sunhv_pops;
473 port->type = PORT_SUNHV;
474 port->uartclk = ( 29491200 / 16 ); /* arbitrary */
475
476 /* Set this just to make uart_configure_port() happy. */
477 port->membase = (unsigned char __iomem *) __pa(port);
478
479 port->irq = get_interrupt();
480 if (!port->irq) {
481 kfree(port);
482 return -ENODEV;
483 }
484
485 sunhv_reg.minor = sunserial_current_minor;
486 sunhv_reg.nr = 1;
487
488 ret = uart_register_driver(&sunhv_reg);
489 if (ret < 0) {
490 printk(KERN_ERR "SUNHV: uart_register_driver() failed %d\n",
491 ret);
492 kfree(port);
493
494 return ret;
495 }
496
497 sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64;
498 sunserial_current_minor += 1;
499
500 sunhv_reg.cons = SUNHV_CONSOLE();
501
502 sunhv_port = port;
503
504 ret = uart_add_one_port(&sunhv_reg, port);
505 if (ret < 0) {
506 printk(KERN_ERR "SUNHV: uart_add_one_port() failed %d\n", ret);
507 sunserial_current_minor -= 1;
508 uart_unregister_driver(&sunhv_reg);
509 kfree(port);
510 sunhv_port = NULL;
511 return -ENODEV;
512 }
513
514 if (request_irq(port->irq, sunhv_interrupt,
515 SA_SHIRQ, "serial(sunhv)", port)) {
516 printk(KERN_ERR "sunhv: Cannot register IRQ\n");
517 uart_remove_one_port(&sunhv_reg, port);
518 sunserial_current_minor -= 1;
519 uart_unregister_driver(&sunhv_reg);
520 kfree(port);
521 sunhv_port = NULL;
522 return -ENODEV;
523 }
524
525 return 0;
526}
527
528static void __exit sunhv_exit(void)
529{
530 struct uart_port *port = sunhv_port;
531
532 BUG_ON(!port);
533
534 free_irq(port->irq, port);
535
536 uart_remove_one_port(&sunhv_reg, port);
537 sunserial_current_minor -= 1;
538
539 uart_unregister_driver(&sunhv_reg);
540
541 kfree(sunhv_port);
542 sunhv_port = NULL;
543}
544
545module_init(sunhv_init);
546module_exit(sunhv_exit);
547
548MODULE_AUTHOR("David S. Miller");
549MODULE_DESCRIPTION("SUN4V Hypervisor console driver")
550MODULE_LICENSE("GPL");
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 85664228a0b6..a2fb0c2fb121 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -955,14 +955,13 @@ static struct console sunsab_console = {
955 .index = -1, 955 .index = -1,
956 .data = &sunsab_reg, 956 .data = &sunsab_reg,
957}; 957};
958#define SUNSAB_CONSOLE (&sunsab_console)
959 958
960static void __init sunsab_console_init(void) 959static inline struct console *SUNSAB_CONSOLE(void)
961{ 960{
962 int i; 961 int i;
963 962
964 if (con_is_present()) 963 if (con_is_present())
965 return; 964 return NULL;
966 965
967 for (i = 0; i < num_channels; i++) { 966 for (i = 0; i < num_channels; i++) {
968 int this_minor = sunsab_reg.minor + i; 967 int this_minor = sunsab_reg.minor + i;
@@ -971,13 +970,14 @@ static void __init sunsab_console_init(void)
971 break; 970 break;
972 } 971 }
973 if (i == num_channels) 972 if (i == num_channels)
974 return; 973 return NULL;
975 974
976 sunsab_console.index = i; 975 sunsab_console.index = i;
977 register_console(&sunsab_console); 976
977 return &sunsab_console;
978} 978}
979#else 979#else
980#define SUNSAB_CONSOLE (NULL) 980#define SUNSAB_CONSOLE() (NULL)
981#define sunsab_console_init() do { } while (0) 981#define sunsab_console_init() do { } while (0)
982#endif 982#endif
983 983
@@ -1124,7 +1124,6 @@ static int __init sunsab_init(void)
1124 1124
1125 sunsab_reg.minor = sunserial_current_minor; 1125 sunsab_reg.minor = sunserial_current_minor;
1126 sunsab_reg.nr = num_channels; 1126 sunsab_reg.nr = num_channels;
1127 sunsab_reg.cons = SUNSAB_CONSOLE;
1128 1127
1129 ret = uart_register_driver(&sunsab_reg); 1128 ret = uart_register_driver(&sunsab_reg);
1130 if (ret < 0) { 1129 if (ret < 0) {
@@ -1143,10 +1142,12 @@ static int __init sunsab_init(void)
1143 return ret; 1142 return ret;
1144 } 1143 }
1145 1144
1145 sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64;
1146
1147 sunsab_reg.cons = SUNSAB_CONSOLE();
1148
1146 sunserial_current_minor += num_channels; 1149 sunserial_current_minor += num_channels;
1147 1150
1148 sunsab_console_init();
1149
1150 for (i = 0; i < num_channels; i++) { 1151 for (i = 0; i < num_channels; i++) {
1151 struct uart_sunsab_port *up = &sunsab_ports[i]; 1152 struct uart_sunsab_port *up = &sunsab_ports[i];
1152 1153
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 4e453fa966ae..46c44b83f57c 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1280,6 +1280,7 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel)
1280 struct serio *serio; 1280 struct serio *serio;
1281#endif 1281#endif
1282 1282
1283 spin_lock_init(&up->port.lock);
1283 up->port.line = channel; 1284 up->port.line = channel;
1284 up->port.type = PORT_UNKNOWN; 1285 up->port.type = PORT_UNKNOWN;
1285 up->port.uartclk = (SU_BASE_BAUD * 16); 1286 up->port.uartclk = (SU_BASE_BAUD * 16);
@@ -1464,18 +1465,17 @@ static struct console sunsu_cons = {
1464 .index = -1, 1465 .index = -1,
1465 .data = &sunsu_reg, 1466 .data = &sunsu_reg,
1466}; 1467};
1467#define SUNSU_CONSOLE (&sunsu_cons)
1468 1468
1469/* 1469/*
1470 * Register console. 1470 * Register console.
1471 */ 1471 */
1472 1472
1473static int __init sunsu_serial_console_init(void) 1473static inline struct console *SUNSU_CONSOLE(void)
1474{ 1474{
1475 int i; 1475 int i;
1476 1476
1477 if (con_is_present()) 1477 if (con_is_present())
1478 return 0; 1478 return NULL;
1479 1479
1480 for (i = 0; i < UART_NR; i++) { 1480 for (i = 0; i < UART_NR; i++) {
1481 int this_minor = sunsu_reg.minor + i; 1481 int this_minor = sunsu_reg.minor + i;
@@ -1484,16 +1484,16 @@ static int __init sunsu_serial_console_init(void)
1484 break; 1484 break;
1485 } 1485 }
1486 if (i == UART_NR) 1486 if (i == UART_NR)
1487 return 0; 1487 return NULL;
1488 if (sunsu_ports[i].port_node == 0) 1488 if (sunsu_ports[i].port_node == 0)
1489 return 0; 1489 return NULL;
1490 1490
1491 sunsu_cons.index = i; 1491 sunsu_cons.index = i;
1492 register_console(&sunsu_cons); 1492
1493 return 0; 1493 return &sunsu_cons;
1494} 1494}
1495#else 1495#else
1496#define SUNSU_CONSOLE (NULL) 1496#define SUNSU_CONSOLE() (NULL)
1497#define sunsu_serial_console_init() do { } while (0) 1497#define sunsu_serial_console_init() do { } while (0)
1498#endif 1498#endif
1499 1499
@@ -1510,6 +1510,7 @@ static int __init sunsu_serial_init(void)
1510 up->su_type == SU_PORT_KBD) 1510 up->su_type == SU_PORT_KBD)
1511 continue; 1511 continue;
1512 1512
1513 spin_lock_init(&up->port.lock);
1513 up->port.flags |= UPF_BOOT_AUTOCONF; 1514 up->port.flags |= UPF_BOOT_AUTOCONF;
1514 up->port.type = PORT_UNKNOWN; 1515 up->port.type = PORT_UNKNOWN;
1515 up->port.uartclk = (SU_BASE_BAUD * 16); 1516 up->port.uartclk = (SU_BASE_BAUD * 16);
@@ -1523,16 +1524,19 @@ static int __init sunsu_serial_init(void)
1523 } 1524 }
1524 1525
1525 sunsu_reg.minor = sunserial_current_minor; 1526 sunsu_reg.minor = sunserial_current_minor;
1526 sunserial_current_minor += instance;
1527 1527
1528 sunsu_reg.nr = instance; 1528 sunsu_reg.nr = instance;
1529 sunsu_reg.cons = SUNSU_CONSOLE;
1530 1529
1531 ret = uart_register_driver(&sunsu_reg); 1530 ret = uart_register_driver(&sunsu_reg);
1532 if (ret < 0) 1531 if (ret < 0)
1533 return ret; 1532 return ret;
1534 1533
1535 sunsu_serial_console_init(); 1534 sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64;
1535
1536 sunserial_current_minor += instance;
1537
1538 sunsu_reg.cons = SUNSU_CONSOLE();
1539
1536 for (i = 0; i < UART_NR; i++) { 1540 for (i = 0; i < UART_NR; i++) {
1537 struct uart_sunsu_port *up = &sunsu_ports[i]; 1541 struct uart_sunsu_port *up = &sunsu_ports[i];
1538 1542
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 5cc4d4c2935c..10b35c6f287d 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1390,7 +1390,6 @@ static struct console sunzilog_console = {
1390 .index = -1, 1390 .index = -1,
1391 .data = &sunzilog_reg, 1391 .data = &sunzilog_reg,
1392}; 1392};
1393#define SUNZILOG_CONSOLE (&sunzilog_console)
1394 1393
1395static int __init sunzilog_console_init(void) 1394static int __init sunzilog_console_init(void)
1396{ 1395{
@@ -1413,8 +1412,31 @@ static int __init sunzilog_console_init(void)
1413 register_console(&sunzilog_console); 1412 register_console(&sunzilog_console);
1414 return 0; 1413 return 0;
1415} 1414}
1415
1416static inline struct console *SUNZILOG_CONSOLE(void)
1417{
1418 int i;
1419
1420 if (con_is_present())
1421 return NULL;
1422
1423 for (i = 0; i < NUM_CHANNELS; i++) {
1424 int this_minor = sunzilog_reg.minor + i;
1425
1426 if ((this_minor - 64) == (serial_console - 1))
1427 break;
1428 }
1429 if (i == NUM_CHANNELS)
1430 return NULL;
1431
1432 sunzilog_console.index = i;
1433 sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS;
1434
1435 return &sunzilog_console;
1436}
1437
1416#else 1438#else
1417#define SUNZILOG_CONSOLE (NULL) 1439#define SUNZILOG_CONSOLE() (NULL)
1418#define sunzilog_console_init() do { } while (0) 1440#define sunzilog_console_init() do { } while (0)
1419#endif 1441#endif
1420 1442
@@ -1666,14 +1688,15 @@ static int __init sunzilog_ports_init(void)
1666 } 1688 }
1667 1689
1668 sunzilog_reg.nr = uart_count; 1690 sunzilog_reg.nr = uart_count;
1669 sunzilog_reg.cons = SUNZILOG_CONSOLE;
1670
1671 sunzilog_reg.minor = sunserial_current_minor; 1691 sunzilog_reg.minor = sunserial_current_minor;
1672 sunserial_current_minor += uart_count;
1673 1692
1674 ret = uart_register_driver(&sunzilog_reg); 1693 ret = uart_register_driver(&sunzilog_reg);
1675 if (ret == 0) { 1694 if (ret == 0) {
1676 sunzilog_console_init(); 1695 sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
1696 sunzilog_reg.cons = SUNZILOG_CONSOLE();
1697
1698 sunserial_current_minor += uart_count;
1699
1677 for (i = 0; i < NUM_CHANNELS; i++) { 1700 for (i = 0; i < NUM_CHANNELS; i++) {
1678 struct uart_sunzilog_port *up = &sunzilog_port_table[i]; 1701 struct uart_sunzilog_port *up = &sunzilog_port_table[i];
1679 1702