- ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data),
- "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch);
- if (ret != 0) {
- dev_err(mmc_dev(host->mmc),
- "%s: omap_request_dma() failed with %d\n",
- mmc_hostname(host->mmc), ret);
- return ret;
- }
- ret = omap_hsmmc_pre_dma_transfer(host, data, NULL);
- if (ret)
- return ret;
+ chan = omap_hsmmc_get_dma_chan(host, data);
+ if (!chan) {
+ ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data),
+ "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch);
+ if (ret != 0) {
+ dev_err(mmc_dev(host->mmc),
+ "%s: omap_request_dma() failed with %d\n",
+ mmc_hostname(host->mmc), ret);
+ return ret;
+ }
+ ret = omap_hsmmc_pre_dma_transfer(host, data, NULL,
+ mmc_dev(host->mmc));
+ if (ret)
+ return ret;
+
+ host->dma_ch = dma_ch;
+ host->dma_sg_idx = 0;
+
+ omap_hsmmc_config_dma_params(host, data, data->sg);
+ } else {
+ struct dma_slave_config cfg;
+ struct dma_async_tx_descriptor *tx;
+
+ cfg.src_addr = host->mapbase + OMAP_HSMMC_DATA;
+ cfg.dst_addr = host->mapbase + OMAP_HSMMC_DATA;
+ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ cfg.src_maxburst = data->blksz / 4;
+ cfg.dst_maxburst = data->blksz / 4;
+
+ ret = dmaengine_slave_config(chan, &cfg);
+ if (ret)
+ return ret;
+
+ ret = omap_hsmmc_pre_dma_transfer(host, data, NULL,
+ chan->device->dev);
+ if (ret)
+ return ret;
+
+ tx = dmaengine_prep_slave_sg(chan, data->sg, data->sg_len,
+ data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!tx) {
+ dev_err(mmc_dev(host->mmc), "prep_slave_sg() failed\n");
+ /* FIXME: cleanup */
+ return -1;
+ }