diff --git a/src/cpu/samsung/exynos5420/clk.h b/src/cpu/samsung/exynos5420/clk.h index 8e2f9edb01..a4e538d370 100644 --- a/src/cpu/samsung/exynos5420/clk.h +++ b/src/cpu/samsung/exynos5420/clk.h @@ -85,6 +85,15 @@ unsigned long clock_get_periph_rate(enum periph_id peripheral); */ int clock_set_mshci(enum periph_id peripheral); +/* + * Set dwmci controller instances clock drivder + * + * @param enum periph_id instance of the dwmci controller + * + * Return 0 if ok else -1 + */ +int clock_set_dwmci(enum periph_id peripheral); + /* * Sets the epll clockrate * diff --git a/src/cpu/samsung/exynos5420/clock.c b/src/cpu/samsung/exynos5420/clock.c index 8c4baf8cc7..694f024ca8 100644 --- a/src/cpu/samsung/exynos5420/clock.c +++ b/src/cpu/samsung/exynos5420/clock.c @@ -66,6 +66,11 @@ static struct st_epll_con_val epll_div[] = { { 180633600, 0, 45, 3, 1, 10381 } }; +static inline unsigned long div_round_up(unsigned int n, unsigned int d) +{ + return (n + d - 1) / d; +} + /* exynos5: return pll clock frequency */ unsigned long get_pll_clk(int pllreg) { @@ -177,13 +182,6 @@ unsigned long clock_get_periph_rate(enum periph_id peripheral) src = readl(&clk->clk_src_isp); div = readl(&clk->clk_div_isp1); break; - case PERIPH_ID_SDMMC0: - case PERIPH_ID_SDMMC1: - case PERIPH_ID_SDMMC2: - case PERIPH_ID_SDMMC3: - src = readl(&clk->clk_src_fsys); - div = readl(&clk->clk_div_fsys1); - break; case PERIPH_ID_I2C0: case PERIPH_ID_I2C1: case PERIPH_ID_I2C2: @@ -250,6 +248,35 @@ unsigned long get_arm_clk(void) return armclk; } +/* exynos5: get the mmc clock */ +static unsigned long get_mmc_clk(int dev_index) +{ + struct exynos5420_clock *clk = samsung_get_base_clock(); + unsigned long uclk, sclk; + unsigned int sel, ratio; + int shift = 0; + + sel = readl(&clk->clk_src_fsys); + sel = (sel >> ((dev_index * 4) + 8)) & 0x7; + + if (sel == 0x3) + sclk = get_pll_clk(MPLL); + else if (sel == 0x6) + sclk = get_pll_clk(EPLL); + else + return 0; + + ratio = readl(&clk->clk_div_fsys1); + + shift = dev_index * 10; + + ratio = (ratio >> shift) & 0x3ff; + uclk = (sclk / (ratio + 1)); + printk(BIOS_DEBUG, "%s(%d): %lu\n", __func__, dev_index, uclk); + + return uclk; +} + /* exynos5: set the mmc clock */ void set_mmc_clk(int dev_index, unsigned int div) { @@ -266,6 +293,24 @@ void set_mmc_clk(int dev_index, unsigned int div) writel(val, addr); } +/* Set DW MMC Controller clock */ +int clock_set_dwmci(enum periph_id peripheral) +{ + /* Request MMC clock value to 52MHz. */ + const unsigned long freq = 52000000; + unsigned long sclk, div; + int device_index = (int)peripheral - (int)PERIPH_ID_SDMMC0; + + ASSERT(device_index >= 0 && device_index < 4); + sclk = get_mmc_clk(device_index); + if (!sclk) { + return -1; + } + div = div_round_up(sclk, freq); + set_mmc_clk(device_index, div); + return 0; +} + void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor) { struct exynos5420_clock *clk = samsung_get_base_clock(); diff --git a/src/cpu/samsung/exynos5420/pinmux.c b/src/cpu/samsung/exynos5420/pinmux.c index 566ba606a3..843a6db723 100644 --- a/src/cpu/samsung/exynos5420/pinmux.c +++ b/src/cpu/samsung/exynos5420/pinmux.c @@ -80,8 +80,8 @@ static void exynos_pinmux_sdmmc(int start, int start_ext) void exynos_pinmux_sdmmc0(void) { - gpio_set_pull(GPIO_C02, GPIO_PULL_UP); exynos_pinmux_sdmmc(GPIO_C00, GPIO_C30); + gpio_set_pull(GPIO_C02, GPIO_PULL_UP); } void exynos_pinmux_sdmmc1(void) diff --git a/src/mainboard/google/pit/romstage.c b/src/mainboard/google/pit/romstage.c index 765ff82fa4..7ead3c9353 100644 --- a/src/mainboard/google/pit/romstage.c +++ b/src/mainboard/google/pit/romstage.c @@ -113,17 +113,12 @@ static void setup_power(int is_resume) static void setup_storage(void) { /* MMC0: Fixed, 8 bit mode, connected with GPIO. */ - if (clock_set_mshci(PERIPH_ID_SDMMC0)) + if (clock_set_dwmci(PERIPH_ID_SDMMC0)) printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__); - if (gpio_direction_output(MMC0_GPIO_PIN, 1)) { - printk(BIOS_CRIT, "%s: Unable to power on MMC0.\n", __func__); - } - gpio_set_pull(MMC0_GPIO_PIN, GPIO_PULL_NONE); - gpio_set_drv(MMC0_GPIO_PIN, GPIO_DRV_4X); exynos_pinmux_sdmmc0(); /* MMC2: Removable, 4 bit mode, no GPIO. */ - clock_set_mshci(PERIPH_ID_SDMMC2); + clock_set_dwmci(PERIPH_ID_SDMMC2); exynos_pinmux_sdmmc2(); }