예제 #1
0
static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
{
	u16 clk;
	unsigned long timeout;

	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
	clk &= ~(SDHCI_CLOCK_CARD_EN);
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

	/* Issue DLL Reset */
	zynqmp_dll_reset(deviceid);

	/* Wait max 20 ms */
	timeout = 100;
	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
				& SDHCI_CLOCK_INT_STABLE)) {
		if (timeout == 0) {
			dev_err(mmc_dev(host->mmc),
				": Internal clock never stabilised.\n");
			return;
		}
		timeout--;
		udelay(1000);
	}

	clk |= SDHCI_CLOCK_CARD_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
}
static void sdhci_save_regs(struct sdhci_host *host)
{
	if (!strcmp("Spread SDIO host1", host->hw_name)){
		host_addr = sdhci_readl(host, SDHCI_DMA_ADDRESS);
		host_blk_size = sdhci_readw(host, SDHCI_BLOCK_SIZE);
		host_blk_cnt = sdhci_readw(host, SDHCI_BLOCK_COUNT);
		host_arg = sdhci_readl(host, SDHCI_ARGUMENT);
		host_tran_mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
		host_ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
		host_power = sdhci_readb(host, SDHCI_POWER_CONTROL);
		host_clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
	}
}
예제 #3
0
static void sdhci_save_regs(struct sdhci_host *host)
{
	struct sprd_host_platdata *host_pdata = sdhci_get_platdata(host);
	if (!host_pdata->regs.is_valid) return;
	host_pdata->regs.addr = sdhci_readl(host, SDHCI_DMA_ADDRESS);
	host_pdata->regs.blk_size = sdhci_readw(host, SDHCI_BLOCK_SIZE);
	host_pdata->regs.blk_cnt = sdhci_readw(host, SDHCI_BLOCK_COUNT);
	host_pdata->regs.arg = sdhci_readl(host, SDHCI_ARGUMENT);
	host_pdata->regs.tran_mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
	host_pdata->regs.ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
	host_pdata->regs.power = sdhci_readb(host, SDHCI_POWER_CONTROL);
	host_pdata->regs.clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
}
예제 #4
0
static int arasan_sdhci_probe(struct udevice *dev)
{
	struct arasan_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);
	u32 caps;
	int ret;

	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
		       SDHCI_QUIRK_BROKEN_R1B;

#ifdef CONFIG_ZYNQ_HISPD_BROKEN
	host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
