diff options
author | Hung-Te Lin <hungte@chromium.org> | 2013-07-03 19:07:21 +0800 |
---|---|---|
committer | Stefan Reinauer <stefan.reinauer@coreboot.org> | 2013-12-12 22:05:52 +0100 |
commit | f6d6e62aaf76ba4bef5e0dcdfc73975c25f5337b (patch) | |
tree | da8e75305c57668ab8496b20f17de53dbc0f7ce4 /src | |
parent | 865912cec083afba64f9ada0a438da8a10daea78 (diff) |
exynos5420: Setup clocks for MMC bus controller.
To configure source clocks on Exynos 5420 for MMC drivers.
Some registers are different from the 5250. FSYS now has two parts
and MMC uses FSYS2. The MMC block uses MPLL as the clock source.
The "high-speed" MMC interface runs as 52MHz, so divider is set
accordingly.
Also, the MMC driver has changed from MSHCI (Mobile Storage Host Controller
Interface) to DWMCI (DesignWare MMC Controller Interface).
Change-Id: I9ba9cf43e2f2dcd9da747888c0c7676bd545177b
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/60858
Reviewed-by: David Hendricks <dhendrix@chromium.org>
Reviewed-on: http://review.coreboot.org/4354
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/cpu/samsung/exynos5420/clk.h | 9 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/clock.c | 59 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/pinmux.c | 2 | ||||
-rw-r--r-- | src/mainboard/google/pit/romstage.c | 9 |
4 files changed, 64 insertions, 15 deletions
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 @@ -86,6 +86,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 * * @param rate Required clock rate to the presacaler in Hz 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(); } |