summaryrefslogtreecommitdiffstats
path: root/drivers/mci/dw_mmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mci/dw_mmc.c')
-rw-r--r--drivers/mci/dw_mmc.c128
1 files changed, 68 insertions, 60 deletions
diff --git a/drivers/mci/dw_mmc.c b/drivers/mci/dw_mmc.c
index f035317ef2..c49e839c94 100644
--- a/drivers/mci/dw_mmc.c
+++ b/drivers/mci/dw_mmc.c
@@ -1,20 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2013 Altera Corporation <www.altera.com>
+// SPDX-FileCopyrightText: 2012 SAMSUNG Electronics
+
/*
- * Copyright (C) 2013 Altera Corporation <www.altera.com>
- *
- * (C) Copyright 2012 SAMSUNG Electronics
* Jaehoon Chung <jh80.chung@samsung.com>
* Rajeshawari Shinde <rajeshwari.s@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
*/
#include <common.h>
@@ -27,23 +17,26 @@
#include <io.h>
#include <platform_data/dw_mmc.h>
#include <linux/bitops.h>
+#include <linux/reset.h>
#include <linux/clk.h>
#include <linux/err.h>
-#include <asm-generic/errno.h>
+#include <errno.h>
#include "dw_mmc.h"
struct dwmci_host {
struct mci_host mci;
+ struct device *dev;
struct clk *clk_biu, *clk_ciu;
void *ioaddr;
unsigned int fifo_size_bytes;
struct dwmci_idmac *idmac;
- unsigned long clkrate;
+ u32 clkrate;
int ciu_div;
u32 fifoth_val;
u32 pwren_value;
+ dma_addr_t idmac_dma;
};
struct dwmci_idmac {
@@ -120,12 +113,12 @@ static int dwmci_prepare_data_pio(struct dwmci_host *host,
}
static int dwmci_prepare_data_dma(struct dwmci_host *host,
- struct mci_data *data)
+ struct mci_data *data, dma_addr_t dma)
{
unsigned long ctrl;
unsigned int i = 0, flags, cnt, blk_cnt;
- unsigned long data_start, start_addr;
struct dwmci_idmac *desc = host->idmac;
+ dma_addr_t desc_dma = host->idmac_dma;
blk_cnt = data->blocks;
@@ -134,13 +127,7 @@ static int dwmci_prepare_data_dma(struct dwmci_host *host,
dwmci_wait_reset(host, DWMCI_CTRL_FIFO_RESET);
- data_start = (uint32_t)desc;
- dwmci_writel(host, DWMCI_DBADDR, (uint32_t)desc);
-
- if (data->flags & MMC_DATA_READ)
- start_addr = (uint32_t)data->dest;
- else
- start_addr = (uint32_t)data->src;
+ dwmci_writel(host, DWMCI_DBADDR, desc_dma);
do {
flags = DWMCI_IDMAC_OWN | DWMCI_IDMAC_CH;
@@ -153,10 +140,12 @@ static int dwmci_prepare_data_dma(struct dwmci_host *host,
cnt = data->blocksize * 8;
}
+ desc_dma += sizeof(*desc);
+
desc->flags = flags;
desc->cnt = cnt;
- desc->addr = start_addr + (i * PAGE_SIZE);
- desc->next_addr = (uint32_t)(desc + 1);
+ desc->addr = dma + (i * PAGE_SIZE);
+ desc->next_addr = desc_dma;
dev_dbg(host->mci.hw_dev, "desc@ 0x%p 0x%08x 0x%08x 0x%08x 0x%08x\n",
desc, flags, cnt, desc->addr, desc->next_addr);
@@ -183,12 +172,12 @@ static int dwmci_prepare_data_dma(struct dwmci_host *host,
}
static int dwmci_prepare_data(struct dwmci_host *host,
- struct mci_data *data)
+ struct mci_data *data, dma_addr_t dma)
{
if (dwmci_use_pio(host))
return dwmci_prepare_data_pio(host, data);
else
- return dwmci_prepare_data_dma(host, data);
+ return dwmci_prepare_data_dma(host, data, dma);
}
static int dwmci_set_transfer_mode(struct dwmci_host *host,
@@ -283,6 +272,7 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
uint64_t start;
int ret;
unsigned int num_bytes = 0;
+ dma_addr_t dma = 0;
start = get_time_ns();
while (1) {
@@ -298,16 +288,20 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
if (data) {
+
num_bytes = data->blocks * data->blocksize;
if (data->flags & MMC_DATA_WRITE)
- dma_sync_single_for_device((unsigned long)data->src,
- num_bytes, DMA_TO_DEVICE);
+ dma = dma_map_single(host->dev, (void *)data->src, num_bytes,
+ DMA_TO_DEVICE);
else
- dma_sync_single_for_device((unsigned long)data->dest,
- num_bytes, DMA_FROM_DEVICE);
+ dma = dma_map_single(host->dev, data->dest, num_bytes,
+ DMA_FROM_DEVICE);
+
+ if (dma_mapping_error(host->dev, dma))
+ return -EFAULT;
- ret = dwmci_prepare_data(host, data);
+ ret = dwmci_prepare_data(host, data, dma);
if (ret)
return ret;
}
@@ -411,11 +405,11 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
dwmci_writel(host, DWMCI_CTRL, ctrl);
if (data->flags & MMC_DATA_WRITE)
- dma_sync_single_for_cpu((unsigned long)data->src,
- num_bytes, DMA_TO_DEVICE);
+ dma_unmap_single(host->dev, dma, num_bytes,
+ DMA_TO_DEVICE);
else
- dma_sync_single_for_cpu((unsigned long)data->dest,
- num_bytes, DMA_FROM_DEVICE);
+ dma_unmap_single(host->dev, dma, num_bytes,
+ DMA_FROM_DEVICE);
}
}
@@ -502,7 +496,7 @@ static int dwmci_card_present(struct mci_host *mci)
return 1;
}
-static int dwmci_init(struct mci_host *mci, struct device_d *dev)
+static int dwmci_init(struct mci_host *mci, struct device *dev)
{
struct dwmci_host *host = to_dwmci_host(mci);
uint32_t fifo_size;
@@ -534,8 +528,8 @@ static int dwmci_init(struct mci_host *mci, struct device_d *dev)
/*
* If fifo-depth property is set, use this value
*/
- if (!of_property_read_u32(host->mci.hw_dev->device_node,
- "fifo-depth", &fifo_size)) {
+ if (!of_property_read_u32(host->mci.hw_dev->of_node,
+ "fifo-depth", &fifo_size)) {
host->fifo_size_bytes = fifo_size;
dev_dbg(host->mci.hw_dev, "Using fifo-depth=%u\n",
host->fifo_size_bytes);
@@ -553,21 +547,18 @@ static int dwmci_init(struct mci_host *mci, struct device_d *dev)
return 0;
}
-static int dw_mmc_detect(struct device_d *dev)
-{
- struct dwmci_host *host = dev->priv;
-
- return mci_detect_card(&host->mci);
-}
-
-static int dw_mmc_probe(struct device_d *dev)
+static int dw_mmc_probe(struct device *dev)
{
+ struct reset_control *rst;
struct resource *iores;
struct dwmci_host *host;
struct dw_mmc_platform_data *pdata = dev->platform_data;
host = xzalloc(sizeof(*host));
+ dma_set_mask(dev, DMA_BIT_MASK(32));
+ host->dev = dev;
+
host->clk_biu = clk_get(dev, "biu");
if (IS_ERR(host->clk_biu))
return PTR_ERR(host->clk_biu);
@@ -579,13 +570,24 @@ static int dw_mmc_probe(struct device_d *dev)
clk_enable(host->clk_biu);
clk_enable(host->clk_ciu);
+ rst = reset_control_get_optional(dev, "reset");
+ if (IS_ERR(rst)) {
+ dev_warn(dev, "error claiming reset: %pe\n", rst);
+ } else if (rst) {
+ reset_control_assert(rst);
+ udelay(10);
+ reset_control_deassert(rst);
+ }
+
iores = dev_request_mem_resource(dev, 0);
if (IS_ERR(iores))
return PTR_ERR(iores);
host->ioaddr = IOMEM(iores->start);
host->idmac = dma_alloc_coherent(sizeof(*host->idmac) * DW_MMC_NUM_IDMACS,
- DMA_ADDRESS_BROKEN);
+ &host->idmac_dma);
+ if (!host->idmac)
+ return -ENOMEM;
host->mci.send_cmd = dwmci_cmd;
host->mci.set_ios = dwmci_set_ios;
@@ -601,23 +603,26 @@ static int dw_mmc_probe(struct device_d *dev)
host->ciu_div = pdata->ciu_div;
host->mci.host_caps &= ~MMC_CAP_BIT_DATA_MASK;
host->mci.host_caps |= pdata->bus_width_caps;
- } else if (dev->device_node) {
- of_property_read_u32(dev->device_node, "dw-mshc-ciu-div",
- &host->ciu_div);
+ } else if (dev->of_node) {
+ of_property_read_u32(dev->of_node, "dw-mshc-ciu-div",
+ &host->ciu_div);
}
/* divider is 0 based in pdata and 1 based in our private struct */
host->ciu_div++;
- if (of_device_is_compatible(dev->device_node,
- "rockchip,rk2928-dw-mshc"))
+ if (of_device_is_compatible(dev->of_node,
+ "rockchip,rk2928-dw-mshc"))
host->pwren_value = 0;
else
host->pwren_value = 1;
- dev->detect = dw_mmc_detect;
+ if (of_device_is_compatible(dev->of_node, "starfive,jh7100-dw-mshc"))
+ of_property_read_u32(dev->of_node, "clock-frequency",
+ &host->clkrate);
+ if (!host->clkrate)
+ host->clkrate = clk_get_rate(host->clk_ciu);
- host->clkrate = clk_get_rate(host->clk_ciu);
host->mci.f_min = host->clkrate / 510 / host->ciu_div;
if (host->mci.f_min < 200000)
host->mci.f_min = 200000;
@@ -625,8 +630,6 @@ static int dw_mmc_probe(struct device_d *dev)
mci_of_parse(&host->mci);
- dev->priv = host;
-
return mci_register(&host->mci);
}
@@ -638,11 +641,16 @@ static __maybe_unused struct of_device_id dw_mmc_compatible[] = {
}, {
.compatible = "rockchip,rk3288-dw-mshc",
}, {
+ .compatible = "snps,dw-mshc",
+ }, {
+ .compatible = "starfive,jh7100-dw-mshc",
+ }, {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, dw_mmc_compatible);
-static struct driver_d dw_mmc_driver = {
+static struct driver dw_mmc_driver = {
.name = "dw_mmc",
.probe = dw_mmc_probe,
.of_compatible = DRV_OF_COMPAT(dw_mmc_compatible),