diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-26 15:48:06 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-26 15:48:06 -0500 |
commit | b0138a6cb7923a997d278b47c176778534d1095b (patch) | |
tree | 4fcb8822a69631baba568e4e1942847747123887 /drivers/serial | |
parent | 6572d6d7d0f965dda19d02af804ed3ae4b3bf1fc (diff) | |
parent | 1055a8af093fea7490445bd15cd671020e542035 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6: (78 commits)
[PARISC] Use symbolic last syscall in __NR_Linux_syscalls
[PARISC] Add missing statfs64 and fstatfs64 syscalls
Revert "[PARISC] Optimize TLB flush on SMP systems"
[PARISC] Compat signal fixes for 64-bit parisc
[PARISC] Reorder syscalls to match unistd.h
Revert "[PATCH] make kernel/signal.c:kill_proc_info() static"
[PARISC] fix sys_rt_sigqueueinfo
[PARISC] fix section mismatch warnings in harmony sound driver
[PARISC] do not export get_register/set_register
[PARISC] add ENTRY()/ENDPROC() and simplify assembly of HP/UX emulation code
[PARISC] convert to use CONFIG_64BIT instead of __LP64__
[PARISC] use CONFIG_64BIT instead of __LP64__
[PARISC] add ASM_EXCEPTIONTABLE_ENTRY() macro
[PARISC] more ENTRY(), ENDPROC(), END() conversions
[PARISC] fix ENTRY() and ENDPROC() for 64bit-parisc
[PARISC] Fixes /proc/cpuinfo cache output on B160L
[PARISC] implement standard ENTRY(), END() and ENDPROC()
[PARISC] kill ENTRY_SYS_CPUS
[PARISC] clean up debugging printks in smp.c
[PARISC] factor syscall_restart code out of do_signal
...
Fix conflict in include/linux/sched.h due to kill_proc_info() being made
publicly available to PARISC again.
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/mux.c | 167 |
1 files changed, 132 insertions, 35 deletions
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index ccb8fa1800a5..83211013deb8 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c | |||
@@ -51,7 +51,11 @@ | |||
51 | 51 | ||
52 | #define MUX_NR 256 | 52 | #define MUX_NR 256 |
53 | static unsigned int port_cnt __read_mostly; | 53 | static unsigned int port_cnt __read_mostly; |
54 | static struct uart_port mux_ports[MUX_NR]; | 54 | struct mux_port { |
55 | struct uart_port port; | ||
56 | int enabled; | ||
57 | }; | ||
58 | static struct mux_port mux_ports[MUX_NR]; | ||
55 | 59 | ||
56 | static struct uart_driver mux_driver = { | 60 | static struct uart_driver mux_driver = { |
57 | .owner = THIS_MODULE, | 61 | .owner = THIS_MODULE, |
@@ -66,7 +70,36 @@ static struct timer_list mux_timer; | |||
66 | 70 | ||
67 | #define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET) | 71 | #define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET) |
68 | #define UART_GET_FIFO_CNT(p) __raw_readl((p)->membase + IO_DCOUNT_REG_OFFSET) | 72 | #define UART_GET_FIFO_CNT(p) __raw_readl((p)->membase + IO_DCOUNT_REG_OFFSET) |
69 | #define GET_MUX_PORTS(iodc_data) ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8 | 73 | |
74 | /** | ||
75 | * get_mux_port_count - Get the number of available ports on the Mux. | ||
76 | * @dev: The parisc device. | ||
77 | * | ||
78 | * This function is used to determine the number of ports the Mux | ||
79 | * supports. The IODC data reports the number of ports the Mux | ||
80 | * can support, but there are cases where not all the Mux ports | ||
81 | * are connected. This function can override the IODC and | ||
82 | * return the true port count. | ||
83 | */ | ||
84 | static int __init get_mux_port_count(struct parisc_device *dev) | ||
85 | { | ||
86 | int status; | ||
87 | u8 iodc_data[32]; | ||
88 | unsigned long bytecnt; | ||
89 | |||
90 | /* If this is the built-in Mux for the K-Class (Eole CAP/MUX), | ||
91 | * we only need to allocate resources for 1 port since the | ||
92 | * other 7 ports are not connected. | ||
93 | */ | ||
94 | if(dev->id.hversion == 0x15) | ||
95 | return 1; | ||
96 | |||
97 | status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); | ||
98 | BUG_ON(status != PDC_OK); | ||
99 | |||
100 | /* Return the number of ports specified in the iodc data. */ | ||
101 | return ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8; | ||
102 | } | ||
70 | 103 | ||
71 | /** | 104 | /** |
72 | * mux_tx_empty - Check if the transmitter fifo is empty. | 105 | * mux_tx_empty - Check if the transmitter fifo is empty. |
@@ -250,7 +283,7 @@ static void mux_read(struct uart_port *port) | |||
250 | */ | 283 | */ |
251 | static int mux_startup(struct uart_port *port) | 284 | static int mux_startup(struct uart_port *port) |
252 | { | 285 | { |
253 | mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); | 286 | mux_ports[port->line].enabled = 1; |
254 | return 0; | 287 | return 0; |
255 | } | 288 | } |
256 | 289 | ||
@@ -262,6 +295,7 @@ static int mux_startup(struct uart_port *port) | |||
262 | */ | 295 | */ |
263 | static void mux_shutdown(struct uart_port *port) | 296 | static void mux_shutdown(struct uart_port *port) |
264 | { | 297 | { |
298 | mux_ports[port->line].enabled = 0; | ||
265 | } | 299 | } |
266 | 300 | ||
267 | /** | 301 | /** |
@@ -319,7 +353,7 @@ static int mux_request_port(struct uart_port *port) | |||
319 | * @port: Ptr to the uart_port. | 353 | * @port: Ptr to the uart_port. |
320 | * @type: Bitmask of required configurations. | 354 | * @type: Bitmask of required configurations. |
321 | * | 355 | * |
322 | * Perform any autoconfiguration steps for the port. This functino is | 356 | * Perform any autoconfiguration steps for the port. This function is |
323 | * called if the UPF_BOOT_AUTOCONF flag is specified for the port. | 357 | * called if the UPF_BOOT_AUTOCONF flag is specified for the port. |
324 | * [Note: This is required for now because of a bug in the Serial core. | 358 | * [Note: This is required for now because of a bug in the Serial core. |
325 | * rmk has already submitted a patch to linus, should be available for | 359 | * rmk has already submitted a patch to linus, should be available for |
@@ -357,11 +391,11 @@ static void mux_poll(unsigned long unused) | |||
357 | int i; | 391 | int i; |
358 | 392 | ||
359 | for(i = 0; i < port_cnt; ++i) { | 393 | for(i = 0; i < port_cnt; ++i) { |
360 | if(!mux_ports[i].info) | 394 | if(!mux_ports[i].enabled) |
361 | continue; | 395 | continue; |
362 | 396 | ||
363 | mux_read(&mux_ports[i]); | 397 | mux_read(&mux_ports[i].port); |
364 | mux_write(&mux_ports[i]); | 398 | mux_write(&mux_ports[i].port); |
365 | } | 399 | } |
366 | 400 | ||
367 | mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); | 401 | mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); |
@@ -371,8 +405,17 @@ static void mux_poll(unsigned long unused) | |||
371 | #ifdef CONFIG_SERIAL_MUX_CONSOLE | 405 | #ifdef CONFIG_SERIAL_MUX_CONSOLE |
372 | static void mux_console_write(struct console *co, const char *s, unsigned count) | 406 | static void mux_console_write(struct console *co, const char *s, unsigned count) |
373 | { | 407 | { |
374 | while(count--) | 408 | /* Wait until the FIFO drains. */ |
375 | pdc_iodc_putc(*s++); | 409 | while(UART_GET_FIFO_CNT(&mux_ports[0].port)) |
410 | udelay(1); | ||
411 | |||
412 | while(count--) { | ||
413 | if(*s == '\n') { | ||
414 | UART_PUT_CHAR(&mux_ports[0].port, '\r'); | ||
415 | } | ||
416 | UART_PUT_CHAR(&mux_ports[0].port, *s++); | ||
417 | } | ||
418 | |||
376 | } | 419 | } |
377 | 420 | ||
378 | static int mux_console_setup(struct console *co, char *options) | 421 | static int mux_console_setup(struct console *co, char *options) |
@@ -428,19 +471,14 @@ static struct uart_ops mux_pops = { | |||
428 | */ | 471 | */ |
429 | static int __init mux_probe(struct parisc_device *dev) | 472 | static int __init mux_probe(struct parisc_device *dev) |
430 | { | 473 | { |
431 | int i, status, ports; | 474 | int i, status; |
432 | u8 iodc_data[32]; | ||
433 | unsigned long bytecnt; | ||
434 | struct uart_port *port; | ||
435 | 475 | ||
436 | status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); | 476 | int port_count = get_mux_port_count(dev); |
437 | if(status != PDC_OK) { | 477 | printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.6\n", port_count); |
438 | printk(KERN_ERR "Serial mux: Unable to read IODC.\n"); | ||
439 | return 1; | ||
440 | } | ||
441 | 478 | ||
442 | ports = GET_MUX_PORTS(iodc_data); | 479 | dev_set_drvdata(&dev->dev, (void *)(long)port_count); |
443 | printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.3\n", ports); | 480 | request_mem_region(dev->hpa.start + MUX_OFFSET, |
481 | port_count * MUX_LINE_OFFSET, "Mux"); | ||
444 | 482 | ||
445 | if(!port_cnt) { | 483 | if(!port_cnt) { |
446 | mux_driver.cons = MUX_CONSOLE; | 484 | mux_driver.cons = MUX_CONSOLE; |
@@ -450,13 +488,10 @@ static int __init mux_probe(struct parisc_device *dev) | |||
450 | printk(KERN_ERR "Serial mux: Unable to register driver.\n"); | 488 | printk(KERN_ERR "Serial mux: Unable to register driver.\n"); |
451 | return 1; | 489 | return 1; |
452 | } | 490 | } |
453 | |||
454 | init_timer(&mux_timer); | ||
455 | mux_timer.function = mux_poll; | ||
456 | } | 491 | } |
457 | 492 | ||
458 | for(i = 0; i < ports; ++i, ++port_cnt) { | 493 | for(i = 0; i < port_count; ++i, ++port_cnt) { |
459 | port = &mux_ports[port_cnt]; | 494 | struct uart_port *port = &mux_ports[port_cnt].port; |
460 | port->iobase = 0; | 495 | port->iobase = 0; |
461 | port->mapbase = dev->hpa.start + MUX_OFFSET + | 496 | port->mapbase = dev->hpa.start + MUX_OFFSET + |
462 | (i * MUX_LINE_OFFSET); | 497 | (i * MUX_LINE_OFFSET); |
@@ -477,27 +512,73 @@ static int __init mux_probe(struct parisc_device *dev) | |||
477 | */ | 512 | */ |
478 | port->timeout = HZ / 50; | 513 | port->timeout = HZ / 50; |
479 | spin_lock_init(&port->lock); | 514 | spin_lock_init(&port->lock); |
515 | |||
480 | status = uart_add_one_port(&mux_driver, port); | 516 | status = uart_add_one_port(&mux_driver, port); |
481 | BUG_ON(status); | 517 | BUG_ON(status); |
482 | } | 518 | } |
483 | 519 | ||
484 | #ifdef CONFIG_SERIAL_MUX_CONSOLE | ||
485 | register_console(&mux_console); | ||
486 | #endif | ||
487 | return 0; | 520 | return 0; |
488 | } | 521 | } |
489 | 522 | ||
523 | static int __devexit mux_remove(struct parisc_device *dev) | ||
524 | { | ||
525 | int i, j; | ||
526 | int port_count = (long)dev_get_drvdata(&dev->dev); | ||
527 | |||
528 | /* Find Port 0 for this card in the mux_ports list. */ | ||
529 | for(i = 0; i < port_cnt; ++i) { | ||
530 | if(mux_ports[i].port.mapbase == dev->hpa.start + MUX_OFFSET) | ||
531 | break; | ||
532 | } | ||
533 | BUG_ON(i + port_count > port_cnt); | ||
534 | |||
535 | /* Release the resources associated with each port on the device. */ | ||
536 | for(j = 0; j < port_count; ++j, ++i) { | ||
537 | struct uart_port *port = &mux_ports[i].port; | ||
538 | |||
539 | uart_remove_one_port(&mux_driver, port); | ||
540 | if(port->membase) | ||
541 | iounmap(port->membase); | ||
542 | } | ||
543 | |||
544 | release_mem_region(dev->hpa.start + MUX_OFFSET, port_count * MUX_LINE_OFFSET); | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | /* Hack. This idea was taken from the 8250_gsc.c on how to properly order | ||
549 | * the serial port detection in the proper order. The idea is we always | ||
550 | * want the builtin mux to be detected before addin mux cards, so we | ||
551 | * specifically probe for the builtin mux cards first. | ||
552 | * | ||
553 | * This table only contains the parisc_device_id of known builtin mux | ||
554 | * devices. All other mux cards will be detected by the generic mux_tbl. | ||
555 | */ | ||
556 | static struct parisc_device_id builtin_mux_tbl[] = { | ||
557 | { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x15, 0x0000D }, /* All K-class */ | ||
558 | { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x44, 0x0000D }, /* E35, E45, and E55 */ | ||
559 | { 0, } | ||
560 | }; | ||
561 | |||
490 | static struct parisc_device_id mux_tbl[] = { | 562 | static struct parisc_device_id mux_tbl[] = { |
491 | { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D }, | 563 | { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D }, |
492 | { 0, } | 564 | { 0, } |
493 | }; | 565 | }; |
494 | 566 | ||
567 | MODULE_DEVICE_TABLE(parisc, builtin_mux_tbl); | ||
495 | MODULE_DEVICE_TABLE(parisc, mux_tbl); | 568 | MODULE_DEVICE_TABLE(parisc, mux_tbl); |
496 | 569 | ||
570 | static struct parisc_driver builtin_serial_mux_driver = { | ||
571 | .name = "builtin_serial_mux", | ||
572 | .id_table = builtin_mux_tbl, | ||
573 | .probe = mux_probe, | ||
574 | .remove = __devexit_p(mux_remove), | ||
575 | }; | ||
576 | |||
497 | static struct parisc_driver serial_mux_driver = { | 577 | static struct parisc_driver serial_mux_driver = { |
498 | .name = "serial_mux", | 578 | .name = "serial_mux", |
499 | .id_table = mux_tbl, | 579 | .id_table = mux_tbl, |
500 | .probe = mux_probe, | 580 | .probe = mux_probe, |
581 | .remove = __devexit_p(mux_remove), | ||
501 | }; | 582 | }; |
502 | 583 | ||
503 | /** | 584 | /** |
@@ -507,7 +588,21 @@ static struct parisc_driver serial_mux_driver = { | |||
507 | */ | 588 | */ |
508 | static int __init mux_init(void) | 589 | static int __init mux_init(void) |
509 | { | 590 | { |
510 | return register_parisc_driver(&serial_mux_driver); | 591 | register_parisc_driver(&builtin_serial_mux_driver); |
592 | register_parisc_driver(&serial_mux_driver); | ||
593 | |||
594 | if(port_cnt > 0) { | ||
595 | /* Start the Mux timer */ | ||
596 | init_timer(&mux_timer); | ||
597 | mux_timer.function = mux_poll; | ||
598 | mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); | ||
599 | |||
600 | #ifdef CONFIG_SERIAL_MUX_CONSOLE | ||
601 | register_console(&mux_console); | ||
602 | #endif | ||
603 | } | ||
604 | |||
605 | return 0; | ||
511 | } | 606 | } |
512 | 607 | ||
513 | /** | 608 | /** |
@@ -517,14 +612,16 @@ static int __init mux_init(void) | |||
517 | */ | 612 | */ |
518 | static void __exit mux_exit(void) | 613 | static void __exit mux_exit(void) |
519 | { | 614 | { |
520 | int i; | 615 | /* Delete the Mux timer. */ |
521 | 616 | if(port_cnt > 0) { | |
522 | for (i = 0; i < port_cnt; i++) { | 617 | del_timer(&mux_timer); |
523 | uart_remove_one_port(&mux_driver, &mux_ports[i]); | 618 | #ifdef CONFIG_SERIAL_MUX_CONSOLE |
524 | if (mux_ports[i].membase) | 619 | unregister_console(&mux_console); |
525 | iounmap(mux_ports[i].membase); | 620 | #endif |
526 | } | 621 | } |
527 | 622 | ||
623 | unregister_parisc_driver(&builtin_serial_mux_driver); | ||
624 | unregister_parisc_driver(&serial_mux_driver); | ||
528 | uart_unregister_driver(&mux_driver); | 625 | uart_unregister_driver(&mux_driver); |
529 | } | 626 | } |
530 | 627 | ||