diff options
Diffstat (limited to 'drivers/serial/sunsab.c')
| -rw-r--r-- | drivers/serial/sunsab.c | 109 |
1 files changed, 71 insertions, 38 deletions
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 39b788d95e39..10e2990a40d4 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c | |||
| @@ -61,6 +61,16 @@ struct uart_sunsab_port { | |||
| 61 | unsigned char pvr_dtr_bit; /* Which PVR bit is DTR */ | 61 | unsigned char pvr_dtr_bit; /* Which PVR bit is DTR */ |
| 62 | unsigned char pvr_dsr_bit; /* Which PVR bit is DSR */ | 62 | unsigned char pvr_dsr_bit; /* Which PVR bit is DSR */ |
| 63 | int type; /* SAB82532 version */ | 63 | int type; /* SAB82532 version */ |
| 64 | |||
| 65 | /* Setting configuration bits while the transmitter is active | ||
| 66 | * can cause garbage characters to get emitted by the chip. | ||
| 67 | * Therefore, we cache such writes here and do the real register | ||
| 68 | * write the next time the transmitter becomes idle. | ||
| 69 | */ | ||
| 70 | unsigned int cached_ebrg; | ||
| 71 | unsigned char cached_mode; | ||
| 72 | unsigned char cached_pvr; | ||
| 73 | unsigned char cached_dafo; | ||
| 64 | }; | 74 | }; |
| 65 | 75 | ||
| 66 | /* | 76 | /* |
| @@ -236,6 +246,7 @@ receive_chars(struct uart_sunsab_port *up, | |||
| 236 | } | 246 | } |
| 237 | 247 | ||
| 238 | static void sunsab_stop_tx(struct uart_port *, unsigned int); | 248 | static void sunsab_stop_tx(struct uart_port *, unsigned int); |
| 249 | static void sunsab_tx_idle(struct uart_sunsab_port *); | ||
| 239 | 250 | ||
| 240 | static void transmit_chars(struct uart_sunsab_port *up, | 251 | static void transmit_chars(struct uart_sunsab_port *up, |
| 241 | union sab82532_irq_status *stat) | 252 | union sab82532_irq_status *stat) |
| @@ -258,6 +269,7 @@ static void transmit_chars(struct uart_sunsab_port *up, | |||
| 258 | return; | 269 | return; |
| 259 | 270 | ||
| 260 | set_bit(SAB82532_XPR, &up->irqflags); | 271 | set_bit(SAB82532_XPR, &up->irqflags); |
| 272 | sunsab_tx_idle(up); | ||
| 261 | 273 | ||
| 262 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | 274 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { |
| 263 | up->interrupt_mask1 |= SAB82532_IMR1_XPR; | 275 | up->interrupt_mask1 |= SAB82532_IMR1_XPR; |
| @@ -397,21 +409,21 @@ static void sunsab_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
| 397 | struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; | 409 | struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; |
| 398 | 410 | ||
| 399 | if (mctrl & TIOCM_RTS) { | 411 | if (mctrl & TIOCM_RTS) { |
| 400 | writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_FRTS, | 412 | up->cached_mode &= ~SAB82532_MODE_FRTS; |
| 401 | &up->regs->rw.mode); | 413 | up->cached_mode |= SAB82532_MODE_RTS; |
| 402 | writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS, | ||
| 403 | &up->regs->rw.mode); | ||
| 404 | } else { | 414 | } else { |
| 405 | writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FRTS, | 415 | up->cached_mode |= (SAB82532_MODE_FRTS | |
| 406 | &up->regs->rw.mode); | 416 | SAB82532_MODE_RTS); |
| 407 | writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS, | ||
| 408 | &up->regs->rw.mode); | ||
| 409 | } | 417 | } |
| 410 | if (mctrl & TIOCM_DTR) { | 418 | if (mctrl & TIOCM_DTR) { |
| 411 | writeb(readb(&up->regs->rw.pvr) & ~(up->pvr_dtr_bit), &up->regs->rw.pvr); | 419 | up->cached_pvr &= ~(up->pvr_dtr_bit); |
| 412 | } else { | 420 | } else { |
| 413 | writeb(readb(&up->regs->rw.pvr) | up->pvr_dtr_bit, &up->regs->rw.pvr); | 421 | up->cached_pvr |= up->pvr_dtr_bit; |
| 414 | } | 422 | } |
| 423 | |||
| 424 | set_bit(SAB82532_REGS_PENDING, &up->irqflags); | ||
| 425 | if (test_bit(SAB82532_XPR, &up->irqflags)) | ||
| 426 | sunsab_tx_idle(up); | ||
| 415 | } | 427 | } |
| 416 | 428 | ||
| 417 | /* port->lock is not held. */ | 429 | /* port->lock is not held. */ |
| @@ -450,6 +462,25 @@ static void sunsab_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
| 450 | } | 462 | } |
| 451 | 463 | ||
| 452 | /* port->lock held by caller. */ | 464 | /* port->lock held by caller. */ |
| 465 | static void sunsab_tx_idle(struct uart_sunsab_port *up) | ||
| 466 | { | ||
| 467 | if (test_bit(SAB82532_REGS_PENDING, &up->irqflags)) { | ||
| 468 | u8 tmp; | ||
| 469 | |||
| 470 | clear_bit(SAB82532_REGS_PENDING, &up->irqflags); | ||
| 471 | writeb(up->cached_mode, &up->regs->rw.mode); | ||
| 472 | writeb(up->cached_pvr, &up->regs->rw.pvr); | ||
| 473 | writeb(up->cached_dafo, &up->regs->w.dafo); | ||
| 474 | |||
| 475 | writeb(up->cached_ebrg & 0xff, &up->regs->w.bgr); | ||
| 476 | tmp = readb(&up->regs->rw.ccr2); | ||
| 477 | tmp &= ~0xc0; | ||
| 478 | tmp |= (up->cached_ebrg >> 2) & 0xc0; | ||
| 479 | writeb(tmp, &up->regs->rw.ccr2); | ||
| 480 | } | ||
| 481 | } | ||
| 482 | |||
| 483 | /* port->lock held by caller. */ | ||
| 453 | static void sunsab_start_tx(struct uart_port *port, unsigned int tty_start) | 484 | static void sunsab_start_tx(struct uart_port *port, unsigned int tty_start) |
| 454 | { | 485 | { |
| 455 | struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; | 486 | struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; |
| @@ -517,12 +548,16 @@ static void sunsab_break_ctl(struct uart_port *port, int break_state) | |||
| 517 | 548 | ||
| 518 | spin_lock_irqsave(&up->port.lock, flags); | 549 | spin_lock_irqsave(&up->port.lock, flags); |
| 519 | 550 | ||
| 520 | val = readb(&up->regs->rw.dafo); | 551 | val = up->cached_dafo; |
| 521 | if (break_state) | 552 | if (break_state) |
| 522 | val |= SAB82532_DAFO_XBRK; | 553 | val |= SAB82532_DAFO_XBRK; |
| 523 | else | 554 | else |
| 524 | val &= ~SAB82532_DAFO_XBRK; | 555 | val &= ~SAB82532_DAFO_XBRK; |
| 525 | writeb(val, &up->regs->rw.dafo); | 556 | up->cached_dafo = val; |
| 557 | |||
| 558 | set_bit(SAB82532_REGS_PENDING, &up->irqflags); | ||
| 559 | if (test_bit(SAB82532_XPR, &up->irqflags)) | ||
| 560 | sunsab_tx_idle(up); | ||
| 526 | 561 | ||
| 527 | spin_unlock_irqrestore(&up->port.lock, flags); | 562 | spin_unlock_irqrestore(&up->port.lock, flags); |
| 528 | } | 563 | } |
| @@ -566,8 +601,9 @@ static int sunsab_startup(struct uart_port *port) | |||
| 566 | SAB82532_CCR2_TOE, &up->regs->w.ccr2); | 601 | SAB82532_CCR2_TOE, &up->regs->w.ccr2); |
| 567 | writeb(0, &up->regs->w.ccr3); | 602 | writeb(0, &up->regs->w.ccr3); |
| 568 | writeb(SAB82532_CCR4_MCK4 | SAB82532_CCR4_EBRG, &up->regs->w.ccr4); | 603 | writeb(SAB82532_CCR4_MCK4 | SAB82532_CCR4_EBRG, &up->regs->w.ccr4); |
| 569 | writeb(SAB82532_MODE_RTS | SAB82532_MODE_FCTS | | 604 | up->cached_mode = (SAB82532_MODE_RTS | SAB82532_MODE_FCTS | |
| 570 | SAB82532_MODE_RAC, &up->regs->w.mode); | 605 | SAB82532_MODE_RAC); |
| 606 | writeb(up->cached_mode, &up->regs->w.mode); | ||
| 571 | writeb(SAB82532_RFC_DPS|SAB82532_RFC_RFTH_32, &up->regs->w.rfc); | 607 | writeb(SAB82532_RFC_DPS|SAB82532_RFC_RFTH_32, &up->regs->w.rfc); |
| 572 | 608 | ||
| 573 | tmp = readb(&up->regs->rw.ccr0); | 609 | tmp = readb(&up->regs->rw.ccr0); |
| @@ -598,7 +634,6 @@ static void sunsab_shutdown(struct uart_port *port) | |||
| 598 | { | 634 | { |
| 599 | struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; | 635 | struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; |
| 600 | unsigned long flags; | 636 | unsigned long flags; |
| 601 | unsigned char tmp; | ||
| 602 | 637 | ||
| 603 | spin_lock_irqsave(&up->port.lock, flags); | 638 | spin_lock_irqsave(&up->port.lock, flags); |
| 604 | 639 | ||
| @@ -609,14 +644,13 @@ static void sunsab_shutdown(struct uart_port *port) | |||
| 609 | writeb(up->interrupt_mask1, &up->regs->w.imr1); | 644 | writeb(up->interrupt_mask1, &up->regs->w.imr1); |
| 610 | 645 | ||
| 611 | /* Disable break condition */ | 646 | /* Disable break condition */ |
| 612 | tmp = readb(&up->regs->rw.dafo); | 647 | up->cached_dafo = readb(&up->regs->rw.dafo); |
| 613 | tmp &= ~SAB82532_DAFO_XBRK; | 648 | up->cached_dafo &= ~SAB82532_DAFO_XBRK; |
| 614 | writeb(tmp, &up->regs->rw.dafo); | 649 | writeb(up->cached_dafo, &up->regs->rw.dafo); |
| 615 | 650 | ||
| 616 | /* Disable Receiver */ | 651 | /* Disable Receiver */ |
| 617 | tmp = readb(&up->regs->rw.mode); | 652 | up->cached_mode &= ~SAB82532_MODE_RAC; |
| 618 | tmp &= ~SAB82532_MODE_RAC; | 653 | writeb(up->cached_mode, &up->regs->rw.mode); |
| 619 | writeb(tmp, &up->regs->rw.mode); | ||
| 620 | 654 | ||
| 621 | /* | 655 | /* |
| 622 | * XXX FIXME | 656 | * XXX FIXME |
| @@ -685,7 +719,6 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla | |||
| 685 | unsigned int iflag, unsigned int baud, | 719 | unsigned int iflag, unsigned int baud, |
| 686 | unsigned int quot) | 720 | unsigned int quot) |
| 687 | { | 721 | { |
| 688 | unsigned int ebrg; | ||
| 689 | unsigned char dafo; | 722 | unsigned char dafo; |
| 690 | int bits, n, m; | 723 | int bits, n, m; |
| 691 | 724 | ||
| @@ -714,10 +747,11 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla | |||
| 714 | } else { | 747 | } else { |
| 715 | dafo |= SAB82532_DAFO_PAR_EVEN; | 748 | dafo |= SAB82532_DAFO_PAR_EVEN; |
| 716 | } | 749 | } |
| 750 | up->cached_dafo = dafo; | ||
| 717 | 751 | ||
| 718 | calc_ebrg(baud, &n, &m); | 752 | calc_ebrg(baud, &n, &m); |
| 719 | 753 | ||
| 720 | ebrg = n | (m << 6); | 754 | up->cached_ebrg = n | (m << 6); |
| 721 | 755 | ||
| 722 | up->tec_timeout = (10 * 1000000) / baud; | 756 | up->tec_timeout = (10 * 1000000) / baud; |
| 723 | up->cec_timeout = up->tec_timeout >> 2; | 757 | up->cec_timeout = up->tec_timeout >> 2; |
| @@ -770,16 +804,13 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla | |||
| 770 | uart_update_timeout(&up->port, cflag, | 804 | uart_update_timeout(&up->port, cflag, |
| 771 | (up->port.uartclk / (16 * quot))); | 805 | (up->port.uartclk / (16 * quot))); |
| 772 | 806 | ||
| 773 | /* Now bang the new settings into the chip. */ | 807 | /* Now schedule a register update when the chip's |
| 774 | sunsab_cec_wait(up); | 808 | * transmitter is idle. |
| 775 | sunsab_tec_wait(up); | 809 | */ |
| 776 | writeb(dafo, &up->regs->w.dafo); | 810 | up->cached_mode |= SAB82532_MODE_RAC; |
| 777 | writeb(ebrg & 0xff, &up->regs->w.bgr); | 811 | set_bit(SAB82532_REGS_PENDING, &up->irqflags); |
| 778 | writeb((readb(&up->regs->rw.ccr2) & ~0xc0) | ((ebrg >> 2) & 0xc0), | 812 | if (test_bit(SAB82532_XPR, &up->irqflags)) |
| 779 | &up->regs->rw.ccr2); | 813 | sunsab_tx_idle(up); |
| 780 | |||
| 781 | writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RAC, &up->regs->rw.mode); | ||
| 782 | |||
| 783 | } | 814 | } |
| 784 | 815 | ||
| 785 | /* port->lock is not held. */ | 816 | /* port->lock is not held. */ |
| @@ -1084,11 +1115,13 @@ static void __init sunsab_init_hw(void) | |||
| 1084 | up->pvr_dsr_bit = (1 << 3); | 1115 | up->pvr_dsr_bit = (1 << 3); |
| 1085 | up->pvr_dtr_bit = (1 << 2); | 1116 | up->pvr_dtr_bit = (1 << 2); |
| 1086 | } | 1117 | } |
| 1087 | writeb((1 << 1) | (1 << 2) | (1 << 4), &up->regs->w.pvr); | 1118 | up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4); |
| 1088 | writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FRTS, | 1119 | writeb(up->cached_pvr, &up->regs->w.pvr); |
| 1089 | &up->regs->rw.mode); | 1120 | up->cached_mode = readb(&up->regs->rw.mode); |
| 1090 | writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS, | 1121 | up->cached_mode |= SAB82532_MODE_FRTS; |
| 1091 | &up->regs->rw.mode); | 1122 | writeb(up->cached_mode, &up->regs->rw.mode); |
| 1123 | up->cached_mode |= SAB82532_MODE_RTS; | ||
| 1124 | writeb(up->cached_mode, &up->regs->rw.mode); | ||
| 1092 | 1125 | ||
| 1093 | up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT; | 1126 | up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT; |
| 1094 | up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT; | 1127 | up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT; |
