mmc: mxcmmc: enable DMA support on mpc512x

Add SDHC DMA channel description to the mpc512x device tree to enable
slave channel requesting in the mxcmmc driver.

mpc512x DMA engine doesn't support endianness conversion when
reading/writing data from peripheral's FIFO, so we have to swap data
buffers before each DMA write and after each DMA read transfer manually.

Since chained SDHC DMA transfers are not supported on mpc512x, limit
'max_segs' tunable parameter to one and initialise it to 64 only when
running on i.MX platforms.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
Anatolij Gustschin 2013-04-08 23:28:09 +02:00 committed by Chris Ball
parent 42477053c3
commit e48fc15aa2
2 changed files with 35 additions and 2 deletions

View File

@ -152,6 +152,8 @@
compatible = "fsl,mpc5121-sdhc"; compatible = "fsl,mpc5121-sdhc";
reg = <0x1500 0x100>; reg = <0x1500 0x100>;
interrupts = <8 0x8>; interrupts = <8 0x8>;
dmas = <&dma0 30>;
dma-names = "rx-tx";
}; };
i2c@1700 { i2c@1700 {

View File

@ -301,6 +301,29 @@ static void mxcmci_softreset(struct mxcmci_host *host)
} }
static int mxcmci_setup_dma(struct mmc_host *mmc); static int mxcmci_setup_dma(struct mmc_host *mmc);
#if IS_ENABLED(CONFIG_PPC_MPC512x)
static inline void buffer_swap32(u32 *buf, int len)
{
int i;
for (i = 0; i < ((len + 3) / 4); i++) {
st_le32(buf, *buf);
buf++;
}
}
static void mxcmci_swap_buffers(struct mmc_data *data)
{
struct scatterlist *sg;
int i;
for_each_sg(data->sg, sg, data->sg_len, i)
buffer_swap32(sg_virt(sg), sg->length);
}
#else
static inline void mxcmci_swap_buffers(struct mmc_data *data) {}
#endif
static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
{ {
unsigned int nob = data->blocks; unsigned int nob = data->blocks;
@ -336,6 +359,8 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
} else { } else {
host->dma_dir = DMA_TO_DEVICE; host->dma_dir = DMA_TO_DEVICE;
slave_dirn = DMA_MEM_TO_DEV; slave_dirn = DMA_MEM_TO_DEV;
mxcmci_swap_buffers(data);
} }
nents = dma_map_sg(host->dma->device->dev, data->sg, nents = dma_map_sg(host->dma->device->dev, data->sg,
@ -461,9 +486,11 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
struct mmc_data *data = host->data; struct mmc_data *data = host->data;
int data_error; int data_error;
if (mxcmci_use_dma(host)) if (mxcmci_use_dma(host)) {
dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
host->dma_dir); host->dma_dir);
mxcmci_swap_buffers(data);
}
if (stat & STATUS_ERR_MASK) { if (stat & STATUS_ERR_MASK) {
dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
@ -1050,7 +1077,6 @@ static int mxcmci_probe(struct platform_device *pdev)
mmc->caps |= MMC_CAP_SDIO_IRQ; mmc->caps |= MMC_CAP_SDIO_IRQ;
/* MMC core transfer sizes tunable parameters */ /* MMC core transfer sizes tunable parameters */
mmc->max_segs = 64;
mmc->max_blk_size = 2048; mmc->max_blk_size = 2048;
mmc->max_blk_count = 65535; mmc->max_blk_count = 65535;
mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
@ -1069,6 +1095,11 @@ static int mxcmci_probe(struct platform_device *pdev)
} else { } else {
host->devtype = pdev->id_entry->driver_data; host->devtype = pdev->id_entry->driver_data;
} }
/* adjust max_segs after devtype detection */
if (!is_mpc512x_mmc(host))
mmc->max_segs = 64;
host->mmc = mmc; host->mmc = mmc;
host->pdata = pdata; host->pdata = pdata;
spin_lock_init(&host->lock); spin_lock_init(&host->lock);