From 7aedafd6b374b9c052474dc248fa7173c5c048a2 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Fri, 9 Sep 2016 18:23:23 +0900 Subject: mmc: s5p_sdhci: support the Driver model for Exynos This patch support the driver model for s5p_sdhci controller. To support the legacy model, maintained the existing code. Note: If use the Driver Model, it needs to modify the device-tree. In future, will update the Device-tree and enable the configuratioin. (CONFIG_BLK, CONFIG_DM_MMC and CONFING_DM_MMC_OPS) Signed-off-by: Jaehoon Chung Reviewed-by: Simon Glass Acked-by: Minkyu Kang Reviewed-by: Simon Glass diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index 3bace21..0d65783 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -16,6 +17,15 @@ #include #include +#ifdef CONFIG_DM_MMC +struct s5p_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +DECLARE_GLOBAL_DATA_PTR; +#endif + static char *S5P_NAME = "SAMSUNG SDHCI"; static void s5p_sdhci_set_control_reg(struct sdhci_host *host) { @@ -79,7 +89,11 @@ static int s5p_sdhci_core_init(struct sdhci_host *host) if (host->bus_width == 8) host->host_caps |= MMC_MODE_8BIT; +#ifndef CONFIG_BLK return add_sdhci(host, 52000000, 400000); +#else + return 0; +#endif } int s5p_sdhci_init(u32 regbase, int index, int bus_width) @@ -215,3 +229,60 @@ int exynos_mmc_init(const void *blob) return process_nodes(blob, node_list, count); } #endif + +#ifdef CONFIG_DM_MMC +static int s5p_sdhci_probe(struct udevice *dev) +{ + struct s5p_sdhci_plat *plat = dev_get_platdata(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct sdhci_host *host = dev_get_priv(dev); + int ret; + + ret = sdhci_get_config(gd->fdt_blob, dev->of_offset, host); + if (ret) + return ret; + + ret = do_sdhci_init(host); + if (ret) + return ret; + + ret = sdhci_setup_cfg(&plat->cfg, host, 52000000, 400000); + if (ret) + return ret; + + host->mmc = &plat->mmc; + host->mmc->priv = host; + host->mmc->dev = dev; + upriv->mmc = host->mmc; + + return sdhci_probe(dev); +} + +static int s5p_sdhci_bind(struct udevice *dev) +{ + struct s5p_sdhci_plat *plat = dev_get_platdata(dev); + int ret; + + ret = sdhci_bind(dev, &plat->mmc, &plat->cfg); + if (ret) + return ret; + + return 0; +} + +static const struct udevice_id s5p_sdhci_ids[] = { + { .compatible = "samsung,exynos4412-sdhci"}, + { } +}; + +U_BOOT_DRIVER(s5p_sdhci_drv) = { + .name = "s5p_sdhci", + .id = UCLASS_MMC, + .of_match = s5p_sdhci_ids, + .bind = s5p_sdhci_bind, + .ops = &sdhci_ops, + .probe = s5p_sdhci_probe, + .priv_auto_alloc_size = sizeof(struct sdhci_host), + .platdata_auto_alloc_size = sizeof(struct s5p_sdhci_plat), +}; +#endif /* CONFIG_DM_MMC */ -- cgit v0.10.2 From e5113c333b318328619f8cf2d9984f05fc5c3b59 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Fri, 23 Sep 2016 19:13:16 +0900 Subject: mmc: dw_mmc: remove the unnecessary arguments for dwmci_setup_cfg Some arguments don't need to pass to dwmci_setup_cfg. They are already included in dwmci_host structure. Signed-off-by: Jaehoon Chung Reviewed-by: Simon Glass diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 074f86c..d6ac46c 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -488,10 +488,10 @@ static const struct mmc_ops dwmci_ops = { }; #endif -void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth, - uint caps, u32 max_clk, u32 min_clk) +void dwmci_setup_cfg(struct mmc_config *cfg, struct dwmci_host *host, + u32 max_clk, u32 min_clk) { - cfg->name = name; + cfg->name = host->name; #ifndef CONFIG_DM_MMC_OPS cfg->ops = &dwmci_ops; #endif @@ -500,9 +500,9 @@ void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth, cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; - cfg->host_caps = caps; + cfg->host_caps = host->caps; - if (buswidth == 8) { + if (host->buswidth == 8) { cfg->host_caps |= MMC_MODE_8BIT; cfg->host_caps &= ~MMC_MODE_4BIT; } else { @@ -522,8 +522,7 @@ int dwmci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg) #else int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk) { - dwmci_setup_cfg(&host->cfg, host->name, host->buswidth, host->caps, - max_clk, min_clk); + dwmci_setup_cfg(&host->cfg, host, max_clk, min_clk); host->mmc = mmc_create(&host->cfg, host); if (host->mmc == NULL) diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index 568fed7..c440399 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -271,8 +271,7 @@ static int exynos_dwmmc_probe(struct udevice *dev) if (err) return err; - dwmci_setup_cfg(&plat->cfg, host->name, host->buswidth, host->caps, - DWMMC_MAX_FREQ, DWMMC_MIN_FREQ); + dwmci_setup_cfg(&plat->cfg, host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ); host->mmc = &plat->mmc; host->mmc->priv = &priv->host; host->priv = dev; diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c index 859760b..47db678 100644 --- a/drivers/mmc/rockchip_dw_mmc.c +++ b/drivers/mmc/rockchip_dw_mmc.c @@ -129,8 +129,7 @@ static int rockchip_dwmmc_probe(struct udevice *dev) return ret; } #endif - dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps, - priv->minmax[1], priv->minmax[0]); + dwmci_setup_cfg(&plat->cfg, host, priv->minmax[1], priv->minmax[0]); host->mmc = &plat->mmc; host->mmc->priv = &priv->host; host->mmc->dev = dev; diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c index 8a96302..5a3a4ff 100644 --- a/drivers/mmc/socfpga_dw_mmc.c +++ b/drivers/mmc/socfpga_dw_mmc.c @@ -111,8 +111,7 @@ static int socfpga_dwmmc_probe(struct udevice *dev) struct dwmci_host *host = &priv->host; #ifdef CONFIG_BLK - dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps, - host->bus_hz, 400000); + dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000); host->mmc = &plat->mmc; #else int ret; diff --git a/include/dwmmc.h b/include/dwmmc.h index 5b9602c..4dda009 100644 --- a/include/dwmmc.h +++ b/include/dwmmc.h @@ -253,14 +253,12 @@ static inline u8 dwmci_readb(struct dwmci_host *host, int reg) * See rockchip_dw_mmc.c for an example. * * @cfg: Configuration structure to fill in (generally &plat->mmc) - * @name: Device name (normally dev->name) - * @buswidth: Bus width (in bits, such as 4 or 8) - * @caps: Host capabilities (MMC_MODE_...) + * @host: DWMMC host * @max_clk: Maximum supported clock speed in HZ (e.g. 150000000) * @min_clk: Minimum supported clock speed in HZ (e.g. 400000) */ -void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth, - uint caps, u32 max_clk, u32 min_clk); +void dwmci_setup_cfg(struct mmc_config *cfg, struct dwmci_host *host, + u32 max_clk, u32 min_clk); /** * dwmci_bind() - Set up a new MMC block device -- cgit v0.10.2 From 895549a2d994ecf1ca1636792e55019e56be2d7d Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Mon, 26 Sep 2016 08:10:01 +0900 Subject: mmc: sdhci: use the host version value in sdhci_setup_cfg "host->version" isn't a SoC specific value. It doesn't need to get in each SoC drivers. Signed-off-by: Jaehoon Chung Reviewed-by: Minkyu Kang diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c index d8f8087..20bba1a 100644 --- a/drivers/mmc/atmel_sdhci.c +++ b/drivers/mmc/atmel_sdhci.c @@ -29,7 +29,6 @@ int atmel_sdhci_init(void *regbase, u32 id) host->name = "atmel_sdhci"; host->ioaddr = regbase; host->quirks = 0; - host->version = sdhci_readw(host, SDHCI_HOST_VERSION); max_clk = at91_get_periph_generated_clk(id); if (!max_clk) { printf("%s: Failed to get the proper clock\n", __func__); diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index 680b754..c1d8700 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -184,7 +184,6 @@ int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; host->ops = &bcm2835_ops; - host->version = sdhci_readw(host, SDHCI_HOST_VERSION); add_sdhci(host, emmc_freq, MIN_FREQ); return 0; diff --git a/drivers/mmc/kona_sdhci.c b/drivers/mmc/kona_sdhci.c index e730caa..c67a262 100644 --- a/drivers/mmc/kona_sdhci.c +++ b/drivers/mmc/kona_sdhci.c @@ -127,11 +127,6 @@ int kona_sdhci_init(int dev_index, u32 min_clk, u32 quirks) return -EINVAL; } - if (quirks & SDHCI_QUIRK_REG32_RW) - host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16; - else - host->version = sdhci_readw(host, SDHCI_HOST_VERSION); - add_sdhci(host, max_clk, min_clk); return ret; } diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index 1b82991..f33714b 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -140,9 +140,6 @@ static int msm_sdc_probe(struct udevice *dev) writel(caps, host->ioaddr + SDHCI_VENDOR_SPEC_CAPABILITIES0); } - /* Set host controller version */ - host->version = sdhci_readw(host, SDHCI_HOST_VERSION); - ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0); host->mmc = &plat->mmc; if (ret) diff --git a/drivers/mmc/mv_sdhci.c b/drivers/mmc/mv_sdhci.c index 82c695f..ca5f872 100644 --- a/drivers/mmc/mv_sdhci.c +++ b/drivers/mmc/mv_sdhci.c @@ -88,9 +88,5 @@ int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks) sdhci_mvebu_mbus_config((void __iomem *)regbase); } - if (quirks & SDHCI_QUIRK_REG32_RW) - host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16; - else - host->version = sdhci_readw(host, SDHCI_HOST_VERSION); return add_sdhci(host, max_clk, min_clk); } diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index 0d65783..d7cfa3e 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -81,7 +81,6 @@ static int s5p_sdhci_core_init(struct sdhci_host *host) SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_USE_WIDE8; host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; - host->version = sdhci_readw(host, SDHCI_HOST_VERSION); host->set_control_reg = &s5p_sdhci_set_control_reg; host->set_clock = set_mmc_clk; diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index b2bf5a0..7337722 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -546,7 +546,11 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, return -EINVAL; } #endif - host->version = sdhci_readw(host, SDHCI_HOST_VERSION); + if (host->quirks & SDHCI_QUIRK_REG32_RW) + host->version = + sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16; + else + host->version = sdhci_readw(host, SDHCI_HOST_VERSION); cfg->name = host->name; #ifndef CONFIG_DM_MMC_OPS diff --git a/drivers/mmc/spear_sdhci.c b/drivers/mmc/spear_sdhci.c index 6ca96a2..06179cd 100644 --- a/drivers/mmc/spear_sdhci.c +++ b/drivers/mmc/spear_sdhci.c @@ -22,11 +22,6 @@ int spear_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks) host->ioaddr = (void *)regbase; host->quirks = quirks; - if (quirks & SDHCI_QUIRK_REG32_RW) - host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16; - else - host->version = sdhci_readw(host, SDHCI_HOST_VERSION); - add_sdhci(host, max_clk, min_clk); return 0; } diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index b991102..3da1385 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -36,8 +36,6 @@ static int arasan_sdhci_probe(struct udevice *dev) host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; #endif - host->version = sdhci_readw(host, SDHCI_HOST_VERSION); - ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, CONFIG_ZYNQ_SDHCI_MIN_FREQ); host->mmc = &plat->mmc; -- cgit v0.10.2 From 2cb5d67c1aceb758033954cc06382367ac89e6ac Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Mon, 26 Sep 2016 08:10:02 +0900 Subject: mmc: sdhci: use the generic error number Use the generic error number instead of meaningless value. Signed-off-by: Jaehoon Chung Reviewed-by: Simon Glass diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index c1d8700..cb2bd40 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -157,7 +157,7 @@ int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) bcm_host = calloc(1, sizeof(*bcm_host)); if (!bcm_host) { printf("sdhci_host calloc fail!\n"); - return 1; + return -ENOMEM; } /* diff --git a/drivers/mmc/ftsdc021_sdhci.c b/drivers/mmc/ftsdc021_sdhci.c index 1f6cdba..6e9fefa 100644 --- a/drivers/mmc/ftsdc021_sdhci.c +++ b/drivers/mmc/ftsdc021_sdhci.c @@ -21,7 +21,7 @@ int ftsdc021_sdhci_init(u32 regbase) host = calloc(1, sizeof(struct sdhci_host)); if (!host) { puts("sdh_host malloc fail!\n"); - return 1; + return -ENOMEM; } host->name = "FTSDC021"; diff --git a/drivers/mmc/kona_sdhci.c b/drivers/mmc/kona_sdhci.c index c67a262..549f6bc 100644 --- a/drivers/mmc/kona_sdhci.c +++ b/drivers/mmc/kona_sdhci.c @@ -27,7 +27,7 @@ static int init_kona_mmc_core(struct sdhci_host *host) if (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL) { printf("%s: sd host controller reset error\n", __func__); - return 1; + return -EBUSY; } /* For kona a hardware reset before anything else. */ @@ -39,7 +39,7 @@ static int init_kona_mmc_core(struct sdhci_host *host) do { if (timeout == 0) { printf("%s: reset timeout error\n", __func__); - return 1; + return -ETIMEDOUT; } timeout--; udelay(100); @@ -67,7 +67,7 @@ static int init_kona_mmc_core(struct sdhci_host *host) while (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { if (timeout == 0) { printf("%s: CARD DETECT timeout error\n", __func__); - return 1; + return -ETIMEDOUT; } timeout--; udelay(100); diff --git a/drivers/mmc/mv_sdhci.c b/drivers/mmc/mv_sdhci.c index ca5f872..e388ad1 100644 --- a/drivers/mmc/mv_sdhci.c +++ b/drivers/mmc/mv_sdhci.c @@ -71,7 +71,7 @@ int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks) host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host)); if (!host) { printf("sdh_host malloc fail!\n"); - return 1; + return -ENOMEM; } host->name = MVSDH_NAME; diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index d7cfa3e..b329bef 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -100,7 +100,7 @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width) struct sdhci_host *host = calloc(1, sizeof(struct sdhci_host)); if (!host) { printf("sdhci__host allocation fail!\n"); - return 1; + return -ENOMEM; } host->ioaddr = (void *)regbase; host->index = index; @@ -154,7 +154,7 @@ static int sdhci_get_config(const void *blob, int node, struct sdhci_host *host) dev_id = pinmux_decode_periph_id(blob, node); if (dev_id < PERIPH_ID_SDMMC0 && dev_id > PERIPH_ID_SDMMC3) { debug("MMC: Can't get device id\n"); - return -1; + return -EINVAL; } host->index = dev_id - PERIPH_ID_SDMMC0; @@ -162,7 +162,7 @@ static int sdhci_get_config(const void *blob, int node, struct sdhci_host *host) bus_width = fdtdec_get_int(blob, node, "samsung,bus-width", 0); if (bus_width <= 0) { debug("MMC: Can't get bus-width\n"); - return -1; + return -EINVAL; } host->bus_width = bus_width; @@ -170,7 +170,7 @@ static int sdhci_get_config(const void *blob, int node, struct sdhci_host *host) base = fdtdec_get_addr(blob, node, "reg"); if (!base) { debug("MMC: Can't get base address\n"); - return -1; + return -EINVAL; } host->ioaddr = (void *)base; diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 7337722..837c538 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -87,7 +87,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data, if (stat & SDHCI_INT_ERROR) { printf("%s: Error detected in status(0x%X)!\n", __func__, stat); - return -1; + return -EIO; } if (stat & rdy) { if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)) @@ -110,7 +110,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data, udelay(10); else { printf("%s: Transfer data timeout\n", __func__); - return -1; + return -ETIMEDOUT; } } while (!(stat & SDHCI_INT_DATA_END)); return 0; @@ -303,7 +303,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) if (timeout == 0) { printf("%s: Timeout to wait cmd & data inhibit\n", __func__); - return -1; + return -EBUSY; } timeout--; @@ -374,7 +374,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) if (timeout == 0) { printf("%s: Internal clock never stabilised.\n", __func__); - return -1; + return -EBUSY; } timeout--; udelay(1000); @@ -477,7 +477,7 @@ static int sdhci_init(struct mmc *mmc) if (!aligned_buffer) { printf("%s: Aligned buffer alloc failed!!!\n", __func__); - return -1; + return -ENOMEM; } } @@ -631,7 +631,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk) host->mmc = mmc_create(&host->cfg, host); if (host->mmc == NULL) { printf("%s: mmc create fail!\n", __func__); - return -1; + return -ENOMEM; } return 0; -- cgit v0.10.2 From 57718f017b10871cd9dc03dca56c3bd690fc2614 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 25 Sep 2016 21:33:10 -0600 Subject: mmc: Fix cast for 64-bit compilation Fix a cast that causes warnings on 64-bit machines. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index 340eef6..3d587cc 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -30,7 +30,7 @@ int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported) mmc_host->name = name; dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase); - mmc_host->ioaddr = (void *)iobase; + mmc_host->ioaddr = (void *)(ulong)iobase; mmc_host->quirks = 0; ret = add_sdhci(mmc_host, 0, 0); if (ret) -- cgit v0.10.2