aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/dz.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial/dz.c')
-rw-r--r--drivers/serial/dz.c289
1 files changed, 188 insertions, 101 deletions
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index c054c1bd8b2..116211fcd36 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
61static char *dz_name = "DECstation DZ serial driver version "; 65
62static char *dz_version = "1.03"; 66MODULE_DESCRIPTION("DECstation DZ serial driver");
67MODULE_LICENSE("GPL");
68
69
70static char dz_name[] __initdata = "DECstation DZ serial driver version ";
71static char dz_version[] __initdata = "1.04";
63 72
64struct dz_port { 73struct 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
69static struct dz_port dz_ports[DZ_NB_PORT]; 79struct 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
86static struct dz_mux dz_mux;
70 87
71static inline struct dz_port *to_dport(struct uart_port *uport) 88static 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
85static inline unsigned short dz_in(struct dz_port *dport, unsigned offset) 102static 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
93static inline void dz_out(struct dz_port *dport, unsigned offset, 109static 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,
112static void dz_stop_tx(struct uart_port *uport) 126static 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)
122static void dz_start_tx(struct uart_port *uport) 136static 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
140static void dz_enable_ms(struct uart_port *port) 154static 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 */
172static inline void dz_receive_chars(struct dz_port *dport_in) 186static 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 */
248static inline void dz_transmit_chars(struct dz_port *dport_in) 262static 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 */
329static irqreturn_t dz_interrupt(int irq, void *dev) 343static 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)
393static int dz_startup(struct uart_port *uport) 408static 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)
419static void dz_shutdown(struct uart_port *uport) 449static 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
554static 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
510static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, 571static 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
584static const char *dz_type(struct uart_port *port) 645static const char *dz_type(struct uart_port *uport)
585{ 646{
586 return "DZ"; 647 return "DZ";
587} 648}
588 649
589static void dz_release_port(struct uart_port *port) 650static 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
594static int dz_request_port(struct uart_port *port) 663static 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
599static void dz_config_port(struct uart_port *port, int flags) 675static 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
701static 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 */
608static int dz_verify_port(struct uart_port *port, struct serial_struct *ser) 718static 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 = {
637static void __init dz_init_ports(void) 748static 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
666static 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
747static int __init dz_console_setup(struct console *co, char *options) 850static 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
834out_unregister: 928 return 0;
835 uart_unregister_driver(&dz_reg);
836
837out:
838 return ret;
839} 929}
840 930
841module_init(dz_init); 931module_init(dz_init);
842
843MODULE_DESCRIPTION("DECstation DZ serial driver");
844MODULE_LICENSE("GPL");