diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mmc/atmel_sdhci.c | 7 | ||||
-rw-r--r-- | drivers/mmc/bfin_sdh.c | 2 | ||||
-rw-r--r-- | drivers/mmc/dw_mmc.c | 23 | ||||
-rw-r--r-- | drivers/mmc/exynos_dw_mmc.c | 7 | ||||
-rw-r--r-- | drivers/mmc/ftsdc010_mci.c | 2 | ||||
-rw-r--r-- | drivers/mmc/gen_atmel_mci.c | 2 | ||||
-rw-r--r-- | drivers/mmc/hi6220_dw_mmc.c | 2 | ||||
-rw-r--r-- | drivers/mmc/kona_sdhci.c | 2 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 68 | ||||
-rw-r--r-- | drivers/mmc/mmc_boot.c | 28 | ||||
-rw-r--r-- | drivers/mmc/mmc_write.c | 9 | ||||
-rw-r--r-- | drivers/mmc/msm_sdhci.c | 7 | ||||
-rw-r--r-- | drivers/mmc/mxcmmc.c | 2 | ||||
-rw-r--r-- | drivers/mmc/mxsmmc.c | 2 | ||||
-rw-r--r-- | drivers/mmc/pic32_sdhci.c | 2 | ||||
-rw-r--r-- | drivers/mmc/pxa_mmc_gen.c | 2 | ||||
-rw-r--r-- | drivers/mmc/rockchip_dw_mmc.c | 7 | ||||
-rw-r--r-- | drivers/mmc/rockchip_sdhci.c | 7 | ||||
-rw-r--r-- | drivers/mmc/sandbox_mmc.c | 7 | ||||
-rw-r--r-- | drivers/mmc/sdhci.c | 105 | ||||
-rw-r--r-- | drivers/mmc/sh_mmcif.c | 2 | ||||
-rw-r--r-- | drivers/mmc/sh_sdhi.c | 2 | ||||
-rw-r--r-- | drivers/mmc/uniphier-sd.c | 50 | ||||
-rw-r--r-- | drivers/mmc/zynq_sdhci.c | 7 |
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[] = { |