summaryrefslogtreecommitdiff
path: root/drivers/mmc/host/moxart-mmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/moxart-mmc.c')
-rw-r--r--drivers/mmc/host/moxart-mmc.c78
1 files changed, 35 insertions, 43 deletions
diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c
index 52ed30f2d9f4..3dd8f232052f 100644
--- a/drivers/mmc/host/moxart-mmc.c
+++ b/drivers/mmc/host/moxart-mmc.c
@@ -254,6 +254,11 @@ static void moxart_dma_complete(void *param)
complete(&host->dma_complete);
}
+static bool moxart_use_dma(struct moxart_host *host)
+{
+ return (host->data_len > host->fifo_width) && host->have_dma;
+}
+
static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host)
{
u32 len, dir_slave;
@@ -291,11 +296,11 @@ static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host)
dma_async_issue_pending(dma_chan);
}
- data->bytes_xfered += host->data_remain;
-
wait_for_completion_interruptible_timeout(&host->dma_complete,
host->timeout);
+ data->bytes_xfered = host->data_len;
+
dma_unmap_sg(dma_chan->device->dev,
data->sg, data->sg_len,
mmc_get_dma_dir(data));
@@ -338,13 +343,7 @@ static void moxart_transfer_pio(struct moxart_host *host)
return;
}
for (len = 0; len < remain && len < host->fifo_width;) {
- /* SCR data must be read in big endian. */
- if (data->mrq->cmd->opcode == SD_APP_SEND_SCR)
- *sgp = ioread32be(host->base +
- REG_DATA_WINDOW);
- else
- *sgp = ioread32(host->base +
- REG_DATA_WINDOW);
+ *sgp = ioread32(host->base + REG_DATA_WINDOW);
sgp++;
len += 4;
}
@@ -381,7 +380,7 @@ static void moxart_prepare_data(struct moxart_host *host)
if (data->flags & MMC_DATA_WRITE)
datactrl |= DCR_DATA_WRITE;
- if ((host->data_len > host->fifo_width) && host->have_dma)
+ if (moxart_use_dma(host))
datactrl |= DCR_DMA_EN;
writel(DCR_DATA_FIFO_RESET, host->base + REG_DATA_CONTROL);
@@ -413,7 +412,7 @@ static void moxart_request(struct mmc_host *mmc, struct mmc_request *mrq)
moxart_send_command(host, host->mrq->cmd);
if (mrq->cmd->data) {
- if ((host->data_len > host->fifo_width) && host->have_dma) {
+ if (moxart_use_dma(host)) {
writel(CARD_CHANGE, host->base + REG_INTERRUPT_MASK);
@@ -559,41 +558,33 @@ static int moxart_probe(struct platform_device *pdev)
int irq, ret;
u32 i;
- mmc = mmc_alloc_host(sizeof(struct moxart_host), dev);
+ mmc = devm_mmc_alloc_host(dev, sizeof(*host));
if (!mmc) {
- dev_err(dev, "mmc_alloc_host failed\n");
- ret = -ENOMEM;
- goto out_mmc;
+ dev_err(dev, "devm_mmc_alloc_host failed\n");
+ return -ENOMEM;
}
ret = of_address_to_resource(node, 0, &res_mmc);
- if (ret) {
- dev_err(dev, "of_address_to_resource failed\n");
- goto out_mmc;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "of_address_to_resource failed\n");
irq = irq_of_parse_and_map(node, 0);
- if (irq <= 0) {
- dev_err(dev, "irq_of_parse_and_map failed\n");
- ret = -EINVAL;
- goto out_mmc;
- }
+ if (irq <= 0)
+ return dev_err_probe(dev, -EINVAL,
+ "irq_of_parse_and_map failed\n");
clk = devm_clk_get(dev, NULL);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- goto out_mmc;
- }
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
reg_mmc = devm_ioremap_resource(dev, &res_mmc);
- if (IS_ERR(reg_mmc)) {
- ret = PTR_ERR(reg_mmc);
- goto out_mmc;
- }
+ if (IS_ERR(reg_mmc))
+ return PTR_ERR(reg_mmc);
ret = mmc_of_parse(mmc);
if (ret)
- goto out_mmc;
+ return ret;
host = mmc_priv(mmc);
host->mmc = mmc;
@@ -611,6 +602,9 @@ static int moxart_probe(struct platform_device *pdev)
mmc->f_max = DIV_ROUND_CLOSEST(host->sysclk, 2);
mmc->f_min = DIV_ROUND_CLOSEST(host->sysclk, CLK_DIV_MASK * 2);
mmc->ocr_avail = 0xffff00; /* Support 2.0v - 3.6v power. */
+ mmc->max_blk_size = 2048; /* Max. block length in REG_DATA_CONTROL */
+ mmc->max_req_size = DATA_LEN_MASK; /* bits 0-23 in REG_DATA_LENGTH */
+ mmc->max_blk_count = mmc->max_req_size / 512;
if (IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) {
if (PTR_ERR(host->dma_chan_tx) == -EPROBE_DEFER ||
@@ -628,6 +622,8 @@ static int moxart_probe(struct platform_device *pdev)
}
dev_dbg(dev, "PIO mode transfer enabled\n");
host->have_dma = false;
+
+ mmc->max_seg_size = mmc->max_req_size;
} else {
dev_dbg(dev, "DMA channels found (%p,%p)\n",
host->dma_chan_tx, host->dma_chan_rx);
@@ -646,6 +642,10 @@ static int moxart_probe(struct platform_device *pdev)
cfg.src_addr = host->reg_phys + REG_DATA_WINDOW;
cfg.dst_addr = 0;
dmaengine_slave_config(host->dma_chan_rx, &cfg);
+
+ mmc->max_seg_size = min3(mmc->max_req_size,
+ dma_get_max_seg_size(host->dma_chan_rx->device->dev),
+ dma_get_max_seg_size(host->dma_chan_tx->device->dev));
}
if (readl(host->base + REG_BUS_WIDTH) & BUS_WIDTH_4_SUPPORT)
@@ -678,19 +678,14 @@ out:
dma_release_channel(host->dma_chan_tx);
if (!IS_ERR_OR_NULL(host->dma_chan_rx))
dma_release_channel(host->dma_chan_rx);
-out_mmc:
- if (mmc)
- mmc_free_host(mmc);
return ret;
}
-static int moxart_remove(struct platform_device *pdev)
+static void moxart_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = dev_get_drvdata(&pdev->dev);
struct moxart_host *host = mmc_priv(mmc);
- dev_set_drvdata(&pdev->dev, NULL);
-
if (!IS_ERR_OR_NULL(host->dma_chan_tx))
dma_release_channel(host->dma_chan_tx);
if (!IS_ERR_OR_NULL(host->dma_chan_rx))
@@ -701,9 +696,6 @@ static int moxart_remove(struct platform_device *pdev)
writel(0, host->base + REG_POWER_CONTROL);
writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF,
host->base + REG_CLOCK_CONTROL);
- mmc_free_host(mmc);
-
- return 0;
}
static const struct of_device_id moxart_mmc_match[] = {
@@ -715,7 +707,7 @@ MODULE_DEVICE_TABLE(of, moxart_mmc_match);
static struct platform_driver moxart_mmc_driver = {
.probe = moxart_probe,
- .remove = moxart_remove,
+ .remove = moxart_remove,
.driver = {
.name = "mmc-moxart",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,