diff options
author | Nicolas Ferre <nicolas.ferre@atmel.com> | 2016-11-24 06:24:58 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-11-25 08:07:09 -0500 |
commit | 7910d9af000acc155745e44be55a5d0dc9e26ce7 (patch) | |
tree | ed2041231dfd74acdee85c2c12d074d7d10d9760 /drivers/spi/spi-atmel.c | |
parent | ce24a513fb142e855b4aa77f91334c2f203c0d99 (diff) |
spi: atmel: Use core SPI_MASTER_MUST_[RT]X handling
We need both RX and TX data for each transfer in any case (PIO, PDC, DMA).
So convert the driver to the core dummy buffer handling with the
SPI_MASTER_MUST_RX/SPI_MASTER_MUST_TX infrastructure.
This move changes the maximum PDC/DMA buffer handling to 65535 bytes
instead of a single page and sets master->max_dma_len to this value.
All dummy buffer management is removed from the driver.
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-atmel.c')
-rw-r--r-- | drivers/spi/spi-atmel.c | 131 |
1 files changed, 35 insertions, 96 deletions
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index a9ae1836e1e2..8f20d4f75e4a 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c | |||
@@ -303,10 +303,6 @@ struct atmel_spi { | |||
303 | 303 | ||
304 | struct completion xfer_completion; | 304 | struct completion xfer_completion; |
305 | 305 | ||
306 | /* scratch buffer */ | ||
307 | void *buffer; | ||
308 | dma_addr_t buffer_dma; | ||
309 | |||
310 | struct atmel_spi_caps caps; | 306 | struct atmel_spi_caps caps; |
311 | 307 | ||
312 | bool use_dma; | 308 | bool use_dma; |
@@ -327,7 +323,7 @@ struct atmel_spi_device { | |||
327 | u32 csr; | 323 | u32 csr; |
328 | }; | 324 | }; |
329 | 325 | ||
330 | #define BUFFER_SIZE PAGE_SIZE | 326 | #define SPI_MAX_DMA_XFER 65535 /* true for both PDC and DMA */ |
331 | #define INVALID_DMA_ADDRESS 0xffffffff | 327 | #define INVALID_DMA_ADDRESS 0xffffffff |
332 | 328 | ||
333 | /* | 329 | /* |
@@ -612,14 +608,10 @@ static void atmel_spi_next_xfer_single(struct spi_master *master, | |||
612 | cpu_relax(); | 608 | cpu_relax(); |
613 | } | 609 | } |
614 | 610 | ||
615 | if (xfer->tx_buf) { | 611 | if (xfer->bits_per_word > 8) |
616 | if (xfer->bits_per_word > 8) | 612 | spi_writel(as, TDR, *(u16 *)(xfer->tx_buf + xfer_pos)); |
617 | spi_writel(as, TDR, *(u16 *)(xfer->tx_buf + xfer_pos)); | 613 | else |
618 | else | 614 | spi_writel(as, TDR, *(u8 *)(xfer->tx_buf + xfer_pos)); |
619 | spi_writel(as, TDR, *(u8 *)(xfer->tx_buf + xfer_pos)); | ||
620 | } else { | ||
621 | spi_writel(as, TDR, 0); | ||
622 | } | ||
623 | 615 | ||
624 | dev_dbg(master->dev.parent, | 616 | dev_dbg(master->dev.parent, |
625 | " start pio xfer %p: len %u tx %p rx %p bitpw %d\n", | 617 | " start pio xfer %p: len %u tx %p rx %p bitpw %d\n", |
@@ -666,17 +658,12 @@ static void atmel_spi_next_xfer_fifo(struct spi_master *master, | |||
666 | 658 | ||
667 | /* Fill TX FIFO */ | 659 | /* Fill TX FIFO */ |
668 | while (num_data >= 2) { | 660 | while (num_data >= 2) { |
669 | if (xfer->tx_buf) { | 661 | if (xfer->bits_per_word > 8) { |
670 | if (xfer->bits_per_word > 8) { | 662 | td0 = *words++; |
671 | td0 = *words++; | 663 | td1 = *words++; |
672 | td1 = *words++; | ||
673 | } else { | ||
674 | td0 = *bytes++; | ||
675 | td1 = *bytes++; | ||
676 | } | ||
677 | } else { | 664 | } else { |
678 | td0 = 0; | 665 | td0 = *bytes++; |
679 | td1 = 0; | 666 | td1 = *bytes++; |
680 | } | 667 | } |
681 | 668 | ||
682 | spi_writel(as, TDR, (td1 << 16) | td0); | 669 | spi_writel(as, TDR, (td1 << 16) | td0); |
@@ -684,14 +671,10 @@ static void atmel_spi_next_xfer_fifo(struct spi_master *master, | |||
684 | } | 671 | } |
685 | 672 | ||
686 | if (num_data) { | 673 | if (num_data) { |
687 | if (xfer->tx_buf) { | 674 | if (xfer->bits_per_word > 8) |
688 | if (xfer->bits_per_word > 8) | 675 | td0 = *words++; |
689 | td0 = *words++; | 676 | else |
690 | else | 677 | td0 = *bytes++; |
691 | td0 = *bytes++; | ||
692 | } else { | ||
693 | td0 = 0; | ||
694 | } | ||
695 | 678 | ||
696 | spi_writew(as, TDR, td0); | 679 | spi_writew(as, TDR, td0); |
697 | num_data--; | 680 | num_data--; |
@@ -750,24 +733,14 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master, | |||
750 | 733 | ||
751 | /* prepare the RX dma transfer */ | 734 | /* prepare the RX dma transfer */ |
752 | sg_init_table(&as->dma.sgrx, 1); | 735 | sg_init_table(&as->dma.sgrx, 1); |
753 | if (xfer->rx_buf) { | 736 | as->dma.sgrx.dma_address = xfer->rx_dma + xfer->len - *plen; |
754 | as->dma.sgrx.dma_address = xfer->rx_dma + xfer->len - *plen; | ||
755 | } else { | ||
756 | as->dma.sgrx.dma_address = as->buffer_dma; | ||
757 | if (len > BUFFER_SIZE) | ||
758 | len = BUFFER_SIZE; | ||
759 | } | ||
760 | 737 | ||
761 | /* prepare the TX dma transfer */ | 738 | /* prepare the TX dma transfer */ |
762 | sg_init_table(&as->dma.sgtx, 1); | 739 | sg_init_table(&as->dma.sgtx, 1); |
763 | if (xfer->tx_buf) { | 740 | as->dma.sgtx.dma_address = xfer->tx_dma + xfer->len - *plen; |
764 | as->dma.sgtx.dma_address = xfer->tx_dma + xfer->len - *plen; | 741 | |
765 | } else { | 742 | if (len > master->max_dma_len) |
766 | as->dma.sgtx.dma_address = as->buffer_dma; | 743 | len = master->max_dma_len; |
767 | if (len > BUFFER_SIZE) | ||
768 | len = BUFFER_SIZE; | ||
769 | memset(as->buffer, 0, len); | ||
770 | } | ||
771 | 744 | ||
772 | sg_dma_len(&as->dma.sgtx) = len; | 745 | sg_dma_len(&as->dma.sgtx) = len; |
773 | sg_dma_len(&as->dma.sgrx) = len; | 746 | sg_dma_len(&as->dma.sgrx) = len; |
@@ -834,25 +807,10 @@ static void atmel_spi_next_xfer_data(struct spi_master *master, | |||
834 | struct atmel_spi *as = spi_master_get_devdata(master); | 807 | struct atmel_spi *as = spi_master_get_devdata(master); |
835 | u32 len = *plen; | 808 | u32 len = *plen; |
836 | 809 | ||
837 | /* use scratch buffer only when rx or tx data is unspecified */ | 810 | *rx_dma = xfer->rx_dma + xfer->len - *plen; |
838 | if (xfer->rx_buf) | 811 | *tx_dma = xfer->tx_dma + xfer->len - *plen; |
839 | *rx_dma = xfer->rx_dma + xfer->len - *plen; | 812 | if (len > master->max_dma_len) |
840 | else { | 813 | len = master->max_dma_len; |
841 | *rx_dma = as->buffer_dma; | ||
842 | if (len > BUFFER_SIZE) | ||
843 | len = BUFFER_SIZE; | ||
844 | } | ||
845 | |||
846 | if (xfer->tx_buf) | ||
847 | *tx_dma = xfer->tx_dma + xfer->len - *plen; | ||
848 | else { | ||
849 | *tx_dma = as->buffer_dma; | ||
850 | if (len > BUFFER_SIZE) | ||
851 | len = BUFFER_SIZE; | ||
852 | memset(as->buffer, 0, len); | ||
853 | dma_sync_single_for_device(&as->pdev->dev, | ||
854 | as->buffer_dma, len, DMA_TO_DEVICE); | ||
855 | } | ||
856 | 814 | ||
857 | *plen = len; | 815 | *plen = len; |
858 | } | 816 | } |
@@ -1026,16 +984,12 @@ atmel_spi_pump_single_data(struct atmel_spi *as, struct spi_transfer *xfer) | |||
1026 | u16 *rxp16; | 984 | u16 *rxp16; |
1027 | unsigned long xfer_pos = xfer->len - as->current_remaining_bytes; | 985 | unsigned long xfer_pos = xfer->len - as->current_remaining_bytes; |
1028 | 986 | ||
1029 | if (xfer->rx_buf) { | 987 | if (xfer->bits_per_word > 8) { |
1030 | if (xfer->bits_per_word > 8) { | 988 | rxp16 = (u16 *)(((u8 *)xfer->rx_buf) + xfer_pos); |
1031 | rxp16 = (u16 *)(((u8 *)xfer->rx_buf) + xfer_pos); | 989 | *rxp16 = spi_readl(as, RDR); |
1032 | *rxp16 = spi_readl(as, RDR); | ||
1033 | } else { | ||
1034 | rxp = ((u8 *)xfer->rx_buf) + xfer_pos; | ||
1035 | *rxp = spi_readl(as, RDR); | ||
1036 | } | ||
1037 | } else { | 990 | } else { |
1038 | spi_readl(as, RDR); | 991 | rxp = ((u8 *)xfer->rx_buf) + xfer_pos; |
992 | *rxp = spi_readl(as, RDR); | ||
1039 | } | 993 | } |
1040 | if (xfer->bits_per_word > 8) { | 994 | if (xfer->bits_per_word > 8) { |
1041 | if (as->current_remaining_bytes > 2) | 995 | if (as->current_remaining_bytes > 2) |
@@ -1074,12 +1028,10 @@ atmel_spi_pump_fifo_data(struct atmel_spi *as, struct spi_transfer *xfer) | |||
1074 | /* Read data */ | 1028 | /* Read data */ |
1075 | while (num_data) { | 1029 | while (num_data) { |
1076 | rd = spi_readl(as, RDR); | 1030 | rd = spi_readl(as, RDR); |
1077 | if (xfer->rx_buf) { | 1031 | if (xfer->bits_per_word > 8) |
1078 | if (xfer->bits_per_word > 8) | 1032 | *words++ = rd; |
1079 | *words++ = rd; | 1033 | else |
1080 | else | 1034 | *bytes++ = rd; |
1081 | *bytes++ = rd; | ||
1082 | } | ||
1083 | num_data--; | 1035 | num_data--; |
1084 | } | 1036 | } |
1085 | } | 1037 | } |
@@ -1561,29 +1513,22 @@ static int atmel_spi_probe(struct platform_device *pdev) | |||
1561 | master->bus_num = pdev->id; | 1513 | master->bus_num = pdev->id; |
1562 | master->num_chipselect = master->dev.of_node ? 0 : 4; | 1514 | master->num_chipselect = master->dev.of_node ? 0 : 4; |
1563 | master->setup = atmel_spi_setup; | 1515 | master->setup = atmel_spi_setup; |
1516 | master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX); | ||
1564 | master->transfer_one_message = atmel_spi_transfer_one_message; | 1517 | master->transfer_one_message = atmel_spi_transfer_one_message; |
1565 | master->cleanup = atmel_spi_cleanup; | 1518 | master->cleanup = atmel_spi_cleanup; |
1566 | master->auto_runtime_pm = true; | 1519 | master->auto_runtime_pm = true; |
1520 | master->max_dma_len = SPI_MAX_DMA_XFER; | ||
1567 | platform_set_drvdata(pdev, master); | 1521 | platform_set_drvdata(pdev, master); |
1568 | 1522 | ||
1569 | as = spi_master_get_devdata(master); | 1523 | as = spi_master_get_devdata(master); |
1570 | 1524 | ||
1571 | /* | ||
1572 | * Scratch buffer is used for throwaway rx and tx data. | ||
1573 | * It's coherent to minimize dcache pollution. | ||
1574 | */ | ||
1575 | as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE, | ||
1576 | &as->buffer_dma, GFP_KERNEL); | ||
1577 | if (!as->buffer) | ||
1578 | goto out_free; | ||
1579 | |||
1580 | spin_lock_init(&as->lock); | 1525 | spin_lock_init(&as->lock); |
1581 | 1526 | ||
1582 | as->pdev = pdev; | 1527 | as->pdev = pdev; |
1583 | as->regs = devm_ioremap_resource(&pdev->dev, regs); | 1528 | as->regs = devm_ioremap_resource(&pdev->dev, regs); |
1584 | if (IS_ERR(as->regs)) { | 1529 | if (IS_ERR(as->regs)) { |
1585 | ret = PTR_ERR(as->regs); | 1530 | ret = PTR_ERR(as->regs); |
1586 | goto out_free_buffer; | 1531 | goto out_unmap_regs; |
1587 | } | 1532 | } |
1588 | as->phybase = regs->start; | 1533 | as->phybase = regs->start; |
1589 | as->irq = irq; | 1534 | as->irq = irq; |
@@ -1681,9 +1626,6 @@ out_free_dma: | |||
1681 | clk_disable_unprepare(clk); | 1626 | clk_disable_unprepare(clk); |
1682 | out_free_irq: | 1627 | out_free_irq: |
1683 | out_unmap_regs: | 1628 | out_unmap_regs: |
1684 | out_free_buffer: | ||
1685 | dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer, | ||
1686 | as->buffer_dma); | ||
1687 | out_free: | 1629 | out_free: |
1688 | spi_master_put(master); | 1630 | spi_master_put(master); |
1689 | return ret; | 1631 | return ret; |
@@ -1708,9 +1650,6 @@ static int atmel_spi_remove(struct platform_device *pdev) | |||
1708 | spi_readl(as, SR); | 1650 | spi_readl(as, SR); |
1709 | spin_unlock_irq(&as->lock); | 1651 | spin_unlock_irq(&as->lock); |
1710 | 1652 | ||
1711 | dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer, | ||
1712 | as->buffer_dma); | ||
1713 | |||
1714 | clk_disable_unprepare(as->clk); | 1653 | clk_disable_unprepare(as->clk); |
1715 | 1654 | ||
1716 | pm_runtime_put_noidle(&pdev->dev); | 1655 | pm_runtime_put_noidle(&pdev->dev); |