aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJanusz Krzysztofik <jkrzyszt@tis.icnet.pl>2010-02-15 13:03:33 -0500
committerTony Lindgren <tony@atomide.com>2010-02-15 13:03:33 -0500
commit96fbd74551e9cae8fd5e9cb62a0a19336a3064fa (patch)
treec929c609f651043fa9eaf1ab99de55a505262a9c /arch
parentc8c99699bd25d8b238ba75d2530d1be90e3c39ea (diff)
omap: McBSP: Use cache when modifying individual register bits
Change the way McBSP registers are updated: use cached values instead of relying upon those read back from the device. With this patch, I have finally managed to get rid of all random playback/recording hangups on my OMAP1510 based Amstrad Delta hardware. Before that, values read back from McBSP registers to be used for updating them happened to be errornous. From the hardware side, the issue appeared to be caused by a relatively high power requirements of an external USB adapter connected to the board's printer dedicated USB port. I think there is one important point that makes this patch worth of applying, apart from my hardware quality. With the current code, if it ever happens to any machine, no matter if OMAP1510 or newer, to read incorrect value from a McBSP register, this wrong value will get written back without any checking. That can lead to hardware damage if, for example, an input pin is turned into output as a result. Applies on top of patch 3 from this series: [PATCH v9 3/4] OMAP: McBSP: Introduce caching in register write operations Tested on OMAP1510 based Amstrad Delta using linux-omap for-next, commit fb7380d70e041e4b3892f6b19dff7efb609d15a4 (2.6.33-rc3+ dated 2010-01-11). Compile-tested with omap_3430sdp_defconfig. Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Acked-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Acked-by: Jarkko Nikula <jhnikula@gmail.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/plat-omap/mcbsp.c78
1 files changed, 47 insertions, 31 deletions
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 61e440a0f7cd..473be3dc2cf5 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -114,7 +114,8 @@ static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
114 dev_err(mcbsp_tx->dev, "TX Frame Sync Error! : 0x%x\n", 114 dev_err(mcbsp_tx->dev, "TX Frame Sync Error! : 0x%x\n",
115 irqst_spcr2); 115 irqst_spcr2);
116 /* Writing zero to XSYNC_ERR clears the IRQ */ 116 /* Writing zero to XSYNC_ERR clears the IRQ */
117 MCBSP_WRITE(mcbsp_tx, SPCR2, irqst_spcr2 & ~(XSYNC_ERR)); 117 MCBSP_WRITE(mcbsp_tx, SPCR2,
118 MCBSP_READ_CACHE(mcbsp_tx, SPCR2) & ~(XSYNC_ERR));
118 } else { 119 } else {
119 complete(&mcbsp_tx->tx_irq_completion); 120 complete(&mcbsp_tx->tx_irq_completion);
120 } 121 }
@@ -134,7 +135,8 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
134 dev_err(mcbsp_rx->dev, "RX Frame Sync Error! : 0x%x\n", 135 dev_err(mcbsp_rx->dev, "RX Frame Sync Error! : 0x%x\n",
135 irqst_spcr1); 136 irqst_spcr1);
136 /* Writing zero to RSYNC_ERR clears the IRQ */ 137 /* Writing zero to RSYNC_ERR clears the IRQ */
137 MCBSP_WRITE(mcbsp_rx, SPCR1, irqst_spcr1 & ~(RSYNC_ERR)); 138 MCBSP_WRITE(mcbsp_rx, SPCR1,
139 MCBSP_READ_CACHE(mcbsp_rx, SPCR1) & ~(RSYNC_ERR));
138 } else { 140 } else {
139 complete(&mcbsp_rx->tx_irq_completion); 141 complete(&mcbsp_rx->tx_irq_completion);
140 } 142 }
@@ -544,24 +546,25 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
544 } 546 }
545 mcbsp = id_to_mcbsp_ptr(id); 547 mcbsp = id_to_mcbsp_ptr(id);
546 548
547 mcbsp->rx_word_length = (MCBSP_READ(mcbsp, RCR1) >> 5) & 0x7; 549 mcbsp->rx_word_length = (MCBSP_READ_CACHE(mcbsp, RCR1) >> 5) & 0x7;
548 mcbsp->tx_word_length = (MCBSP_READ(mcbsp, XCR1) >> 5) & 0x7; 550 mcbsp->tx_word_length = (MCBSP_READ_CACHE(mcbsp, XCR1) >> 5) & 0x7;
549 551
550 idle = !((MCBSP_READ(mcbsp, SPCR2) | MCBSP_READ(mcbsp, SPCR1)) & 1); 552 idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
553 MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
551 554
552 if (idle) { 555 if (idle) {
553 /* Start the sample generator */ 556 /* Start the sample generator */
554 w = MCBSP_READ(mcbsp, SPCR2); 557 w = MCBSP_READ_CACHE(mcbsp, SPCR2);
555 MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6)); 558 MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6));
556 } 559 }
557 560
558 /* Enable transmitter and receiver */ 561 /* Enable transmitter and receiver */
559 tx &= 1; 562 tx &= 1;
560 w = MCBSP_READ(mcbsp, SPCR2); 563 w = MCBSP_READ_CACHE(mcbsp, SPCR2);
561 MCBSP_WRITE(mcbsp, SPCR2, w | tx); 564 MCBSP_WRITE(mcbsp, SPCR2, w | tx);
562 565
563 rx &= 1; 566 rx &= 1;
564 w = MCBSP_READ(mcbsp, SPCR1); 567 w = MCBSP_READ_CACHE(mcbsp, SPCR1);
565 MCBSP_WRITE(mcbsp, SPCR1, w | rx); 568 MCBSP_WRITE(mcbsp, SPCR1, w | rx);
566 569
567 /* 570 /*
@@ -574,16 +577,16 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
574 577
575 if (idle) { 578 if (idle) {
576 /* Start frame sync */ 579 /* Start frame sync */
577 w = MCBSP_READ(mcbsp, SPCR2); 580 w = MCBSP_READ_CACHE(mcbsp, SPCR2);
578 MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7)); 581 MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
579 } 582 }
580 583
581 if (cpu_is_omap2430() || cpu_is_omap34xx()) { 584 if (cpu_is_omap2430() || cpu_is_omap34xx()) {
582 /* Release the transmitter and receiver */ 585 /* Release the transmitter and receiver */
583 w = MCBSP_READ(mcbsp, XCCR); 586 w = MCBSP_READ_CACHE(mcbsp, XCCR);
584 w &= ~(tx ? XDISABLE : 0); 587 w &= ~(tx ? XDISABLE : 0);
585 MCBSP_WRITE(mcbsp, XCCR, w); 588 MCBSP_WRITE(mcbsp, XCCR, w);
586 w = MCBSP_READ(mcbsp, RCCR); 589 w = MCBSP_READ_CACHE(mcbsp, RCCR);
587 w &= ~(rx ? RDISABLE : 0); 590 w &= ~(rx ? RDISABLE : 0);
588 MCBSP_WRITE(mcbsp, RCCR, w); 591 MCBSP_WRITE(mcbsp, RCCR, w);
589 } 592 }
@@ -609,28 +612,29 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
609 /* Reset transmitter */ 612 /* Reset transmitter */
610 tx &= 1; 613 tx &= 1;
611 if (cpu_is_omap2430() || cpu_is_omap34xx()) { 614 if (cpu_is_omap2430() || cpu_is_omap34xx()) {
612 w = MCBSP_READ(mcbsp, XCCR); 615 w = MCBSP_READ_CACHE(mcbsp, XCCR);
613 w |= (tx ? XDISABLE : 0); 616 w |= (tx ? XDISABLE : 0);
614 MCBSP_WRITE(mcbsp, XCCR, w); 617 MCBSP_WRITE(mcbsp, XCCR, w);
615 } 618 }
616 w = MCBSP_READ(mcbsp, SPCR2); 619 w = MCBSP_READ_CACHE(mcbsp, SPCR2);
617 MCBSP_WRITE(mcbsp, SPCR2, w & ~tx); 620 MCBSP_WRITE(mcbsp, SPCR2, w & ~tx);
618 621
619 /* Reset receiver */ 622 /* Reset receiver */
620 rx &= 1; 623 rx &= 1;
621 if (cpu_is_omap2430() || cpu_is_omap34xx()) { 624 if (cpu_is_omap2430() || cpu_is_omap34xx()) {
622 w = MCBSP_READ(mcbsp, RCCR); 625 w = MCBSP_READ_CACHE(mcbsp, RCCR);
623 w |= (rx ? RDISABLE : 0); 626 w |= (rx ? RDISABLE : 0);
624 MCBSP_WRITE(mcbsp, RCCR, w); 627 MCBSP_WRITE(mcbsp, RCCR, w);
625 } 628 }
626 w = MCBSP_READ(mcbsp, SPCR1); 629 w = MCBSP_READ_CACHE(mcbsp, SPCR1);
627 MCBSP_WRITE(mcbsp, SPCR1, w & ~rx); 630 MCBSP_WRITE(mcbsp, SPCR1, w & ~rx);
628 631
629 idle = !((MCBSP_READ(mcbsp, SPCR2) | MCBSP_READ(mcbsp, SPCR1)) & 1); 632 idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
633 MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
630 634
631 if (idle) { 635 if (idle) {
632 /* Reset the sample rate generator */ 636 /* Reset the sample rate generator */
633 w = MCBSP_READ(mcbsp, SPCR2); 637 w = MCBSP_READ_CACHE(mcbsp, SPCR2);
634 MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6)); 638 MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6));
635 } 639 }
636} 640}
@@ -653,7 +657,7 @@ int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
653 if (MCBSP_READ(mcbsp, SPCR2) & XSYNC_ERR) { 657 if (MCBSP_READ(mcbsp, SPCR2) & XSYNC_ERR) {
654 /* clear error */ 658 /* clear error */
655 MCBSP_WRITE(mcbsp, SPCR2, 659 MCBSP_WRITE(mcbsp, SPCR2,
656 MCBSP_READ(mcbsp, SPCR2) & (~XSYNC_ERR)); 660 MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XSYNC_ERR));
657 /* resend */ 661 /* resend */
658 return -1; 662 return -1;
659 } else { 663 } else {
@@ -662,10 +666,12 @@ int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
662 while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) { 666 while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) {
663 if (attemps++ > 1000) { 667 if (attemps++ > 1000) {
664 MCBSP_WRITE(mcbsp, SPCR2, 668 MCBSP_WRITE(mcbsp, SPCR2,
665 MCBSP_READ(mcbsp, SPCR2) & (~XRST)); 669 MCBSP_READ_CACHE(mcbsp, SPCR2) &
670 (~XRST));
666 udelay(10); 671 udelay(10);
667 MCBSP_WRITE(mcbsp, SPCR2, 672 MCBSP_WRITE(mcbsp, SPCR2,
668 MCBSP_READ(mcbsp, SPCR2) | (XRST)); 673 MCBSP_READ_CACHE(mcbsp, SPCR2) |
674 (XRST));
669 udelay(10); 675 udelay(10);
670 dev_err(mcbsp->dev, "Could not write to" 676 dev_err(mcbsp->dev, "Could not write to"
671 " McBSP%d Register\n", mcbsp->id); 677 " McBSP%d Register\n", mcbsp->id);
@@ -692,7 +698,7 @@ int omap_mcbsp_pollread(unsigned int id, u16 *buf)
692 if (MCBSP_READ(mcbsp, SPCR1) & RSYNC_ERR) { 698 if (MCBSP_READ(mcbsp, SPCR1) & RSYNC_ERR) {
693 /* clear error */ 699 /* clear error */
694 MCBSP_WRITE(mcbsp, SPCR1, 700 MCBSP_WRITE(mcbsp, SPCR1,
695 MCBSP_READ(mcbsp, SPCR1) & (~RSYNC_ERR)); 701 MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RSYNC_ERR));
696 /* resend */ 702 /* resend */
697 return -1; 703 return -1;
698 } else { 704 } else {
@@ -701,10 +707,12 @@ int omap_mcbsp_pollread(unsigned int id, u16 *buf)
701 while (!(MCBSP_READ(mcbsp, SPCR1) & RRDY)) { 707 while (!(MCBSP_READ(mcbsp, SPCR1) & RRDY)) {
702 if (attemps++ > 1000) { 708 if (attemps++ > 1000) {
703 MCBSP_WRITE(mcbsp, SPCR1, 709 MCBSP_WRITE(mcbsp, SPCR1,
704 MCBSP_READ(mcbsp, SPCR1) & (~RRST)); 710 MCBSP_READ_CACHE(mcbsp, SPCR1) &
711 (~RRST));
705 udelay(10); 712 udelay(10);
706 MCBSP_WRITE(mcbsp, SPCR1, 713 MCBSP_WRITE(mcbsp, SPCR1,
707 MCBSP_READ(mcbsp, SPCR1) | (RRST)); 714 MCBSP_READ_CACHE(mcbsp, SPCR1) |
715 (RRST));
708 udelay(10); 716 udelay(10);
709 dev_err(mcbsp->dev, "Could not read from" 717 dev_err(mcbsp->dev, "Could not read from"
710 " McBSP%d Register\n", mcbsp->id); 718 " McBSP%d Register\n", mcbsp->id);
@@ -790,9 +798,11 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
790 spcr2 = MCBSP_READ(mcbsp, SPCR2); 798 spcr2 = MCBSP_READ(mcbsp, SPCR2);
791 if (attempts++ > 1000) { 799 if (attempts++ > 1000) {
792 /* We must reset the transmitter */ 800 /* We must reset the transmitter */
793 MCBSP_WRITE(mcbsp, SPCR2, spcr2 & (~XRST)); 801 MCBSP_WRITE(mcbsp, SPCR2,
802 MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST));
794 udelay(10); 803 udelay(10);
795 MCBSP_WRITE(mcbsp, SPCR2, spcr2 | XRST); 804 MCBSP_WRITE(mcbsp, SPCR2,
805 MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST);
796 udelay(10); 806 udelay(10);
797 dev_err(mcbsp->dev, "McBSP%d transmitter not " 807 dev_err(mcbsp->dev, "McBSP%d transmitter not "
798 "ready\n", mcbsp->id); 808 "ready\n", mcbsp->id);
@@ -811,9 +821,11 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
811 spcr1 = MCBSP_READ(mcbsp, SPCR1); 821 spcr1 = MCBSP_READ(mcbsp, SPCR1);
812 if (attempts++ > 1000) { 822 if (attempts++ > 1000) {
813 /* We must reset the receiver */ 823 /* We must reset the receiver */
814 MCBSP_WRITE(mcbsp, SPCR1, spcr1 & (~RRST)); 824 MCBSP_WRITE(mcbsp, SPCR1,
825 MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST));
815 udelay(10); 826 udelay(10);
816 MCBSP_WRITE(mcbsp, SPCR1, spcr1 | RRST); 827 MCBSP_WRITE(mcbsp, SPCR1,
828 MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST);
817 udelay(10); 829 udelay(10);
818 dev_err(mcbsp->dev, "McBSP%d receiver not " 830 dev_err(mcbsp->dev, "McBSP%d receiver not "
819 "ready\n", mcbsp->id); 831 "ready\n", mcbsp->id);
@@ -857,9 +869,11 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)
857 spcr2 = MCBSP_READ(mcbsp, SPCR2); 869 spcr2 = MCBSP_READ(mcbsp, SPCR2);
858 if (attempts++ > 1000) { 870 if (attempts++ > 1000) {
859 /* We must reset the transmitter */ 871 /* We must reset the transmitter */
860 MCBSP_WRITE(mcbsp, SPCR2, spcr2 & (~XRST)); 872 MCBSP_WRITE(mcbsp, SPCR2,
873 MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST));
861 udelay(10); 874 udelay(10);
862 MCBSP_WRITE(mcbsp, SPCR2, spcr2 | XRST); 875 MCBSP_WRITE(mcbsp, SPCR2,
876 MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST);
863 udelay(10); 877 udelay(10);
864 dev_err(mcbsp->dev, "McBSP%d transmitter not " 878 dev_err(mcbsp->dev, "McBSP%d transmitter not "
865 "ready\n", mcbsp->id); 879 "ready\n", mcbsp->id);
@@ -878,9 +892,11 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)
878 spcr1 = MCBSP_READ(mcbsp, SPCR1); 892 spcr1 = MCBSP_READ(mcbsp, SPCR1);
879 if (attempts++ > 1000) { 893 if (attempts++ > 1000) {
880 /* We must reset the receiver */ 894 /* We must reset the receiver */
881 MCBSP_WRITE(mcbsp, SPCR1, spcr1 & (~RRST)); 895 MCBSP_WRITE(mcbsp, SPCR1,
896 MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST));
882 udelay(10); 897 udelay(10);
883 MCBSP_WRITE(mcbsp, SPCR1, spcr1 | RRST); 898 MCBSP_WRITE(mcbsp, SPCR1,
899 MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST);
884 udelay(10); 900 udelay(10);
885 dev_err(mcbsp->dev, "McBSP%d receiver not " 901 dev_err(mcbsp->dev, "McBSP%d receiver not "
886 "ready\n", mcbsp->id); 902 "ready\n", mcbsp->id);