diff options
author | Mark Brown <broonie@kernel.org> | 2017-02-19 16:40:55 +0000 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-02-19 16:40:55 +0000 |
commit | 3490462378944c7e137657d0d66bb707303cfc96 (patch) | |
tree | ed0a745abd1c44b02629c8aaa8943ef88f7300f9 /drivers/spi | |
parent | 42af2f5c52daec0c182af66984927ef64885bbcc (diff) | |
parent | 1ce24864bff40e11500a699789412115fdf244bf (diff) |
Merge remote-tracking branch 'spi/topic/dma' into spi-next
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-mt65xx.c | 37 | ||||
-rw-r--r-- | drivers/spi/spi.c | 8 |
2 files changed, 37 insertions, 8 deletions
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 899d7a8f0889..278867a31950 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -73,7 +73,7 @@ #define MTK_SPI_IDLE 0 #define MTK_SPI_PAUSED 1 -#define MTK_SPI_MAX_FIFO_SIZE 32 +#define MTK_SPI_MAX_FIFO_SIZE 32U #define MTK_SPI_PACKET_SIZE 1024 struct mtk_spi_compatible { @@ -333,7 +333,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master, struct mtk_spi *mdata = spi_master_get_devdata(master); mdata->cur_transfer = xfer; - mdata->xfer_len = xfer->len; + mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len); mtk_spi_prepare_transfer(master, xfer); mtk_spi_setup_packet(master); @@ -410,7 +410,10 @@ static bool mtk_spi_can_dma(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) { - return xfer->len > MTK_SPI_MAX_FIFO_SIZE; + /* Buffers for DMA transactions must be 4-byte aligned */ + return (xfer->len > MTK_SPI_MAX_FIFO_SIZE && + (unsigned long)xfer->tx_buf % 4 == 0 && + (unsigned long)xfer->rx_buf % 4 == 0); } static int mtk_spi_setup(struct spi_device *spi) @@ -451,7 +454,33 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) ®_val, remainder); } } - spi_finalize_current_transfer(master); + + trans->len -= mdata->xfer_len; + if (!trans->len) { + spi_finalize_current_transfer(master); + return IRQ_HANDLED; + } + + if (trans->tx_buf) + trans->tx_buf += mdata->xfer_len; + if (trans->rx_buf) + trans->rx_buf += mdata->xfer_len; + + mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, trans->len); + mtk_spi_setup_packet(master); + + cnt = trans->len / 4; + iowrite32_rep(mdata->base + SPI_TX_DATA_REG, trans->tx_buf, cnt); + + remainder = trans->len % 4; + if (remainder > 0) { + reg_val = 0; + memcpy(®_val, trans->tx_buf + (cnt * 4), remainder); + writel(reg_val, mdata->base + SPI_TX_DATA_REG); + } + + mtk_spi_enable_transfer(master); + return IRQ_HANDLED; } diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 59cb26470d70..e70955339d33 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -807,12 +807,12 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg) if (master->dma_tx) tx_dev = master->dma_tx->device->dev; else - tx_dev = &master->dev; + tx_dev = master->dev.parent; if (master->dma_rx) rx_dev = master->dma_rx->device->dev; else - rx_dev = &master->dev; + rx_dev = master->dev.parent; list_for_each_entry(xfer, &msg->transfers, transfer_list) { if (!master->can_dma(master, msg->spi, xfer)) @@ -854,12 +854,12 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg) if (master->dma_tx) tx_dev = master->dma_tx->device->dev; else - tx_dev = &master->dev; + tx_dev = master->dev.parent; if (master->dma_rx) rx_dev = master->dma_rx->device->dev; else - rx_dev = &master->dev; + rx_dev = master->dev.parent; list_for_each_entry(xfer, &msg->transfers, transfer_list) { if (!master->can_dma(master, msg->spi, xfer)) |