diff options
author | Arnd Bergmann <arnd@arndb.de> | 2015-11-16 11:08:41 -0500 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2015-12-22 05:32:08 -0500 |
commit | 27cbd7e815a8e223ff7c4fe56daca724101288ac (patch) | |
tree | 266ebb891eef1311d145ade805e21fde3b8f8a72 /drivers/mmc | |
parent | 2e4456f08fa81b9a4804379c56c7ef02c0b0d8f0 (diff) |
mmc: sh_mmcif: rework dma channel handling
When compiling the sh_mmcif driver for ARM64, we currently
get a harmless build warning:
../drivers/mmc/host/sh_mmcif.c: In function 'sh_mmcif_request_dma_one':
../drivers/mmc/host/sh_mmcif.c:417:4: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
(void *)pdata->slave_id_tx :
^
../drivers/mmc/host/sh_mmcif.c:418:4: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
(void *)pdata->slave_id_rx;
This could be worked around by adding another cast to uintptr_t, but
I decided to simplify the code a little more to avoid that. This
splits out the platform data using code into a separate function
and builds that only for CONFIG_SUPERH. This part still has a typecast
but does not need a second one. The SH platform code could be further
modified to pass a pointer directly as we do on other architectures
when we have a filter function.
The normal case is simplified further and now just calls
dma_request_slave_channel() directly without going through the
compat handling.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/sh_mmcif.c | 84 |
1 files changed, 38 insertions, 46 deletions
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index ad9ffea7d659..1ca8a1359cbc 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -397,38 +397,26 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) | |||
397 | } | 397 | } |
398 | 398 | ||
399 | static struct dma_chan * | 399 | static struct dma_chan * |
400 | sh_mmcif_request_dma_one(struct sh_mmcif_host *host, | 400 | sh_mmcif_request_dma_pdata(struct sh_mmcif_host *host, uintptr_t slave_id) |
401 | struct sh_mmcif_plat_data *pdata, | ||
402 | enum dma_transfer_direction direction) | ||
403 | { | 401 | { |
404 | struct dma_slave_config cfg = { 0, }; | ||
405 | struct dma_chan *chan; | ||
406 | void *slave_data = NULL; | ||
407 | struct resource *res; | ||
408 | struct device *dev = sh_mmcif_host_to_dev(host); | ||
409 | dma_cap_mask_t mask; | 402 | dma_cap_mask_t mask; |
410 | int ret; | ||
411 | 403 | ||
412 | dma_cap_zero(mask); | 404 | dma_cap_zero(mask); |
413 | dma_cap_set(DMA_SLAVE, mask); | 405 | dma_cap_set(DMA_SLAVE, mask); |
406 | if (slave_id <= 0) | ||
407 | return NULL; | ||
414 | 408 | ||
415 | if (pdata) | 409 | return dma_request_channel(mask, shdma_chan_filter, (void *)slave_id); |
416 | slave_data = direction == DMA_MEM_TO_DEV ? | 410 | } |
417 | (void *)pdata->slave_id_tx : | ||
418 | (void *)pdata->slave_id_rx; | ||
419 | |||
420 | chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, | ||
421 | slave_data, dev, | ||
422 | direction == DMA_MEM_TO_DEV ? "tx" : "rx"); | ||
423 | |||
424 | dev_dbg(dev, "%s: %s: got channel %p\n", __func__, | ||
425 | direction == DMA_MEM_TO_DEV ? "TX" : "RX", chan); | ||
426 | 411 | ||
427 | if (!chan) | 412 | static int sh_mmcif_dma_slave_config(struct sh_mmcif_host *host, |
428 | return NULL; | 413 | struct dma_chan *chan, |
414 | enum dma_transfer_direction direction) | ||
415 | { | ||
416 | struct resource *res; | ||
417 | struct dma_slave_config cfg = { 0, }; | ||
429 | 418 | ||
430 | res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); | 419 | res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); |
431 | |||
432 | cfg.direction = direction; | 420 | cfg.direction = direction; |
433 | 421 | ||
434 | if (direction == DMA_DEV_TO_MEM) { | 422 | if (direction == DMA_DEV_TO_MEM) { |
@@ -439,38 +427,42 @@ sh_mmcif_request_dma_one(struct sh_mmcif_host *host, | |||
439 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | 427 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
440 | } | 428 | } |
441 | 429 | ||
442 | ret = dmaengine_slave_config(chan, &cfg); | 430 | return dmaengine_slave_config(chan, &cfg); |
443 | if (ret < 0) { | ||
444 | dma_release_channel(chan); | ||
445 | return NULL; | ||
446 | } | ||
447 | |||
448 | return chan; | ||
449 | } | 431 | } |
450 | 432 | ||
451 | static void sh_mmcif_request_dma(struct sh_mmcif_host *host, | 433 | static void sh_mmcif_request_dma(struct sh_mmcif_host *host) |
452 | struct sh_mmcif_plat_data *pdata) | ||
453 | { | 434 | { |
454 | struct device *dev = sh_mmcif_host_to_dev(host); | 435 | struct device *dev = sh_mmcif_host_to_dev(host); |
455 | host->dma_active = false; | 436 | host->dma_active = false; |
456 | 437 | ||
457 | if (pdata) { | 438 | /* We can only either use DMA for both Tx and Rx or not use it at all */ |
458 | if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) | 439 | if (IS_ENABLED(CONFIG_SUPERH) && dev->platform_data) { |
459 | return; | 440 | struct sh_mmcif_plat_data *pdata = dev->platform_data; |
460 | } else if (!dev->of_node) { | 441 | |
461 | return; | 442 | host->chan_tx = sh_mmcif_request_dma_pdata(host, |
443 | pdata->slave_id_tx); | ||
444 | host->chan_rx = sh_mmcif_request_dma_pdata(host, | ||
445 | pdata->slave_id_rx); | ||
446 | } else { | ||
447 | host->chan_tx = dma_request_slave_channel(dev, "tx"); | ||
448 | host->chan_tx = dma_request_slave_channel(dev, "rx"); | ||
462 | } | 449 | } |
450 | dev_dbg(dev, "%s: got channel TX %p RX %p\n", __func__, host->chan_tx, | ||
451 | host->chan_rx); | ||
463 | 452 | ||
464 | /* We can only either use DMA for both Tx and Rx or not use it at all */ | 453 | if (!host->chan_tx || !host->chan_rx || |
465 | host->chan_tx = sh_mmcif_request_dma_one(host, pdata, DMA_MEM_TO_DEV); | 454 | sh_mmcif_dma_slave_config(host, host->chan_tx, DMA_MEM_TO_DEV) || |
466 | if (!host->chan_tx) | 455 | sh_mmcif_dma_slave_config(host, host->chan_rx, DMA_DEV_TO_MEM)) |
467 | return; | 456 | goto error; |
468 | 457 | ||
469 | host->chan_rx = sh_mmcif_request_dma_one(host, pdata, DMA_DEV_TO_MEM); | 458 | return; |
470 | if (!host->chan_rx) { | 459 | |
460 | error: | ||
461 | if (host->chan_tx) | ||
471 | dma_release_channel(host->chan_tx); | 462 | dma_release_channel(host->chan_tx); |
472 | host->chan_tx = NULL; | 463 | if (host->chan_rx) |
473 | } | 464 | dma_release_channel(host->chan_rx); |
465 | host->chan_tx = host->chan_rx = NULL; | ||
474 | } | 466 | } |
475 | 467 | ||
476 | static void sh_mmcif_release_dma(struct sh_mmcif_host *host) | 468 | static void sh_mmcif_release_dma(struct sh_mmcif_host *host) |
@@ -1102,7 +1094,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1102 | if (ios->power_mode == MMC_POWER_UP) { | 1094 | if (ios->power_mode == MMC_POWER_UP) { |
1103 | if (!host->card_present) { | 1095 | if (!host->card_present) { |
1104 | /* See if we also get DMA */ | 1096 | /* See if we also get DMA */ |
1105 | sh_mmcif_request_dma(host, dev->platform_data); | 1097 | sh_mmcif_request_dma(host); |
1106 | host->card_present = true; | 1098 | host->card_present = true; |
1107 | } | 1099 | } |
1108 | sh_mmcif_set_power(host, ios); | 1100 | sh_mmcif_set_power(host, ios); |