Exemplo n.º 1
0
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);
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
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);
	}
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
0
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;
}