aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorYi Li <yi.li@analog.com>2009-06-03 05:46:22 -0400
committerMike Frysinger <vapier@gentoo.org>2010-10-18 02:49:29 -0400
commitf6a6d96685be6e784849d067b44acb831f595417 (patch)
tree74676924942c6823b0b1517569394239d834943a /drivers/spi
parentbb8beecd98de45f821a3360e0b061fc1f8da947c (diff)
spi/bfin_spi: utilize the SPI interrupt in PIO mode
The current behavior in PIO mode is to poll the SPI status registers which can obviously lead to higher latencies when doing a lot of SPI traffic. There is a SPI interrupt which can be used instead to signal individual completion of transactions. Signed-off-by: Yi Li <yi.li@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi_bfin5xx.c235
1 files changed, 185 insertions, 50 deletions
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index b8352546c589..3736c3596a41 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -92,6 +92,9 @@ struct driver_data {
92 dma_addr_t rx_dma; 92 dma_addr_t rx_dma;
93 dma_addr_t tx_dma; 93 dma_addr_t tx_dma;
94 94
95 int irq_requested;
96 int spi_irq;
97
95 size_t rx_map_len; 98 size_t rx_map_len;
96 size_t tx_map_len; 99 size_t tx_map_len;
97 u8 n_bytes; 100 u8 n_bytes;
@@ -115,6 +118,7 @@ struct chip_data {
115 u16 cs_chg_udelay; /* Some devices require > 255usec delay */ 118 u16 cs_chg_udelay; /* Some devices require > 255usec delay */
116 u32 cs_gpio; 119 u32 cs_gpio;
117 u16 idle_tx_val; 120 u16 idle_tx_val;
121 u8 pio_interrupt; /* use spi data irq */
118 void (*write) (struct driver_data *); 122 void (*write) (struct driver_data *);
119 void (*read) (struct driver_data *); 123 void (*read) (struct driver_data *);
120 void (*duplex) (struct driver_data *); 124 void (*duplex) (struct driver_data *);
@@ -525,6 +529,79 @@ static void bfin_spi_giveback(struct driver_data *drv_data)
525 msg->complete(msg->context); 529 msg->complete(msg->context);
526} 530}
527 531
532/* spi data irq handler */
533static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
534{
535 struct driver_data *drv_data = dev_id;
536 struct chip_data *chip = drv_data->cur_chip;
537 struct spi_message *msg = drv_data->cur_msg;
538 int n_bytes = drv_data->n_bytes;
539
540 /* wait until transfer finished. */
541 while (!(read_STAT(drv_data) & BIT_STAT_RXS))
542 cpu_relax();
543
544 if ((drv_data->tx && drv_data->tx >= drv_data->tx_end) ||
545 (drv_data->rx && drv_data->rx >= (drv_data->rx_end - n_bytes))) {
546 /* last read */
547 if (drv_data->rx) {
548 dev_dbg(&drv_data->pdev->dev, "last read\n");
549 if (n_bytes == 2)
550 *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
551 else if (n_bytes == 1)
552 *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
553 drv_data->rx += n_bytes;
554 }
555
556 msg->actual_length += drv_data->len_in_bytes;
557 if (drv_data->cs_change)
558 bfin_spi_cs_deactive(drv_data, chip);
559 /* Move to next transfer */
560 msg->state = bfin_spi_next_transfer(drv_data);
561
562 disable_irq(drv_data->spi_irq);
563
564 /* Schedule transfer tasklet */
565 tasklet_schedule(&drv_data->pump_transfers);
566 return IRQ_HANDLED;
567 }
568
569 if (drv_data->rx && drv_data->tx) {
570 /* duplex */
571 dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
572 if (drv_data->n_bytes == 2) {
573 *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
574 write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
575 } else if (drv_data->n_bytes == 1) {
576 *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
577 write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
578 }
579 } else if (drv_data->rx) {
580 /* read */
581 dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
582 if (drv_data->n_bytes == 2)
583 *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
584 else if (drv_data->n_bytes == 1)
585 *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
586 write_TDBR(drv_data, chip->idle_tx_val);
587 } else if (drv_data->tx) {
588 /* write */
589 dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
590 bfin_spi_dummy_read(drv_data);
591 if (drv_data->n_bytes == 2)
592 write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
593 else if (drv_data->n_bytes == 1)
594 write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
595 }
596
597 if (drv_data->tx)
598 drv_data->tx += n_bytes;
599 if (drv_data->rx)
600 drv_data->rx += n_bytes;
601
602 return IRQ_HANDLED;
603}
604
528static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id) 605static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
529{ 606{
530 struct driver_data *drv_data = dev_id; 607 struct driver_data *drv_data = dev_id;
@@ -700,6 +777,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
700 777
701 default: 778 default:
702 /* No change, the same as default setting */ 779 /* No change, the same as default setting */
780 transfer->bits_per_word = chip->bits_per_word;
703 drv_data->n_bytes = chip->n_bytes; 781 drv_data->n_bytes = chip->n_bytes;
704 width = chip->width; 782 width = chip->width;
705 drv_data->write = drv_data->tx ? chip->write : bfin_spi_null_writer; 783 drv_data->write = drv_data->tx ? chip->write : bfin_spi_null_writer;
@@ -842,60 +920,86 @@ static void bfin_spi_pump_transfers(unsigned long data)
842 dma_enable_irq(drv_data->dma_channel); 920 dma_enable_irq(drv_data->dma_channel);
843 local_irq_restore(flags); 921 local_irq_restore(flags);
844 922
845 } else { 923 return;
846 /* IO mode write then read */ 924 }
847 dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
848 925
849 /* we always use SPI_WRITE mode. SPI_READ mode 926 if (chip->pio_interrupt) {
850 seems to have problems with setting up the 927 /* use write mode. spi irq should have been disabled */
851 output value in TDBR prior to the transfer. */ 928 cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD));
852 write_CTRL(drv_data, (cr | CFG_SPI_WRITE)); 929 write_CTRL(drv_data, (cr | CFG_SPI_WRITE));
853 930
854 if (full_duplex) { 931 /* discard old RX data and clear RXS */
855 /* full duplex mode */ 932 bfin_spi_dummy_read(drv_data);
856 BUG_ON((drv_data->tx_end - drv_data->tx) !=
857 (drv_data->rx_end - drv_data->rx));
858 dev_dbg(&drv_data->pdev->dev,
859 "IO duplex: cr is 0x%x\n", cr);
860
861 drv_data->duplex(drv_data);
862
863 if (drv_data->tx != drv_data->tx_end)
864 tranf_success = 0;
865 } else if (drv_data->tx != NULL) {
866 /* write only half duplex */
867 dev_dbg(&drv_data->pdev->dev,
868 "IO write: cr is 0x%x\n", cr);
869 933
870 drv_data->write(drv_data); 934 /* start transfer */
935 if (drv_data->tx == NULL)
936 write_TDBR(drv_data, chip->idle_tx_val);
937 else {
938 if (transfer->bits_per_word == 8)
939 write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
940 else if (transfer->bits_per_word == 16)
941 write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
942 drv_data->tx += drv_data->n_bytes;
943 }
871 944
872 if (drv_data->tx != drv_data->tx_end) 945 /* once TDBR is empty, interrupt is triggered */
873 tranf_success = 0; 946 enable_irq(drv_data->spi_irq);
874 } else if (drv_data->rx != NULL) { 947 return;
875 /* read only half duplex */ 948 }
876 dev_dbg(&drv_data->pdev->dev,
877 "IO read: cr is 0x%x\n", cr);
878 949
879 drv_data->read(drv_data); 950 /* IO mode */
880 if (drv_data->rx != drv_data->rx_end) 951 dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
881 tranf_success = 0; 952
882 } 953 /* we always use SPI_WRITE mode. SPI_READ mode
954 seems to have problems with setting up the
955 output value in TDBR prior to the transfer. */
956 write_CTRL(drv_data, (cr | CFG_SPI_WRITE));
957
958 if (full_duplex) {
959 /* full duplex mode */
960 BUG_ON((drv_data->tx_end - drv_data->tx) !=
961 (drv_data->rx_end - drv_data->rx));
962 dev_dbg(&drv_data->pdev->dev,
963 "IO duplex: cr is 0x%x\n", cr);
964
965 drv_data->duplex(drv_data);
966
967 if (drv_data->tx != drv_data->tx_end)
968 tranf_success = 0;
969 } else if (drv_data->tx != NULL) {
970 /* write only half duplex */
971 dev_dbg(&drv_data->pdev->dev,
972 "IO write: cr is 0x%x\n", cr);
973
974 drv_data->write(drv_data);
975
976 if (drv_data->tx != drv_data->tx_end)
977 tranf_success = 0;
978 } else if (drv_data->rx != NULL) {
979 /* read only half duplex */
980 dev_dbg(&drv_data->pdev->dev,
981 "IO read: cr is 0x%x\n", cr);
982
983 drv_data->read(drv_data);
984 if (drv_data->rx != drv_data->rx_end)
985 tranf_success = 0;
986 }
883 987
884 if (!tranf_success) { 988 if (!tranf_success) {
885 dev_dbg(&drv_data->pdev->dev, 989 dev_dbg(&drv_data->pdev->dev,
886 "IO write error!\n"); 990 "IO write error!\n");
887 message->state = ERROR_STATE; 991 message->state = ERROR_STATE;
888 } else { 992 } else {
889 /* Update total byte transfered */ 993 /* Update total byte transfered */
890 message->actual_length += drv_data->len_in_bytes; 994 message->actual_length += drv_data->len_in_bytes;
891 /* Move to next transfer of this msg */ 995 /* Move to next transfer of this msg */
892 message->state = bfin_spi_next_transfer(drv_data); 996 message->state = bfin_spi_next_transfer(drv_data);
893 if (drv_data->cs_change) 997 if (drv_data->cs_change)
894 bfin_spi_cs_deactive(drv_data, chip); 998 bfin_spi_cs_deactive(drv_data, chip);
895 }
896 /* Schedule next transfer tasklet */
897 tasklet_schedule(&drv_data->pump_transfers);
898 } 999 }
1000
1001 /* Schedule next transfer tasklet */
1002 tasklet_schedule(&drv_data->pump_transfers);
899} 1003}
900 1004
901/* pop a msg from queue and kick off real transfer */ 1005/* pop a msg from queue and kick off real transfer */
@@ -1047,6 +1151,7 @@ static int bfin_spi_setup(struct spi_device *spi)
1047 chip->cs_chg_udelay = chip_info->cs_chg_udelay; 1151 chip->cs_chg_udelay = chip_info->cs_chg_udelay;
1048 chip->cs_gpio = chip_info->cs_gpio; 1152 chip->cs_gpio = chip_info->cs_gpio;
1049 chip->idle_tx_val = chip_info->idle_tx_val; 1153 chip->idle_tx_val = chip_info->idle_tx_val;
1154 chip->pio_interrupt = chip_info->pio_interrupt;
1050 } 1155 }
1051 1156
1052 /* translate common spi framework into our register */ 1157 /* translate common spi framework into our register */
@@ -1096,6 +1201,11 @@ static int bfin_spi_setup(struct spi_device *spi)
1096 goto error; 1201 goto error;
1097 } 1202 }
1098 1203
1204 if (chip->enable_dma && chip->pio_interrupt) {
1205 dev_err(&spi->dev, "enable_dma is set, "
1206 "do not set pio_interrupt\n");
1207 goto error;
1208 }
1099 /* 1209 /*
1100 * if any one SPI chip is registered and wants DMA, request the 1210 * if any one SPI chip is registered and wants DMA, request the
1101 * DMA channel for it 1211 * DMA channel for it
@@ -1119,6 +1229,18 @@ static int bfin_spi_setup(struct spi_device *spi)
1119 dma_disable_irq(drv_data->dma_channel); 1229 dma_disable_irq(drv_data->dma_channel);
1120 } 1230 }
1121 1231
1232 if (chip->pio_interrupt && !drv_data->irq_requested) {
1233 ret = request_irq(drv_data->spi_irq, bfin_spi_pio_irq_handler,
1234 IRQF_DISABLED, "BFIN_SPI", drv_data);
1235 if (ret) {
1236 dev_err(&spi->dev, "Unable to register spi IRQ\n");
1237 goto error;
1238 }
1239 drv_data->irq_requested = 1;
1240 /* we use write mode, spi irq has to be disabled here */
1241 disable_irq(drv_data->spi_irq);
1242 }
1243
1122 if (chip->chip_select_num == 0) { 1244 if (chip->chip_select_num == 0) {
1123 ret = gpio_request(chip->cs_gpio, spi->modalias); 1245 ret = gpio_request(chip->cs_gpio, spi->modalias);
1124 if (ret) { 1246 if (ret) {
@@ -1328,11 +1450,19 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
1328 goto out_error_ioremap; 1450 goto out_error_ioremap;
1329 } 1451 }
1330 1452
1331 drv_data->dma_channel = platform_get_irq(pdev, 0); 1453 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
1332 if (drv_data->dma_channel < 0) { 1454 if (res == NULL) {
1333 dev_err(dev, "No DMA channel specified\n"); 1455 dev_err(dev, "No DMA channel specified\n");
1334 status = -ENOENT; 1456 status = -ENOENT;
1335 goto out_error_no_dma_ch; 1457 goto out_error_free_io;
1458 }
1459 drv_data->dma_channel = res->start;
1460
1461 drv_data->spi_irq = platform_get_irq(pdev, 0);
1462 if (drv_data->spi_irq < 0) {
1463 dev_err(dev, "No spi pio irq specified\n");
1464 status = -ENOENT;
1465 goto out_error_free_io;
1336 } 1466 }
1337 1467
1338 /* Initial and start queue */ 1468 /* Initial and start queue */
@@ -1375,7 +1505,7 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
1375 1505
1376out_error_queue_alloc: 1506out_error_queue_alloc:
1377 bfin_spi_destroy_queue(drv_data); 1507 bfin_spi_destroy_queue(drv_data);
1378out_error_no_dma_ch: 1508out_error_free_io:
1379 iounmap((void *) drv_data->regs_base); 1509 iounmap((void *) drv_data->regs_base);
1380out_error_ioremap: 1510out_error_ioremap:
1381out_error_get_res: 1511out_error_get_res:
@@ -1407,6 +1537,11 @@ static int __devexit bfin_spi_remove(struct platform_device *pdev)
1407 free_dma(drv_data->dma_channel); 1537 free_dma(drv_data->dma_channel);
1408 } 1538 }
1409 1539
1540 if (drv_data->irq_requested) {
1541 free_irq(drv_data->spi_irq, drv_data);
1542 drv_data->irq_requested = 0;
1543 }
1544
1410 /* Disconnect from the SPI framework */ 1545 /* Disconnect from the SPI framework */
1411 spi_unregister_master(drv_data->master); 1546 spi_unregister_master(drv_data->master);
1412 1547