static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios) { struct mmc_host *mmc = host->mmc; if (!IS_ERR(mmc->supply.vmmc)) /* Errors ignored... */ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->power_mode ? ios->vdd : 0); }
static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios) { struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data; struct mmc_host *mmc = host->mmc; if (pd && pd->set_pwr) pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF); if (!IS_ERR(mmc->supply.vmmc)) /* Errors ignored... */ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->power_mode ? ios->vdd : 0); }
static void pxav3_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd) { struct mmc_host *mmc = host->mmc; u8 pwr = host->pwr; sdhci_set_power(host, mode, vdd); if (host->pwr == pwr) return; if (host->pwr == 0) vdd = 0; if (!IS_ERR(mmc->supply.vmmc)) { spin_unlock_irq(&host->lock); mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); spin_lock_irq(&host->lock); } }
static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct mmci_host *host = mmc_priv(mmc); u32 pwr = 0; unsigned long flags; switch (ios->power_mode) { case MMC_POWER_OFF: if(host->vcc && regulator_is_enabled(host->vcc)) regulator_disable(host->vcc); break; case MMC_POWER_UP: #ifdef CONFIG_REGULATOR if (host->vcc) /* This implicitly enables the regulator */ mmc_regulator_set_ocr(host->vcc, ios->vdd); #endif /* * The translate_vdd function is not used if you have * an external regulator, or your design is really weird. * Using it would mean sending in power control BOTH using * a regulator AND the 4 MMCIPWR bits. If we don't have * a regulator, we might have some other platform specific * power control behind this translate function. */ if (!host->vcc && host->plat->translate_vdd) pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd); /* The ST version does not have this, fall through to POWER_ON */ if (host->hw_designer != AMBA_VENDOR_ST) { pwr |= MCI_PWR_UP; break; } case MMC_POWER_ON: pwr |= MCI_PWR_ON; break; } if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) { if (host->hw_designer != AMBA_VENDOR_ST) pwr |= MCI_ROD; else { /* * The ST Micro variant use the ROD bit for something * else and only has OD (Open Drain). */ pwr |= MCI_OD; } } spin_lock_irqsave(&host->lock, flags); mmci_set_clkreg(host, ios->clock); if (host->pwr != pwr) { host->pwr = pwr; writel(pwr, host->base + MMCIPOWER); } spin_unlock_irqrestore(&host->lock, flags); }
static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct meson_host *host = mmc_priv(mmc); u32 bus_width; u32 val, orig; /* * GPIO regulator, only controls switching between 1v8 and * 3v3, doesn't support MMC_POWER_OFF, MMC_POWER_ON. */ switch (ios->power_mode) { case MMC_POWER_OFF: if (!IS_ERR(mmc->supply.vmmc)) mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) { regulator_disable(mmc->supply.vqmmc); host->vqmmc_enabled = false; } break; case MMC_POWER_UP: if (!IS_ERR(mmc->supply.vmmc)) mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); break; case MMC_POWER_ON: if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) { int ret = regulator_enable(mmc->supply.vqmmc); if (ret < 0) dev_err(mmc_dev(mmc), "failed to enable vqmmc regulator\n"); else host->vqmmc_enabled = true; } break; } meson_mmc_clk_set(host, ios->clock); /* Bus width */ switch (ios->bus_width) { case MMC_BUS_WIDTH_1: bus_width = CFG_BUS_WIDTH_1; break; case MMC_BUS_WIDTH_4: bus_width = CFG_BUS_WIDTH_4; break; case MMC_BUS_WIDTH_8: bus_width = CFG_BUS_WIDTH_8; break; default: dev_err(host->dev, "Invalid ios->bus_width: %u. Setting to 4.\n", ios->bus_width); bus_width = CFG_BUS_WIDTH_4; } val = readl(host->regs + SD_EMMC_CFG); orig = val; val &= ~(CFG_BUS_WIDTH_MASK << CFG_BUS_WIDTH_SHIFT); val |= bus_width << CFG_BUS_WIDTH_SHIFT; val &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT); val |= ilog2(SD_EMMC_CFG_BLK_SIZE) << CFG_BLK_LEN_SHIFT; val &= ~(CFG_RESP_TIMEOUT_MASK << CFG_RESP_TIMEOUT_SHIFT); val |= ilog2(SD_EMMC_CFG_RESP_TIMEOUT) << CFG_RESP_TIMEOUT_SHIFT; val &= ~(CFG_RC_CC_MASK << CFG_RC_CC_SHIFT); val |= ilog2(SD_EMMC_CFG_CMD_GAP) << CFG_RC_CC_SHIFT; val &= ~CFG_DDR; if (ios->timing == MMC_TIMING_UHS_DDR50 || ios->timing == MMC_TIMING_MMC_DDR52 || ios->timing == MMC_TIMING_MMC_HS400) val |= CFG_DDR; val &= ~CFG_CHK_DS; if (ios->timing == MMC_TIMING_MMC_HS400) val |= CFG_CHK_DS; writel(val, host->regs + SD_EMMC_CFG); if (val != orig) dev_dbg(host->dev, "%s: SD_EMMC_CFG: 0x%08x -> 0x%08x\n", __func__, orig, val); }
static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int vdd) { int ret = 0; struct twl_mmc_controller *c = NULL; struct omap_mmc_platform_data *mmc = dev->platform_data; int i; for (i = 1; i < ARRAY_SIZE(hsmmc); i++) { if (mmc == hsmmc[i].mmc) { c = &hsmmc[i]; break; } } if (c == NULL) return -ENODEV; /* If we don't see a Vcc regulator, assume it's a fixed * voltage always-on regulator. */ if (!c->vcc) return 0; /* * Assume Vcc regulator is used only to power the card ... OMAP * VDDS is used to power the pins, optionally with a transceiver to * support cards using voltages other than VDDS (1.8V nominal). When a * transceiver is used, DAT3..7 are muxed as transceiver control pins. * * In some cases this regulator won't support enable/disable; * e.g. it's a fixed rail for a WLAN chip. * * In other cases vcc_aux switches interface power. Example, for * eMMC cards it represents VccQ. Sometimes transceivers or SDIO * chips/cards need an interface voltage rail too. */ if (power_on) { if (!cpu_is_omap44xx()) { /* only MMC2 supports a CLKIN */ if (mmc->slots[0].internal_clock) { u32 reg; reg = omap_ctrl_readl(control_devconf1_offset); reg |= OMAP2_MMCSDIO2ADPCLKISEL; omap_ctrl_writel(reg, control_devconf1_offset); } } ret = mmc_regulator_set_ocr(c->vcc, vdd); /* enable interface voltage rail, if needed */ if (ret == 0 && c->vcc_aux) { ret = regulator_enable(c->vcc_aux); if (ret < 0) ret = mmc_regulator_set_ocr(c->vcc, 0); } } else { if (c->vcc_aux && (ret = regulator_is_enabled(c->vcc_aux)) > 0) ret = regulator_disable(c->vcc_aux); if (ret == 0) ret = mmc_regulator_set_ocr(c->vcc, 0); } return ret; }
static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, int vdd) { u32 reg, prog_io; int ret = 0; struct twl_mmc_controller *c = &hsmmc[0]; struct omap_mmc_platform_data *mmc = dev->platform_data; // printk("[twl_mmc] '%s' called, power=%d\n", __func__, power_on); /* * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the * card with Vcc regulator (from twl4030 or whatever). OMAP has both * 1.8V and 3.0V modes, controlled by the PBIAS register. * * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which * is most naturally TWL VSIM; those pins also use PBIAS. * * FIXME handle VMMC1A as needed ... */ if (power_on) { if (cpu_is_omap2430()) { reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1); if ((1 << vdd) >= MMC_VDD_30_31) reg |= OMAP243X_MMC1_ACTIVE_OVERWRITE; else reg &= ~OMAP243X_MMC1_ACTIVE_OVERWRITE; omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1); } if (!cpu_is_omap44xx()) { if (mmc->slots[0].internal_clock) { reg = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); reg |= OMAP2_MMCSDIO1ADPCLKISEL; omap_ctrl_writel(reg, OMAP2_CONTROL_DEVCONF0); } reg = omap_ctrl_readl(control_pbias_offset); if (cpu_is_omap3630()) { /* Set MMC I/O to 52Mhz */ prog_io = omap_ctrl_readl (OMAP343X_CONTROL_PROG_IO1); prog_io |= OMAP3630_PRG_SDMMC1_SPEEDCTRL; omap_ctrl_writel (prog_io, OMAP343X_CONTROL_PROG_IO1); } else { reg |= OMAP2_PBIASSPEEDCTRL0; } reg &= ~OMAP2_PBIASLITEPWRDNZ0; } else { reg = omap_ctrl_readl(control_pbias_offset); reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDWNZ); } omap_ctrl_writel(reg, control_pbias_offset); ret = mmc_regulator_set_ocr(c->vcc, vdd); /* 100ms delay required for PBIAS configuration */ msleep(100); if (!cpu_is_omap44xx()) { reg = omap_ctrl_readl(control_pbias_offset); reg |= (OMAP2_PBIASLITEPWRDNZ0 | OMAP2_PBIASSPEEDCTRL0); if ((1 << vdd) <= MMC_VDD_165_195) reg &= ~OMAP2_PBIASLITEVMODE0; else reg |= OMAP2_PBIASLITEVMODE0; } else { reg = omap_ctrl_readl(control_pbias_offset); reg |= OMAP4_MMC1_PBIASLITE_PWRDNZ; if ((1 << vdd) <= MMC_VDD_165_195) reg &= ~(OMAP4_MMC1_PBIASLITE_VMODE); else reg |= (OMAP4_MMC1_PBIASLITE_VMODE); reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDWNZ); } omap_ctrl_writel(reg, control_pbias_offset); } else { if (!cpu_is_omap44xx()) { reg = omap_ctrl_readl(control_pbias_offset); reg &= ~OMAP2_PBIASLITEPWRDNZ0; } else { reg = omap_ctrl_readl(control_pbias_offset); reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDWNZ); } omap_ctrl_writel(reg, control_pbias_offset); ret = mmc_regulator_set_ocr(c->vcc, 0); /* 100ms delay required for PBIAS configuration */ msleep(100); if (!cpu_is_omap44xx()) { reg = omap_ctrl_readl(control_pbias_offset); reg |= (OMAP2_PBIASSPEEDCTRL0 | OMAP2_PBIASLITEPWRDNZ0 | OMAP2_PBIASLITEVMODE0); } else { reg = omap_ctrl_readl(control_pbias_offset); reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PBIASLITE_VMODE | OMAP4_MMC1_PWRDWNZ); } omap_ctrl_writel(reg, control_pbias_offset); } return ret; }