Skip to content

Commit c8c3576

Browse files
committed
Merge branch 'at91-4.9-trunk/spi' into linux-4.9-at91
2 parents 6325907 + a8ca87b commit c8c3576

1 file changed

Lines changed: 85 additions & 30 deletions

File tree

drivers/spi/spi-atmel.c

Lines changed: 85 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ struct atmel_spi {
291291
struct spi_transfer *current_transfer;
292292
int current_remaining_bytes;
293293
int done_status;
294+
dma_addr_t dma_addr_rx_bbuf;
295+
dma_addr_t dma_addr_tx_bbuf;
296+
void *addr_rx_bbuf;
297+
void *addr_tx_bbuf;
294298

295299
struct completion xfer_completion;
296300

@@ -436,6 +440,11 @@ static void atmel_spi_unlock(struct atmel_spi *as) __releases(&as->lock)
436440
spin_unlock_irqrestore(&as->lock, as->flags);
437441
}
438442

443+
static inline bool atmel_spi_is_vmalloc_xfer(struct spi_transfer *xfer)
444+
{
445+
return is_vmalloc_addr(xfer->tx_buf) || is_vmalloc_addr(xfer->rx_buf);
446+
}
447+
439448
static inline bool atmel_spi_use_dma(struct atmel_spi *as,
440449
struct spi_transfer *xfer)
441450
{
@@ -448,7 +457,12 @@ static bool atmel_spi_can_dma(struct spi_master *master,
448457
{
449458
struct atmel_spi *as = spi_master_get_devdata(master);
450459

451-
return atmel_spi_use_dma(as, xfer);
460+
if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5))
461+
return atmel_spi_use_dma(as, xfer) &&
462+
!atmel_spi_is_vmalloc_xfer(xfer);
463+
else
464+
return atmel_spi_use_dma(as, xfer);
465+
452466
}
453467

454468
static int atmel_spi_dma_slave_config(struct atmel_spi *as,
@@ -594,6 +608,11 @@ static void dma_callback(void *data)
594608
struct spi_master *master = data;
595609
struct atmel_spi *as = spi_master_get_devdata(master);
596610

611+
if (is_vmalloc_addr(as->current_transfer->rx_buf) &&
612+
IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
613+
memcpy(as->current_transfer->rx_buf, as->addr_rx_bbuf,
614+
as->current_transfer->len);
615+
}
597616
complete(&as->xfer_completion);
598617
}
599618

@@ -744,17 +763,41 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
744763
goto err_exit;
745764

