diff options
Diffstat (limited to 'drivers/spi/davinci_spi.c')
-rw-r--r-- | drivers/spi/davinci_spi.c | 96 |
1 files changed, 41 insertions, 55 deletions
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 198f062da370..cd37697850cf 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c | |||
@@ -91,6 +91,10 @@ | |||
91 | #define SPIFLG_BITERR_MASK BIT(4) | 91 | #define SPIFLG_BITERR_MASK BIT(4) |
92 | #define SPIFLG_OVRRUN_MASK BIT(6) | 92 | #define SPIFLG_OVRRUN_MASK BIT(6) |
93 | #define SPIFLG_BUF_INIT_ACTIVE_MASK BIT(24) | 93 | #define SPIFLG_BUF_INIT_ACTIVE_MASK BIT(24) |
94 | #define SPIFLG_ERROR_MASK (SPIFLG_DLEN_ERR_MASK \ | ||
95 | | SPIFLG_TIMEOUT_MASK | SPIFLG_PARERR_MASK \ | ||
96 | | SPIFLG_DESYNC_MASK | SPIFLG_BITERR_MASK \ | ||
97 | | SPIFLG_OVRRUN_MASK) | ||
94 | 98 | ||
95 | #define SPIINT_DMA_REQ_EN BIT(16) | 99 | #define SPIINT_DMA_REQ_EN BIT(16) |
96 | 100 | ||
@@ -601,10 +605,10 @@ static int davinci_spi_check_error(struct davinci_spi *davinci_spi, | |||
601 | static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) | 605 | static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) |
602 | { | 606 | { |
603 | struct davinci_spi *davinci_spi; | 607 | struct davinci_spi *davinci_spi; |
604 | int status, count, ret; | 608 | int ret; |
605 | u8 conv; | 609 | int rcount, wcount; |
606 | u32 tx_data, data1_reg_val; | 610 | u32 tx_data, data1_reg_val; |
607 | u32 buf_val, flg_val; | 611 | u32 errors = 0; |
608 | struct davinci_spi_platform_data *pdata; | 612 | struct davinci_spi_platform_data *pdata; |
609 | 613 | ||
610 | davinci_spi = spi_master_get_devdata(spi->master); | 614 | davinci_spi = spi_master_get_devdata(spi->master); |
@@ -612,70 +616,51 @@ static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) | |||
612 | 616 | ||
613 | davinci_spi->tx = t->tx_buf; | 617 | davinci_spi->tx = t->tx_buf; |
614 | davinci_spi->rx = t->rx_buf; | 618 | davinci_spi->rx = t->rx_buf; |
615 | 619 | wcount = t->len / davinci_spi->bytes_per_word[spi->chip_select]; | |
616 | /* convert len to words based on bits_per_word */ | 620 | rcount = wcount; |
617 | conv = davinci_spi->bytes_per_word[spi->chip_select]; | ||
618 | data1_reg_val = ioread32(davinci_spi->base + SPIDAT1); | ||
619 | 621 | ||
620 | ret = davinci_spi_bufs_prep(spi, davinci_spi); | 622 | ret = davinci_spi_bufs_prep(spi, davinci_spi); |
621 | if (ret) | 623 | if (ret) |
622 | return ret; | 624 | return ret; |
623 | 625 | ||
626 | data1_reg_val = ioread32(davinci_spi->base + SPIDAT1); | ||
627 | |||
624 | /* Enable SPI */ | 628 | /* Enable SPI */ |
625 | set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); | 629 | set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); |
626 | 630 | ||
627 | count = t->len / conv; | ||
628 | |||
629 | clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL); | 631 | clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL); |
630 | 632 | ||
631 | /* Determine the command to execute READ or WRITE */ | 633 | /* start the transfer */ |
632 | if (t->tx_buf) { | 634 | wcount--; |
635 | tx_data = davinci_spi->get_tx(davinci_spi); | ||
636 | data1_reg_val &= 0xFFFF0000; | ||
637 | data1_reg_val |= tx_data & 0xFFFF; | ||
638 | iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); | ||
633 | 639 | ||
634 | while (1) { | 640 | while (rcount > 0 || wcount > 0) { |
635 | tx_data = davinci_spi->get_tx(davinci_spi); | ||
636 | 641 | ||
637 | data1_reg_val &= ~(0xFFFF); | 642 | u32 buf, status; |
638 | data1_reg_val |= (0xFFFF & tx_data); | ||
639 | |||
640 | buf_val = ioread32(davinci_spi->base + SPIBUF); | ||
641 | if ((buf_val & SPIBUF_TXFULL_MASK) == 0) { | ||
642 | iowrite32(data1_reg_val, | ||
643 | davinci_spi->base + SPIDAT1); | ||
644 | |||
645 | count--; | ||
646 | } | ||
647 | while (ioread32(davinci_spi->base + SPIBUF) | ||
648 | & SPIBUF_RXEMPTY_MASK) | ||
649 | cpu_relax(); | ||
650 | |||
651 | /* getting the returned byte */ | ||
652 | if (t->rx_buf) { | ||
653 | buf_val = ioread32(davinci_spi->base + SPIBUF); | ||
654 | davinci_spi->get_rx(buf_val, davinci_spi); | ||
655 | } | ||
656 | if (count <= 0) | ||
657 | break; | ||
658 | } | ||
659 | } else { | ||
660 | while (1) { | ||
661 | /* keeps the serial clock going */ | ||
662 | if ((ioread32(davinci_spi->base + SPIBUF) | ||
663 | & SPIBUF_TXFULL_MASK) == 0) | ||
664 | iowrite32(data1_reg_val, | ||
665 | davinci_spi->base + SPIDAT1); | ||
666 | 643 | ||
667 | while (ioread32(davinci_spi->base + SPIBUF) & | 644 | buf = ioread32(davinci_spi->base + SPIBUF); |
668 | SPIBUF_RXEMPTY_MASK) | ||
669 | cpu_relax(); | ||
670 | 645 | ||
671 | flg_val = ioread32(davinci_spi->base + SPIFLG); | 646 | if (!(buf & SPIBUF_RXEMPTY_MASK)) { |
672 | buf_val = ioread32(davinci_spi->base + SPIBUF); | 647 | davinci_spi->get_rx(buf & 0xFFFF, davinci_spi); |
648 | rcount--; | ||
649 | } | ||
673 | 650 | ||
674 | davinci_spi->get_rx(buf_val, davinci_spi); | 651 | status = ioread32(davinci_spi->base + SPIFLG); |
675 | 652 | ||
676 | count--; | 653 | if (unlikely(status & SPIFLG_ERROR_MASK)) { |
677 | if (count <= 0) | 654 | errors = status & SPIFLG_ERROR_MASK; |
678 | break; | 655 | break; |
656 | } | ||
657 | |||
658 | if (wcount > 0 && !(buf & SPIBUF_TXFULL_MASK)) { | ||
659 | wcount--; | ||
660 | tx_data = davinci_spi->get_tx(davinci_spi); | ||
661 | data1_reg_val &= ~0xFFFF; | ||
662 | data1_reg_val |= 0xFFFF & tx_data; | ||
663 | iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); | ||
679 | } | 664 | } |
680 | } | 665 | } |
681 | 666 | ||
@@ -683,11 +668,12 @@ static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) | |||
683 | * Check for bit error, desync error,parity error,timeout error and | 668 | * Check for bit error, desync error,parity error,timeout error and |
684 | * receive overflow errors | 669 | * receive overflow errors |
685 | */ | 670 | */ |
686 | status = ioread32(davinci_spi->base + SPIFLG); | 671 | if (errors) { |
687 | 672 | ret = davinci_spi_check_error(davinci_spi, errors); | |
688 | ret = davinci_spi_check_error(davinci_spi, status); | 673 | WARN(!ret, "%s: error reported but no error found!\n", |
689 | if (ret != 0) | 674 | dev_name(&spi->dev)); |
690 | return ret; | 675 | return ret; |
676 | } | ||
691 | 677 | ||
692 | return t->len; | 678 | return t->len; |
693 | } | 679 | } |