unsigned char mmc_clock_config(unsigned int iclk, unsigned short clk_div) { unsigned int val; mmc_reg_out(&mmc_base->sysctl, (ICE_MASK | DTO_MASK | CEN_MASK), (ICE_STOP | DTO_15THDTO | CEN_DISABLE)); switch (iclk) { case CLK_INITSEQ: val = MMC_INIT_SEQ_CLK / 2; break; case CLK_400KHZ: val = MMC_400kHz_CLK; break; case CLK_MISC: val = clk_div; break; default: return 0; } mmc_reg_out(&mmc_base->sysctl, ICE_MASK | CLKD_MASK, (val << CLKD_OFFSET) | ICE_OSCILLATE); while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY); writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl); return 1; }
unsigned char mmc_clock_config(unsigned int iclk, unsigned short clk_div) { unsigned int val; mmc_reg_out(OMAP_HSMMC_SYSCTL, (ICE_MASK | DTO_MASK | CEN_MASK), (ICE_STOP | DTO_15THDTO | CEN_DISABLE)); switch (iclk) { case CLK_INITSEQ: val = MMC_INIT_SEQ_CLK / 2; break; case CLK_400KHZ: val = MMC_400kHz_CLK; break; case CLK_MISC: val = clk_div; break; default: return 0; } mmc_reg_out(OMAP_HSMMC_SYSCTL, ICE_MASK | CLKD_MASK, (val << CLKD_OFFSET) | ICE_OSCILLATE); while ((OMAP_HSMMC_SYSCTL & ICS_MASK) == ICS_NOTREADY) { } OMAP_HSMMC_SYSCTL |= CEN_ENABLE; return 1; }
void CmtSdCard::ClockConfig( OMAP_MMCHS_REGS *mmc, uint32 iclk, uint32 clk_div ) { uint32 val; mmc_reg_out( mmc->MMCHS_SYSCTL, (ICE_MASK | DTO_MASK | CEN_MASK), (ICE_STOP | DTO_15THDTO | CEN_DISABLE) ); switch (iclk) { case CLK_INITSEQ: val = MMC_INIT_SEQ_CLK / 2; break; case CLK_400KHZ: val = MMC_400kHz_CLK; break; case CLK_MISC: val = clk_div; break; default: return; } mmc_reg_out( mmc->MMCHS_SYSCTL, ICE_MASK | CLKD_MASK, (val << CLKD_OFFSET) | ICE_OSCILLATE ); while( (__raw_readl( &(mmc->MMCHS_SYSCTL) ) & ICS_MASK) == ICS_NOTREADY ); mmc->MMCHS_SYSCTL |= CEN_ENABLE; }
static void mmc_set_ios(struct mmc *mmc) { puts(__FUNCTION__); struct hsmmc *mmc_base; unsigned int dsor = 0; ulong start; mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr; printf("mmc bus width: %d\n", mmc->bus_width); /* 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. */ printf("mmc clock: %d\n", mmc->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; } } writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl); }
static void mmc_set_ios(struct mmc *mmc) { hsmmc_t *mmc_base = (hsmmc_t *)mmc->priv; unsigned int dsor = 0; /* 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); while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) ; writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl); }
static int mmc_init_setup(struct mmc *mmc) { hsmmc_t *mmc_base = (hsmmc_t *)mmc->priv; unsigned int reg_val; unsigned int dsor; mmc_board_init(mmc_base); writel(readl(&mmc_base->sysconfig) | MMC_SOFTRESET, &mmc_base->sysconfig); while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) ; writel(readl(&mmc_base->sysctl) | SOFTRESETALL, &mmc_base->sysctl); while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0x0) ; writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl); writel(readl(&mmc_base->capa) | VS30_3V0SUP | VS18_1V8SUP, &mmc_base->capa); reg_val = readl(&mmc_base->con) & RESERVED_MASK; writel(CTPL_MMC_SD | reg_val | WPP_ACTIVEHIGH | CDP_ACTIVEHIGH | MIT_CTO | DW8_1_4BITMODE | MODE_FUNC | STR_BLOCK | HR_NOHOSTRESP | INIT_NOINIT | NOOPENDRAIN, &mmc_base->con); dsor = 240; 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); while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) ; writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl); writel(readl(&mmc_base->hctl) | SDBP_PWRON, &mmc_base->hctl); writel(IE_BADA | IE_CERR | IE_DEB | IE_DCRC | IE_DTO | IE_CIE | IE_CEB | IE_CCRC | IE_CTO | IE_BRR | IE_BWR | IE_TC | IE_CC, &mmc_base->ie); mmc_init_stream(mmc_base); return 0; }
/* * MMC controller internal finite state machine reset * * Used to reset command or data internal state machines, using respectively * SRC or SRD bit of SYSCTL register */ static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit) { ulong start; mmc_reg_out(&mmc_base->sysctl, bit, bit); start = get_timer(0); while ((readl(&mmc_base->sysctl) & bit) != 0) { if (get_timer(0) - start > MAX_RETRY_MS) { printf("%s: timedout waiting for sysctl %x to clear\n", __func__, bit); return; } } }
/* * MMC controller internal finite state machine reset * * Used to reset command or data internal state machines, using respectively * SRC or SRD bit of SYSCTL register */ static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit) { ulong start; mmc_reg_out(&mmc_base->sysctl, bit, bit); /* * CMD(DAT) lines reset procedures are slightly different * for OMAP3 and OMAP4(AM335x,OMAP5,DRA7xx). * According to OMAP3 TRM: * Set SRC(SRD) bit in MMCHS_SYSCTL register to 0x1 and wait until it * returns to 0x0. * According to OMAP4(AM335x,OMAP5,DRA7xx) TRMs, CMD(DATA) lines reset * procedure steps must be as follows: * 1. Initiate CMD(DAT) line reset by writing 0x1 to SRC(SRD) bit in * MMCHS_SYSCTL register (SD_SYSCTL for AM335x). * 2. Poll the SRC(SRD) bit until it is set to 0x1. * 3. Wait until the SRC (SRD) bit returns to 0x0 * (reset procedure is completed). */ #if defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \ defined(CONFIG_AM33XX) || defined(CONFIG_AM43XX) if (!(readl(&mmc_base->sysctl) & bit)) { start = get_timer(0); while (!(readl(&mmc_base->sysctl) & bit)) { if (get_timer(0) - start > MAX_RETRY_MS) return; } } #endif start = get_timer(0); while ((readl(&mmc_base->sysctl) & bit) != 0) { if (get_timer(0) - start > MAX_RETRY_MS) { printf("%s: timedout waiting for sysctl %x to clear\n", __func__, bit); return; } } }
static int omap_hsmmc_init_setup(struct mmc *mmc) { struct hsmmc *mmc_base; unsigned int reg_val; unsigned int dsor; ulong start; mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr; mmc_board_init(mmc); writel(readl(&mmc_base->sysconfig) | MMC_SOFTRESET, &mmc_base->sysconfig); start = get_timer(0); while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) { if (get_timer(0) - start > MAX_RETRY_MS) { printf("%s: timedout waiting for cc2!\n", __func__); return -ETIMEDOUT; } } writel(readl(&mmc_base->sysctl) | SOFTRESETALL, &mmc_base->sysctl); start = get_timer(0); while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0x0) { if (get_timer(0) - start > MAX_RETRY_MS) { printf("%s: timedout waiting for softresetall!\n", __func__); return -ETIMEDOUT; } } writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl); writel(readl(&mmc_base->capa) | VS30_3V0SUP | VS18_1V8SUP, &mmc_base->capa); reg_val = readl(&mmc_base->con) & RESERVED_MASK; writel(CTPL_MMC_SD | reg_val | WPP_ACTIVEHIGH | CDP_ACTIVEHIGH | MIT_CTO | DW8_1_4BITMODE | MODE_FUNC | STR_BLOCK | HR_NOHOSTRESP | INIT_NOINIT | NOOPENDRAIN, &mmc_base->con); dsor = 240; 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); writel(readl(&mmc_base->hctl) | SDBP_PWRON, &mmc_base->hctl); writel(IE_BADA | IE_CERR | IE_DEB | IE_DCRC | IE_DTO | IE_CIE | IE_CEB | IE_CCRC | IE_CTO | IE_BRR | IE_BWR | IE_TC | IE_CC, &mmc_base->ie); mmc_init_stream(mmc_base); return 0; }
static int mmc_init_setup(struct mmc *mmc) { hsmmc_t *mmc_base = (hsmmc_t *)mmc->priv; unsigned int reg_val; unsigned int dsor; unsigned int sdio_mode = (mmc_base == (hsmmc_t *)OMAP_SDIO_BASE)? 1 : 0; ulong start; mmc_board_init(mmc_base); writel(readl(&mmc_base->sysconfig) | MMC_SOFTRESET, &mmc_base->sysconfig); start = get_timer(0); while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) { if (get_timer(0) - start > MAX_RETRY_MS) { printf("%s: timedout waiting for cc2!\n", __func__); return TIMEOUT; } } writel(readl(&mmc_base->sysctl) | SOFTRESETALL, &mmc_base->sysctl); start = get_timer(0); while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0x0) { if (get_timer(0) - start > MAX_RETRY_MS) { printf("%s: timedout waiting for softresetall!\n", __func__); return TIMEOUT; } } if (sdio_mode) { writel(0x00000C00, &mmc_base->hctl); writel(0x200, &mmc_base->blk); } else writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl); writel(readl(&mmc_base->capa) | VS30_3V0SUP | VS18_1V8SUP, &mmc_base->capa); if (sdio_mode) { reg_val = readl(&mmc_base->con) & (0x3 << 9); writel(reg_val, &mmc_base->con); } else { reg_val = readl(&mmc_base->con) & RESERVED_MASK; writel(CTPL_MMC_SD | reg_val | WPP_ACTIVEHIGH | CDP_ACTIVEHIGH | MIT_CTO | DW8_1_4BITMODE | MODE_FUNC | STR_BLOCK | HR_NOHOSTRESP | INIT_NOINIT | NOOPENDRAIN, &mmc_base->con); } if (sdio_mode) dsor = 600; else dsor = 240; 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 TIMEOUT; } } writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl); writel(readl(&mmc_base->hctl) | SDBP_PWRON, &mmc_base->hctl); /* Enable Interrupts */ writel(IE_BADA | IE_CERR | IE_DEB | IE_DCRC | IE_DTO | IE_CIE | IE_CEB | IE_CCRC | IE_CTO | IE_BRR | IE_BWR | IE_TC | IE_CC, &mmc_base->ie); mmc_init_stream(mmc_base); 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 }, { } };