746765
/* Send both scatterlists */
747-
rxdesc = dmaengine_prep_slave_sg(rxchan,
748-
xfer->rx_sg.sgl, xfer->rx_sg.nents,
749-
DMA_FROM_DEVICE,
750-
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
766+
if (atmel_spi_is_vmalloc_xfer(xfer) &&
767+
IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
768+
rxdesc = dmaengine_prep_slave_single(rxchan,
769+
as->dma_addr_rx_bbuf,
770+
xfer->len,
771+
DMA_FROM_DEVICE,
772+
DMA_PREP_INTERRUPT |
773+
DMA_CTRL_ACK);
774+
} else {
775+
rxdesc = dmaengine_prep_slave_sg(rxchan,
776+
xfer->rx_sg.sgl,
777+
xfer->rx_sg.nents,
778+
DMA_FROM_DEVICE,
779+
DMA_PREP_INTERRUPT |
780+
DMA_CTRL_ACK);
781+
}
751782
if (!rxdesc)
752783
goto err_dma;
753784

754-
txdesc = dmaengine_prep_slave_sg(txchan,
755-
xfer->tx_sg.sgl, xfer->tx_sg.nents,
756-
DMA_TO_DEVICE,
757-
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
785+
if (atmel_spi_is_vmalloc_xfer(xfer) &&
786+
IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
787+
memcpy(as->addr_tx_bbuf, xfer->tx_buf, xfer->len);
788+
txdesc = dmaengine_prep_slave_single(txchan,
789+
as->dma_addr_tx_bbuf,
790+
xfer->len, DMA_TO_DEVICE,
791+
DMA_PREP_INTERRUPT |
792+
DMA_CTRL_ACK);
793+
} else {
794+
txdesc = dmaengine_prep_slave_sg(txchan,
795+
xfer->tx_sg.sgl,
796+
xfer->tx_sg.nents,
797+
DMA_TO_DEVICE,
798+
DMA_PREP_INTERRUPT |
799+
DMA_CTRL_ACK);
800+
}
758801
if (!txdesc)
759802
goto err_dma;
760803

@@ -1426,27 +1469,7 @@ static void atmel_get_caps(struct atmel_spi *as)
14261469

14271470
as->caps.is_spi2 = version > 0x121;
14281471
as->caps.has_wdrbt = version >= 0x210;
1429-
#ifdef CONFIG_SOC_SAM_V4_V5
1430-
/*
1431-
* Atmel SoCs based on ARM9 (SAM9x) cores should not use spi_map_buf()
1432-
* since this later function tries to map buffers with dma_map_sg()
1433-
* even if they have not been allocated inside DMA-safe areas.
1434-
* On SoCs based on Cortex A5 (SAMA5Dx), it works anyway because for
1435-
* those ARM cores, the data cache follows the PIPT model.
1436-
* Also the L2 cache controller of SAMA5D2 uses the PIPT model too.
1437-
* In case of PIPT caches, there cannot be cache aliases.
1438-
* However on ARM9 cores, the data cache follows the VIVT model, hence
1439-
* the cache aliases issue can occur when buffers are allocated from
1440-
* DMA-unsafe areas, by vmalloc() for instance, where cache coherency is
1441-
* not taken into account or at least not handled completely (cache
1442-
* lines of aliases are not invalidated).
1443-
* This is not a theorical issue: it was reproduced when trying to mount
1444-
* a UBI file-system on a at91sam9g35ek board.
1445-
*/
1446-
as->caps.has_dma_support = false;
1447-
#else
14481472
as->caps.has_dma_support = version >= 0x212;
1449-
#endif
14501473
as->caps.has_pdc_support = version < 0x212;
14511474
}
14521475

@@ -1592,6 +1615,30 @@ static int atmel_spi_probe(struct platform_device *pdev)
15921615
as->use_pdc = true;
15931616
}
15941617

1618+
if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
1619+
as->addr_rx_bbuf = dma_alloc_coherent(&pdev->dev,
1620+
SPI_MAX_DMA_XFER,
1621+
&as->dma_addr_rx_bbuf,
1622+
GFP_KERNEL | GFP_DMA);
1623+
if (!as->addr_rx_bbuf) {
1624+
as->use_dma = false;
1625+
} else {
1626+
as->addr_tx_bbuf = dma_alloc_coherent(&pdev->dev,
1627+
SPI_MAX_DMA_XFER,
1628+
&as->dma_addr_tx_bbuf,
1629+
GFP_KERNEL | GFP_DMA);
1630+
if (!as->addr_tx_bbuf) {
1631+
as->use_dma = false;
1632+
dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
1633+
as->addr_rx_bbuf,
1634+
as->dma_addr_rx_bbuf);
1635+
}
1636+
}
1637+
if (!as->use_dma)
1638+
dev_info(master->dev.parent,
1639+
" can not allocate dma coherent memory\n");
1640+
}
1641+
15951642
if (as->caps.has_dma_support && !as->use_dma)
15961643
dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n");
15971644

@@ -1661,12 +1708,20 @@ static int atmel_spi_remove(struct platform_device *pdev)
16611708
pm_runtime_get_sync(&pdev->dev);
16621709

16631710
/* reset the hardware and block queue progress */
1664-
spin_lock_irq(&as->lock);
16651711
if (as->use_dma) {
16661712
atmel_spi_stop_dma(master);
16671713
atmel_spi_release_dma(master);
1714+
if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
1715+
dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
1716+
as->addr_tx_bbuf,
1717+
as->dma_addr_tx_bbuf);
1718+
dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
1719+
as->addr_rx_bbuf,
1720+
as->dma_addr_rx_bbuf);
1721+
}
16681722
}
16691723

1724+
spin_lock_irq(&as->lock);
16701725
spi_writel(as, CR, SPI_BIT(SWRST));
16711726
spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
16721727
spi_readl(as, SR);

0 commit comments

Comments
 (0)