diff options
author | Brian Niebuhr <bniebuhr@efjohnson.com> | 2010-09-02 07:22:06 -0400 |
---|---|---|
committer | Sekhar Nori <nsekhar@ti.com> | 2010-11-18 08:08:30 -0500 |
commit | e0d205e9914476e96596c5339fa440fb314ef03b (patch) | |
tree | 73e66099f725499b8adb145b8835d90add228c8e /drivers/spi | |
parent | 839c996ca8dd56f9ea80d7fc0c8b18b01394c82a (diff) |
spi: davinci: add support for interrupt mode
Add support for SPI interrupt mode operation.
Define a per chip-select "io type" variable which
specifies if the transfers on this chip-select should
happen in interrupt mode or polled mode.
Introduce a new function davinci_spi_process_events()
to help consolidate the code between interrupt mode
processing and polled mode processing.
Signed-off-by: Brian Niebuhr <bniebuhr@efjohnson.com>
Tested-By: Michael Williamson <michael.williamson@criticallink.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/davinci_spi.c | 145 |
1 files changed, 115 insertions, 30 deletions
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index cd37697850cf..45cc1a77a512 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c | |||
@@ -59,6 +59,9 @@ | |||
59 | #define SPIPC0_SPIENA_MASK BIT(8) /* nREADY */ | 59 | #define SPIPC0_SPIENA_MASK BIT(8) /* nREADY */ |
60 | 60 | ||
61 | #define SPIINT_MASKALL 0x0101035F | 61 | #define SPIINT_MASKALL 0x0101035F |
62 | #define SPIINT_MASKINT 0x0000015F | ||
63 | #define SPI_INTLVL_1 0x000001FF | ||
64 | #define SPI_INTLVL_0 0x00000000 | ||
62 | 65 | ||
63 | /* SPIDAT1 (upper 16 bit defines) */ | 66 | /* SPIDAT1 (upper 16 bit defines) */ |
64 | #define SPIDAT1_CSHOLD_MASK BIT(12) | 67 | #define SPIDAT1_CSHOLD_MASK BIT(12) |
@@ -132,10 +135,14 @@ struct davinci_spi { | |||
132 | resource_size_t pbase; | 135 | resource_size_t pbase; |
133 | void __iomem *base; | 136 | void __iomem *base; |
134 | size_t region_size; | 137 | size_t region_size; |
138 | u32 irq; | ||
139 | struct completion done; | ||
135 | 140 | ||
136 | const void *tx; | 141 | const void *tx; |
137 | void *rx; | 142 | void *rx; |
138 | u8 *tmp_buf; | 143 | u8 *tmp_buf; |
144 | int rcount; | ||
145 | int wcount; | ||
139 | struct davinci_spi_dma *dma_channels; | 146 | struct davinci_spi_dma *dma_channels; |
140 | struct davinci_spi_platform_data *pdata; | 147 | struct davinci_spi_platform_data *pdata; |
141 | 148 | ||
@@ -594,6 +601,43 @@ static int davinci_spi_check_error(struct davinci_spi *davinci_spi, | |||
594 | } | 601 | } |
595 | 602 | ||
596 | /** | 603 | /** |
604 | * davinci_spi_process_events - check for and handle any SPI controller events | ||
605 | * @davinci_spi: the controller data | ||
606 | * | ||
607 | * This function will check the SPIFLG register and handle any events that are | ||
608 | * detected there | ||
609 | */ | ||
610 | static int davinci_spi_process_events(struct davinci_spi *davinci_spi) | ||
611 | { | ||
612 | u32 buf, status, errors = 0, data1_reg_val; | ||
613 | |||
614 | buf = ioread32(davinci_spi->base + SPIBUF); | ||
615 | |||
616 | if (davinci_spi->rcount > 0 && !(buf & SPIBUF_RXEMPTY_MASK)) { | ||
617 | davinci_spi->get_rx(buf & 0xFFFF, davinci_spi); | ||
618 | davinci_spi->rcount--; | ||
619 | } | ||
620 | |||
621 | status = ioread32(davinci_spi->base + SPIFLG); | ||
622 | |||
623 | if (unlikely(status & SPIFLG_ERROR_MASK)) { | ||
624 | errors = status & SPIFLG_ERROR_MASK; | ||
625 | goto out; | ||
626 | } | ||
627 | |||
628 | if (davinci_spi->wcount > 0 && !(buf & SPIBUF_TXFULL_MASK)) { | ||
629 | data1_reg_val = ioread32(davinci_spi->base + SPIDAT1); | ||
630 | davinci_spi->wcount--; | ||
631 | data1_reg_val &= ~0xFFFF; | ||
632 | data1_reg_val |= 0xFFFF & davinci_spi->get_tx(davinci_spi); | ||
633 | iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); | ||
634 | } | ||
635 | |||
636 | out: | ||
637 | return errors; | ||
638 | } | ||
639 | |||
640 | /** | ||
597 | * davinci_spi_bufs - functions which will handle transfer data | 641 | * davinci_spi_bufs - functions which will handle transfer data |
598 | * @spi: spi device on which data transfer to be done | 642 | * @spi: spi device on which data transfer to be done |
599 | * @t: spi transfer in which transfer info is filled | 643 | * @t: spi transfer in which transfer info is filled |
@@ -606,18 +650,22 @@ static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) | |||
606 | { | 650 | { |
607 | struct davinci_spi *davinci_spi; | 651 | struct davinci_spi *davinci_spi; |
608 | int ret; | 652 | int ret; |
609 | int rcount, wcount; | ||
610 | u32 tx_data, data1_reg_val; | 653 | u32 tx_data, data1_reg_val; |
611 | u32 errors = 0; | 654 | u32 errors = 0; |
655 | struct davinci_spi_config *spicfg; | ||
612 | struct davinci_spi_platform_data *pdata; | 656 | struct davinci_spi_platform_data *pdata; |
613 | 657 | ||
614 | davinci_spi = spi_master_get_devdata(spi->master); | 658 | davinci_spi = spi_master_get_devdata(spi->master); |
615 | pdata = davinci_spi->pdata; | 659 | pdata = davinci_spi->pdata; |
660 | spicfg = (struct davinci_spi_config *)spi->controller_data; | ||
661 | if (!spicfg) | ||
662 | spicfg = &davinci_spi_default_cfg; | ||
616 | 663 | ||
617 | davinci_spi->tx = t->tx_buf; | 664 | davinci_spi->tx = t->tx_buf; |
618 | davinci_spi->rx = t->rx_buf; | 665 | davinci_spi->rx = t->rx_buf; |
619 | wcount = t->len / davinci_spi->bytes_per_word[spi->chip_select]; | 666 | davinci_spi->wcount = t->len / |
620 | rcount = wcount; | 667 | davinci_spi->bytes_per_word[spi->chip_select]; |
668 | davinci_spi->rcount = davinci_spi->wcount; | ||
621 | 669 | ||
622 | ret = davinci_spi_bufs_prep(spi, davinci_spi); | 670 | ret = davinci_spi_bufs_prep(spi, davinci_spi); |
623 | if (ret) | 671 | if (ret) |
@@ -628,42 +676,32 @@ static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) | |||
628 | /* Enable SPI */ | 676 | /* Enable SPI */ |
629 | set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); | 677 | set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); |
630 | 678 | ||
631 | clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL); | 679 | if (spicfg->io_type == SPI_IO_TYPE_INTR) { |
680 | set_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKINT); | ||
681 | INIT_COMPLETION(davinci_spi->done); | ||
682 | } | ||
632 | 683 | ||
633 | /* start the transfer */ | 684 | /* start the transfer */ |
634 | wcount--; | 685 | davinci_spi->wcount--; |
635 | tx_data = davinci_spi->get_tx(davinci_spi); | 686 | tx_data = davinci_spi->get_tx(davinci_spi); |
636 | data1_reg_val &= 0xFFFF0000; | 687 | data1_reg_val &= 0xFFFF0000; |
637 | data1_reg_val |= tx_data & 0xFFFF; | 688 | data1_reg_val |= tx_data & 0xFFFF; |
638 | iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); | 689 | iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); |
639 | 690 | ||
640 | while (rcount > 0 || wcount > 0) { | 691 | /* Wait for the transfer to complete */ |
641 | 692 | if (spicfg->io_type == SPI_IO_TYPE_INTR) { | |
642 | u32 buf, status; | 693 | wait_for_completion_interruptible(&(davinci_spi->done)); |
643 | 694 | } else { | |
644 | buf = ioread32(davinci_spi->base + SPIBUF); | 695 | while (davinci_spi->rcount > 0 || davinci_spi->wcount > 0) { |
645 | 696 | errors = davinci_spi_process_events(davinci_spi); | |
646 | if (!(buf & SPIBUF_RXEMPTY_MASK)) { | 697 | if (errors) |
647 | davinci_spi->get_rx(buf & 0xFFFF, davinci_spi); | 698 | break; |
648 | rcount--; | 699 | cpu_relax(); |
649 | } | ||
650 | |||
651 | status = ioread32(davinci_spi->base + SPIFLG); | ||
652 | |||
653 | if (unlikely(status & SPIFLG_ERROR_MASK)) { | ||
654 | errors = status & SPIFLG_ERROR_MASK; | ||
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); | ||
664 | } | 700 | } |
665 | } | 701 | } |
666 | 702 | ||
703 | clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL); | ||
704 | |||
667 | /* | 705 | /* |
668 | * Check for bit error, desync error,parity error,timeout error and | 706 | * Check for bit error, desync error,parity error,timeout error and |
669 | * receive overflow errors | 707 | * receive overflow errors |
@@ -678,6 +716,32 @@ static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) | |||
678 | return t->len; | 716 | return t->len; |
679 | } | 717 | } |
680 | 718 | ||
719 | /** | ||
720 | * davinci_spi_irq - Interrupt handler for SPI Master Controller | ||
721 | * @irq: IRQ number for this SPI Master | ||
722 | * @context_data: structure for SPI Master controller davinci_spi | ||
723 | * | ||
724 | * ISR will determine that interrupt arrives either for READ or WRITE command. | ||
725 | * According to command it will do the appropriate action. It will check | ||
726 | * transfer length and if it is not zero then dispatch transfer command again. | ||
727 | * If transfer length is zero then it will indicate the COMPLETION so that | ||
728 | * davinci_spi_bufs function can go ahead. | ||
729 | */ | ||
730 | static irqreturn_t davinci_spi_irq(s32 irq, void *context_data) | ||
731 | { | ||
732 | struct davinci_spi *davinci_spi = context_data; | ||
733 | int status; | ||
734 | |||
735 | status = davinci_spi_process_events(davinci_spi); | ||
736 | if (unlikely(status != 0)) | ||
737 | clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKINT); | ||
738 | |||
739 | if ((!davinci_spi->rcount && !davinci_spi->wcount) || status) | ||
740 | complete(&davinci_spi->done); | ||
741 | |||
742 | return IRQ_HANDLED; | ||
743 | } | ||
744 | |||
681 | static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t) | 745 | static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t) |
682 | { | 746 | { |
683 | struct davinci_spi *davinci_spi; | 747 | struct davinci_spi *davinci_spi; |
@@ -866,11 +930,22 @@ static int davinci_spi_probe(struct platform_device *pdev) | |||
866 | goto release_region; | 930 | goto release_region; |
867 | } | 931 | } |
868 | 932 | ||
933 | davinci_spi->irq = platform_get_irq(pdev, 0); | ||
934 | if (davinci_spi->irq <= 0) { | ||
935 | ret = -EINVAL; | ||
936 | goto unmap_io; | ||
937 | } | ||
938 | |||
939 | ret = request_irq(davinci_spi->irq, davinci_spi_irq, 0, | ||
940 | dev_name(&pdev->dev), davinci_spi); | ||
941 | if (ret) | ||
942 | goto unmap_io; | ||
943 | |||
869 | /* Allocate tmp_buf for tx_buf */ | 944 | /* Allocate tmp_buf for tx_buf */ |
870 | davinci_spi->tmp_buf = kzalloc(SPI_BUFSIZ, GFP_KERNEL); | 945 | davinci_spi->tmp_buf = kzalloc(SPI_BUFSIZ, GFP_KERNEL); |
871 | if (davinci_spi->tmp_buf == NULL) { | 946 | if (davinci_spi->tmp_buf == NULL) { |
872 | ret = -ENOMEM; | 947 | ret = -ENOMEM; |
873 | goto unmap_io; | 948 | goto irq_free; |
874 | } | 949 | } |
875 | 950 | ||
876 | davinci_spi->bitbang.master = spi_master_get(master); | 951 | davinci_spi->bitbang.master = spi_master_get(master); |
@@ -946,6 +1021,8 @@ static int davinci_spi_probe(struct platform_device *pdev) | |||
946 | davinci_spi->get_rx = davinci_spi_rx_buf_u8; | 1021 | davinci_spi->get_rx = davinci_spi_rx_buf_u8; |
947 | davinci_spi->get_tx = davinci_spi_tx_buf_u8; | 1022 | davinci_spi->get_tx = davinci_spi_tx_buf_u8; |
948 | 1023 | ||
1024 | init_completion(&davinci_spi->done); | ||
1025 | |||
949 | /* Reset In/OUT SPI module */ | 1026 | /* Reset In/OUT SPI module */ |
950 | iowrite32(0, davinci_spi->base + SPIGCR0); | 1027 | iowrite32(0, davinci_spi->base + SPIGCR0); |
951 | udelay(100); | 1028 | udelay(100); |
@@ -967,6 +1044,11 @@ static int davinci_spi_probe(struct platform_device *pdev) | |||
967 | clear_io_bits(davinci_spi->base + SPIGCR1, | 1044 | clear_io_bits(davinci_spi->base + SPIGCR1, |
968 | SPIGCR1_CLKMOD_MASK); | 1045 | SPIGCR1_CLKMOD_MASK); |
969 | 1046 | ||
1047 | if (pdata->intr_line) | ||
1048 | iowrite32(SPI_INTLVL_1, davinci_spi->base + SPILVL); | ||
1049 | else | ||
1050 | iowrite32(SPI_INTLVL_0, davinci_spi->base + SPILVL); | ||
1051 | |||
970 | iowrite32(CS_DEFAULT, davinci_spi->base + SPIDEF); | 1052 | iowrite32(CS_DEFAULT, davinci_spi->base + SPIDEF); |
971 | 1053 | ||
972 | /* master mode default */ | 1054 | /* master mode default */ |
@@ -987,6 +1069,8 @@ put_master: | |||
987 | spi_master_put(master); | 1069 | spi_master_put(master); |
988 | free_tmp_buf: | 1070 | free_tmp_buf: |
989 | kfree(davinci_spi->tmp_buf); | 1071 | kfree(davinci_spi->tmp_buf); |
1072 | irq_free: | ||
1073 | free_irq(davinci_spi->irq, davinci_spi); | ||
990 | unmap_io: | 1074 | unmap_io: |
991 | iounmap(davinci_spi->base); | 1075 | iounmap(davinci_spi->base); |
992 | release_region: | 1076 | release_region: |
@@ -1020,6 +1104,7 @@ static int __exit davinci_spi_remove(struct platform_device *pdev) | |||
1020 | clk_put(davinci_spi->clk); | 1104 | clk_put(davinci_spi->clk); |
1021 | spi_master_put(master); | 1105 | spi_master_put(master); |
1022 | kfree(davinci_spi->tmp_buf); | 1106 | kfree(davinci_spi->tmp_buf); |
1107 | free_irq(davinci_spi->irq, davinci_spi); | ||
1023 | iounmap(davinci_spi->base); | 1108 | iounmap(davinci_spi->base); |
1024 | release_mem_region(davinci_spi->pbase, davinci_spi->region_size); | 1109 | release_mem_region(davinci_spi->pbase, davinci_spi->region_size); |
1025 | 1110 | ||