diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/Makefile | 1 | ||||
-rw-r--r-- | drivers/mmc/dw_mmc.c | 2 | ||||
-rw-r--r-- | drivers/mmc/exynos_dw_mmc.c | 71 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 8 | ||||
-rw-r--r-- | drivers/mmc/omap_hsmmc.c | 4 | ||||
-rw-r--r-- | drivers/mmc/pci_mmc.c | 42 | ||||
-rw-r--r-- | drivers/mmc/s5p_sdhci.c | 20 | ||||
-rw-r--r-- | drivers/mmc/sdhci.c | 3 | ||||
-rw-r--r-- | drivers/mmc/sunxi_mmc.c | 20 | ||||
-rw-r--r-- | drivers/mmc/tegra_mmc.c | 36 |
10 files changed, 146 insertions, 61 deletions
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 4ba5878936..ed73687735 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o obj-$(CONFIG_MXC_MMC) += mxcmmc.o obj-$(CONFIG_MXS_MMC) += mxsmmc.o obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o +obj-$(CONFIG_X86) += pci_mmc.o obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o obj-$(CONFIG_S3C_SDI) += s3c_sdi.o diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index b18c75dee2..76fa0b0534 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -321,7 +321,7 @@ static void dwmci_set_ios(struct mmc *mmc) if (mmc->ddr_mode) regs |= DWMCI_DDR_MODE; else - regs &= DWMCI_DDR_MODE; + regs &= ~DWMCI_DDR_MODE; dwmci_writel(host, DWMCI_UHS_REG, regs); diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index dfa209bded..e083745235 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -13,14 +13,20 @@ #include <asm/arch/dwmmc.h> #include <asm/arch/clk.h> #include <asm/arch/pinmux.h> +#include <asm/arch/power.h> #include <asm/gpio.h> #include <asm-generic/errno.h> #define DWMMC_MAX_CH_NUM 4 #define DWMMC_MAX_FREQ 52000000 #define DWMMC_MIN_FREQ 400000 -#define DWMMC_MMC0_CLKSEL_VAL 0x03030001 -#define DWMMC_MMC2_CLKSEL_VAL 0x03020001 +#define DWMMC_MMC0_SDR_TIMING_VAL 0x03030001 +#define DWMMC_MMC2_SDR_TIMING_VAL 0x03020001 + +/* Exynos implmentation specific drver private data */ +struct dwmci_exynos_priv_data { + u32 sdr_timing; +}; /* * Function used as callback function to initialise the @@ -28,7 +34,9 @@ */ static void exynos_dwmci_clksel(struct dwmci_host *host) { - dwmci_writel(host, DWMCI_CLKSEL, host->clksel_val); + struct dwmci_exynos_priv_data *priv = host->priv; + + dwmci_writel(host, DWMCI_CLKSEL, priv->sdr_timing); } unsigned int exynos_dwmci_get_clk(struct dwmci_host *host) @@ -55,6 +63,8 @@ unsigned int exynos_dwmci_get_clk(struct dwmci_host *host) static void exynos_dwmci_board_init(struct dwmci_host *host) { + struct dwmci_exynos_priv_data *priv = host->priv; + if (host->quirks & DWMCI_QUIRK_DISABLE_SMU) { dwmci_writel(host, EMMCP_MPSBEGIN0, 0); dwmci_writel(host, EMMCP_SEND0, 0); @@ -64,12 +74,17 @@ static void exynos_dwmci_board_init(struct dwmci_host *host) MPSCTRL_NON_SECURE_READ_BIT | MPSCTRL_NON_SECURE_WRITE_BIT | MPSCTRL_VALID); } + + /* Set to timing value at initial time */ + if (priv->sdr_timing) + exynos_dwmci_clksel(host); } static int exynos_dwmci_core_init(struct dwmci_host *host, int index) { unsigned int div; unsigned long freq, sclk; + struct dwmci_exynos_priv_data *priv = host->priv; if (host->bus_hz) freq = host->bus_hz; @@ -88,11 +103,11 @@ static int exynos_dwmci_core_init(struct dwmci_host *host, int index) #endif host->board_init = exynos_dwmci_board_init; - if (!host->clksel_val) { + if (!priv->sdr_timing) { if (index == 0) - host->clksel_val = DWMMC_MMC0_CLKSEL_VAL; + priv->sdr_timing = DWMMC_MMC0_SDR_TIMING_VAL; else if (index == 2) - host->clksel_val = DWMMC_MMC2_CLKSEL_VAL; + priv->sdr_timing = DWMMC_MMC2_SDR_TIMING_VAL; } host->caps = MMC_MODE_DDR_52MHz; @@ -118,6 +133,7 @@ static int exynos_dwmci_core_init(struct dwmci_host *host, int index) int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel) { struct dwmci_host *host = NULL; + struct dwmci_exynos_priv_data *priv; host = malloc(sizeof(struct dwmci_host)); if (!host) { @@ -125,11 +141,19 @@ int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel) return -ENOMEM; } + priv = malloc(sizeof(struct dwmci_exynos_priv_data)); + if (!priv) { + error("dwmci_exynos_priv_data malloc fail!\n"); + return -ENOMEM; + } + host->ioaddr = (void *)regbase; host->buswidth = bus_width; if (clksel) - host->clksel_val = clksel; + priv->sdr_timing = clksel; + + host->priv = priv; return exynos_dwmci_core_init(host, index); } @@ -157,7 +181,14 @@ static int exynos_dwmci_get_config(const void *blob, int node, struct dwmci_host *host) { int err = 0; - u32 base, clksel_val, timing[3]; + u32 base, timing[3]; + struct dwmci_exynos_priv_data *priv; + + priv = malloc(sizeof(struct dwmci_exynos_priv_data)); + if (!priv) { + error("dwmci_exynos_priv_data malloc fail!\n"); + return -ENOMEM; + } /* Extract device id for each mmc channel */ host->dev_id = pinmux_decode_periph_id(blob, node); @@ -166,7 +197,6 @@ static int exynos_dwmci_get_config(const void *blob, int node, if (host->dev_index == host->dev_id) host->dev_index = host->dev_id - PERIPH_ID_SDMMC0; - /* Get the bus width from the device node */ host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 0); if (host->buswidth <= 0) { @@ -190,16 +220,24 @@ static int exynos_dwmci_get_config(const void *blob, int node, return -EINVAL; } - clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) | + priv->sdr_timing = (DWMCI_SET_SAMPLE_CLK(timing[0]) | DWMCI_SET_DRV_CLK(timing[1]) | DWMCI_SET_DIV_RATIO(timing[2])); - if (clksel_val) - host->clksel_val = clksel_val; + + /* sdr_timing didn't assigned anything, use the default value */ + if (!priv->sdr_timing) { + if (host->dev_index == 0) + priv->sdr_timing = DWMMC_MMC0_SDR_TIMING_VAL; + else if (host->dev_index == 2) + priv->sdr_timing = DWMMC_MMC2_SDR_TIMING_VAL; + } host->fifoth_val = fdtdec_get_int(blob, node, "fifoth_val", 0); host->bus_hz = fdtdec_get_int(blob, node, "bus_hz", 0); host->div = fdtdec_get_int(blob, node, "div", 0); + host->priv = priv; + return 0; } @@ -229,12 +267,21 @@ int exynos_dwmmc_init(const void *blob) { int compat_id; int node_list[DWMMC_MAX_CH_NUM]; + int boot_dev_node; int err = 0, count; compat_id = COMPAT_SAMSUNG_EXYNOS_DWMMC; count = fdtdec_find_aliases_for_id(blob, "mmc", compat_id, node_list, DWMMC_MAX_CH_NUM); + + /* For DWMMC always set boot device as mmc 0 */ + if (count >= 3 && get_boot_mode() == BOOT_MODE_SD) { + boot_dev_node = node_list[2]; + node_list[2] = node_list[0]; + node_list[0] = boot_dev_node; + } + err = exynos_dwmci_process_node(blob, node_list, count); return err; diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index b8039cd092..a13769ea25 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1693,11 +1693,19 @@ void print_mmc_devices(char separator) { struct mmc *m; struct list_head *entry; + char *mmc_type; list_for_each(entry, &mmc_devices) { m = list_entry(entry, struct mmc, link); + if (m->has_init) + mmc_type = IS_SD(m) ? "SD" : "eMMC"; + else + mmc_type = NULL; + printf("%s: %d", m->cfg->name, m->block_dev.dev); + if (mmc_type) + printf(" (%s)", mmc_type); if (entry->next != &mmc_devices) { printf("%c", separator); diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index c880cedb0a..dc725cb5b0 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -134,6 +134,10 @@ static unsigned char mmc_board_init(struct mmc *mmc) pbias_lite = readl(&t2_base->pbias_lite); pbias_lite &= ~(PBIASLITEPWRDNZ1 | PBIASLITEPWRDNZ0); +#ifdef CONFIG_TARGET_OMAP3_CAIRO + /* for cairo board, we need to set up 1.8 Volt bias level on MMC1 */ + pbias_lite &= ~PBIASLITEVMODE0; +#endif writel(pbias_lite, &t2_base->pbias_lite); writel(pbias_lite | PBIASLITEPWRDNZ1 | diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c new file mode 100644 index 0000000000..37171bfa71 --- /dev/null +++ b/drivers/mmc/pci_mmc.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015, Google, Inc + * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <malloc.h> +#include <sdhci.h> +#include <asm/pci.h> + +int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported, + int num_ids) +{ + struct sdhci_host *mmc_host; + pci_dev_t devbusfn; + u32 iobase; + int ret; + int i; + + for (i = 0; i < num_ids; i++) { + devbusfn = pci_find_devices(mmc_supported, i); + if (devbusfn == -1) + return -ENODEV; + + mmc_host = malloc(sizeof(struct sdhci_host)); + if (!mmc_host) + return -ENOMEM; + + mmc_host->name = (char *)name; + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase); + mmc_host->ioaddr = (void *)iobase; + mmc_host->quirks = 0; + ret = add_sdhci(mmc_host, 0, 0); + if (ret) + return ret; + } + + return 0; +} diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index a5d34876bb..3899372e0e 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -102,17 +102,14 @@ struct sdhci_host sdhci_host[SDHCI_MAX_HOSTS]; static int do_sdhci_init(struct sdhci_host *host) { - char str[20]; int dev_id, flag; int err = 0; flag = host->bus_width == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE; dev_id = host->index + PERIPH_ID_SDMMC0; - if (fdt_gpio_isvalid(&host->pwr_gpio)) { - sprintf(str, "sdhci%d_power", host->index & 0xf); - gpio_request(host->pwr_gpio.gpio, str); - gpio_direction_output(host->pwr_gpio.gpio, 1); + if (dm_gpio_is_valid(&host->pwr_gpio)) { + dm_gpio_set_value(&host->pwr_gpio, 1); err = exynos_pinmux_config(dev_id, flag); if (err) { debug("MMC not configured\n"); @@ -120,11 +117,8 @@ static int do_sdhci_init(struct sdhci_host *host) } } - if (fdt_gpio_isvalid(&host->cd_gpio)) { - sprintf(str, "sdhci%d_cd", host->index & 0xf); - gpio_request(host->cd_gpio.gpio, str); - gpio_direction_input(host->cd_gpio.gpio); - if (gpio_get_value(host->cd_gpio.gpio)) + if (dm_gpio_is_valid(&host->cd_gpio)) { + if (dm_gpio_get_value(&host->cd_gpio)) return -ENODEV; err = exynos_pinmux_config(dev_id, flag); @@ -166,8 +160,10 @@ static int sdhci_get_config(const void *blob, int node, struct sdhci_host *host) } host->ioaddr = (void *)base; - fdtdec_decode_gpio(blob, node, "pwr-gpios", &host->pwr_gpio); - fdtdec_decode_gpio(blob, node, "cd-gpios", &host->cd_gpio); + gpio_request_by_name_nodev(blob, node, "pwr-gpios", 0, &host->pwr_gpio, + GPIOD_IS_OUT); + gpio_request_by_name_nodev(blob, node, "cd-gpios", 0, &host->cd_gpio, + GPIOD_IS_IN); return 0; } diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index de88e19609..82d7984a51 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -374,7 +374,8 @@ static void sdhci_set_ios(struct mmc *mmc) (host->quirks & SDHCI_QUIRK_USE_WIDE8)) ctrl |= SDHCI_CTRL_8BITBUS; } else { - if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) + if ((SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) || + (host->quirks & SDHCI_QUIRK_USE_WIDE8)) ctrl &= ~SDHCI_CTRL_8BITBUS; if (mmc->bus_width == 4) ctrl |= SDHCI_CTRL_4BITBUS; diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 510479516b..22335452c5 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -215,7 +215,7 @@ static int mmc_config_clock(struct mmc *mmc) return 0; } -static void mmc_set_ios(struct mmc *mmc) +static void sunxi_mmc_set_ios(struct mmc *mmc) { struct sunxi_mmc_host *mmchost = mmc->priv; @@ -237,7 +237,7 @@ static void mmc_set_ios(struct mmc *mmc) writel(0x0, &mmchost->reg->width); } -static int mmc_core_init(struct mmc *mmc) +static int sunxi_mmc_core_init(struct mmc *mmc) { struct sunxi_mmc_host *mmchost = mmc->priv; @@ -298,8 +298,8 @@ static int mmc_rint_wait(struct mmc *mmc, unsigned int timeout_msecs, return 0; } -static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, - struct mmc_data *data) +static int sunxi_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, + struct mmc_data *data) { struct sunxi_mmc_host *mmchost = mmc->priv; unsigned int cmdval = SUNXI_MMC_CMD_START; @@ -432,9 +432,9 @@ static int sunxi_mmc_getcd(struct mmc *mmc) } static const struct mmc_ops sunxi_mmc_ops = { - .send_cmd = mmc_send_cmd, - .set_ios = mmc_set_ios, - .init = mmc_core_init, + .send_cmd = sunxi_mmc_send_cmd, + .set_ios = sunxi_mmc_set_ios, + .init = sunxi_mmc_core_init, .getcd = sunxi_mmc_getcd, }; @@ -449,11 +449,7 @@ struct mmc *sunxi_mmc_init(int sdc_no) cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; cfg->host_caps = MMC_MODE_4BIT; - cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; -#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \ - defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN9I) - cfg->host_caps |= MMC_MODE_HC; -#endif + cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; cfg->f_min = 400000; diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index 2bd36b0ee7..2cd8cf10ae 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -515,8 +515,8 @@ static int tegra_mmc_getcd(struct mmc *mmc) debug("tegra_mmc_getcd called\n"); - if (fdt_gpio_isvalid(&host->cd_gpio)) - return fdtdec_get_gpio(&host->cd_gpio); + if (dm_gpio_is_valid(&host->cd_gpio)) + return dm_gpio_get_value(&host->cd_gpio); return 1; } @@ -531,7 +531,6 @@ static const struct mmc_ops tegra_mmc_ops = { static int do_mmc_init(int dev_index) { struct mmc_host *host; - char gpusage[12]; /* "SD/MMCn PWR" or "SD/MMCn CD" */ struct mmc *mmc; /* DT should have been read & host config filled in */ @@ -539,27 +538,15 @@ static int do_mmc_init(int dev_index) if (!host->enabled) return -1; - debug(" do_mmc_init: index %d, bus width %d " - "pwr_gpio %d cd_gpio %d\n", - dev_index, host->width, - host->pwr_gpio.gpio, host->cd_gpio.gpio); + debug(" do_mmc_init: index %d, bus width %d pwr_gpio %d cd_gpio %d\n", + dev_index, host->width, gpio_get_number(&host->pwr_gpio), + gpio_get_number(&host->cd_gpio)); host->clock = 0; clock_start_periph_pll(host->mmc_id, CLOCK_ID_PERIPH, 20000000); - if (fdt_gpio_isvalid(&host->pwr_gpio)) { - sprintf(gpusage, "SD/MMC%d PWR", dev_index); - gpio_request(host->pwr_gpio.gpio, gpusage); - gpio_direction_output(host->pwr_gpio.gpio, 1); - debug(" Power GPIO name = %s\n", host->pwr_gpio.name); - } - - if (fdt_gpio_isvalid(&host->cd_gpio)) { - sprintf(gpusage, "SD/MMC%d CD", dev_index); - gpio_request(host->cd_gpio.gpio, gpusage); - gpio_direction_input(host->cd_gpio.gpio); - debug(" CD GPIO name = %s\n", host->cd_gpio.name); - } + if (dm_gpio_is_valid(&host->pwr_gpio)) + dm_gpio_set_value(&host->pwr_gpio, 1); memset(&host->cfg, 0, sizeof(host->cfg)); @@ -626,9 +613,12 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host) debug("%s: no sdmmc width found\n", __func__); /* These GPIOs are optional */ - fdtdec_decode_gpio(blob, node, "cd-gpios", &host->cd_gpio); - fdtdec_decode_gpio(blob, node, "wp-gpios", &host->wp_gpio); - fdtdec_decode_gpio(blob, node, "power-gpios", &host->pwr_gpio); + gpio_request_by_name_nodev(blob, node, "cd-gpios", 0, &host->cd_gpio, + GPIOD_IS_IN); + gpio_request_by_name_nodev(blob, node, "wp-gpios", 0, &host->wp_gpio, + GPIOD_IS_IN); + gpio_request_by_name_nodev(blob, node, "power-gpios", 0, + &host->pwr_gpio, GPIOD_IS_OUT); debug("%s: found controller at %p, width = %d, periph_id = %d\n", __func__, host->reg, host->width, host->mmc_id); |