i2c: tegra: Allocate DMA memory for DMA engine
When the I2C controllers are running in DMA mode, it is the DMA engine that performs the memory accesses rather than the I2C controller. Pass the DMA engine's struct device pointer to the DMA API to make sure the correct DMA operations are used. This fixes an issue where the DMA engine's SMMU stream ID needs to be misleadingly set for the I2C controllers in device tree. Suggested-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Wolfram Sang <wsa@kernel.org>
This commit is contained in:
Родитель
569bea74c9
Коммит
cdbf26251d
|
@ -284,6 +284,7 @@ struct tegra_i2c_dev {
|
|||
struct dma_chan *tx_dma_chan;
|
||||
struct dma_chan *rx_dma_chan;
|
||||
unsigned int dma_buf_size;
|
||||
struct device *dma_dev;
|
||||
dma_addr_t dma_phys;
|
||||
void *dma_buf;
|
||||
|
||||
|
@ -420,7 +421,7 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len)
|
|||
static void tegra_i2c_release_dma(struct tegra_i2c_dev *i2c_dev)
|
||||
{
|
||||
if (i2c_dev->dma_buf) {
|
||||
dma_free_coherent(i2c_dev->dev, i2c_dev->dma_buf_size,
|
||||
dma_free_coherent(i2c_dev->dma_dev, i2c_dev->dma_buf_size,
|
||||
i2c_dev->dma_buf, i2c_dev->dma_phys);
|
||||
i2c_dev->dma_buf = NULL;
|
||||
}
|
||||
|
@ -472,10 +473,13 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
|
|||
|
||||
i2c_dev->tx_dma_chan = chan;
|
||||
|
||||
WARN_ON(i2c_dev->tx_dma_chan->device != i2c_dev->rx_dma_chan->device);
|
||||
i2c_dev->dma_dev = chan->device->dev;
|
||||
|
||||
i2c_dev->dma_buf_size = i2c_dev->hw->quirks->max_write_len +
|
||||
I2C_PACKET_HEADER_SIZE;
|
||||
|
||||
dma_buf = dma_alloc_coherent(i2c_dev->dev, i2c_dev->dma_buf_size,
|
||||
dma_buf = dma_alloc_coherent(i2c_dev->dma_dev, i2c_dev->dma_buf_size,
|
||||
&dma_phys, GFP_KERNEL | __GFP_NOWARN);
|
||||
if (!dma_buf) {
|
||||
dev_err(i2c_dev->dev, "failed to allocate DMA buffer\n");
|
||||
|
@ -1272,7 +1276,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
|
|||
|
||||
if (i2c_dev->dma_mode) {
|
||||
if (i2c_dev->msg_read) {
|
||||
dma_sync_single_for_device(i2c_dev->dev,
|
||||
dma_sync_single_for_device(i2c_dev->dma_dev,
|
||||
i2c_dev->dma_phys,
|
||||
xfer_size, DMA_FROM_DEVICE);
|
||||
|
||||
|
@ -1280,7 +1284,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
|
|||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
dma_sync_single_for_cpu(i2c_dev->dev,
|
||||
dma_sync_single_for_cpu(i2c_dev->dma_dev,
|
||||
i2c_dev->dma_phys,
|
||||
xfer_size, DMA_TO_DEVICE);
|
||||
}
|
||||
|
@ -1293,7 +1297,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
|
|||
memcpy(i2c_dev->dma_buf + I2C_PACKET_HEADER_SIZE,
|
||||
msg->buf, msg->len);
|
||||
|
||||
dma_sync_single_for_device(i2c_dev->dev,
|
||||
dma_sync_single_for_device(i2c_dev->dma_dev,
|
||||
i2c_dev->dma_phys,
|
||||
xfer_size, DMA_TO_DEVICE);
|
||||
|
||||
|
@ -1344,7 +1348,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
|
|||
}
|
||||
|
||||
if (i2c_dev->msg_read && i2c_dev->msg_err == I2C_ERR_NONE) {
|
||||
dma_sync_single_for_cpu(i2c_dev->dev,
|
||||
dma_sync_single_for_cpu(i2c_dev->dma_dev,
|
||||
i2c_dev->dma_phys,
|
||||
xfer_size, DMA_FROM_DEVICE);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче