diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2013-10-30 07:34:51 -0400 |
---|---|---|
committer | Chris Ball <chris@printf.net> | 2014-01-13 12:48:25 -0500 |
commit | e5a233cb647d749de2f188477c9a54b94d90477f (patch) | |
tree | 77c100b8c11c31e95e69a56aea6be92bbfeed255 | |
parent | e3c418f1b26b59841bd074baa740a43afc15199b (diff) |
mmc: sh_mmcif: Factorize DMA channel request and configuration code
The channel request and configuration code is duplicated for the rx and
tx channels. Create a function that requests a single channel and call
it twice instead.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r-- | drivers/mmc/host/sh_mmcif.c | 100 |
1 files changed, 51 insertions, 49 deletions
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index d032b080ac4d..bebf2fe38ea0 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -381,73 +381,75 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) | |||
381 | desc, cookie); | 381 | desc, cookie); |
382 | } | 382 | } |
383 | 383 | ||
384 | static void sh_mmcif_request_dma(struct sh_mmcif_host *host, | 384 | static struct dma_chan * |
385 | struct sh_mmcif_plat_data *pdata) | 385 | sh_mmcif_request_dma_one(struct sh_mmcif_host *host, |
386 | struct sh_mmcif_plat_data *pdata, | ||
387 | enum dma_transfer_direction direction) | ||
386 | { | 388 | { |
387 | struct resource *res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); | ||
388 | struct dma_slave_config cfg; | 389 | struct dma_slave_config cfg; |
390 | struct dma_chan *chan; | ||
391 | unsigned int slave_id; | ||
392 | struct resource *res; | ||
389 | dma_cap_mask_t mask; | 393 | dma_cap_mask_t mask; |
390 | int ret; | 394 | int ret; |
391 | 395 | ||
392 | host->dma_active = false; | ||
393 | |||
394 | if (pdata) { | ||
395 | if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) | ||
396 | return; | ||
397 | } else if (!host->pd->dev.of_node) { | ||
398 | return; | ||
399 | } | ||
400 | |||
401 | /* We can only either use DMA for both Tx and Rx or not use it at all */ | ||
402 | dma_cap_zero(mask); | 396 | dma_cap_zero(mask); |
403 | dma_cap_set(DMA_SLAVE, mask); | 397 | dma_cap_set(DMA_SLAVE, mask); |
404 | 398 | ||
405 | host->chan_tx = dma_request_slave_channel_compat(mask, shdma_chan_filter, | 399 | if (pdata) |
406 | pdata ? (void *)pdata->slave_id_tx : NULL, | 400 | slave_id = direction == DMA_MEM_TO_DEV |
407 | &host->pd->dev, "tx"); | 401 | ? pdata->slave_id_tx : pdata->slave_id_rx; |
408 | dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__, | 402 | else |
409 | host->chan_tx); | 403 | slave_id = 0; |
410 | 404 | ||
411 | if (!host->chan_tx) | 405 | chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, |
412 | return; | 406 | (void *)slave_id, &host->pd->dev, |
407 | direction == DMA_MEM_TO_DEV ? "tx" : "rx"); | ||
408 | |||
409 | dev_dbg(&host->pd->dev, "%s: %s: got channel %p\n", __func__, | ||
410 | direction == DMA_MEM_TO_DEV ? "TX" : "RX", chan); | ||
411 | |||
412 | if (!chan) | ||
413 | return NULL; | ||
414 | |||
415 | res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); | ||
413 | 416 | ||
414 | /* In the OF case the driver will get the slave ID from the DT */ | 417 | /* In the OF case the driver will get the slave ID from the DT */ |
415 | if (pdata) | 418 | cfg.slave_id = slave_id; |
416 | cfg.slave_id = pdata->slave_id_tx; | 419 | cfg.direction = direction; |
417 | cfg.direction = DMA_MEM_TO_DEV; | ||
418 | cfg.dst_addr = res->start + MMCIF_CE_DATA; | 420 | cfg.dst_addr = res->start + MMCIF_CE_DATA; |
419 | cfg.src_addr = 0; | 421 | cfg.src_addr = 0; |
420 | ret = dmaengine_slave_config(host->chan_tx, &cfg); | 422 | ret = dmaengine_slave_config(chan, &cfg); |
421 | if (ret < 0) | 423 | if (ret < 0) { |
422 | goto ecfgtx; | 424 | dma_release_channel(chan); |
425 | return NULL; | ||
426 | } | ||
423 | 427 | ||
424 | host->chan_rx = dma_request_slave_channel_compat(mask, shdma_chan_filter, | 428 | return chan; |
425 | pdata ? (void *)pdata->slave_id_rx : NULL, | 429 | } |
426 | &host->pd->dev, "rx"); | ||
427 | dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__, | ||
428 | host->chan_rx); | ||
429 | 430 | ||
430 | if (!host->chan_rx) | 431 | static void sh_mmcif_request_dma(struct sh_mmcif_host *host, |
431 | goto erqrx; | 432 | struct sh_mmcif_plat_data *pdata) |
433 | { | ||
434 | host->dma_active = false; | ||
432 | 435 | ||
433 | if (pdata) | 436 | if (pdata) { |
434 | cfg.slave_id = pdata->slave_id_rx; | 437 | if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) |
435 | cfg.direction = DMA_DEV_TO_MEM; | 438 | return; |
436 | cfg.dst_addr = 0; | 439 | } else if (!host->pd->dev.of_node) { |
437 | cfg.src_addr = res->start + MMCIF_CE_DATA; | 440 | return; |
438 | ret = dmaengine_slave_config(host->chan_rx, &cfg); | 441 | } |
439 | if (ret < 0) | ||
440 | goto ecfgrx; | ||
441 | 442 | ||
442 | return; | 443 | /* We can only either use DMA for both Tx and Rx or not use it at all */ |
444 | host->chan_tx = sh_mmcif_request_dma_one(host, pdata, DMA_MEM_TO_DEV); | ||
445 | if (!host->chan_tx) | ||
446 | return; | ||
443 | 447 | ||
444 | ecfgrx: | 448 | host->chan_rx = sh_mmcif_request_dma_one(host, pdata, DMA_DEV_TO_MEM); |
445 | dma_release_channel(host->chan_rx); | 449 | if (!host->chan_rx) { |
446 | host->chan_rx = NULL; | 450 | dma_release_channel(host->chan_tx); |
447 | erqrx: | 451 | host->chan_tx = NULL; |
448 | ecfgtx: | 452 | } |
449 | dma_release_channel(host->chan_tx); | ||
450 | host->chan_tx = NULL; | ||
451 | } | 453 | } |
452 | 454 | ||
453 | static void sh_mmcif_release_dma(struct sh_mmcif_host *host) | 455 | static void sh_mmcif_release_dma(struct sh_mmcif_host *host) |