#endif

	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);

	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
	ret = sdhci_setup_cfg(&plat->cfg, dev->name, host->bus_width,
			      caps, CONFIG_ZYNQ_SDHCI_MAX_FREQ,
			      CONFIG_ZYNQ_SDHCI_MIN_FREQ, host->version,
			      host->quirks, 0);
	host->mmc = &plat->mmc;
	if (ret)
		return ret;
	host->mmc->priv = host;
	host->mmc->dev = dev;
	upriv->mmc = host->mmc;

	return sdhci_probe(dev);
}
예제 #5
0
static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = pltfm_host->priv;
	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
	u32 misc_ctrl;

	sdhci_reset(host, mask);

	if (!(mask & SDHCI_RESET_ALL))
		return;

	misc_ctrl = sdhci_readw(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
	/* Erratum: Enable SDHCI spec v3.00 support */
	if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300)
		misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300;
	/* Don't advertise UHS modes which aren't supported yet */
	if (soc_data->nvquirks & NVQUIRK_DISABLE_SDR50)
		misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR50;
	if (soc_data->nvquirks & NVQUIRK_DISABLE_DDR50)
		misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_DDR50;
	if (soc_data->nvquirks & NVQUIRK_DISABLE_SDR104)
		misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR104;
	sdhci_writew(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
}
예제 #6
0
static int sdhci_set_clock(struct mmc_host *mmc, u32 clock)
{
	struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
	u32 div, clk, timeout;

	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);

	if (clock == 0) {
		return VMM_OK;
	}

	if ((host->sdhci_version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300) {
		/* Version 3.00 divisors must be a multiple of 2. */
		if (mmc->f_max <= clock)
			div = 1;
		else {
			for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
				if (udiv32(mmc->f_max, div) <= clock) {
					break;
				}
			}
		}
	} else {
		/* Version 2.00 divisors must be a power of 2. */
		for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
			if (udiv32(mmc->f_max, div) <= clock) {
				break;
			}
		}
	}
	div >>= 1;

	if (host->ops.set_clock) {
		host->ops.set_clock(host, div);
	}

	clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
	clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
		<< SDHCI_DIVIDER_HI_SHIFT;
	clk |= SDHCI_CLOCK_INT_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

	/* Wait max 20 ms */
	timeout = 20;
	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
		& SDHCI_CLOCK_INT_STABLE)) {
		if (timeout == 0) {
			vmm_printf("%s: Internal clock never stabilised.\n", 
				   __func__);
			return VMM_EFAIL;
		}
		timeout--;
		vmm_udelay(1000);
	}

	clk |= SDHCI_CLOCK_CARD_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

	return VMM_OK;
}
예제 #7
0
static inline void sdhci_sprd_sd_clk_off(struct sdhci_host *host)
{
	u16 ctrl = sdhci_readw(host, SDHCI_CLOCK_CONTROL);

	ctrl &= ~SDHCI_CLOCK_CARD_EN;
	sdhci_writew(host, ctrl, SDHCI_CLOCK_CONTROL);
}
예제 #8
0
static void sdhci_display_bus_width(struct sdhci_ctrlr *sdhci_ctrlr)
{
	if (IS_ENABLED(CONFIG_SDHC_DEBUG)) {
		int bits;
		uint8_t host_ctrl;
		uint16_t host2;
		const char *rate;
		uint16_t timing;

		/* Display the bus width */
		host_ctrl = sdhci_readb(sdhci_ctrlr, SDHCI_HOST_CONTROL);
		host2 = sdhci_readw(sdhci_ctrlr, SDHCI_HOST_CONTROL2);
		timing = host2 & SDHCI_CTRL_UHS_MASK;
		bits = 1;
		if (host_ctrl & SDHCI_CTRL_8BITBUS)
			bits = 8;
		else if (host_ctrl & SDHCI_CTRL_4BITBUS)
			bits = 4;
		rate = "SDR";
		if ((timing == SDHCI_CTRL_UHS_DDR50)
			|| (timing == SDHCI_CTRL_HS400))
			rate = "DDR";
		sdhc_debug("SDHCI bus width: %d bit%s %s\n", bits,
			(bits != 1) ? "s" : "", rate);
	}
}
예제 #9
0
static void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask)
{
    if (sdhci_readw(host, SDHCI_CLOCK_CONTROL) == 0)
        sdhci_writew(host, 0xBC01, SDHCI_CLOCK_CONTROL);

    sdhci_reset(host, mask);
}
예제 #10
0
static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
{
	u16 ctrl_2;

	/*
	 * Set V18_EN -- UHS modes do not work without this.
	 * does not change signaling voltage
	 */
	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);

	/* Select Bus Speed Mode for host */
	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
	switch (uhs) {
	case MMC_TIMING_UHS_SDR12:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
		break;
	case MMC_TIMING_UHS_SDR25:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
		break;
	case MMC_TIMING_UHS_SDR50:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
		break;
	case MMC_TIMING_UHS_SDR104:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
		break;
	case MMC_TIMING_UHS_DDR50:
		ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
		break;
	}

	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
	dev_dbg(mmc_dev(host->mmc),
		"%s uhs = %d, ctrl_2 = %04X\n",
		__func__, uhs, ctrl_2);
}
예제 #11
0
파일: sdhci-s3c.c 프로젝트: AllenWeb/linux
/* sdhci_cmu_set_clock - callback on clock change.*/
static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
{
	struct sdhci_s3c *ourhost = to_s3c(host);
	unsigned long timeout;
	u16 clk = 0;

	/* don't bother if the clock is going off */
	if (clock == 0)
		return;

	sdhci_s3c_set_clock(host, clock);

	clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);

	host->clock = clock;

	clk = SDHCI_CLOCK_INT_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

	/* Wait max 20 ms */
	timeout = 20;
	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
		& SDHCI_CLOCK_INT_STABLE)) {
		if (timeout == 0) {
			printk(KERN_ERR "%s: Internal clock never "
				"stabilised.\n", mmc_hostname(host->mmc));
			return;
		}
		timeout--;
		mdelay(1);
	}

	clk |= SDHCI_CLOCK_CARD_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
}
예제 #12
0
static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
	u16 ctrl_2;

	/*
	 * Set V18_EN -- UHS modes do not work without this.
	 * does not change signaling voltage
	 */
	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);

	/* Select Bus Speed Mode for host */
	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
	switch (uhs) {
	case MMC_TIMING_UHS_SDR12:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
		break;
	case MMC_TIMING_UHS_SDR25:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
		break;
	case MMC_TIMING_UHS_SDR50:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
		break;
	case MMC_TIMING_UHS_SDR104:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
		break;
	case MMC_TIMING_MMC_DDR52:
	case MMC_TIMING_UHS_DDR50:
		ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
		break;
	}

	/*
	 * Update SDIO3 Configuration register according to erratum
	 * FE-2946959
	 */
	if (pxa->sdio3_conf_reg) {
		u8 reg_val  = readb(pxa->sdio3_conf_reg);

		if (uhs == MMC_TIMING_UHS_SDR50 ||
		    uhs == MMC_TIMING_UHS_DDR50) {
			reg_val &= ~SDIO3_CONF_CLK_INV;
			reg_val |= SDIO3_CONF_SD_FB_CLK;
		} else if (uhs == MMC_TIMING_MMC_HS) {
			reg_val &= ~SDIO3_CONF_CLK_INV;
			reg_val &= ~SDIO3_CONF_SD_FB_CLK;
		} else {
			reg_val |= SDIO3_CONF_CLK_INV;
			reg_val &= ~SDIO3_CONF_SD_FB_CLK;
		}
		writeb(reg_val, pxa->sdio3_conf_reg);
	}

	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
	dev_dbg(mmc_dev(host->mmc),
		"%s uhs = %d, ctrl_2 = %04X\n",
		__func__, uhs, ctrl_2);
}
예제 #13
0
파일: sdhci.c 프로젝트: sky8336/mn201307
static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
{
	struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
	unsigned int div, clk, timeout;

	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);

	if (clock == 0)
		return 0;
	if(host->clock == clock)
		return 0;

	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
		/* Version 3.00 divisors must be a multiple of 2. */
		if (mmc->f_max <= clock)
			div = 1;
		else {
			for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
				if ((mmc->f_max / div) <= clock)
					break;
			}
		}
	} else {
		/* Version 2.00 divisors must be a power of 2. */
		for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
			if ((mmc->f_max / div) <= clock)
				break;
		}
	}
	div >>= 1;
	div = div -1;
	if (host->set_clock)
		host->set_clock(host->index, div);
	clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
	clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
		<< SDHCI_DIVIDER_HI_SHIFT;
	clk |= SDHCI_CLOCK_INT_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

	host->clock = clock;

	/* Wait max 20 ms */
	timeout = 20;
	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
		& SDHCI_CLOCK_INT_STABLE)) {
		if (timeout == 0) {
			errorf("%s: Internal clock never stabilised.\n",
			       __func__);
			return -1;
		}
		timeout--;
		udelay(1000);
	}

	clk |= SDHCI_CLOCK_CARD_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
	return 0;
}
예제 #14
0
static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock)
{
	u16 clk;
	unsigned long timeout;

	host->mmc->actual_clock = 0;

	/*
	 * There is no requirement to disable the internal clock before
	 * changing the SD clock configuration. Moreover, disabling the
	 * internal clock, changing the configuration and re-enabling the
	 * internal clock causes some bugs. It can prevent to get the internal
	 * clock stable flag ready and an unexpected switch to the base clock
	 * when using presets.
	 */
	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
	clk &= SDHCI_CLOCK_INT_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

	if (clock == 0)
		return;

	clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);

	clk |= SDHCI_CLOCK_INT_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

	/* Wait max 20 ms */
	timeout = 20;
	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
		& SDHCI_CLOCK_INT_STABLE)) {
		if (timeout == 0) {
			pr_err("%s: Internal clock never stabilised.\n",
			       mmc_hostname(host->mmc));
			return;
		}
		timeout--;
		mdelay(1);
	}

	clk |= SDHCI_CLOCK_CARD_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
}
예제 #15
0
static void sdhci_dumpregs_err(struct sdhci_host *host)
{
	printf("sdhci: ============== REGISTER DUMP ==============\n");
	printf("sdhci: SDHCI_DMA_ADDRESS:\t0x%08x\n",
		sdhci_readl(host, SDHCI_DMA_ADDRESS));
	printf("sdhci: SDHCI_BLOCK_SIZE:\t0x%08x\n",
		sdhci_readl(host, SDHCI_BLOCK_SIZE));
	printf("sdhci: SDHCI_ARGUMENT:\t\t0x%08x\n",
		sdhci_readl(host, SDHCI_ARGUMENT));
	printf("sdhci: SDHCI_TRANSFER_MODE:\t0x%08x\n",
		sdhci_readl(host, SDHCI_TRANSFER_MODE));
	printf("sdhci: SDHCI_COMMAND:\t\t0x%08x\n",
		sdhci_readw(host, SDHCI_COMMAND));
	printf("sdhci: SDHCI_RESPONSE0:\t\t0x%08x\n",
		sdhci_readl(host, SDHCI_RESPONSE));
	printf("sdhci: SDHCI_RESPONSE1:\t\t0x%08x\n",
		sdhci_readl(host, SDHCI_RESPONSE + 0x4));
	printf("sdhci: SDHCI_RESPONSE2:\t\t0x%08x\n",
		sdhci_readl(host, SDHCI_RESPONSE + 0x8));
	printf("sdhci: SDHCI_RESPONSE3:\t\t0x%08x\n",
		sdhci_readl(host, SDHCI_RESPONSE + 0xC));
	printf("sdhci: SDHCI_BUFFER:\t\t0x%08x\n",
		sdhci_readl(host, SDHCI_BUFFER));
	printf("sdhci: SDHCI_PRESENT_STATE:\t0x%08x\n",
		sdhci_readl(host, SDHCI_PRESENT_STATE));
	printf("sdhci: SDHCI_HOST_CONTROL:\t0x%08x\n",
		sdhci_readl(host, SDHCI_HOST_CONTROL));
	printf("sdhci: SDHCI_CLOCK_CONTROL:\t0x%08x\n",
		sdhci_readl(host, SDHCI_CLOCK_CONTROL));
	printf("sdhci: SDHCI_INT_STATUS:\t0x%08x\n",
		sdhci_readl(host, SDHCI_INT_STATUS));
	printf("sdhci: SDHCI_INT_ENABLE:\t0x%08x\n",
		sdhci_readl(host, SDHCI_INT_ENABLE));
	printf("sdhci: SDHCI_SIGNAL_ENABLE:\t0x%08x\n",
		sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
	printf("sdhci: SDHCI_ACMD12_ERR:\t0x%08x\n",
		sdhci_readl(host, SDHCI_ACMD12_ERR));
	printf("sdhci: SDHCI_CAPABILITIES:\t0x%08x\n",
		sdhci_readl(host, SDHCI_CAPABILITIES));
	printf("sdhci: SDHCI_CAPABILITIES_1:\t0x%08x\n",
		sdhci_readl(host, SDHCI_CAPABILITIES_1));
	printf("sdhci: SDHCI_MAX_CURRENT:\t0x%08x\n",
		sdhci_readl(host, SDHCI_MAX_CURRENT));
	printf("sdhci: SDHCI_SET_ACMD12_ERROR:\t0x%08x\n",
		sdhci_readl(host, SDHCI_SET_ACMD12_ERROR));
	printf("sdhci: SDHCI_ADMA_ERROR:\t0x%08x\n",
		sdhci_readl(host, SDHCI_ADMA_ERROR));
	printf("sdhci: SDHCI_ADMA_ADDRESS:\t0x%08x\n",
		sdhci_readl(host, SDHCI_ADMA_ADDRESS));
	printf("sdhci: SDHCI_SLOT_INT_STATUS:\t0x%08x\n",
		sdhci_readl(host, SDHCI_SLOT_INT_STATUS));
	printf("sdhci: ===========================================\n");
}
예제 #16
0
static int arasan_phy_read(struct sdhci_host *host, u8 offset, u8 *data)
{
	int ret;

	sdhci_writew(host, 0, PHY_DAT_REG);
	sdhci_writew(host, offset, PHY_ADDR_REG);
	ret = arasan_phy_addr_poll(host, PHY_ADDR_REG, PHY_BUSY);

	/* Masking valid data bits */
	*data = sdhci_readw(host, PHY_DAT_REG) & DATA_MASK;
	return ret;
}
static void pxav3_clk_gate_auto(struct sdhci_host *host, unsigned int ctrl)
{
	u16 tmp;

	tmp = sdhci_readw(host, SD_FIFO_PARAM);
	tmp &= ~PAD_CLK_GATE_MASK;
	sdhci_writew(host, tmp, SD_FIFO_PARAM);

	/*
	 * FIXME: according to spec, bit SDHCI_CTRL_ASYNC_INT
	 * should be used to deliver async interrupt requested by sdio device
	 * rather than auto clock gate. But current host controller use this
	 * bit to enable/disable auto clock gate.
	 */
	tmp = sdhci_readw(host, SDHCI_HOST_CONTROL2);
	if (ctrl)
		tmp |= SDHCI_CTRL_ASYNC_INT;
	else
		tmp &= ~SDHCI_CTRL_ASYNC_INT;
	sdhci_writew(host, tmp, SDHCI_HOST_CONTROL2);
}
예제 #18
0
static int arasan_sdhci_probe(struct udevice *dev)
{
	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
	struct sdhci_host *host = dev_get_priv(dev);

	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
		       SDHCI_QUIRK_BROKEN_R1B;
	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);

	add_sdhci(host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, 0);

	upriv->mmc = host->mmc;

	return 0;
}
예제 #19
0
static int arasan_phy_addr_poll(struct sdhci_host *host, u32 offset, u32 mask)
{
	ktime_t timeout = ktime_add_us(ktime_get(), 100);
	bool failed;
	u8 val = 0;

	while (1) {
		failed = ktime_after(ktime_get(), timeout);
		val = sdhci_readw(host, PHY_ADDR_REG);
		if (!(val & mask))
			return 0;
		if (failed)
			return -EBUSY;
	}
}
예제 #20
0
static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
{
	struct sdhci_host *host = mmc->priv;
	unsigned int div, clk = 0, timeout;
	u32 reg;

	while (sdhci_readl(host, SDHCI_PRESENT_STATE) & (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT))
		;

	reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
	reg &= ~SDHCI_CLOCK_CARD_EN;
	sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);

	if (clock == 0)
		return 0;

	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
		/*
		 * Check if the Host Controller supports Programmable Clock
		 * Mode.
		 */
		if (host->clk_mul) {
			for (div = 1; div <= 1024; div++) {
				if ((mmc->cfg->f_max / div) <= clock)
					break;
			}

			/*
			 * Set Programmable Clock Mode in the Clock
			 * Control register.
			 */
			clk = SDHCI_PROG_CLOCK_MODE;
			div--;
		} else {
			/* Version 3.00 divisors must be a multiple of 2. */
			if (mmc->cfg->f_max <= clock) {
				div = 1;
			} else {
				for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
					if ((mmc->cfg->f_max / div) <= clock)
						break;
				}
			}
			div >>= 1;
		}
	} else {
		/* Version 2.00 divisors must be a power of 2. */
		for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
예제 #21
0
파일: sdhci-msm.c 프로젝트: AK101111/linux
static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
					unsigned int uhs)
{
	struct mmc_host *mmc = host->mmc;
	u16 ctrl_2;

	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
	/* Select Bus Speed Mode for host */
	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
	switch (uhs) {
	case MMC_TIMING_UHS_SDR12:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
		break;
	case MMC_TIMING_UHS_SDR25:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
		break;
	case MMC_TIMING_UHS_SDR50:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
		break;
	case MMC_TIMING_MMC_HS200:
	case MMC_TIMING_UHS_SDR104:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
		break;
	case MMC_TIMING_UHS_DDR50:
	case MMC_TIMING_MMC_DDR52:
		ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
		break;
	}

	/*
	 * When clock frequency is less than 100MHz, the feedback clock must be
	 * provided and DLL must not be used so that tuning can be skipped. To
	 * provide feedback clock, the mode selection can be any value less
	 * than 3'b011 in bits [2:0] of HOST CONTROL2 register.
	 */
	if (host->clock <= 100000000 &&
	    (uhs == MMC_TIMING_MMC_HS400 ||
	     uhs == MMC_TIMING_MMC_HS200 ||
	     uhs == MMC_TIMING_UHS_SDR104))
		ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;

	dev_dbg(mmc_dev(mmc), "%s: clock=%u uhs=%u ctrl_2=0x%x\n",
		mmc_hostname(host->mmc), host->clock, uhs, ctrl_2);
	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
}
예제 #22
0
void sdhci_dumpregs(struct sdhci_host *host)
{
	int i = 0;
	printf(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n");
	printf(KERN_DEBUG DRIVER_NAME ":AHB CTRL 0x%08x\n", *((unsigned int*)0x20900200));
#if 1
	for(i = 0; i < MAX_DUMP_NUM; i++){
		printf(KERN_DEBUG DRIVER_NAME ": address 0x%08x | value 0x%08x\n", host->ioaddr + i*4, sdhci_readl(host, i*4));
	}
#endif

	printf(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version:  0x%08x\n",
			sdhci_readl(host, SDHCI_DMA_ADDRESS),
			sdhci_readw(host, SDHCI_HOST_VERSION));
	printf(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt:  0x%08x\n",
			sdhci_readw(host, SDHCI_BLOCK_SIZE),
			sdhci_readw(host, SDHCI_BLOCK_COUNT));
	printf(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
			sdhci_readl(host, SDHCI_ARGUMENT),
			sdhci_readw(host, SDHCI_TRANSFER_MODE));
	printf(KERN_DEBUG DRIVER_NAME ": Present:  0x%08x | Host ctl: 0x%08x\n",
			sdhci_readl(host, SDHCI_PRESENT_STATE),
			sdhci_readb(host, SDHCI_HOST_CONTROL));
	printf(KERN_DEBUG DRIVER_NAME ": Power:    0x%08x | Blk gap:  0x%08x\n",
			sdhci_readb(host, SDHCI_POWER_CONTROL),
			sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL));
	printf(KERN_DEBUG DRIVER_NAME ": Wake-up:  0x%08x | Clock:    0x%08x\n",
			sdhci_readb(host, SDHCI_WAKE_UP_CONTROL),
			sdhci_readw(host, SDHCI_CLOCK_CONTROL));
	printf(KERN_DEBUG DRIVER_NAME ": Timeout:  0x%08x | Int stat: 0x%08x\n",
			sdhci_readb(host, SDHCI_TIMEOUT_CONTROL),
			sdhci_readl(host, SDHCI_INT_STATUS));
	printf(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
			sdhci_readl(host, SDHCI_INT_ENABLE),
			sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
	printf(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
			sdhci_readw(host, SDHCI_ACMD12_ERR),
			sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
	printf(KERN_DEBUG DRIVER_NAME ": Caps:     0x%08x | Max curr: 0x%08x\n",
			sdhci_readl(host, SDHCI_CAPABILITIES),
			sdhci_readl(host, SDHCI_MAX_CURRENT));

		printf(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
				readl(host->ioaddr + SDHCI_ADMA_ERROR),
				readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
	printf(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
}
예제 #23
0
static int s5p_sdhci_core_init(struct sdhci_host *host)
{
	host->name = S5P_NAME;

	host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE |
		SDHCI_QUIRK_BROKEN_R1B | 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;

	if (host->bus_width == 8)
		host->host_caps |= MMC_MODE_8BIT;

	return add_sdhci(host, 52000000, 400000);
}
예제 #24
0
int zynq_sdhci_init(phys_addr_t regbase)
{
	struct sdhci_host *host = NULL;

	host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
	if (!host) {
		printf("zynq_sdhci_init: sdhci_host malloc fail\n");
		return 1;
	}

	host->name = "zynq_sdhci";
	host->ioaddr = (void *)regbase;
	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
		       SDHCI_QUIRK_BROKEN_R1B;
	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);

	add_sdhci(host, 52000000, 52000000 >> 9);
	return 0;
}
예제 #25
0
static void sdhci_snps_set_clock(struct sdhci_host *host, unsigned int clock)
{
	u16 clk;
	u32 reg, vendor_ptr;

	vendor_ptr = sdhci_readw(host, SDHCI_VENDOR_PTR_R);

	/* Disable software managed rx tuning */
	reg = sdhci_readl(host, (SDHC_AT_CTRL_R + vendor_ptr));
	reg &= ~SDHC_SW_TUNE_EN;
	sdhci_writel(host, reg, (SDHC_AT_CTRL_R + vendor_ptr));

	if (clock <= 52000000) {
		sdhci_set_clock(host, clock);
	} else {
		/* Assert reset to MMCM */
		reg = sdhci_readl(host, (SDHC_GPIO_OUT + vendor_ptr));
		reg |= SDHC_CCLK_MMCM_RST;
		sdhci_writel(host, reg, (SDHC_GPIO_OUT + vendor_ptr));

		/* Configure MMCM */
		if (clock == 100000000) {
			sdhci_writel(host, DIV_REG_100_MHZ, SDHC_MMCM_DIV_REG);
			sdhci_writel(host, CLKFBOUT_100_MHZ,
					SDHC_MMCM_CLKFBOUT);
		} else {
			sdhci_writel(host, DIV_REG_200_MHZ, SDHC_MMCM_DIV_REG);
			sdhci_writel(host, CLKFBOUT_200_MHZ,
					SDHC_MMCM_CLKFBOUT);
		}

		/* De-assert reset to MMCM */
		reg = sdhci_readl(host, (SDHC_GPIO_OUT + vendor_ptr));
		reg &= ~SDHC_CCLK_MMCM_RST;
		sdhci_writel(host, reg, (SDHC_GPIO_OUT + vendor_ptr));

		/* Enable clock */
		clk = SDHCI_PROG_CLOCK_MODE | SDHCI_CLOCK_INT_EN |
			SDHCI_CLOCK_CARD_EN;
		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
	}
}
예제 #26
0
static void sdhci_sprd_set_uhs_signaling(struct sdhci_host *host,
					 unsigned int timing)
{
	u16 ctrl_2;

	if (timing == host->timing)
		return;

	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
	/* Select Bus Speed Mode for host */
	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
	switch (timing) {
	case MMC_TIMING_UHS_SDR12:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
		break;
	case MMC_TIMING_MMC_HS:
	case MMC_TIMING_SD_HS:
	case MMC_TIMING_UHS_SDR25:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
		break;
	case MMC_TIMING_UHS_SDR50:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
		break;
	case MMC_TIMING_UHS_SDR104:
		ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
		break;
	case MMC_TIMING_UHS_DDR50:
	case MMC_TIMING_MMC_DDR52:
		ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
		break;
	case MMC_TIMING_MMC_HS200:
		ctrl_2 |= SDHCI_SPRD_CTRL_HS200;
		break;
	case MMC_TIMING_MMC_HS400:
		ctrl_2 |= SDHCI_SPRD_CTRL_HS400;
		break;
	default:
		break;
	}

	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
}
예제 #27
0
static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool enable)
{
	bool status;
	u32 reg;

	reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
	status = !!(reg & SDHCI_CLOCK_CARD_EN);

	if (status == enable)
		return status;

	if (enable)
		reg |= SDHCI_CLOCK_CARD_EN;
	else
		reg &= ~SDHCI_CLOCK_CARD_EN;

	sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);

	return status;
}
예제 #28
0
int zynq_sdhci_init(u32 regbase)
{
	struct sdhci_host *host = NULL;

	host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
	if (!host) {
		printf("zynq_sdhci_init: sdhci_host malloc fail\n");
		return 1;
	}

	host->name = "zynq_sdhci";
	host->ioaddr = (void *)regbase;
	host->quirks = SDHCI_QUIRK_NO_CD | SDHCI_QUIRK_WAIT_SEND_CMD;
	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);

	host->host_caps = MMC_MODE_HC;

	add_sdhci(host, 52000000, 52000000 >> 9);
	return 0;
}
예제 #29
0
static void sdhci_display_clock(struct sdhci_ctrlr *sdhci_ctrlr)
{
	if (IS_ENABLED(CONFIG_SDHC_DEBUG)) {
		uint16_t clk_ctrl;
		uint32_t clock;
		uint32_t divisor;

		/* Display the clock */
		clk_ctrl = sdhci_readw(sdhci_ctrlr, SDHCI_CLOCK_CONTROL);
		sdhc_debug("SDHCI bus clock: ");
		if (clk_ctrl & SDHCI_CLOCK_CARD_EN) {
			divisor = (clk_ctrl >> SDHCI_DIVIDER_SHIFT)
				& SDHCI_DIV_MASK;
			divisor |= ((clk_ctrl >> SDHCI_DIVIDER_SHIFT)
				<< SDHCI_DIV_MASK_LEN) & SDHCI_DIV_HI_MASK;
			divisor <<= 1;
			clock = sdhci_ctrlr->sd_mmc_ctrlr.clock_base;
			if (divisor)
				clock /= divisor;
			sdhc_debug("%d.%03d MHz\n", clock / 1000000,
				(clock / 1000) % 1000);
		} else
예제 #30
0
/*
 * This driver has only been tested with eMMC devices; SD devices may
 * not work.
 */
int bcmstb_sdhci_init(phys_addr_t regbase)
{
	struct sdhci_host *host = NULL;

	host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
	if (!host) {
		printf("%s: Failed to allocate memory\n", __func__);
		return 1;
	}
	memset(host, 0, sizeof(*host));

	host->name = BCMSTB_SDHCI_NAME;
	host->ioaddr = (void *)regbase;
	host->quirks = 0;

	host->cfg.part_type = PART_TYPE_DOS;

	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);

	return add_sdhci(host,
			 BCMSTB_SDHCI_MAXIMUM_CLOCK_FREQUENCY,
			 BCMSTB_SDHCI_MINIMUM_CLOCK_FREQUENCY);
}