summaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/Kconfig1
-rw-r--r--drivers/mmc/atmel_sdhci.c7
-rw-r--r--drivers/mmc/bfin_sdh.c2
-rw-r--r--drivers/mmc/dw_mmc.c23
-rw-r--r--drivers/mmc/exynos_dw_mmc.c7
-rw-r--r--drivers/mmc/ftsdc010_mci.c2
-rw-r--r--drivers/mmc/gen_atmel_mci.c2
-rw-r--r--drivers/mmc/hi6220_dw_mmc.c2
-rw-r--r--drivers/mmc/kona_sdhci.c2
-rw-r--r--drivers/mmc/mmc.c68
-rw-r--r--drivers/mmc/mmc_boot.c28
-rw-r--r--drivers/mmc/mmc_write.c9
-rw-r--r--drivers/mmc/msm_sdhci.c7
-rw-r--r--drivers/mmc/mxcmmc.c2
-rw-r--r--drivers/mmc/mxsmmc.c2
-rw-r--r--drivers/mmc/pic32_sdhci.c2
-rw-r--r--drivers/mmc/pxa_mmc_gen.c2
-rw-r--r--drivers/mmc/rockchip_dw_mmc.c7
-rw-r--r--drivers/mmc/rockchip_sdhci.c7
-rw-r--r--drivers/mmc/sandbox_mmc.c7
-rw-r--r--drivers/mmc/sdhci.c105
-rw-r--r--drivers/mmc/sh_mmcif.c2
-rw-r--r--drivers/mmc/sh_sdhi.c2
-rw-r--r--drivers/mmc/uniphier-sd.c50
-rw-r--r--drivers/mmc/zynq_sdhci.c7
25 files changed, 204 insertions, 151 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index a71afa59be..ba9a7237b4 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -80,6 +80,7 @@ config ROCKCHIP_SDHCI
config MMC_UNIPHIER
bool "UniPhier SD/MMC Host Controller support"
depends on ARCH_UNIPHIER
+ depends on BLK
select DM_MMC_OPS
help
This selects support for the SD/MMC Host Controller on UniPhier SoCs.
diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c
index dd6bd33515..d8f8087b68 100644
--- a/drivers/mmc/atmel_sdhci.c
+++ b/drivers/mmc/atmel_sdhci.c
@@ -136,13 +136,8 @@ static int atmel_sdhci_probe(struct udevice *dev)
static int atmel_sdhci_bind(struct udevice *dev)
{
struct atmel_sdhci_plat *plat = dev_get_platdata(dev);
- int ret;
- ret = sdhci_bind(dev, &plat->mmc, &plat->cfg);
- if (ret)
- return ret;
-
- return 0;
+ return sdhci_bind(dev, &plat->mmc, &plat->cfg);
}
static const struct udevice_id atmel_sdhci_ids[] = {
diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c
index 0e493dae0e..993a00cdb1 100644
--- a/drivers/mmc/bfin_sdh.c
+++ b/drivers/mmc/bfin_sdh.c
@@ -12,7 +12,7 @@
#include <mmc.h>
#include <asm/io.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
#include <asm/byteorder.h>
#include <asm/blackfin.h>
#include <asm/clock.h>
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index afc674dd14..074f86c502 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -120,9 +120,9 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
if (host->fifo_mode && size) {
len = 0;
- if (data->flags == MMC_DATA_READ) {
- if ((dwmci_readl(host, DWMCI_RINTSTS) &
- DWMCI_INTMSK_RXDR)) {
+ if (data->flags == MMC_DATA_READ &&
+ (mask & DWMCI_INTMSK_RXDR)) {
+ while (size) {
len = dwmci_readl(host, DWMCI_STATUS);
len = (len >> DWMCI_FIFO_SHIFT) &
DWMCI_FIFO_MASK;
@@ -130,12 +130,13 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
for (i = 0; i < len; i++)
*buf++ =
dwmci_readl(host, DWMCI_DATA);
- dwmci_writel(host, DWMCI_RINTSTS,
- DWMCI_INTMSK_RXDR);
+ size = size > len ? (size - len) : 0;
}
- } else {
- if ((dwmci_readl(host, DWMCI_RINTSTS) &
- DWMCI_INTMSK_TXDR)) {
+ dwmci_writel(host, DWMCI_RINTSTS,
+ DWMCI_INTMSK_RXDR);
+ } else if (data->flags == MMC_DATA_WRITE &&
+ (mask & DWMCI_INTMSK_TXDR)) {
+ while (size) {
len = dwmci_readl(host, DWMCI_STATUS);
len = fifo_depth - ((len >>
DWMCI_FIFO_SHIFT) &
@@ -144,11 +145,11 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
for (i = 0; i < len; i++)
dwmci_writel(host, DWMCI_DATA,
*buf++);
- dwmci_writel(host, DWMCI_RINTSTS,
- DWMCI_INTMSK_TXDR);
+ size = size > len ? (size - len) : 0;
}
+ dwmci_writel(host, DWMCI_RINTSTS,
+ DWMCI_INTMSK_TXDR);
}
- size = size > len ? (size - len) : 0;
}
/* Data arrived correctly. */
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
index 57271f18b0..568fed74be 100644
--- a/drivers/mmc/exynos_dw_mmc.c
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -284,13 +284,8 @@ static int exynos_dwmmc_probe(struct udevice *dev)
static int exynos_dwmmc_bind(struct udevice *dev)
{
struct exynos_mmc_plat *plat = dev_get_platdata(dev);
- int ret;
- ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
- if (ret)
- return ret;
-
- return 0;
+ return dwmci_bind(dev, &plat->mmc, &plat->cfg);
}
static const struct udevice_id exynos_dwmmc_ids[] = {
diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c
index c02740f0ef..e88c6322e9 100644
--- a/drivers/mmc/ftsdc010_mci.c
+++ b/drivers/mmc/ftsdc010_mci.c
@@ -13,7 +13,7 @@
#include <mmc.h>
#include <asm/io.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
#include <asm/byteorder.h>
#include <faraday/ftsdc010.h>
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index 69770df44d..cca0b04a60 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -14,7 +14,7 @@
#include <part.h>
#include <malloc.h>
#include <asm/io.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
#include <asm/byteorder.h>
#include <asm/arch/clk.h>
#include <asm/arch/hardware.h>
diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c
index b0d063c698..fdaf1e40bc 100644
--- a/drivers/mmc/hi6220_dw_mmc.c
+++ b/drivers/mmc/hi6220_dw_mmc.c
@@ -8,7 +8,7 @@
#include <common.h>
#include <dwmmc.h>
#include <malloc.h>
-#include <asm-generic/errno.h>
+#include <linux/errno.h>
#define DWMMC_MAX_CH_NUM 4
diff --git a/drivers/mmc/kona_sdhci.c b/drivers/mmc/kona_sdhci.c
index 3653d00b1b..e730caa207 100644
--- a/drivers/mmc/kona_sdhci.c
+++ b/drivers/mmc/kona_sdhci.c
@@ -7,7 +7,7 @@
#include <common.h>
#include <malloc.h>
#include <sdhci.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
#include <asm/kona-common/clk.h>
#define SDHCI_CORECTRL_OFFSET 0x00008000
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 43ea0bba76..0312da91af 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -21,6 +21,14 @@
#include <div64.h>
#include "mmc_private.h"
+static const unsigned int sd_au_size[] = {
+ 0, SZ_16K / 512, SZ_32K / 512,
+ SZ_64K / 512, SZ_128K / 512, SZ_256K / 512,
+ SZ_512K / 512, SZ_1M / 512, SZ_2M / 512,
+ SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512,
+ SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, SZ_64M / 512,
+};
+
#ifndef CONFIG_DM_MMC_OPS
__weak int board_mmc_getwp(struct mmc *mmc)
{
@@ -945,6 +953,62 @@ retry_scr:
return 0;
}
+static int sd_read_ssr(struct mmc *mmc)
+{
+ int err, i;
+ struct mmc_cmd cmd;
+ ALLOC_CACHE_ALIGN_BUFFER(uint, ssr, 16);
+ struct mmc_data data;
+ int timeout = 3;
+ unsigned int au, eo, et, es;
+
+ cmd.cmdidx = MMC_CMD_APP_CMD;
+ cmd.resp_type = MMC_RSP_R1;
+ cmd.cmdarg = mmc->rca << 16;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err)
+ return err;
+
+ cmd.cmdidx = SD_CMD_APP_SD_STATUS;
+ cmd.resp_type = MMC_RSP_R1;
+ cmd.cmdarg = 0;
+
+retry_ssr:
+ data.dest = (char *)ssr;
+ data.blocksize = 64;
+ data.blocks = 1;
+ data.flags = MMC_DATA_READ;
+
+ err = mmc_send_cmd(mmc, &cmd, &data);
+ if (err) {
+ if (timeout--)
+ goto retry_ssr;
+
+ return err;
+ }
+
+ for (i = 0; i < 16; i++)
+ ssr[i] = be32_to_cpu(ssr[i]);
+
+ au = (ssr[2] >> 12) & 0xF;
+ if ((au <= 9) || (mmc->version == SD_VERSION_3)) {
+ mmc->ssr.au = sd_au_size[au];
+ es = (ssr[3] >> 24) & 0xFF;
+ es |= (ssr[2] & 0xFF) << 8;
+ et = (ssr[3] >> 18) & 0x3F;
+ if (es && et) {
+ eo = (ssr[3] >> 16) & 0x3;
+ mmc->ssr.erase_timeout = (et * 1000) / es;
+ mmc->ssr.erase_offset = eo * 1000;
+ }
+ } else {
+ debug("Invalid Allocation Unit Size.\n");
+ }
+
+ return 0;
+}
+
/* frequency bases */
/* divided by 10 to be nice to platforms without floating point */
static const int fbase[] = {
@@ -1350,6 +1414,10 @@ static int mmc_startup(struct mmc *mmc)
mmc_set_bus_width(mmc, 4);
}
+ err = sd_read_ssr(mmc);
+ if (err)
+ return err;
+
if (mmc->card_caps & MMC_MODE_HS)
mmc->tran_speed = 50000000;
else
diff --git a/drivers/mmc/mmc_boot.c b/drivers/mmc/mmc_boot.c
index 756a9824e3..ac6f56f157 100644
--- a/drivers/mmc/mmc_boot.c
+++ b/drivers/mmc/mmc_boot.c
@@ -85,16 +85,10 @@ int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
*/
int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
{
- int err;
-
- err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH,
- EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) |
- EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) |
- EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width));
-
- if (err)
- return err;
- return 0;
+ return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH,
+ EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) |
+ EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) |
+ EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width));
}
/*
@@ -106,16 +100,10 @@ int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
*/
int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
{
- int err;
-
- err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
- EXT_CSD_BOOT_ACK(ack) |
- EXT_CSD_BOOT_PART_NUM(part_num) |
- EXT_CSD_PARTITION_ACCESS(access));
-
- if (err)
- return err;
- return 0;
+ return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
+ EXT_CSD_BOOT_ACK(ack) |
+ EXT_CSD_BOOT_PART_NUM(part_num) |
+ EXT_CSD_PARTITION_ACCESS(access));
}
/*
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index 0f8b5c79d7..2289640375 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -100,8 +100,13 @@ unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start,
& ~(mmc->erase_grp_size - 1)) - 1);
while (blk < blkcnt) {
- blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
- mmc->erase_grp_size : (blkcnt - blk);
+ if (IS_SD(mmc) && mmc->ssr.au) {
+ blk_r = ((blkcnt - blk) > mmc->ssr.au) ?
+ mmc->ssr.au : (blkcnt - blk);
+ } else {
+ blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
+ mmc->erase_grp_size : (blkcnt - blk);
+ }
err = mmc_erase_t(mmc, start + blk, blk_r);
if (err)
break;
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
index 8d4399e967..1b82991c0e 100644
--- a/drivers/mmc/msm_sdhci.c
+++ b/drivers/mmc/msm_sdhci.c
@@ -190,13 +190,8 @@ static int msm_ofdata_to_platdata(struct udevice *dev)
static int msm_sdc_bind(struct udevice *dev)
{
struct msm_sdhc_plat *plat = dev_get_platdata(dev);
- int ret;
- ret = sdhci_bind(dev, &plat->mmc, &plat->cfg);
- if (ret)
- return ret;
-
- return 0;
+ return sdhci_bind(dev, &plat->mmc, &plat->cfg);
}
static const struct udevice_id msm_mmc_ids[] = {
diff --git a/drivers/mmc/mxcmmc.c b/drivers/mmc/mxcmmc.c
index 8038f90452..5a385a37f8 100644
--- a/drivers/mmc/mxcmmc.c
+++ b/drivers/mmc/mxcmmc.c
@@ -23,7 +23,7 @@
#include <part.h>
#include <malloc.h>
#include <mmc.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
index 40f3eaaa86..0896028403 100644
--- a/drivers/mmc/mxsmmc.c
+++ b/drivers/mmc/mxsmmc.c
@@ -20,7 +20,7 @@
#include <common.h>
#include <malloc.h>
#include <mmc.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/imx-regs.h>
diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c
index abe74293ed..2abf943bdb 100644
--- a/drivers/mmc/pic32_sdhci.c
+++ b/drivers/mmc/pic32_sdhci.c
@@ -10,7 +10,7 @@
#include <dm.h>
#include <common.h>
#include <sdhci.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
#include <mach/pic32.h>
DECLARE_GLOBAL_DATA_PTR;
diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c
index 19ae81d470..a5462e2148 100644
--- a/drivers/mmc/pxa_mmc_gen.c
+++ b/drivers/mmc/pxa_mmc_gen.c
@@ -9,7 +9,7 @@
#include <common.h>
#include <asm/arch/hardware.h>
#include <asm/arch/regs-mmc.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
#include <asm/io.h>
#include <malloc.h>
#include <mmc.h>
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index 020a59b921..859760b8b0 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -142,13 +142,8 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
static int rockchip_dwmmc_bind(struct udevice *dev)
{
struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
- int ret;
- ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
- if (ret)
- return ret;
-
- return 0;
+ return dwmci_bind(dev, &plat->mmc, &plat->cfg);
}
static const struct udevice_id rockchip_dwmmc_ids[] = {
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index 624029bd20..c56e1a3a1c 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -62,13 +62,8 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
static int rockchip_sdhci_bind(struct udevice *dev)
{
struct rockchip_sdhc_plat *plat = dev_get_platdata(dev);
- int ret;
- ret = sdhci_bind(dev, &plat->mmc, &plat->cfg);
- if (ret)
- return ret;
-
- return 0;
+ return sdhci_bind(dev, &plat->mmc, &plat->cfg);
}
static const struct udevice_id arasan_sdhci_ids[] = {
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c
index 5f1333b748..fdb29a5505 100644
--- a/drivers/mmc/sandbox_mmc.c
+++ b/drivers/mmc/sandbox_mmc.c
@@ -112,7 +112,6 @@ int sandbox_mmc_bind(struct udevice *dev)
{
struct sandbox_mmc_plat *plat = dev_get_platdata(dev);
struct mmc_config *cfg = &plat->cfg;
- int ret;
cfg->name = dev->name;
cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_8BIT;
@@ -121,11 +120,7 @@ int sandbox_mmc_bind(struct udevice *dev)
cfg->f_max = 52000000;
cfg->b_max = U32_MAX;
- ret = mmc_bind(dev, &plat->mmc, cfg);
- if (ret)
- return ret;
-
- return 0;
+ return mmc_bind(dev, &plat->mmc, cfg);
}
int sandbox_mmc_unbind(struct udevice *dev)
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 7ddb549e03..b2bf5a03fa 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -121,13 +121,10 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
* for card ready state.
* Every time when card is busy after timeout then (last) timeout value will be
* increased twice but only if it doesn't exceed global defined maximum.
- * Each function call will use last timeout value. Max timeout can be redefined
- * in board config file.
+ * Each function call will use last timeout value.
*/
-#ifndef CONFIG_SDHCI_CMD_MAX_TIMEOUT
-#define CONFIG_SDHCI_CMD_MAX_TIMEOUT 3200
-#endif
-#define CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT 100
+#define SDHCI_CMD_MAX_TIMEOUT 3200
+#define SDHCI_CMD_DEFAULT_TIMEOUT 100
#define SDHCI_READ_STATUS_TIMEOUT 1000
#ifdef CONFIG_DM_MMC_OPS
@@ -151,7 +148,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
unsigned start = get_timer(0);
/* Timeout unit - ms */
- static unsigned int cmd_timeout = CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT;
+ static unsigned int cmd_timeout = SDHCI_CMD_DEFAULT_TIMEOUT;
sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;
@@ -164,7 +161,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
if (time >= cmd_timeout) {
printf("%s: MMC: %d busy ", __func__, mmc_dev);
- if (2 * cmd_timeout <= CONFIG_SDHCI_CMD_MAX_TIMEOUT) {
+ if (2 * cmd_timeout <= SDHCI_CMD_MAX_TIMEOUT) {
cmd_timeout += cmd_timeout;
printf("timeout increasing to: %u ms.\n",
cmd_timeout);
@@ -297,7 +294,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
{
struct sdhci_host *host = mmc->priv;
- unsigned int div, clk, timeout, reg;
+ unsigned int div, clk = 0, timeout, reg;
/* Wait max 20 ms */
timeout = 200;
@@ -321,14 +318,36 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
return 0;
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
- /* Version 3.00 divisors must be a multiple of 2. */
- if (mmc->cfg->f_max <= clock)
- div = 1;
- else {
- for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
- if ((mmc->cfg->f_max / div) <= clock)
+ /*
+ * Check if the Host Controller supports Programmable Clock
+ * Mode.
+ */
+ if (host->clk_mul) {
+ for (div = 1; div <= 1024; div++) {
+ if ((mmc->cfg->f_max * host->clk_mul / div)
+ <= clock)
break;
}
+
+ /*
+ * Set Programmable Clock Mode in the Clock
+ * Control register.
+ */
+ clk = SDHCI_PROG_CLOCK_MODE;
+ div--;
+ } else {
+ /* Version 3.00 divisors must be a multiple of 2. */
+ if (mmc->cfg->f_max <= clock) {
+ div = 1;
+ } else {
+ for (div = 2;
+ div < SDHCI_MAX_DIV_SPEC_300;
+ div += 2) {
+ if ((mmc->cfg->f_max / div) <= clock)
+ break;
+ }
+ }
+ div >>= 1;
}
} else {
/* Version 2.00 divisors must be a power of 2. */
@@ -336,13 +355,13 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
if ((mmc->cfg->f_max / div) <= clock)
break;
}
+ div >>= 1;
}
- div >>= 1;
if (host->set_clock)
host->set_clock(host->index, div);
- clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
+ clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
<< SDHCI_DIVIDER_HI_SHIFT;
clk |= SDHCI_CLOCK_INT_EN;
@@ -451,6 +470,8 @@ static int sdhci_init(struct mmc *mmc)
{
struct sdhci_host *host = mmc->priv;
+ sdhci_reset(host, SDHCI_RESET_ALL);
+
if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && !aligned_buffer) {
aligned_buffer = memalign(8, 512*1024);
if (!aligned_buffer) {
@@ -514,9 +535,17 @@ static const struct mmc_ops sdhci_ops = {
int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
u32 max_clk, u32 min_clk)
{
- u32 caps;
+ u32 caps, caps_1;
caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+
+#ifdef CONFIG_MMC_SDMA
+ if (!(caps & SDHCI_CAN_DO_SDMA)) {
+ printf("%s: Your controller doesn't support SDMA!!\n",
+ __func__);
+ return -EINVAL;
+ }
+#endif
host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
cfg->name = host->name;
@@ -534,8 +563,11 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
SDHCI_CLOCK_BASE_SHIFT;
cfg->f_max *= 1000000;
}
- if (cfg->f_max == 0)
+ if (cfg->f_max == 0) {
+ printf("%s: Hardware doesn't specify base clock frequency\n",
+ __func__);
return -EINVAL;
+ }
if (min_clk)
cfg->f_min = min_clk;
else {
@@ -552,6 +584,9 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
if (caps & SDHCI_CAN_VDD_180)
cfg->voltages |= MMC_VDD_165_195;
+ if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
+ cfg->voltages |= host->voltages;
+
cfg->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
if (caps & SDHCI_CAN_DO_8BIT)
@@ -564,6 +599,14 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+ /*
+ * In case of Host Controller v3.00, find out whether clock
+ * multiplier is supported.
+ */
+ caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+ host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >>
+ SDHCI_CLOCK_MUL_SHIFT;
+
return 0;
}
@@ -575,27 +618,11 @@ int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg)
#else
int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
{
-#ifdef CONFIG_MMC_SDMA
- unsigned int caps;
-
- caps = sdhci_readl(host, SDHCI_CAPABILITIES);
- if (!(caps & SDHCI_CAN_DO_SDMA)) {
- printf("%s: Your controller doesn't support SDMA!!\n",
- __func__);
- return -1;
- }
-#endif
-
- if (sdhci_setup_cfg(&host->cfg, host, max_clk, min_clk)) {
- printf("%s: Hardware doesn't specify base clock frequency\n",
- __func__);
- return -EINVAL;
- }
+ int ret;
- if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
- host->cfg.voltages |= host->voltages;
-
- sdhci_reset(host, SDHCI_RESET_ALL);
+ ret = sdhci_setup_cfg(&host->cfg, host, max_clk, min_clk);
+ if (ret)
+ return ret;
host->mmc = mmc_create(&host->cfg, host);
if (host->mmc == NULL) {
diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c
index bc4b344811..69ded9ee2c 100644
--- a/drivers/mmc/sh_mmcif.c
+++ b/drivers/mmc/sh_mmcif.c
@@ -12,7 +12,7 @@
#include <command.h>
#include <mmc.h>
#include <malloc.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
#include <asm/io.h>
#include "sh_mmcif.h"
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c
index ea82e2b449..78e2ef643c 100644
--- a/drivers/mmc/sh_sdhi.c
+++ b/drivers/mmc/sh_sdhi.c
@@ -13,7 +13,7 @@
#include <common.h>
#include <malloc.h>
#include <mmc.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
#include <asm/io.h>
#include <asm/arch/rmobile.h>
#include <asm/arch/sh_sdhi.h>
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
index 701b26f44c..4af7fdb13c 100644
--- a/drivers/mmc/uniphier-sd.c
+++ b/drivers/mmc/uniphier-sd.c
@@ -119,9 +119,12 @@ DECLARE_GLOBAL_DATA_PTR;
/* alignment required by the DMA engine of this controller */
#define UNIPHIER_SD_DMA_MINALIGN 0x10
-struct uniphier_sd_priv {
+struct uniphier_sd_plat {
struct mmc_config cfg;
- struct mmc *mmc;
+ struct mmc mmc;
+};
+
+struct uniphier_sd_priv {
void __iomem *regbase;
unsigned long mclk;
unsigned int version;
@@ -654,8 +657,16 @@ static void uniphier_sd_host_init(struct uniphier_sd_priv *priv)
}
}
+static int uniphier_sd_bind(struct udevice *dev)
+{
+ struct uniphier_sd_plat *plat = dev_get_platdata(dev);
+
+ return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+
static int uniphier_sd_probe(struct udevice *dev)
{
+ struct uniphier_sd_plat *plat = dev_get_platdata(dev);
struct uniphier_sd_priv *priv = dev_get_priv(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
fdt_addr_t base;
@@ -691,15 +702,15 @@ static int uniphier_sd_probe(struct udevice *dev)
return ret;
}
- priv->cfg.name = dev->name;
- priv->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
+ plat->cfg.name = dev->name;
+ plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
switch (fdtdec_get_int(gd->fdt_blob, dev->of_offset, "bus-width", 1)) {
case 8:
- priv->cfg.host_caps |= MMC_MODE_8BIT;
+ plat->cfg.host_caps |= MMC_MODE_8BIT;
break;
case 4:
- priv->cfg.host_caps |= MMC_MODE_4BIT;
+ plat->cfg.host_caps |= MMC_MODE_4BIT;
break;
case 1:
break;
@@ -722,27 +733,13 @@ static int uniphier_sd_probe(struct udevice *dev)
uniphier_sd_host_init(priv);
- priv->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
- priv->cfg.f_min = priv->mclk /
+ plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
+ plat->cfg.f_min = priv->mclk /
(priv->caps & UNIPHIER_SD_CAP_DIV1024 ? 1024 : 512);
- priv->cfg.f_max = priv->mclk;
- priv->cfg.b_max = U32_MAX; /* max value of UNIPHIER_SD_SECCNT */
-
- priv->mmc = mmc_create(&priv->cfg, priv);
- if (!priv->mmc)
- return -EIO;
-
- upriv->mmc = priv->mmc;
- priv->mmc->dev = dev;
-
- return 0;
-}
-
-static int uniphier_sd_remove(struct udevice *dev)
-{
- struct uniphier_sd_priv *priv = dev_get_priv(dev);
+ plat->cfg.f_max = priv->mclk;
+ plat->cfg.b_max = U32_MAX; /* max value of UNIPHIER_SD_SECCNT */
- mmc_destroy(priv->mmc);
+ upriv->mmc = &plat->mmc;
return 0;
}
@@ -756,8 +753,9 @@ U_BOOT_DRIVER(uniphier_mmc) = {
.name = "uniphier-mmc",
.id = UCLASS_MMC,
.of_match = uniphier_sd_match,
+ .bind = uniphier_sd_bind,
.probe = uniphier_sd_probe,
- .remove = uniphier_sd_remove,
.priv_auto_alloc_size = sizeof(struct uniphier_sd_priv),
+ .platdata_auto_alloc_size = sizeof(struct uniphier_sd_plat),
.ops = &uniphier_sd_ops,
};
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 3815b94329..b991102c2a 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -63,13 +63,8 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
static int arasan_sdhci_bind(struct udevice *dev)
{
struct arasan_sdhci_plat *plat = dev_get_platdata(dev);
- int ret;
- ret = sdhci_bind(dev, &plat->mmc, &plat->cfg);
- if (ret)
- return ret;
-
- return 0;
+ return sdhci_bind(dev, &plat->mmc, &plat->cfg);
}
static const struct udevice_id arasan_sdhci_ids[] = {