int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, int wp_gpio) { struct mmc *mmc = &hsmmc_dev[dev_index]; struct omap_hsmmc_data *priv_data = &hsmmc_dev_data[dev_index]; uint host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; sprintf(mmc->name, "OMAP SD/MMC"); mmc->send_cmd = mmc_send_cmd; mmc->set_ios = mmc_set_ios; mmc->init = mmc_init_setup; mmc->priv = priv_data; switch (dev_index) { case 0: priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE; break; #ifdef OMAP_HSMMC2_BASE case 1: priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE; #if (defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \ defined(CONFIG_DRA7XX)) && defined(CONFIG_HSMMC2_8BIT) /* Enable 8-bit interface for eMMC on OMAP4/5 or DRA7XX */ host_caps_val |= MMC_MODE_8BIT; #endif break; #endif #ifdef OMAP_HSMMC3_BASE case 2: priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC3_BASE; #if defined(CONFIG_DRA7XX) && defined(CONFIG_HSMMC3_8BIT) /* Enable 8-bit interface for eMMC on DRA7XX */ host_caps_val |= MMC_MODE_8BIT; #endif break; #endif default: priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE; return 1; } priv_data->cd_gpio = omap_mmc_setup_gpio_in(cd_gpio, "mmc_cd"); if (priv_data->cd_gpio != -1) mmc->getcd = omap_mmc_getcd; priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp"); if (priv_data->wp_gpio != -1) mmc->getwp = omap_mmc_getwp; mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; mmc->host_caps = host_caps_val & ~host_caps_mask; mmc->f_min = 400000; if (f_max != 0) mmc->f_max = f_max; else { if (mmc->host_caps & MMC_MODE_HS) { if (mmc->host_caps & MMC_MODE_HS_52MHz) mmc->f_max = 52000000; else mmc->f_max = 26000000; } else mmc->f_max = 20000000; } mmc->b_max = 0; #if defined(CONFIG_OMAP34XX) /* * Silicon revs 2.1 and older do not support multiblock transfers. */ if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21)) mmc->b_max = 1; #endif mmc_register(mmc); return 0; }
int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, int wp_gpio) { struct mmc *mmc; struct omap_hsmmc_data *priv_data; struct mmc_config *cfg; uint host_caps_val; priv_data = malloc(sizeof(*priv_data)); if (priv_data == NULL) return -1; host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS; switch (dev_index) { case 0: priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE; break; #ifdef OMAP_HSMMC2_BASE case 1: priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE; #if (defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \ defined(CONFIG_DRA7XX) || defined(CONFIG_AM33XX) || \ defined(CONFIG_AM43XX) || defined(CONFIG_SOC_KEYSTONE)) && \ defined(CONFIG_HSMMC2_8BIT) /* Enable 8-bit interface for eMMC on OMAP4/5 or DRA7XX */ host_caps_val |= MMC_MODE_8BIT; #endif break; #endif #ifdef OMAP_HSMMC3_BASE case 2: priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC3_BASE; #if defined(CONFIG_DRA7XX) && defined(CONFIG_HSMMC3_8BIT) /* Enable 8-bit interface for eMMC on DRA7XX */ host_caps_val |= MMC_MODE_8BIT; #endif break; #endif default: priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE; return 1; } #ifdef OMAP_HSMMC_USE_GPIO /* on error gpio values are set to -1, which is what we want */ priv_data->cd_gpio = omap_mmc_setup_gpio_in(cd_gpio, "mmc_cd"); priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp"); #endif cfg = &priv_data->cfg; cfg->name = "OMAP SD/MMC"; cfg->ops = &omap_hsmmc_ops; cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; cfg->host_caps = host_caps_val & ~host_caps_mask; cfg->f_min = 400000; if (f_max != 0) cfg->f_max = f_max; else { if (cfg->host_caps & MMC_MODE_HS) { if (cfg->host_caps & MMC_MODE_HS_52MHz) cfg->f_max = 52000000; else cfg->f_max = 26000000; } else cfg->f_max = 20000000; } cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; #if defined(CONFIG_OMAP34XX) /* * Silicon revs 2.1 and older do not support multiblock transfers. */ if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21)) cfg->b_max = 1; #endif mmc = mmc_create(cfg, priv_data); if (mmc == NULL) return -1; return 0; }
static int omap_hsmmc_set_ios(struct mmc *mmc) { struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc); #else static int omap_hsmmc_set_ios(struct udevice *dev) { struct omap_hsmmc_data *priv = dev_get_priv(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct mmc *mmc = upriv->mmc; #endif struct hsmmc *mmc_base; unsigned int dsor = 0; ulong start; mmc_base = priv->base_addr; /* configue bus width */ switch (mmc->bus_width) { case 8: writel(readl(&mmc_base->con) | DTW_8_BITMODE, &mmc_base->con); break; case 4: writel(readl(&mmc_base->con) & ~DTW_8_BITMODE, &mmc_base->con); writel(readl(&mmc_base->hctl) | DTW_4_BITMODE, &mmc_base->hctl); break; case 1: default: writel(readl(&mmc_base->con) & ~DTW_8_BITMODE, &mmc_base->con); writel(readl(&mmc_base->hctl) & ~DTW_4_BITMODE, &mmc_base->hctl); break; } /* configure clock with 96Mhz system clock. */ if (mmc->clock != 0) { dsor = (MMC_CLOCK_REFERENCE * 1000000 / mmc->clock); if ((MMC_CLOCK_REFERENCE * 1000000) / dsor > mmc->clock) dsor++; } mmc_reg_out(&mmc_base->sysctl, (ICE_MASK | DTO_MASK | CEN_MASK), (ICE_STOP | DTO_15THDTO | CEN_DISABLE)); mmc_reg_out(&mmc_base->sysctl, ICE_MASK | CLKD_MASK, (dsor << CLKD_OFFSET) | ICE_OSCILLATE); start = get_timer(0); while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) { if (get_timer(0) - start > MAX_RETRY_MS) { printf("%s: timedout waiting for ics!\n", __func__); return -ETIMEDOUT; } } writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl); return 0; } #ifdef OMAP_HSMMC_USE_GPIO #if CONFIG_IS_ENABLED(DM_MMC) static int omap_hsmmc_getcd(struct udevice *dev) { struct omap_hsmmc_data *priv = dev_get_priv(dev); int value; value = dm_gpio_get_value(&priv->cd_gpio); /* if no CD return as 1 */ if (value < 0) return 1; if (priv->cd_inverted) return !value; return value; } static int omap_hsmmc_getwp(struct udevice *dev) { struct omap_hsmmc_data *priv = dev_get_priv(dev); int value; value = dm_gpio_get_value(&priv->wp_gpio); /* if no WP return as 0 */ if (value < 0) return 0; return value; } #else static int omap_hsmmc_getcd(struct mmc *mmc) { struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc); int cd_gpio; /* if no CD return as 1 */ cd_gpio = priv->cd_gpio; if (cd_gpio < 0) return 1; /* NOTE: assumes card detect signal is active-low */ return !gpio_get_value(cd_gpio); } static int omap_hsmmc_getwp(struct mmc *mmc) { struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc); int wp_gpio; /* if no WP return as 0 */ wp_gpio = priv->wp_gpio; if (wp_gpio < 0) return 0; /* NOTE: assumes write protect signal is active-high */ return gpio_get_value(wp_gpio); } #endif #endif #if CONFIG_IS_ENABLED(DM_MMC) static const struct dm_mmc_ops omap_hsmmc_ops = { .send_cmd = omap_hsmmc_send_cmd, .set_ios = omap_hsmmc_set_ios, #ifdef OMAP_HSMMC_USE_GPIO .get_cd = omap_hsmmc_getcd, .get_wp = omap_hsmmc_getwp, #endif }; #else static const struct mmc_ops omap_hsmmc_ops = { .send_cmd = omap_hsmmc_send_cmd, .set_ios = omap_hsmmc_set_ios, .init = omap_hsmmc_init_setup, #ifdef OMAP_HSMMC_USE_GPIO .getcd = omap_hsmmc_getcd, .getwp = omap_hsmmc_getwp, #endif }; #endif #if !CONFIG_IS_ENABLED(DM_MMC) int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, int wp_gpio) { struct mmc *mmc; struct omap_hsmmc_data *priv; struct mmc_config *cfg; uint host_caps_val; priv = malloc(sizeof(*priv)); if (priv == NULL) return -1; host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS; switch (dev_index) { case 0: priv->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE; break; #ifdef OMAP_HSMMC2_BASE case 1: priv->base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE; #if (defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \ defined(CONFIG_DRA7XX) || defined(CONFIG_AM33XX) || \ defined(CONFIG_AM43XX) || defined(CONFIG_SOC_KEYSTONE)) && \ defined(CONFIG_HSMMC2_8BIT) /* Enable 8-bit interface for eMMC on OMAP4/5 or DRA7XX */ host_caps_val |= MMC_MODE_8BIT; #endif break; #endif #ifdef OMAP_HSMMC3_BASE case 2: priv->base_addr = (struct hsmmc *)OMAP_HSMMC3_BASE; #if defined(CONFIG_DRA7XX) && defined(CONFIG_HSMMC3_8BIT) /* Enable 8-bit interface for eMMC on DRA7XX */ host_caps_val |= MMC_MODE_8BIT; #endif break; #endif default: priv->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE; return 1; } #ifdef OMAP_HSMMC_USE_GPIO /* on error gpio values are set to -1, which is what we want */ priv->cd_gpio = omap_mmc_setup_gpio_in(cd_gpio, "mmc_cd"); priv->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp"); #endif cfg = &priv->cfg; cfg->name = "OMAP SD/MMC"; cfg->ops = &omap_hsmmc_ops; cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; cfg->host_caps = host_caps_val & ~host_caps_mask; cfg->f_min = 400000; if (f_max != 0) cfg->f_max = f_max; else { if (cfg->host_caps & MMC_MODE_HS) { if (cfg->host_caps & MMC_MODE_HS_52MHz) cfg->f_max = 52000000; else cfg->f_max = 26000000; } else cfg->f_max = 20000000; } cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; #if defined(CONFIG_OMAP34XX) /* * Silicon revs 2.1 and older do not support multiblock transfers. */ if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21)) cfg->b_max = 1; #endif mmc = mmc_create(cfg, priv); if (mmc == NULL) return -1; return 0; } #else #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) static int omap_hsmmc_ofdata_to_platdata(struct udevice *dev) { struct omap_hsmmc_plat *plat = dev_get_platdata(dev); struct mmc_config *cfg = &plat->cfg; struct omap2_mmc_platform_config *data = (struct omap2_mmc_platform_config *)dev_get_driver_data(dev); const void *fdt = gd->fdt_blob; int node = dev_of_offset(dev); int val; plat->base_addr = map_physmem(devfdt_get_addr(dev), sizeof(struct hsmmc *), MAP_NOCACHE) + data->reg_offset; cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS; val = fdtdec_get_int(fdt, node, "bus-width", -1); if (val < 0) { printf("error: bus-width property missing\n"); return -ENOENT; } switch (val) { case 0x8: cfg->host_caps |= MMC_MODE_8BIT; case 0x4: cfg->host_caps |= MMC_MODE_4BIT; break; default: printf("error: invalid bus-width property\n"); return -ENOENT; } cfg->f_min = 400000; cfg->f_max = fdtdec_get_int(fdt, node, "max-frequency", 52000000); cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; #ifdef OMAP_HSMMC_USE_GPIO plat->cd_inverted = fdtdec_get_bool(fdt, node, "cd-inverted"); #endif return 0; } #endif #ifdef CONFIG_BLK static int omap_hsmmc_bind(struct udevice *dev) { struct omap_hsmmc_plat *plat = dev_get_platdata(dev); return mmc_bind(dev, &plat->mmc, &plat->cfg); } #endif static int omap_hsmmc_probe(struct udevice *dev) { struct omap_hsmmc_plat *plat = dev_get_platdata(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct omap_hsmmc_data *priv = dev_get_priv(dev); struct mmc_config *cfg = &plat->cfg; struct mmc *mmc; cfg->name = "OMAP SD/MMC"; priv->base_addr = plat->base_addr; #ifdef OMAP_HSMMC_USE_GPIO priv->cd_inverted = plat->cd_inverted; #endif #ifdef CONFIG_BLK mmc = &plat->mmc; #else mmc = mmc_create(cfg, priv); if (mmc == NULL) return -1; #endif #if defined(OMAP_HSMMC_USE_GPIO) && CONFIG_IS_ENABLED(OF_CONTROL) gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN); gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, GPIOD_IS_IN); #endif mmc->dev = dev; upriv->mmc = mmc; return omap_hsmmc_init_setup(mmc); } #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) static const struct omap2_mmc_platform_config omap3_mmc_pdata = { .reg_offset = 0, }; static const struct omap2_mmc_platform_config am33xx_mmc_pdata = { .reg_offset = 0x100, }; static const struct omap2_mmc_platform_config omap4_mmc_pdata = { .reg_offset = 0x100, }; static const struct udevice_id omap_hsmmc_ids[] = { { .compatible = "ti,omap3-hsmmc", .data = (ulong)&omap3_mmc_pdata }, { .compatible = "ti,omap4-hsmmc", .data = (ulong)&omap4_mmc_pdata }, { .compatible = "ti,am33xx-hsmmc", .data = (ulong)&am33xx_mmc_pdata }, { } };