diff options
Diffstat (limited to 'drivers/mmc/host/usdhi6rol0.c')
| -rw-r--r-- | drivers/mmc/host/usdhi6rol0.c | 73 |
1 files changed, 38 insertions, 35 deletions
diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index 369b8dee2e3d..3bccf800339b 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -323,7 +323,7 @@ static void usdhi6_blk_bounce(struct usdhi6_host *host, host->head_pg.page = host->pg.page; host->head_pg.mapped = host->pg.mapped; - host->pg.page = nth_page(host->pg.page, 1); + host->pg.page = host->pg.page + 1; host->pg.mapped = kmap(host->pg.page); host->blk_page = host->bounce_buf; @@ -503,7 +503,7 @@ static void usdhi6_sg_advance(struct usdhi6_host *host) /* We cannot get here after crossing a page border */ /* Next page in the same SG */ - host->pg.page = nth_page(sg_page(host->sg), host->page_idx); + host->pg.page = sg_page(host->sg) + host->page_idx; host->pg.mapped = kmap(host->pg.page); host->blk_page = host->pg.mapped; @@ -631,9 +631,9 @@ static void usdhi6_dma_kill(struct usdhi6_host *host) __func__, data->sg_len, data->blocks, data->blksz); /* Abort DMA */ if (data->flags & MMC_DATA_READ) - dmaengine_terminate_all(host->chan_rx); + dmaengine_terminate_sync(host->chan_rx); else - dmaengine_terminate_all(host->chan_tx); + dmaengine_terminate_sync(host->chan_tx); } static void usdhi6_dma_check_error(struct usdhi6_host *host) @@ -1186,6 +1186,15 @@ static int usdhi6_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios) return ret; } +static int usdhi6_card_busy(struct mmc_host *mmc) +{ + struct usdhi6_host *host = mmc_priv(mmc); + u32 tmp = usdhi6_read(host, USDHI6_SD_INFO2); + + /* Card is busy if it is pulling dat[0] low */ + return !(tmp & USDHI6_SD_INFO2_SDDAT0); +} + static const struct mmc_host_ops usdhi6_ops = { .request = usdhi6_request, .set_ios = usdhi6_set_ios, @@ -1193,6 +1202,7 @@ static const struct mmc_host_ops usdhi6_ops = { .get_ro = usdhi6_get_ro, .enable_sdio_irq = usdhi6_enable_sdio_irq, .start_signal_voltage_switch = usdhi6_sig_volt_switch, + .card_busy = usdhi6_card_busy, }; /* State machine handlers */ @@ -1343,7 +1353,7 @@ static int usdhi6_stop_cmd(struct usdhi6_host *host) host->wait = USDHI6_WAIT_FOR_STOP; return 0; } - /* fall through - Unsupported STOP command. */ + fallthrough; /* Unsupported STOP command */ default: dev_err(mmc_dev(host->mmc), "unsupported stop CMD%d for CMD%d\n", @@ -1691,7 +1701,7 @@ static void usdhi6_timeout_work(struct work_struct *work) switch (host->wait) { default: dev_err(mmc_dev(host->mmc), "Invalid state %u\n", host->wait); - /* fall through - mrq can be NULL, but is impossible. */ + fallthrough; /* mrq can be NULL, but is impossible */ case USDHI6_WAIT_FOR_CMD: usdhi6_error_code(host); if (mrq) @@ -1713,7 +1723,7 @@ static void usdhi6_timeout_work(struct work_struct *work) host->offset, data->blocks, data->blksz, data->sg_len, sg_dma_len(sg), sg->offset); usdhi6_sg_unmap(host, true); - /* fall through - page unmapped in USDHI6_WAIT_FOR_DATA_END. */ + fallthrough; /* page unmapped in USDHI6_WAIT_FOR_DATA_END */ case USDHI6_WAIT_FOR_DATA_END: usdhi6_error_code(host); data->error = -ETIMEDOUT; @@ -1747,20 +1757,22 @@ static int usdhi6_probe(struct platform_device *pdev) irq_cd = platform_get_irq_byname(pdev, "card detect"); irq_sd = platform_get_irq_byname(pdev, "data"); irq_sdio = platform_get_irq_byname(pdev, "SDIO"); - if (irq_sd < 0 || irq_sdio < 0) - return -ENODEV; + if (irq_sd < 0) + return irq_sd; + if (irq_sdio < 0) + return irq_sdio; - mmc = mmc_alloc_host(sizeof(struct usdhi6_host), dev); + mmc = devm_mmc_alloc_host(dev, sizeof(*host)); if (!mmc) return -ENOMEM; ret = mmc_regulator_get_supply(mmc); if (ret) - goto e_free_mmc; + return ret; ret = mmc_of_parse(mmc); if (ret < 0) - goto e_free_mmc; + return ret; host = mmc_priv(mmc); host->mmc = mmc; @@ -1773,34 +1785,28 @@ static int usdhi6_probe(struct platform_device *pdev) mmc->max_busy_timeout = USDHI6_REQ_TIMEOUT_MS; host->pinctrl = devm_pinctrl_get(&pdev->dev); - if (IS_ERR(host->pinctrl)) { - ret = PTR_ERR(host->pinctrl); - goto e_free_mmc; - } + if (IS_ERR(host->pinctrl)) + return PTR_ERR(host->pinctrl); host->pins_uhs = pinctrl_lookup_state(host->pinctrl, "state_uhs"); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - host->base = devm_ioremap_resource(dev, res); - if (IS_ERR(host->base)) { - ret = PTR_ERR(host->base); - goto e_free_mmc; - } + host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(host->base)) + return PTR_ERR(host->base); host->clk = devm_clk_get(dev, NULL); - if (IS_ERR(host->clk)) { - ret = PTR_ERR(host->clk); - goto e_free_mmc; - } + if (IS_ERR(host->clk)) + return PTR_ERR(host->clk); host->imclk = clk_get_rate(host->clk); ret = clk_prepare_enable(host->clk); if (ret < 0) - goto e_free_mmc; + return ret; version = usdhi6_read(host, USDHI6_VERSION); if ((version & 0xfff) != 0xa0d) { + ret = -EPERM; dev_err(dev, "Version not recognized %x\n", version); goto e_clk_off; } @@ -1858,19 +1864,18 @@ static int usdhi6_probe(struct platform_device *pdev) ret = mmc_add_host(mmc); if (ret < 0) - goto e_clk_off; + goto e_release_dma; return 0; +e_release_dma: + usdhi6_dma_release(host); e_clk_off: clk_disable_unprepare(host->clk); -e_free_mmc: - mmc_free_host(mmc); - return ret; } -static int usdhi6_remove(struct platform_device *pdev) +static void usdhi6_remove(struct platform_device *pdev) { struct usdhi6_host *host = platform_get_drvdata(pdev); @@ -1880,9 +1885,6 @@ static int usdhi6_remove(struct platform_device *pdev) cancel_delayed_work_sync(&host->timeout_work); usdhi6_dma_release(host); clk_disable_unprepare(host->clk); - mmc_free_host(host->mmc); - - return 0; } static struct platform_driver usdhi6_driver = { @@ -1890,6 +1892,7 @@ static struct platform_driver usdhi6_driver = { .remove = usdhi6_remove, .driver = { .name = "usdhi6rol0", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = usdhi6_of_match, }, }; |
