diff options
-rw-r--r-- | drivers/serial/dz.c | 289 |
1 files changed, 188 insertions, 101 deletions
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index c054c1bd8b24..116211fcd36f 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/errno.h> | 39 | #include <linux/errno.h> |
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
42 | #include <linux/ioport.h> | ||
42 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
43 | #include <linux/major.h> | 44 | #include <linux/major.h> |
44 | #include <linux/module.h> | 45 | #include <linux/module.h> |
@@ -47,7 +48,9 @@ | |||
47 | #include <linux/sysrq.h> | 48 | #include <linux/sysrq.h> |
48 | #include <linux/tty.h> | 49 | #include <linux/tty.h> |
49 | 50 | ||
51 | #include <asm/atomic.h> | ||
50 | #include <asm/bootinfo.h> | 52 | #include <asm/bootinfo.h> |
53 | #include <asm/io.h> | ||
51 | #include <asm/system.h> | 54 | #include <asm/system.h> |
52 | 55 | ||
53 | #include <asm/dec/interrupts.h> | 56 | #include <asm/dec/interrupts.h> |
@@ -55,18 +58,32 @@ | |||
55 | #include <asm/dec/kn02.h> | 58 | #include <asm/dec/kn02.h> |
56 | #include <asm/dec/machtype.h> | 59 | #include <asm/dec/machtype.h> |
57 | #include <asm/dec/prom.h> | 60 | #include <asm/dec/prom.h> |
61 | #include <asm/dec/system.h> | ||
58 | 62 | ||
59 | #include "dz.h" | 63 | #include "dz.h" |
60 | 64 | ||
61 | static char *dz_name = "DECstation DZ serial driver version "; | 65 | |
62 | static char *dz_version = "1.03"; | 66 | MODULE_DESCRIPTION("DECstation DZ serial driver"); |
67 | MODULE_LICENSE("GPL"); | ||
68 | |||
69 | |||
70 | static char dz_name[] __initdata = "DECstation DZ serial driver version "; | ||
71 | static char dz_version[] __initdata = "1.04"; | ||
63 | 72 | ||
64 | struct dz_port { | 73 | struct dz_port { |
74 | struct dz_mux *mux; | ||
65 | struct uart_port port; | 75 | struct uart_port port; |
66 | unsigned int cflag; | 76 | unsigned int cflag; |
67 | }; | 77 | }; |
68 | 78 | ||
69 | static struct dz_port dz_ports[DZ_NB_PORT]; | 79 | struct dz_mux { |
80 | struct dz_port dport[DZ_NB_PORT]; | ||
81 | atomic_t map_guard; | ||
82 | atomic_t irq_guard; | ||
83 | int initialised; | ||
84 | }; | ||
85 | |||
86 | static struct dz_mux dz_mux; | ||
70 | 87 | ||
71 | static inline struct dz_port *to_dport(struct uart_port *uport) | 88 | static inline struct dz_port *to_dport(struct uart_port *uport) |
72 | { | 89 | { |
@@ -82,21 +99,18 @@ static inline struct dz_port *to_dport(struct uart_port *uport) | |||
82 | * ------------------------------------------------------------ | 99 | * ------------------------------------------------------------ |
83 | */ | 100 | */ |
84 | 101 | ||
85 | static inline unsigned short dz_in(struct dz_port *dport, unsigned offset) | 102 | static u16 dz_in(struct dz_port *dport, unsigned offset) |
86 | { | 103 | { |
87 | volatile unsigned short *addr = | 104 | void __iomem *addr = dport->port.membase + offset; |
88 | (volatile unsigned short *) (dport->port.membase + offset); | ||
89 | 105 | ||
90 | return *addr; | 106 | return readw(addr); |
91 | } | 107 | } |
92 | 108 | ||
93 | static inline void dz_out(struct dz_port *dport, unsigned offset, | 109 | static void dz_out(struct dz_port *dport, unsigned offset, u16 value) |
94 | unsigned short value) | ||
95 | { | 110 | { |
96 | volatile unsigned short *addr = | 111 | void __iomem *addr = dport->port.membase + offset; |
97 | (volatile unsigned short *) (dport->port.membase + offset); | ||
98 | 112 | ||
99 | *addr = value; | 113 | writew(value, addr); |
100 | } | 114 | } |
101 | 115 | ||
102 | /* | 116 | /* |
@@ -112,7 +126,7 @@ static inline void dz_out(struct dz_port *dport, unsigned offset, | |||
112 | static void dz_stop_tx(struct uart_port *uport) | 126 | static void dz_stop_tx(struct uart_port *uport) |
113 | { | 127 | { |
114 | struct dz_port *dport = to_dport(uport); | 128 | struct dz_port *dport = to_dport(uport); |
115 | unsigned short tmp, mask = 1 << dport->port.line; | 129 | u16 tmp, mask = 1 << dport->port.line; |
116 | 130 | ||
117 | tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ | 131 | tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ |
118 | tmp &= ~mask; /* clear the TX flag */ | 132 | tmp &= ~mask; /* clear the TX flag */ |
@@ -122,7 +136,7 @@ static void dz_stop_tx(struct uart_port *uport) | |||
122 | static void dz_start_tx(struct uart_port *uport) | 136 | static void dz_start_tx(struct uart_port *uport) |
123 | { | 137 | { |
124 | struct dz_port *dport = to_dport(uport); | 138 | struct dz_port *dport = to_dport(uport); |
125 | unsigned short tmp, mask = 1 << dport->port.line; | 139 | u16 tmp, mask = 1 << dport->port.line; |
126 | 140 | ||
127 | tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ | 141 | tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ |
128 | tmp |= mask; /* set the TX flag */ | 142 | tmp |= mask; /* set the TX flag */ |
@@ -137,7 +151,7 @@ static void dz_stop_rx(struct uart_port *uport) | |||
137 | dz_out(dport, DZ_LPR, dport->cflag); | 151 | dz_out(dport, DZ_LPR, dport->cflag); |
138 | } | 152 | } |
139 | 153 | ||
140 | static void dz_enable_ms(struct uart_port *port) | 154 | static void dz_enable_ms(struct uart_port *uport) |
141 | { | 155 | { |
142 | /* nothing to do */ | 156 | /* nothing to do */ |
143 | } | 157 | } |
@@ -169,19 +183,19 @@ static void dz_enable_ms(struct uart_port *port) | |||
169 | * This routine deals with inputs from any lines. | 183 | * This routine deals with inputs from any lines. |
170 | * ------------------------------------------------------------ | 184 | * ------------------------------------------------------------ |
171 | */ | 185 | */ |
172 | static inline void dz_receive_chars(struct dz_port *dport_in) | 186 | static inline void dz_receive_chars(struct dz_mux *mux) |
173 | { | 187 | { |
174 | struct uart_port *uport; | 188 | struct uart_port *uport; |
175 | struct dz_port *dport; | 189 | struct dz_port *dport = &mux->dport[0]; |
176 | struct tty_struct *tty = NULL; | 190 | struct tty_struct *tty = NULL; |
177 | struct uart_icount *icount; | 191 | struct uart_icount *icount; |
178 | int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 }; | 192 | int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 }; |
179 | unsigned short status; | ||
180 | unsigned char ch, flag; | 193 | unsigned char ch, flag; |
194 | u16 status; | ||
181 | int i; | 195 | int i; |
182 | 196 | ||
183 | while ((status = dz_in(dport_in, DZ_RBUF)) & DZ_DVAL) { | 197 | while ((status = dz_in(dport, DZ_RBUF)) & DZ_DVAL) { |
184 | dport = &dz_ports[LINE(status)]; | 198 | dport = &mux->dport[LINE(status)]; |
185 | uport = &dport->port; | 199 | uport = &dport->port; |
186 | tty = uport->info->tty; /* point to the proper dev */ | 200 | tty = uport->info->tty; /* point to the proper dev */ |
187 | 201 | ||
@@ -235,7 +249,7 @@ static inline void dz_receive_chars(struct dz_port *dport_in) | |||
235 | } | 249 | } |
236 | for (i = 0; i < DZ_NB_PORT; i++) | 250 | for (i = 0; i < DZ_NB_PORT; i++) |
237 | if (lines_rx[i]) | 251 | if (lines_rx[i]) |
238 | tty_flip_buffer_push(dz_ports[i].port.info->tty); | 252 | tty_flip_buffer_push(mux->dport[i].port.info->tty); |
239 | } | 253 | } |
240 | 254 | ||
241 | /* | 255 | /* |
@@ -245,15 +259,15 @@ static inline void dz_receive_chars(struct dz_port *dport_in) | |||
245 | * This routine deals with outputs to any lines. | 259 | * This routine deals with outputs to any lines. |
246 | * ------------------------------------------------------------ | 260 | * ------------------------------------------------------------ |
247 | */ | 261 | */ |
248 | static inline void dz_transmit_chars(struct dz_port *dport_in) | 262 | static inline void dz_transmit_chars(struct dz_mux *mux) |
249 | { | 263 | { |
250 | struct dz_port *dport; | 264 | struct dz_port *dport = &mux->dport[0]; |
251 | struct circ_buf *xmit; | 265 | struct circ_buf *xmit; |
252 | unsigned short status; | ||
253 | unsigned char tmp; | 266 | unsigned char tmp; |
267 | u16 status; | ||
254 | 268 | ||
255 | status = dz_in(dport_in, DZ_CSR); | 269 | status = dz_in(dport, DZ_CSR); |
256 | dport = &dz_ports[LINE(status)]; | 270 | dport = &mux->dport[LINE(status)]; |
257 | xmit = &dport->port.info->xmit; | 271 | xmit = &dport->port.info->xmit; |
258 | 272 | ||
259 | if (dport->port.x_char) { /* XON/XOFF chars */ | 273 | if (dport->port.x_char) { /* XON/XOFF chars */ |
@@ -305,7 +319,7 @@ static inline void check_modem_status(struct dz_port *dport) | |||
305 | * 1. No status change interrupt; use a timer. | 319 | * 1. No status change interrupt; use a timer. |
306 | * 2. Handle the 3100/5000 as appropriate. --macro | 320 | * 2. Handle the 3100/5000 as appropriate. --macro |
307 | */ | 321 | */ |
308 | unsigned short status; | 322 | u16 status; |
309 | 323 | ||
310 | /* If not the modem line just return. */ | 324 | /* If not the modem line just return. */ |
311 | if (dport->port.line != DZ_MODEM) | 325 | if (dport->port.line != DZ_MODEM) |
@@ -326,19 +340,20 @@ static inline void check_modem_status(struct dz_port *dport) | |||
326 | * It deals with the multiple ports. | 340 | * It deals with the multiple ports. |
327 | * ------------------------------------------------------------ | 341 | * ------------------------------------------------------------ |
328 | */ | 342 | */ |
329 | static irqreturn_t dz_interrupt(int irq, void *dev) | 343 | static irqreturn_t dz_interrupt(int irq, void *dev_id) |
330 | { | 344 | { |
331 | struct dz_port *dport = dev; | 345 | struct dz_mux *mux = dev_id; |
332 | unsigned short status; | 346 | struct dz_port *dport = &mux->dport[0]; |
347 | u16 status; | ||
333 | 348 | ||
334 | /* get the reason why we just got an irq */ | 349 | /* get the reason why we just got an irq */ |
335 | status = dz_in(dport, DZ_CSR); | 350 | status = dz_in(dport, DZ_CSR); |
336 | 351 | ||
337 | if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE)) | 352 | if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE)) |
338 | dz_receive_chars(dport); | 353 | dz_receive_chars(mux); |
339 | 354 | ||
340 | if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE)) | 355 | if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE)) |
341 | dz_transmit_chars(dport); | 356 | dz_transmit_chars(mux); |
342 | 357 | ||
343 | return IRQ_HANDLED; | 358 | return IRQ_HANDLED; |
344 | } | 359 | } |
@@ -371,7 +386,7 @@ static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl) | |||
371 | * FIXME: Handle the 3100/5000 as appropriate. --macro | 386 | * FIXME: Handle the 3100/5000 as appropriate. --macro |
372 | */ | 387 | */ |
373 | struct dz_port *dport = to_dport(uport); | 388 | struct dz_port *dport = to_dport(uport); |
374 | unsigned short tmp; | 389 | u16 tmp; |
375 | 390 | ||
376 | if (dport->port.line == DZ_MODEM) { | 391 | if (dport->port.line == DZ_MODEM) { |
377 | tmp = dz_in(dport, DZ_TCR); | 392 | tmp = dz_in(dport, DZ_TCR); |
@@ -393,14 +408,29 @@ static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl) | |||
393 | static int dz_startup(struct uart_port *uport) | 408 | static int dz_startup(struct uart_port *uport) |
394 | { | 409 | { |
395 | struct dz_port *dport = to_dport(uport); | 410 | struct dz_port *dport = to_dport(uport); |
411 | struct dz_mux *mux = dport->mux; | ||
396 | unsigned long flags; | 412 | unsigned long flags; |
397 | unsigned short tmp; | 413 | int irq_guard; |
414 | int ret; | ||
415 | u16 tmp; | ||
416 | |||
417 | irq_guard = atomic_add_return(1, &mux->irq_guard); | ||
418 | if (irq_guard != 1) | ||
419 | return 0; | ||
420 | |||
421 | ret = request_irq(dport->port.irq, dz_interrupt, | ||
422 | IRQF_SHARED, "dz", mux); | ||
423 | if (ret) { | ||
424 | atomic_add(-1, &mux->irq_guard); | ||
425 | printk(KERN_ERR "dz: Cannot get IRQ %d!\n", dport->port.irq); | ||
426 | return ret; | ||
427 | } | ||
398 | 428 | ||
399 | spin_lock_irqsave(&dport->port.lock, flags); | 429 | spin_lock_irqsave(&dport->port.lock, flags); |
400 | 430 | ||
401 | /* enable the interrupt and the scanning */ | 431 | /* Enable interrupts. */ |
402 | tmp = dz_in(dport, DZ_CSR); | 432 | tmp = dz_in(dport, DZ_CSR); |
403 | tmp |= DZ_RIE | DZ_TIE | DZ_MSE; | 433 | tmp |= DZ_RIE | DZ_TIE; |
404 | dz_out(dport, DZ_CSR, tmp); | 434 | dz_out(dport, DZ_CSR, tmp); |
405 | 435 | ||
406 | spin_unlock_irqrestore(&dport->port.lock, flags); | 436 | spin_unlock_irqrestore(&dport->port.lock, flags); |
@@ -419,11 +449,24 @@ static int dz_startup(struct uart_port *uport) | |||
419 | static void dz_shutdown(struct uart_port *uport) | 449 | static void dz_shutdown(struct uart_port *uport) |
420 | { | 450 | { |
421 | struct dz_port *dport = to_dport(uport); | 451 | struct dz_port *dport = to_dport(uport); |
452 | struct dz_mux *mux = dport->mux; | ||
422 | unsigned long flags; | 453 | unsigned long flags; |
454 | int irq_guard; | ||
455 | u16 tmp; | ||
423 | 456 | ||
424 | spin_lock_irqsave(&dport->port.lock, flags); | 457 | spin_lock_irqsave(&dport->port.lock, flags); |
425 | dz_stop_tx(&dport->port); | 458 | dz_stop_tx(&dport->port); |
426 | spin_unlock_irqrestore(&dport->port.lock, flags); | 459 | spin_unlock_irqrestore(&dport->port.lock, flags); |
460 | |||
461 | irq_guard = atomic_add_return(-1, &mux->irq_guard); | ||
462 | if (!irq_guard) { | ||
463 | /* Disable interrupts. */ | ||
464 | tmp = dz_in(dport, DZ_CSR); | ||
465 | tmp &= ~(DZ_RIE | DZ_TIE); | ||
466 | dz_out(dport, DZ_CSR, tmp); | ||
467 | |||
468 | free_irq(dport->port.irq, mux); | ||
469 | } | ||
427 | } | 470 | } |
428 | 471 | ||
429 | /* | 472 | /* |
@@ -507,6 +550,24 @@ static int dz_encode_baud_rate(unsigned int baud) | |||
507 | } | 550 | } |
508 | } | 551 | } |
509 | 552 | ||
553 | |||
554 | static void dz_reset(struct dz_port *dport) | ||
555 | { | ||
556 | struct dz_mux *mux = dport->mux; | ||
557 | |||
558 | if (mux->initialised) | ||
559 | return; | ||
560 | |||
561 | dz_out(dport, DZ_CSR, DZ_CLR); | ||
562 | while (dz_in(dport, DZ_CSR) & DZ_CLR); | ||
563 | iob(); | ||
564 | |||
565 | /* Enable scanning. */ | ||
566 | dz_out(dport, DZ_CSR, DZ_MSE); | ||
567 | |||
568 | mux->initialised = 1; | ||
569 | } | ||
570 | |||
510 | static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, | 571 | static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, |
511 | struct ktermios *old_termios) | 572 | struct ktermios *old_termios) |
512 | { | 573 | { |
@@ -581,36 +642,86 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, | |||
581 | spin_unlock_irqrestore(&dport->port.lock, flags); | 642 | spin_unlock_irqrestore(&dport->port.lock, flags); |
582 | } | 643 | } |
583 | 644 | ||
584 | static const char *dz_type(struct uart_port *port) | 645 | static const char *dz_type(struct uart_port *uport) |
585 | { | 646 | { |
586 | return "DZ"; | 647 | return "DZ"; |
587 | } | 648 | } |
588 | 649 | ||
589 | static void dz_release_port(struct uart_port *port) | 650 | static void dz_release_port(struct uart_port *uport) |
590 | { | 651 | { |
591 | /* nothing to do */ | 652 | struct dz_mux *mux = to_dport(uport)->mux; |
653 | int map_guard; | ||
654 | |||
655 | iounmap(uport->membase); | ||
656 | uport->membase = NULL; | ||
657 | |||
658 | map_guard = atomic_add_return(-1, &mux->map_guard); | ||
659 | if (!map_guard) | ||
660 | release_mem_region(uport->mapbase, dec_kn_slot_size); | ||
592 | } | 661 | } |
593 | 662 | ||
594 | static int dz_request_port(struct uart_port *port) | 663 | static int dz_map_port(struct uart_port *uport) |
595 | { | 664 | { |
665 | if (!uport->membase) | ||
666 | uport->membase = ioremap_nocache(uport->mapbase, | ||
667 | dec_kn_slot_size); | ||
668 | if (!uport->membase) { | ||
669 | printk(KERN_ERR "dz: Cannot map MMIO\n"); | ||
670 | return -ENOMEM; | ||
671 | } | ||
596 | return 0; | 672 | return 0; |
597 | } | 673 | } |
598 | 674 | ||
599 | static void dz_config_port(struct uart_port *port, int flags) | 675 | static int dz_request_port(struct uart_port *uport) |
600 | { | 676 | { |
601 | if (flags & UART_CONFIG_TYPE) | 677 | struct dz_mux *mux = to_dport(uport)->mux; |
602 | port->type = PORT_DZ; | 678 | int map_guard; |
679 | int ret; | ||
680 | |||
681 | map_guard = atomic_add_return(1, &mux->map_guard); | ||
682 | if (map_guard == 1) { | ||
683 | if (!request_mem_region(uport->mapbase, dec_kn_slot_size, | ||
684 | "dz")) { | ||
685 | atomic_add(-1, &mux->map_guard); | ||
686 | printk(KERN_ERR | ||
687 | "dz: Unable to reserve MMIO resource\n"); | ||
688 | return -EBUSY; | ||
689 | } | ||
690 | } | ||
691 | ret = dz_map_port(uport); | ||
692 | if (ret) { | ||
693 | map_guard = atomic_add_return(-1, &mux->map_guard); | ||
694 | if (!map_guard) | ||
695 | release_mem_region(uport->mapbase, dec_kn_slot_size); | ||
696 | return ret; | ||
697 | } | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | static void dz_config_port(struct uart_port *uport, int flags) | ||
702 | { | ||
703 | struct dz_port *dport = to_dport(uport); | ||
704 | |||
705 | if (flags & UART_CONFIG_TYPE) { | ||
706 | if (dz_request_port(uport)) | ||
707 | return; | ||
708 | |||
709 | uport->type = PORT_DZ; | ||
710 | |||
711 | dz_reset(dport); | ||
712 | } | ||
603 | } | 713 | } |
604 | 714 | ||
605 | /* | 715 | /* |
606 | * verify the new serial_struct (for TIOCSSERIAL). | 716 | * Verify the new serial_struct (for TIOCSSERIAL). |
607 | */ | 717 | */ |
608 | static int dz_verify_port(struct uart_port *port, struct serial_struct *ser) | 718 | static int dz_verify_port(struct uart_port *uport, struct serial_struct *ser) |
609 | { | 719 | { |
610 | int ret = 0; | 720 | int ret = 0; |
721 | |||
611 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ) | 722 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ) |
612 | ret = -EINVAL; | 723 | ret = -EINVAL; |
613 | if (ser->irq != port->irq) | 724 | if (ser->irq != uport->irq) |
614 | ret = -EINVAL; | 725 | ret = -EINVAL; |
615 | return ret; | 726 | return ret; |
616 | } | 727 | } |
@@ -637,40 +748,32 @@ static struct uart_ops dz_ops = { | |||
637 | static void __init dz_init_ports(void) | 748 | static void __init dz_init_ports(void) |
638 | { | 749 | { |
639 | static int first = 1; | 750 | static int first = 1; |
640 | struct dz_port *dport; | ||
641 | unsigned long base; | 751 | unsigned long base; |
642 | int i; | 752 | int line; |
643 | 753 | ||
644 | if (!first) | 754 | if (!first) |
645 | return; | 755 | return; |
646 | first = 0; | 756 | first = 0; |
647 | 757 | ||
648 | if (mips_machtype == MACH_DS23100 || | 758 | if (mips_machtype == MACH_DS23100 || mips_machtype == MACH_DS5100) |
649 | mips_machtype == MACH_DS5100) | 759 | base = dec_kn_slot_base + KN01_DZ11; |
650 | base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_DZ11); | ||
651 | else | 760 | else |
652 | base = CKSEG1ADDR(KN02_SLOT_BASE + KN02_DZ11); | 761 | base = dec_kn_slot_base + KN02_DZ11; |
653 | |||
654 | for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { | ||
655 | spin_lock_init(&dport->port.lock); | ||
656 | dport->port.membase = (char *) base; | ||
657 | dport->port.iotype = UPIO_MEM; | ||
658 | dport->port.irq = dec_interrupt[DEC_IRQ_DZ11]; | ||
659 | dport->port.line = i; | ||
660 | dport->port.fifosize = 1; | ||
661 | dport->port.ops = &dz_ops; | ||
662 | dport->port.flags = UPF_BOOT_AUTOCONF; | ||
663 | } | ||
664 | } | ||
665 | 762 | ||
666 | static void dz_reset(struct dz_port *dport) | 763 | for (line = 0; line < DZ_NB_PORT; line++) { |
667 | { | 764 | struct dz_port *dport = &dz_mux.dport[line]; |
668 | dz_out(dport, DZ_CSR, DZ_CLR); | 765 | struct uart_port *uport = &dport->port; |
669 | while (dz_in(dport, DZ_CSR) & DZ_CLR); | ||
670 | iob(); | ||
671 | 766 | ||
672 | /* enable scanning */ | 767 | dport->mux = &dz_mux; |
673 | dz_out(dport, DZ_CSR, DZ_MSE); | 768 | |
769 | uport->irq = dec_interrupt[DEC_IRQ_DZ11]; | ||
770 | uport->fifosize = 1; | ||
771 | uport->iotype = UPIO_MEM; | ||
772 | uport->flags = UPF_BOOT_AUTOCONF; | ||
773 | uport->ops = &dz_ops; | ||
774 | uport->line = line; | ||
775 | uport->mapbase = base; | ||
776 | } | ||
674 | } | 777 | } |
675 | 778 | ||
676 | #ifdef CONFIG_SERIAL_DZ_CONSOLE | 779 | #ifdef CONFIG_SERIAL_DZ_CONSOLE |
@@ -737,7 +840,7 @@ static void dz_console_print(struct console *co, | |||
737 | const char *str, | 840 | const char *str, |
738 | unsigned int count) | 841 | unsigned int count) |
739 | { | 842 | { |
740 | struct dz_port *dport = &dz_ports[co->index]; | 843 | struct dz_port *dport = &dz_mux.dport[co->index]; |
741 | #ifdef DEBUG_DZ | 844 | #ifdef DEBUG_DZ |
742 | prom_printf((char *) str); | 845 | prom_printf((char *) str); |
743 | #endif | 846 | #endif |
@@ -746,17 +849,23 @@ static void dz_console_print(struct console *co, | |||
746 | 849 | ||
747 | static int __init dz_console_setup(struct console *co, char *options) | 850 | static int __init dz_console_setup(struct console *co, char *options) |
748 | { | 851 | { |
749 | struct dz_port *dport = &dz_ports[co->index]; | 852 | struct dz_port *dport = &dz_mux.dport[co->index]; |
853 | struct uart_port *uport = &dport->port; | ||
750 | int baud = 9600; | 854 | int baud = 9600; |
751 | int bits = 8; | 855 | int bits = 8; |
752 | int parity = 'n'; | 856 | int parity = 'n'; |
753 | int flow = 'n'; | 857 | int flow = 'n'; |
858 | int ret; | ||
754 | 859 | ||
755 | if (options) | 860 | ret = dz_map_port(uport); |
756 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 861 | if (ret) |
862 | return ret; | ||
757 | 863 | ||
758 | dz_reset(dport); | 864 | dz_reset(dport); |
759 | 865 | ||
866 | if (options) | ||
867 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
868 | |||
760 | return uart_set_options(&dport->port, co, baud, parity, bits, flow); | 869 | return uart_set_options(&dport->port, co, baud, parity, bits, flow); |
761 | } | 870 | } |
762 | 871 | ||
@@ -809,36 +918,14 @@ static int __init dz_init(void) | |||
809 | 918 | ||
810 | dz_init_ports(); | 919 | dz_init_ports(); |
811 | 920 | ||
812 | #ifndef CONFIG_SERIAL_DZ_CONSOLE | ||
813 | /* reset the chip */ | ||
814 | dz_reset(&dz_ports[0]); | ||
815 | #endif | ||
816 | |||
817 | ret = uart_register_driver(&dz_reg); | 921 | ret = uart_register_driver(&dz_reg); |
818 | if (ret != 0) | 922 | if (ret) |
819 | goto out; | 923 | return ret; |
820 | |||
821 | ret = request_irq(dz_ports[0].port.irq, dz_interrupt, IRQF_DISABLED, | ||
822 | "DZ", &dz_ports[0]); | ||
823 | if (ret != 0) { | ||
824 | printk(KERN_ERR "dz: Cannot get IRQ %d!\n", | ||
825 | dz_ports[0].port.irq); | ||
826 | goto out_unregister; | ||
827 | } | ||
828 | 924 | ||
829 | for (i = 0; i < DZ_NB_PORT; i++) | 925 | for (i = 0; i < DZ_NB_PORT; i++) |
830 | uart_add_one_port(&dz_reg, &dz_ports[i].port); | 926 | uart_add_one_port(&dz_reg, &dz_mux.dport[i].port); |
831 | |||
832 | return ret; | ||
833 | 927 | ||
834 | out_unregister: | 928 | return 0; |
835 | uart_unregister_driver(&dz_reg); | ||
836 | |||
837 | out: | ||
838 | return ret; | ||
839 | } | 929 | } |
840 | 930 | ||
841 | module_init(dz_init); | 931 | module_init(dz_init); |
842 | |||
843 | MODULE_DESCRIPTION("DECstation DZ serial driver"); | ||
844 | MODULE_LICENSE("GPL"); | ||