aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-10-05 06:51:14 -0400
committerMark Brown <broonie@linaro.org>2013-10-11 15:10:17 -0400
commit0732a9d2a1551e3be5fd8a3ea680deb3d9e56193 (patch)
tree7438d037ad4a4000034c77844c479057cf30ce1e /drivers/spi
parent2cc6e2e0c8157b9e6ed8dbe5c7284865f6afbd46 (diff)
spi/s3c64xx: Use core message handling
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-s3c64xx.c152
1 files changed, 56 insertions, 96 deletions
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index c7b36c06ef40..25eb352d6a42 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -879,121 +879,81 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master,
879 return 0; 879 return 0;
880} 880}
881 881
882static int s3c64xx_spi_transfer_one_message(struct spi_master *master, 882static int s3c64xx_spi_transfer_one(struct spi_master *master,
883 struct spi_message *msg) 883 struct spi_device *spi,
884 struct spi_transfer *xfer)
884{ 885{
885 struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); 886 struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
886 struct spi_device *spi = msg->spi; 887 int status;
887 struct spi_transfer *xfer;
888 int status = 0, cs_toggle = 0;
889 u32 speed; 888 u32 speed;
890 u8 bpw; 889 u8 bpw;
890 unsigned long flags;
891 int use_dma;
891 892
892 list_for_each_entry(xfer, &msg->transfers, transfer_list) { 893 INIT_COMPLETION(sdd->xfer_completion);
893
894 unsigned long flags;
895 int use_dma;
896
897 INIT_COMPLETION(sdd->xfer_completion);
898
899 /* Only BPW and Speed may change across transfers */
900 bpw = xfer->bits_per_word;
901 speed = xfer->speed_hz ? : spi->max_speed_hz;
902
903 if (xfer->len % (bpw / 8)) {
904 dev_err(&spi->dev,
905 "Xfer length(%u) not a multiple of word size(%u)\n",
906 xfer->len, bpw / 8);
907 status = -EIO;
908 goto out;
909 }
910
911 if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
912 sdd->cur_bpw = bpw;
913 sdd->cur_speed = speed;
914 s3c64xx_spi_config(sdd);
915 }
916
917 /* Slave Select */
918 enable_cs(sdd, spi);
919
920 /* Polling method for xfers not bigger than FIFO capacity */
921 use_dma = 0;
922 if (!is_polling(sdd) &&
923 (sdd->rx_dma.ch && sdd->tx_dma.ch &&
924 (xfer->len > ((FIFO_LVL_MASK(sdd) >> 1) + 1))))
925 use_dma = 1;
926
927 spin_lock_irqsave(&sdd->lock, flags);
928 894
929 /* Pending only which is to be done */ 895 /* Only BPW and Speed may change across transfers */
930 sdd->state &= ~RXBUSY; 896 bpw = xfer->bits_per_word;
931 sdd->state &= ~TXBUSY; 897 speed = xfer->speed_hz ? : spi->max_speed_hz;
932 898
933 enable_datapath(sdd, spi, xfer, use_dma); 899 if (xfer->len % (bpw / 8)) {
934 900 dev_err(&spi->dev,
935 /* Start the signals */ 901 "Xfer length(%u) not a multiple of word size(%u)\n",
936 writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); 902 xfer->len, bpw / 8);
903 return -EIO;
904 }
937 905
938 /* Start the signals */ 906 if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
939 writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); 907 sdd->cur_bpw = bpw;
908 sdd->cur_speed = speed;
909 s3c64xx_spi_config(sdd);
910 }
940 911
941 spin_unlock_irqrestore(&sdd->lock, flags); 912 /* Polling method for xfers not bigger than FIFO capacity */
913 use_dma = 0;
914 if (!is_polling(sdd) &&
915 (sdd->rx_dma.ch && sdd->tx_dma.ch &&
916 (xfer->len > ((FIFO_LVL_MASK(sdd) >> 1) + 1))))
917 use_dma = 1;
942 918
943 status = wait_for_xfer(sdd, xfer, use_dma); 919 spin_lock_irqsave(&sdd->lock, flags);
944 920
945 if (status) { 921 /* Pending only which is to be done */
946 dev_err(&spi->dev, "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n", 922 sdd->state &= ~RXBUSY;
947 xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0, 923 sdd->state &= ~TXBUSY;
948 (sdd->state & RXBUSY) ? 'f' : 'p',
949 (sdd->state & TXBUSY) ? 'f' : 'p',
950 xfer->len);
951 924
952 if (use_dma) { 925 enable_datapath(sdd, spi, xfer, use_dma);
953 if (xfer->tx_buf != NULL
954 && (sdd->state & TXBUSY))
955 s3c64xx_spi_dma_stop(sdd, &sdd->tx_dma);
956 if (xfer->rx_buf != NULL
957 && (sdd->state & RXBUSY))
958 s3c64xx_spi_dma_stop(sdd, &sdd->rx_dma);
959 }
960 926
961 goto out; 927 /* Start the signals */
962 } 928 writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
963 929
964 flush_fifo(sdd); 930 /* Start the signals */
931 writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
965 932
966 if (xfer->delay_usecs) 933 spin_unlock_irqrestore(&sdd->lock, flags);
967 udelay(xfer->delay_usecs);
968 934
969 if (xfer->cs_change) { 935 status = wait_for_xfer(sdd, xfer, use_dma);
970 /* Hint that the next mssg is gonna be 936
971 for the same device */ 937 if (status) {
972 if (list_is_last(&xfer->transfer_list, 938 dev_err(&spi->dev, "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n",
973 &msg->transfers)) 939 xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0,
974 cs_toggle = 1; 940 (sdd->state & RXBUSY) ? 'f' : 'p',
941 (sdd->state & TXBUSY) ? 'f' : 'p',
942 xfer->len);
943
944 if (use_dma) {
945 if (xfer->tx_buf != NULL
946 && (sdd->state & TXBUSY))
947 s3c64xx_spi_dma_stop(sdd, &sdd->tx_dma);
948 if (xfer->rx_buf != NULL
949 && (sdd->state & RXBUSY))
950 s3c64xx_spi_dma_stop(sdd, &sdd->rx_dma);
975 } 951 }
976
977 msg->actual_length += xfer->len;
978 }
979
980out:
981 if (!cs_toggle || status) {
982 /* Quiese the signals */
983 writel(S3C64XX_SPI_SLAVE_SIG_INACT,
984 sdd->regs + S3C64XX_SPI_SLAVE_SEL);
985 disable_cs(sdd, spi);
986 } else { 952 } else {
987 sdd->tgl_spi = spi; 953 flush_fifo(sdd);
988 } 954 }
989 955
990 s3c64xx_spi_unmap_mssg(sdd, msg); 956 return status;
991
992 msg->status = status;
993
994 spi_finalize_current_message(master);
995
996 return 0;
997} 957}
998 958
999static int s3c64xx_spi_unprepare_message(struct spi_master *master, 959static int s3c64xx_spi_unprepare_message(struct spi_master *master,
@@ -1379,7 +1339,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
1379 master->cleanup = s3c64xx_spi_cleanup; 1339 master->cleanup = s3c64xx_spi_cleanup;
1380 master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; 1340 master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
1381 master->prepare_message = s3c64xx_spi_prepare_message; 1341 master->prepare_message = s3c64xx_spi_prepare_message;
1382 master->transfer_one_message = s3c64xx_spi_transfer_one_message; 1342 master->transfer_one = s3c64xx_spi_transfer_one;
1383 master->unprepare_message = s3c64xx_spi_unprepare_message; 1343 master->unprepare_message = s3c64xx_spi_unprepare_message;
1384 master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; 1344 master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
1385 master->num_chipselect = sci->num_cs; 1345 master->num_chipselect = sci->num_cs;