diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-05-19 18:31:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-05-19 18:31:18 -0400 |
commit | 66e60f92518268f4d2a702a1c4ffbe1caacd6290 (patch) | |
tree | 889a1e2919ac50253be8136a1b0855fde27fcb36 | |
parent | 804c64ea864d0a8ee13f3de0b74158a3e9c3166d (diff) | |
parent | 4b40033ef110b833986c1a1d958a951b695f9fbc (diff) |
Automatic merge of rsync://rsync.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6.git/
-rw-r--r-- | arch/sparc64/kernel/pci_iommu.c | 165 | ||||
-rw-r--r-- | arch/sparc64/kernel/sbus.c | 31 | ||||
-rw-r--r-- | drivers/sbus/char/aurora.c | 8 | ||||
-rw-r--r-- | drivers/serial/sunsab.c | 109 | ||||
-rw-r--r-- | drivers/serial/sunsab.h | 1 |
5 files changed, 162 insertions, 152 deletions
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 292983413ae2..f009b1b45501 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
9 | #include <linux/sched.h> | 9 | #include <linux/sched.h> |
10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
11 | #include <linux/delay.h> | ||
11 | 12 | ||
12 | #include <asm/pbm.h> | 13 | #include <asm/pbm.h> |
13 | 14 | ||
@@ -379,6 +380,54 @@ bad: | |||
379 | return PCI_DMA_ERROR_CODE; | 380 | return PCI_DMA_ERROR_CODE; |
380 | } | 381 | } |
381 | 382 | ||
383 | static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages) | ||
384 | { | ||
385 | int limit; | ||
386 | |||
387 | PCI_STC_FLUSHFLAG_INIT(strbuf); | ||
388 | if (strbuf->strbuf_ctxflush && | ||
389 | iommu->iommu_ctxflush) { | ||
390 | unsigned long matchreg, flushreg; | ||
391 | |||
392 | flushreg = strbuf->strbuf_ctxflush; | ||
393 | matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); | ||
394 | |||
395 | limit = 10000; | ||
396 | do { | ||
397 | pci_iommu_write(flushreg, ctx); | ||
398 | udelay(10); | ||
399 | limit--; | ||
400 | if (!limit) | ||
401 | break; | ||
402 | } while(((long)pci_iommu_read(matchreg)) < 0L); | ||
403 | if (!limit) | ||
404 | printk(KERN_WARNING "pci_strbuf_flush: ctx flush " | ||
405 | "timeout vaddr[%08x] ctx[%lx]\n", | ||
406 | vaddr, ctx); | ||
407 | } else { | ||
408 | unsigned long i; | ||
409 | |||
410 | for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) | ||
411 | pci_iommu_write(strbuf->strbuf_pflush, vaddr); | ||
412 | } | ||
413 | |||
414 | pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); | ||
415 | (void) pci_iommu_read(iommu->write_complete_reg); | ||
416 | |||
417 | limit = 10000; | ||
418 | while (!PCI_STC_FLUSHFLAG_SET(strbuf)) { | ||
419 | limit--; | ||
420 | if (!limit) | ||
421 | break; | ||
422 | udelay(10); | ||
423 | membar("#LoadLoad"); | ||
424 | } | ||
425 | if (!limit) | ||
426 | printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout " | ||
427 | "vaddr[%08x] ctx[%lx] npages[%ld]\n", | ||
428 | vaddr, ctx, npages); | ||
429 | } | ||
430 | |||
382 | /* Unmap a single streaming mode DMA translation. */ | 431 | /* Unmap a single streaming mode DMA translation. */ |
383 | void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) | 432 | void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) |
384 | { | 433 | { |
@@ -386,7 +435,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int | |||
386 | struct pci_iommu *iommu; | 435 | struct pci_iommu *iommu; |
387 | struct pci_strbuf *strbuf; | 436 | struct pci_strbuf *strbuf; |
388 | iopte_t *base; | 437 | iopte_t *base; |
389 | unsigned long flags, npages, i, ctx; | 438 | unsigned long flags, npages, ctx; |
390 | 439 | ||
391 | if (direction == PCI_DMA_NONE) | 440 | if (direction == PCI_DMA_NONE) |
392 | BUG(); | 441 | BUG(); |
@@ -414,29 +463,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int | |||
414 | ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; | 463 | ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; |
415 | 464 | ||
416 | /* Step 1: Kick data out of streaming buffers if necessary. */ | 465 | /* Step 1: Kick data out of streaming buffers if necessary. */ |
417 | if (strbuf->strbuf_enabled) { | 466 | if (strbuf->strbuf_enabled) |
418 | u32 vaddr = bus_addr; | 467 | pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); |
419 | |||
420 | PCI_STC_FLUSHFLAG_INIT(strbuf); | ||
421 | if (strbuf->strbuf_ctxflush && | ||
422 | iommu->iommu_ctxflush) { | ||
423 | unsigned long matchreg, flushreg; | ||
424 | |||
425 | flushreg = strbuf->strbuf_ctxflush; | ||
426 | matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); | ||
427 | do { | ||
428 | pci_iommu_write(flushreg, ctx); | ||
429 | } while(((long)pci_iommu_read(matchreg)) < 0L); | ||
430 | } else { | ||
431 | for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) | ||
432 | pci_iommu_write(strbuf->strbuf_pflush, vaddr); | ||
433 | } | ||
434 | |||
435 | pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); | ||
436 | (void) pci_iommu_read(iommu->write_complete_reg); | ||
437 | while (!PCI_STC_FLUSHFLAG_SET(strbuf)) | ||
438 | membar("#LoadLoad"); | ||
439 | } | ||
440 | 468 | ||
441 | /* Step 2: Clear out first TSB entry. */ | 469 | /* Step 2: Clear out first TSB entry. */ |
442 | iopte_make_dummy(iommu, base); | 470 | iopte_make_dummy(iommu, base); |
@@ -647,29 +675,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, | |||
647 | ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; | 675 | ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; |
648 | 676 | ||
649 | /* Step 1: Kick data out of streaming buffers if necessary. */ | 677 | /* Step 1: Kick data out of streaming buffers if necessary. */ |
650 | if (strbuf->strbuf_enabled) { | 678 | if (strbuf->strbuf_enabled) |
651 | u32 vaddr = (u32) bus_addr; | 679 | pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); |
652 | |||
653 | PCI_STC_FLUSHFLAG_INIT(strbuf); | ||
654 | if (strbuf->strbuf_ctxflush && | ||
655 | iommu->iommu_ctxflush) { | ||
656 | unsigned long matchreg, flushreg; | ||
657 | |||
658 | flushreg = strbuf->strbuf_ctxflush; | ||
659 | matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); | ||
660 | do { | ||
661 | pci_iommu_write(flushreg, ctx); | ||
662 | } while(((long)pci_iommu_read(matchreg)) < 0L); | ||
663 | } else { | ||
664 | for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) | ||
665 | pci_iommu_write(strbuf->strbuf_pflush, vaddr); | ||
666 | } | ||
667 | |||
668 | pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); | ||
669 | (void) pci_iommu_read(iommu->write_complete_reg); | ||
670 | while (!PCI_STC_FLUSHFLAG_SET(strbuf)) | ||
671 | membar("#LoadLoad"); | ||
672 | } | ||
673 | 680 | ||
674 | /* Step 2: Clear out first TSB entry. */ | 681 | /* Step 2: Clear out first TSB entry. */ |
675 | iopte_make_dummy(iommu, base); | 682 | iopte_make_dummy(iommu, base); |
@@ -715,28 +722,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size | |||
715 | } | 722 | } |
716 | 723 | ||
717 | /* Step 2: Kick data out of streaming buffers. */ | 724 | /* Step 2: Kick data out of streaming buffers. */ |
718 | PCI_STC_FLUSHFLAG_INIT(strbuf); | 725 | pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); |
719 | if (iommu->iommu_ctxflush && | ||
720 | strbuf->strbuf_ctxflush) { | ||
721 | unsigned long matchreg, flushreg; | ||
722 | |||
723 | flushreg = strbuf->strbuf_ctxflush; | ||
724 | matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); | ||
725 | do { | ||
726 | pci_iommu_write(flushreg, ctx); | ||
727 | } while(((long)pci_iommu_read(matchreg)) < 0L); | ||
728 | } else { | ||
729 | unsigned long i; | ||
730 | |||
731 | for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE) | ||
732 | pci_iommu_write(strbuf->strbuf_pflush, bus_addr); | ||
733 | } | ||
734 | |||
735 | /* Step 3: Perform flush synchronization sequence. */ | ||
736 | pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); | ||
737 | (void) pci_iommu_read(iommu->write_complete_reg); | ||
738 | while (!PCI_STC_FLUSHFLAG_SET(strbuf)) | ||
739 | membar("#LoadLoad"); | ||
740 | 726 | ||
741 | spin_unlock_irqrestore(&iommu->lock, flags); | 727 | spin_unlock_irqrestore(&iommu->lock, flags); |
742 | } | 728 | } |
@@ -749,7 +735,8 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i | |||
749 | struct pcidev_cookie *pcp; | 735 | struct pcidev_cookie *pcp; |
750 | struct pci_iommu *iommu; | 736 | struct pci_iommu *iommu; |
751 | struct pci_strbuf *strbuf; | 737 | struct pci_strbuf *strbuf; |
752 | unsigned long flags, ctx; | 738 | unsigned long flags, ctx, npages, i; |
739 | u32 bus_addr; | ||
753 | 740 | ||
754 | pcp = pdev->sysdata; | 741 | pcp = pdev->sysdata; |
755 | iommu = pcp->pbm->iommu; | 742 | iommu = pcp->pbm->iommu; |
@@ -772,36 +759,14 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i | |||
772 | } | 759 | } |
773 | 760 | ||
774 | /* Step 2: Kick data out of streaming buffers. */ | 761 | /* Step 2: Kick data out of streaming buffers. */ |
775 | PCI_STC_FLUSHFLAG_INIT(strbuf); | 762 | bus_addr = sglist[0].dma_address & IO_PAGE_MASK; |
776 | if (iommu->iommu_ctxflush && | 763 | for(i = 1; i < nelems; i++) |
777 | strbuf->strbuf_ctxflush) { | 764 | if (!sglist[i].dma_length) |
778 | unsigned long matchreg, flushreg; | 765 | break; |
779 | 766 | i--; | |
780 | flushreg = strbuf->strbuf_ctxflush; | 767 | npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) |
781 | matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); | 768 | - bus_addr) >> IO_PAGE_SHIFT; |
782 | do { | 769 | pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); |
783 | pci_iommu_write(flushreg, ctx); | ||
784 | } while (((long)pci_iommu_read(matchreg)) < 0L); | ||
785 | } else { | ||
786 | unsigned long i, npages; | ||
787 | u32 bus_addr; | ||
788 | |||
789 | bus_addr = sglist[0].dma_address & IO_PAGE_MASK; | ||
790 | |||
791 | for(i = 1; i < nelems; i++) | ||
792 | if (!sglist[i].dma_length) | ||
793 | break; | ||
794 | i--; | ||
795 | npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT; | ||
796 | for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE) | ||
797 | pci_iommu_write(strbuf->strbuf_pflush, bus_addr); | ||
798 | } | ||
799 | |||
800 | /* Step 3: Perform flush synchronization sequence. */ | ||
801 | pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); | ||
802 | (void) pci_iommu_read(iommu->write_complete_reg); | ||
803 | while (!PCI_STC_FLUSHFLAG_SET(strbuf)) | ||
804 | membar("#LoadLoad"); | ||
805 | 770 | ||
806 | spin_unlock_irqrestore(&iommu->lock, flags); | 771 | spin_unlock_irqrestore(&iommu->lock, flags); |
807 | } | 772 | } |
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 14d9c3a21b9a..d3eca98e1fe7 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c | |||
@@ -117,19 +117,34 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages | |||
117 | 117 | ||
118 | #define STRBUF_TAG_VALID 0x02UL | 118 | #define STRBUF_TAG_VALID 0x02UL |
119 | 119 | ||
120 | static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) | 120 | static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) |
121 | { | 121 | { |
122 | unsigned long n; | ||
123 | int limit; | ||
124 | |||
122 | iommu->strbuf_flushflag = 0UL; | 125 | iommu->strbuf_flushflag = 0UL; |
123 | while (npages--) | 126 | n = npages; |
124 | upa_writeq(base + (npages << IO_PAGE_SHIFT), | 127 | while (n--) |
128 | upa_writeq(base + (n << IO_PAGE_SHIFT), | ||
125 | iommu->strbuf_regs + STRBUF_PFLUSH); | 129 | iommu->strbuf_regs + STRBUF_PFLUSH); |
126 | 130 | ||
127 | /* Whoopee cushion! */ | 131 | /* Whoopee cushion! */ |
128 | upa_writeq(__pa(&iommu->strbuf_flushflag), | 132 | upa_writeq(__pa(&iommu->strbuf_flushflag), |
129 | iommu->strbuf_regs + STRBUF_FSYNC); | 133 | iommu->strbuf_regs + STRBUF_FSYNC); |
130 | upa_readq(iommu->sbus_control_reg); | 134 | upa_readq(iommu->sbus_control_reg); |
131 | while (iommu->strbuf_flushflag == 0UL) | 135 | |
136 | limit = 10000; | ||
137 | while (iommu->strbuf_flushflag == 0UL) { | ||
138 | limit--; | ||
139 | if (!limit) | ||
140 | break; | ||
141 | udelay(10); | ||
132 | membar("#LoadLoad"); | 142 | membar("#LoadLoad"); |
143 | } | ||
144 | if (!limit) | ||
145 | printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout " | ||
146 | "vaddr[%08x] npages[%ld]\n", | ||
147 | base, npages); | ||
133 | } | 148 | } |
134 | 149 | ||
135 | static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) | 150 | static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) |
@@ -406,7 +421,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, | |||
406 | 421 | ||
407 | spin_lock_irqsave(&iommu->lock, flags); | 422 | spin_lock_irqsave(&iommu->lock, flags); |
408 | free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); | 423 | free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); |
409 | strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT); | 424 | sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT); |
410 | spin_unlock_irqrestore(&iommu->lock, flags); | 425 | spin_unlock_irqrestore(&iommu->lock, flags); |
411 | } | 426 | } |
412 | 427 | ||
@@ -569,7 +584,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int | |||
569 | iommu = sdev->bus->iommu; | 584 | iommu = sdev->bus->iommu; |
570 | spin_lock_irqsave(&iommu->lock, flags); | 585 | spin_lock_irqsave(&iommu->lock, flags); |
571 | free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); | 586 | free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); |
572 | strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT); | 587 | sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT); |
573 | spin_unlock_irqrestore(&iommu->lock, flags); | 588 | spin_unlock_irqrestore(&iommu->lock, flags); |
574 | } | 589 | } |
575 | 590 | ||
@@ -581,7 +596,7 @@ void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t | |||
581 | size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); | 596 | size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); |
582 | 597 | ||
583 | spin_lock_irqsave(&iommu->lock, flags); | 598 | spin_lock_irqsave(&iommu->lock, flags); |
584 | strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT); | 599 | sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT); |
585 | spin_unlock_irqrestore(&iommu->lock, flags); | 600 | spin_unlock_irqrestore(&iommu->lock, flags); |
586 | } | 601 | } |
587 | 602 | ||
@@ -605,7 +620,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int | |||
605 | size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base; | 620 | size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base; |
606 | 621 | ||
607 | spin_lock_irqsave(&iommu->lock, flags); | 622 | spin_lock_irqsave(&iommu->lock, flags); |
608 | strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT); | 623 | sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT); |
609 | spin_unlock_irqrestore(&iommu->lock, flags); | 624 | spin_unlock_irqrestore(&iommu->lock, flags); |
610 | } | 625 | } |
611 | 626 | ||
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c index e5fa1703856b..650d5e924f47 100644 --- a/drivers/sbus/char/aurora.c +++ b/drivers/sbus/char/aurora.c | |||
@@ -81,10 +81,6 @@ unsigned char irqs[4] = { | |||
81 | int irqhit=0; | 81 | int irqhit=0; |
82 | #endif | 82 | #endif |
83 | 83 | ||
84 | #ifndef MIN | ||
85 | #define MIN(a,b) ((a) < (b) ? (a) : (b)) | ||
86 | #endif | ||
87 | |||
88 | static struct tty_driver *aurora_driver; | 84 | static struct tty_driver *aurora_driver; |
89 | static struct Aurora_board aurora_board[AURORA_NBOARD] = { | 85 | static struct Aurora_board aurora_board[AURORA_NBOARD] = { |
90 | {0,}, | 86 | {0,}, |
@@ -594,7 +590,7 @@ static void aurora_transmit(struct Aurora_board const * bp, int chip) | |||
594 | &bp->r[chip]->r[CD180_TDR]); | 590 | &bp->r[chip]->r[CD180_TDR]); |
595 | port->COR2 &= ~COR2_ETC; | 591 | port->COR2 &= ~COR2_ETC; |
596 | } | 592 | } |
597 | count = MIN(port->break_length, 0xff); | 593 | count = min(port->break_length, 0xff); |
598 | sbus_writeb(CD180_C_ESC, | 594 | sbus_writeb(CD180_C_ESC, |
599 | &bp->r[chip]->r[CD180_TDR]); | 595 | &bp->r[chip]->r[CD180_TDR]); |
600 | sbus_writeb(CD180_C_DELAY, | 596 | sbus_writeb(CD180_C_DELAY, |
@@ -1575,7 +1571,7 @@ static int aurora_write(struct tty_struct * tty, | |||
1575 | save_flags(flags); | 1571 | save_flags(flags); |
1576 | while (1) { | 1572 | while (1) { |
1577 | cli(); | 1573 | cli(); |
1578 | c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, | 1574 | c = min(count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, |
1579 | SERIAL_XMIT_SIZE - port->xmit_head)); | 1575 | SERIAL_XMIT_SIZE - port->xmit_head)); |
1580 | if (c <= 0) { | 1576 | if (c <= 0) { |
1581 | restore_flags(flags); | 1577 | restore_flags(flags); |
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; |
diff --git a/drivers/serial/sunsab.h b/drivers/serial/sunsab.h index 686086fcbbf5..b78e1f7b8050 100644 --- a/drivers/serial/sunsab.h +++ b/drivers/serial/sunsab.h | |||
@@ -126,6 +126,7 @@ union sab82532_irq_status { | |||
126 | /* irqflags bits */ | 126 | /* irqflags bits */ |
127 | #define SAB82532_ALLS 0x00000001 | 127 | #define SAB82532_ALLS 0x00000001 |
128 | #define SAB82532_XPR 0x00000002 | 128 | #define SAB82532_XPR 0x00000002 |
129 | #define SAB82532_REGS_PENDING 0x00000004 | ||
129 | 130 | ||
130 | /* RFIFO Status Byte */ | 131 | /* RFIFO Status Byte */ |
131 | #define SAB82532_RSTAT_PE 0x80 | 132 | #define SAB82532_RSTAT_PE 0x80 |