summaryrefslogtreecommitdiff
path: root/drivers/mmc/host/usdhi6rol0.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/usdhi6rol0.c')
-rw-r--r--drivers/mmc/host/usdhi6rol0.c73
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,
},
};