Exemplo n.º 1
0
/*
 * This function adds the mmc channel to be registered with mmc core.
 * index -	mmc channel number.
 * regbase -	register base address of mmc channel specified in 'index'.
 * bus_width -	operating bus width of mmc channel specified in 'index'.
 * clksel -	value to be written into CLKSEL register in case of FDT.
 *		NULL in case od non-FDT.
 */
int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)
{
	struct dwmci_host *host = NULL;
	unsigned int div;
	unsigned long freq, sclk;
	host = malloc(sizeof(struct dwmci_host));
	if (!host) {
		printf("dwmci_host malloc fail!\n");
		return 1;
	}
	/* request mmc clock vlaue of 52MHz.  */
	freq = 52000000;
	sclk = get_mmc_clk(index);
	div = DIV_ROUND_UP(sclk, freq);
	/* set the clock divisor for mmc */
	set_mmc_clk(index, div);

	host->name = "EXYNOS DWMMC";
	host->ioaddr = (void *)regbase;
	host->buswidth = bus_width;

	if (clksel) {
		host->clksel_val = clksel;
	} else {
		if (0 == index)
			host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;
		if (2 == index)
			host->clksel_val = DWMMC_MMC2_CLKSEL_VAL;
	}

	host->clksel = exynos_dwmci_clksel;
	host->dev_index = index;
	host->mmc_clk = exynos_dwmci_get_clk;
	/* Add the mmc channel to be registered with mmc core */
	if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) {
		debug("dwmmc%d registration failed\n", index);
		return -1;
	}
	return 0;
}
Exemplo n.º 2
0
static void mmc_change_clock(struct mmc_host *host, uint clock)
{
	int div;
	unsigned short clk;
	unsigned long timeout;
	unsigned long ctrl2;

	/*
	 * SELBASECLK[5:4]
	 * 00/01 = HCLK
	 * 10 = EPLL
	 * 11 = XTI or XEXTCLK
	 */
	ctrl2 = readl(&host->reg->control2);
	ctrl2 &= ~(3 << 4);
	ctrl2 |= (2 << 4);
	writel(ctrl2, &host->reg->control2);

	writew(0, &host->reg->clkcon);

	/* XXX: we assume that clock is between 40MHz and 50MHz */
	if (clock == 0)
		goto out;
	else if (clock <= 400000)
		div = 0x100;
	else if (clock <= 20000000)
		div = 4;
	else if (clock <= 26000000)
		div = 2;
	else
		div = 1;
	debug("div: %d\n", div);

	div >>= 1;
	/*
	 * CLKCON
	 * SELFREQ[15:8]	: base clock divied by value
	 * ENSDCLK[2]		: SD Clock Enable
	 * STBLINTCLK[1]	: Internal Clock Stable
	 * ENINTCLK[0]		: Internal Clock Enable
	 */
	clk = (div << 8) | (1 << 0);
	writew(clk, &host->reg->clkcon);

	set_mmc_clk(host->dev_index, div);

	/* Wait max 10 ms */
	timeout = 10;
	while (!(readw(&host->reg->clkcon) & (1 << 1))) {
		if (timeout == 0) {
			printf("%s: timeout error\n", __func__);
			return;
		}
		timeout--;
		udelay(1000);
	}

	clk |= (1 << 2);
	writew(clk, &host->reg->clkcon);

out:
	host->clock = clock;
}