/* * 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; }
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; }