Commit 07df8e09 authored by David Brownell's avatar David Brownell Committed by Kevin Hilman

MMC DMA ... not just for MMC0

Update the davinci_mmc driver to stop hard-wiring use of
mmc0 DMA channels:  look them up during probe, record them,
and use the recorded values everywhere, not constants.
Add a previously-missing diagnostic if probe() fails.

Also fix a seeming bug in the rarely-used davinci_abort_dma()
call.  It was aborting the wrong channel ... the idle one,
not the active one.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent 70a3a094
...@@ -327,17 +327,13 @@ static void davinci_fifo_data_trans(struct mmc_davinci_host *host, int n) ...@@ -327,17 +327,13 @@ static void davinci_fifo_data_trans(struct mmc_davinci_host *host, int n)
host->buffer = p; host->buffer = p;
} }
static void davinci_reinit_chan(void) static void davinci_reinit_chan(struct mmc_davinci_host *host)
{ {
int sync_dev; davinci_stop_dma(host->txdma);
davinci_clean_channel(host->txdma);
sync_dev = DAVINCI_DMA_MMCTXEVT; davinci_stop_dma(host->rxdma);
davinci_stop_dma(sync_dev); davinci_clean_channel(host->rxdma);
davinci_clean_channel(sync_dev);
sync_dev = DAVINCI_DMA_MMCRXEVT;
davinci_stop_dma(sync_dev);
davinci_clean_channel(sync_dev);
} }
static void davinci_abort_dma(struct mmc_davinci_host *host) static void davinci_abort_dma(struct mmc_davinci_host *host)
...@@ -345,9 +341,9 @@ static void davinci_abort_dma(struct mmc_davinci_host *host) ...@@ -345,9 +341,9 @@ static void davinci_abort_dma(struct mmc_davinci_host *host)
int sync_dev = 0; int sync_dev = 0;
if (host->data_dir == DAVINCI_MMC_DATADIR_READ) if (host->data_dir == DAVINCI_MMC_DATADIR_READ)
sync_dev = DAVINCI_DMA_MMCTXEVT; sync_dev = host->rxdma;
else else
sync_dev = DAVINCI_DMA_MMCRXEVT; sync_dev = host->txdma;
davinci_stop_dma(sync_dev); davinci_stop_dma(sync_dev);
davinci_clean_channel(sync_dev); davinci_clean_channel(sync_dev);
...@@ -391,8 +387,8 @@ static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, ...@@ -391,8 +387,8 @@ static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host,
static int davinci_release_dma_channels(struct mmc_davinci_host *host) static int davinci_release_dma_channels(struct mmc_davinci_host *host)
{ {
davinci_free_dma(DAVINCI_DMA_MMCTXEVT); davinci_free_dma(host->txdma);
davinci_free_dma(DAVINCI_DMA_MMCRXEVT); davinci_free_dma(host->rxdma);
if (host->edma_ch_details.cnt_chanel) { if (host->edma_ch_details.cnt_chanel) {
davinci_free_dma(host->edma_ch_details.chanel_num[0]); davinci_free_dma(host->edma_ch_details.chanel_num[0]);
...@@ -408,7 +404,7 @@ static int davinci_acquire_dma_channels(struct mmc_davinci_host *host) ...@@ -408,7 +404,7 @@ static int davinci_acquire_dma_channels(struct mmc_davinci_host *host)
enum dma_event_q queue_no = EVENTQ_0; enum dma_event_q queue_no = EVENTQ_0;
/* Acquire master DMA write channel */ /* Acquire master DMA write channel */
r = davinci_request_dma(DAVINCI_DMA_MMCTXEVT, "MMC_WRITE", r = davinci_request_dma(host->txdma, "MMC_WRITE",
mmc_davinci_dma_cb, host, &edma_chan_num, &tcc, queue_no); mmc_davinci_dma_cb, host, &edma_chan_num, &tcc, queue_no);
if (r != 0) { if (r != 0) {
dev_warn(mmc_dev(host->mmc), dev_warn(mmc_dev(host->mmc),
...@@ -418,7 +414,7 @@ static int davinci_acquire_dma_channels(struct mmc_davinci_host *host) ...@@ -418,7 +414,7 @@ static int davinci_acquire_dma_channels(struct mmc_davinci_host *host)
} }
/* Acquire master DMA read channel */ /* Acquire master DMA read channel */
r = davinci_request_dma(DAVINCI_DMA_MMCRXEVT, "MMC_READ", r = davinci_request_dma(host->rxdma, "MMC_READ",
mmc_davinci_dma_cb, host, &edma_chan_num, &tcc, queue_no); mmc_davinci_dma_cb, host, &edma_chan_num, &tcc, queue_no);
if (r != 0) { if (r != 0) {
dev_warn(mmc_dev(host->mmc), dev_warn(mmc_dev(host->mmc),
...@@ -434,7 +430,7 @@ static int davinci_acquire_dma_channels(struct mmc_davinci_host *host) ...@@ -434,7 +430,7 @@ static int davinci_acquire_dma_channels(struct mmc_davinci_host *host)
/* Create a DMA slave read channel /* Create a DMA slave read channel
* (assuming max segments handled is 2) */ * (assuming max segments handled is 2) */
sync_dev = DAVINCI_DMA_MMCRXEVT; sync_dev = host->rxdma;
r = davinci_request_dma(DAVINCI_EDMA_PARAM_ANY, "LINK", NULL, NULL, r = davinci_request_dma(DAVINCI_EDMA_PARAM_ANY, "LINK", NULL, NULL,
&edma_chan_num, &sync_dev, queue_no); &edma_chan_num, &sync_dev, queue_no);
if (r != 0) { if (r != 0) {
...@@ -449,9 +445,9 @@ static int davinci_acquire_dma_channels(struct mmc_davinci_host *host) ...@@ -449,9 +445,9 @@ static int davinci_acquire_dma_channels(struct mmc_davinci_host *host)
return 0; return 0;
free_master_read: free_master_read:
davinci_free_dma(DAVINCI_DMA_MMCRXEVT); davinci_free_dma(host->rxdma);
free_master_write: free_master_write:
davinci_free_dma(DAVINCI_DMA_MMCTXEVT); davinci_free_dma(host->txdma);
return r; return r;
} }
...@@ -520,7 +516,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host, ...@@ -520,7 +516,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) { if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
/*AB Sync Transfer */ /*AB Sync Transfer */
sync_dev = DAVINCI_DMA_MMCTXEVT; sync_dev = host->txdma;
src_port = (unsigned int)sg_dma_address(sg); src_port = (unsigned int)sg_dma_address(sg);
mode_src = INCR; mode_src = INCR;
...@@ -538,7 +534,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host, ...@@ -538,7 +534,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
sync_mode = ABSYNC; sync_mode = ABSYNC;
} else { } else {
sync_dev = DAVINCI_DMA_MMCRXEVT; sync_dev = host->rxdma;
src_port = (unsigned int)(host->mem_res->start + src_port = (unsigned int)(host->mem_res->start +
DAVINCI_MMCDRR); DAVINCI_MMCDRR);
...@@ -566,7 +562,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host, ...@@ -566,7 +562,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
sync_mode); sync_mode);
davinci_get_dma_params(sync_dev, &temp); davinci_get_dma_params(sync_dev, &temp);
if (sync_dev == DAVINCI_DMA_MMCTXEVT) { if (sync_dev == host->txdma) {
if (host->option_write == 0) { if (host->option_write == 0) {
host->option_write = temp.opt; host->option_write = temp.opt;
} else { } else {
...@@ -574,7 +570,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host, ...@@ -574,7 +570,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
davinci_set_dma_params(sync_dev, &temp); davinci_set_dma_params(sync_dev, &temp);
} }
} }
if (sync_dev == DAVINCI_DMA_MMCRXEVT) { if (sync_dev == host->rxdma) {
if (host->option_read == 0) { if (host->option_read == 0) {
host->option_read = temp.opt; host->option_read = temp.opt;
} else { } else {
...@@ -612,7 +608,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host, ...@@ -612,7 +608,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
ccnt = count >> ((mmcsd_cfg.rw_threshold == 32)? 5 : 4); ccnt = count >> ((mmcsd_cfg.rw_threshold == 32)? 5 : 4);
if (sync_dev == DAVINCI_DMA_MMCTXEVT) if (sync_dev == host->txdma)
temp.src = (unsigned int)sg_dma_address(sg); temp.src = (unsigned int)sg_dma_address(sg);
else else
temp.dst = (unsigned int)sg_dma_address(sg); temp.dst = (unsigned int)sg_dma_address(sg);
...@@ -1253,7 +1249,7 @@ static void davinci_mmc_check_status(unsigned long data) ...@@ -1253,7 +1249,7 @@ static void davinci_mmc_check_status(unsigned long data)
if (!host->is_card_busy) { if (!host->is_card_busy) {
if (host->old_card_state ^ host->new_card_state) { if (host->old_card_state ^ host->new_card_state) {
davinci_reinit_chan(); davinci_reinit_chan(host);
init_mmcsd_host(host); init_mmcsd_host(host);
mmc_detect_change(host->mmc, 0); mmc_detect_change(host->mmc, 0);
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
...@@ -1319,8 +1315,18 @@ static int davinci_mmcsd_probe(struct platform_device *pdev) ...@@ -1319,8 +1315,18 @@ static int davinci_mmcsd_probe(struct platform_device *pdev)
host = mmc_priv(mmc); host = mmc_priv(mmc);
host->mmc = mmc; /* Important */ host->mmc = mmc; /* Important */
r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (!r)
goto out;
host->rxdma = r->start;
r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (!r)
goto out;
host->txdma = r->start;
host->mem_res = mem; host->mem_res = mem;
host->base = ioremap(r->start, SZ_4K); host->base = ioremap(mem->start, SZ_4K);
if (!host->base) if (!host->base)
goto out; goto out;
...@@ -1414,6 +1420,7 @@ out: ...@@ -1414,6 +1420,7 @@ out:
if (mem) if (mem)
release_resource(mem); release_resource(mem);
dev_dbg(&pdev->dev, "probe err %d\n", ret);
return ret; return ret;
} }
......
...@@ -178,6 +178,7 @@ struct mmc_davinci_host { ...@@ -178,6 +178,7 @@ struct mmc_davinci_host {
u8 *buffer; u8 *buffer;
u32 bytes_left; u32 bytes_left;
u8 rxdma, txdma;
bool use_dma; bool use_dma;
bool do_dma; bool do_dma;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment