[U-Boot] [PATCH] Exynos5: Clock: Generic api to set and get clock rate and source

Rajeshwari Birje rajeshwari.birje at gmail.com
Mon Nov 11 14:08:44 CET 2013


Hi All,

This patch is based on:

[U-Boot] [PATCH 00/10 V6] EXYNOS5420: Add SMDK5420 board support

-- 
Regards,
Rajeshwari Shinde

On Mon, Nov 11, 2013 at 6:23 PM, Rajeshwari S Shinde
<rajeshwari.s at samsung.com> wrote:
> This patch implements generic api for exynos5250 and exynos5420.
> These api's set and get clock rate based on the peripheral id.
>
> Signed-off-by: Andrew Bresticker <abrestic at chromium.org>
> Signed-off-by: Rajeshwari S Shinde <rajeshwari.s at samsung.com>
> ---
>  arch/arm/cpu/armv7/exynos/clock.c      | 958 ++++++++++++---------------------
>  arch/arm/include/asm/arch-exynos/clk.h |  30 +-
>  drivers/mmc/exynos_dw_mmc.c            |  15 +-
>  3 files changed, 385 insertions(+), 618 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
> index b52e61a..09e156c 100644
> --- a/arch/arm/cpu/armv7/exynos/clock.c
> +++ b/arch/arm/cpu/armv7/exynos/clock.c
> @@ -16,46 +16,97 @@
>  #define PLL_DIV_65536  65536
>
>  /* *
> - * This structure is to store the src bit, div bit and prediv bit
> - * positions of the peripheral clocks of the src and div registers
> + * This structure store positions of the peripheral clocks
> + * and their source, divider and predivider information.
> + * @periph_id: id of the peripheral
> + * @src_offset: offset of the source register
> + * @div_offset: offset of the divider register
> + * @prediv_offset: offset of the pre divider register
> + * @src_bit: bit location in the source register
> + * @div_bit: bit location in the divider register
> + * @pre_div_bit: bit location in the pre divider register
> + * @src_mask: mask for the source register value
> + * @div_mask: mask for the divider register value
> + * @pre_div_mask: mask for the pre divider register value
>   */
>  struct clk_bit_info {
> +       int32_t periph_id;
> +       int32_t src_offset;
> +       int32_t div_offset;
> +       int32_t prediv_offset;
>         int8_t src_bit;
>         int8_t div_bit;
> -       int8_t prediv_bit;
> +       int8_t pre_div_bit;
> +       int8_t src_mask;
> +       int32_t div_mask;
> +       int32_t pre_div_mask;
>  };
>
> -/* src_bit div_bit prediv_bit */
> -static struct clk_bit_info clk_bit_info[PERIPH_ID_COUNT] = {
> -       {0,     0,      -1},
> -       {4,     4,      -1},
> -       {8,     8,      -1},
> -       {12,    12,     -1},
> -       {0,     0,      8},
> -       {4,     16,     24},
> -       {8,     0,      8},
> -       {12,    16,     24},
> -       {-1,    -1,     -1},
> -       {16,    0,      8},
> -       {20,    16,     24},
> -       {24,    0,      8},
> -       {0,     0,      4},
> -       {4,     12,     16},
> -       {-1,    -1,     -1},
> -       {-1,    -1,     -1},
> -       {-1,    24,     0},
> -       {-1,    24,     0},
> -       {-1,    24,     0},
> -       {-1,    24,     0},
> -       {-1,    24,     0},
> -       {-1,    24,     0},
> -       {-1,    24,     0},
> -       {-1,    24,     0},
> -       {24,    0,      -1},
> -       {24,    0,      -1},
> -       {24,    0,      -1},
> -       {24,    0,      -1},
> -       {24,    0,      -1},
> +static struct clk_bit_info exynos5_bit_info_table[] = {
> +       {PERIPH_ID_UART0, 0x10250, 0x10558, -1, 0, 0, -1, 0xf, 0xf, -1},
> +       {PERIPH_ID_UART1, 0x10250, 0x10558, -1, 4, 4, -1, 0xf, 0xf, -1},
> +       {PERIPH_ID_UART2, 0x10250, 0x10558, -1, 8, 8, -1, 0xf, 0xf, -1},
> +       {PERIPH_ID_UART3, 0x10250, 0x10558, -1, 12, 12, -1, 0xf, 0xf, -1},
> +       {PERIPH_ID_I2C0, -1, 0x10514, 0x10510, -1, 24, 0, -1, 0x7, 0x7},
> +       {PERIPH_ID_I2C1, -1, 0x10514, 0x10510, -1, 24, 0, -1, 0x7, 0x7},
> +       {PERIPH_ID_I2C2, -1, 0x10514, 0x10510, -1, 24, 0, -1, 0x7, 0x7},
> +       {PERIPH_ID_I2C3, -1, 0x10514, 0x10510, -1, 24, 0, -1, 0x7, 0x7},
> +       {PERIPH_ID_I2C4, -1, 0x10514, 0x10510, -1, 24, 0, -1, 0x7, 0x7},
> +       {PERIPH_ID_I2C5, -1, 0x10514, 0x10510, -1, 24, 0, -1, 0x7, 0x7},
> +       {PERIPH_ID_I2C6, -1, 0x10514, 0x10510, -1, 24, 0, -1, 0x7, 0x7},
> +       {PERIPH_ID_I2C7, -1, 0x10514, 0x10510, -1, 24, 0, -1, 0x7, 0x7},
> +       {PERIPH_ID_I2C8, -1, 0x10514, 0x10510, -1, 24, 0, -1, 0x7, 0x7},
> +       {PERIPH_ID_I2C9, -1, 0x10514, 0x10510, -1, 24, 0, -1, 0x7, 0x7},
> +       {PERIPH_ID_I2C10, -1, 0x10514, 0x10510, -1, 24, 0, -1, 0x7, 0x7},
> +       {PERIPH_ID_SPI0, 0x10254, 0x1055c, 0x1055c, 16, 0, 8, 0xf, 0xf, 0xff},
> +       {PERIPH_ID_SPI1, 0x10254, 0x1055c, 0x1055c, 20, 16, 24, 0xf, 0xf, 0xff},
> +       {PERIPH_ID_SPI2, 0x10254, 0x10560, 0x10560, 24, 0, 8, 0xf, 0xf, 0xff},
> +       {PERIPH_ID_SPI3, 0x10270, 0x10580, 0x10580, 0, 0, 4, 0xf, 0xf, 0xff},
> +       {PERIPH_ID_SPI4, 0x10270, 0x10580, 0x10580, 4, 12, 16, 0xf, 0xf, 0xff},
> +       {PERIPH_ID_SDMMC0, 0x10244, 0x1054c, 0x1054c, 0, 0, 8, 0xf, 0xf, 0xff},
> +       {PERIPH_ID_SDMMC1, 0x10244, 0x1054c, 0x1054c, 4, 16, 24, 0xf, 0xf,
> +        0xff},
> +       {PERIPH_ID_SDMMC2, 0x10244, 0x10550, 0x10550, 8, 0, 8, 0xf, 0xf, 0xff},
> +       {PERIPH_ID_SDMMC3, 0x10244, 0x10550, 0x10550, 12, 16, 24, 0xf, 0xf,
> +        0xff},
> +       {PERIPH_ID_PWM0, 0x10250, 0x10564, -1, 24, 0, 0xf, 0xf, -1},
> +       {PERIPH_ID_PWM1, 0x10250, 0x10564, -1, 24, 0, 0xf, 0xf, -1},
> +       {PERIPH_ID_PWM2, 0x10250, 0x10564, -1, 24, 0, 0xf, 0xf, -1},
> +       {PERIPH_ID_PWM3, 0x10250, 0x10564, -1, 24, 0, 0xf, 0xf, -1},
> +       {PERIPH_ID_PWM4, 0x10250, 0x10564, -1, 24, 0, 0xf, 0xf, -1},
> +       {PERIPH_ID_I2S0, 0x10240, 0x10544, -1, 0, 0, -1, 0xf, 0xf, -1},
> +};
> +
> +static struct clk_bit_info exynos5420_bit_info_table[] = {
> +       {PERIPH_ID_UART0, 0x10250, 0x10558, -1, 4, 8, -1, 0x7, 0xf, -1},
> +       {PERIPH_ID_UART1, 0x10250, 0x10558, -1, 8, 12, -1, 0x7, 0xf, -1},
> +       {PERIPH_ID_UART2, 0x10250, 0x10558, -1, 12, 16, -1, 0x7, 0xf, -1},
> +       {PERIPH_ID_UART3, 0x10250, 0x10558, -1, 16, 20, -1, 0x7, 0xf, -1},
> +       {PERIPH_ID_I2C0, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_I2C1, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_I2C2, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_I2C3, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_I2C4, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_I2C5, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_I2C6, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_I2C7, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_I2C8, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_I2C9, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_I2C10, -1, 0x10504, -1, -1, 8, -1, 0x3f, -1, -1},
> +       {PERIPH_ID_SPI0, 0x10254, 0x1055c, 0x10568, 20, 20, 8, 0x7, 0xf, 0xff},
> +       {PERIPH_ID_SPI1, 0x10254, 0x1055c, 0x10568, 24, 24, 16, 0x7, 0xf, 0xff},
> +       {PERIPH_ID_SPI2, 0x10254, 0x1055c, 0x10568, 28, 28, 24, 0x7, 0xf, 0xff},
> +       {PERIPH_ID_SPI3, 0x10270, 0x10584, 0x10584, 12, 16, 0, 0x7, 0xf, 0xff},
> +       {PERIPH_ID_SPI4, 0x10270, 0x10584, 0x10584, 16, 20, 8, 0x7, 0xf, 0xff},
> +       {PERIPH_ID_SDMMC0, 0x10244, 0x1054c, -1, 8, 0, -1, 0x7, 0x3ff, -1},
> +       {PERIPH_ID_SDMMC1, 0x10244, 0x1054c, -1, 12, 10, -1, 0x7, 0x3ff, -1},
> +       {PERIPH_ID_SDMMC2, 0x10244, 0x1054c, -1, 16, 20, -1, 0x7, 0x3ff, -1},
> +       {PERIPH_ID_PWM0, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_PWM1, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_PWM2, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_PWM3, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_PWM4, -1, 0x10504, -1, -1, 8, -1, -1, 0x3f, -1},
> +       {PERIPH_ID_I2S0, 0x10240, 0x10544, -1, 28, 20, -1, 0x7, 0xf, -1},
>  };
>
>  /* Epll Clock division values to achive different frequency output */
> @@ -69,6 +120,27 @@ static struct set_epll_con_val exynos5_epll_div[] = {
>         { 180633600, 0, 45, 3, 1, 10381 }
>  };
>
> +static struct clk_bit_info *get_table_index(int periph_id)
> +{
> +       int i, count;
> +       struct clk_bit_info *table;
> +
> +       if (proid_is_exynos5420()) {
> +               table = exynos5420_bit_info_table;
> +               count = ARRAY_SIZE(exynos5420_bit_info_table);
> +       } else {
> +               table = exynos5_bit_info_table;
> +               count = ARRAY_SIZE(exynos5_bit_info_table);
> +       }
> +
> +       for (i = 0; i < count; i++) {
> +               if ((table + i)->periph_id == periph_id)
> +                       return table + i;
> +       }
> +
> +       return NULL;
> +}
> +
>  /* exynos: return pll clock frequency */
>  static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
>  {
> @@ -258,111 +330,6 @@ static unsigned long exynos5_get_pll_clk(int pllreg)
>         return fout;
>  }
>
> -static unsigned long exynos5_get_periph_rate(int peripheral)
> -{
> -       struct clk_bit_info *bit_info = &clk_bit_info[peripheral];
> -       unsigned long sclk, sub_clk;
> -       unsigned int src, div, sub_div;
> -       struct exynos5_clock *clk =
> -                       (struct exynos5_clock *)samsung_get_base_clock();
> -
> -       switch (peripheral) {
> -       case PERIPH_ID_UART0:
> -       case PERIPH_ID_UART1:
> -       case PERIPH_ID_UART2:
> -       case PERIPH_ID_UART3:
> -               src = readl(&clk->src_peric0);
> -               div = readl(&clk->div_peric0);
> -               break;
> -       case PERIPH_ID_PWM0:
> -       case PERIPH_ID_PWM1:
> -       case PERIPH_ID_PWM2:
> -       case PERIPH_ID_PWM3:
> -       case PERIPH_ID_PWM4:
> -               src = readl(&clk->src_peric0);
> -               div = readl(&clk->div_peric3);
> -               break;
> -       case PERIPH_ID_I2S0:
> -               src = readl(&clk->src_mau);
> -               div = readl(&clk->div_mau);
> -       case PERIPH_ID_SPI0:
> -       case PERIPH_ID_SPI1:
> -               src = readl(&clk->src_peric1);
> -               div = readl(&clk->div_peric1);
> -               break;
> -       case PERIPH_ID_SPI2:
> -               src = readl(&clk->src_peric1);
> -               div = readl(&clk->div_peric2);
> -               break;
> -       case PERIPH_ID_SPI3:
> -       case PERIPH_ID_SPI4:
> -               src = readl(&clk->sclk_src_isp);
> -               div = readl(&clk->sclk_div_isp);
> -               break;
> -       case PERIPH_ID_SDMMC0:
> -       case PERIPH_ID_SDMMC1:
> -       case PERIPH_ID_SDMMC2:
> -       case PERIPH_ID_SDMMC3:
> -               src = readl(&clk->src_fsys);
> -               div = readl(&clk->div_fsys1);
> -               break;
> -       case PERIPH_ID_I2C0:
> -       case PERIPH_ID_I2C1:
> -       case PERIPH_ID_I2C2:
> -       case PERIPH_ID_I2C3:
> -       case PERIPH_ID_I2C4:
> -       case PERIPH_ID_I2C5:
> -       case PERIPH_ID_I2C6:
> -       case PERIPH_ID_I2C7:
> -               sclk = exynos5_get_pll_clk(MPLL);
> -               sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
> -                                                               & 0x7) + 1;
> -               div = ((readl(&clk->div_top0) >> bit_info->prediv_bit)
> -                                                               & 0x7) + 1;
> -               return (sclk / sub_div) / div;
> -       default:
> -               debug("%s: invalid peripheral %d", __func__, peripheral);
> -               return -1;
> -       };
> -
> -       src = (src >> bit_info->src_bit) & 0xf;
> -
> -       switch (src) {
> -       case EXYNOS_SRC_MPLL:
> -               sclk = exynos5_get_pll_clk(MPLL);
> -               break;
> -       case EXYNOS_SRC_EPLL:
> -               sclk = exynos5_get_pll_clk(EPLL);
> -               break;
> -       case EXYNOS_SRC_VPLL:
> -               sclk = exynos5_get_pll_clk(VPLL);
> -               break;
> -       default:
> -               return 0;
> -       }
> -
> -       /* Ratio clock division for this peripheral */
> -       sub_div = (div >> bit_info->div_bit) & 0xf;
> -       sub_clk = sclk / (sub_div + 1);
> -
> -       /* Pre-ratio clock division for SDMMC0 and 2 */
> -       if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) {
> -               div = (div >> bit_info->prediv_bit) & 0xff;
> -               return sub_clk / (div + 1);
> -       }
> -
> -       return sub_clk;
> -}
> -
> -unsigned long clock_get_periph_rate(int peripheral)
> -{
> -       if (cpu_is_exynos5())
> -               return exynos5_get_periph_rate(peripheral);
> -       else
> -               return 0;
> -}
> -
> -/* exynos5420: return pll clock frequency */
>  static unsigned long exynos5420_get_pll_clk(int pllreg)
>  {
>         struct exynos5420_clock *clk =
> @@ -391,6 +358,15 @@ static unsigned long exynos5420_get_pll_clk(int pllreg)
>                 r = readl(&clk->rpll_con0);
>                 k = readl(&clk->rpll_con1);
>                 break;
> +       case SPLL:
> +               r = readl(&clk->spll_con0);
> +               break;
> +       case CPLL:
> +               r = readl(&clk->cpll_con0);
> +               break;
> +       case DPLL:
> +               r = readl(&clk->dpll_con0);
> +               break;
>         default:
>                 printf("Unsupported PLL (%d)\n", pllreg);
>                 return 0;
> @@ -399,6 +375,240 @@ static unsigned long exynos5420_get_pll_clk(int pllreg)
>         return exynos_get_pll_clk(pllreg, r, k);
>  }
>
> +static unsigned long exynos5420_src_clk(int peripheral)
> +{
> +       unsigned int src;
> +       unsigned long sclk;
> +       unsigned long clk_base = samsung_get_base_clock();
> +       struct clk_bit_info *bit_info = get_table_index(peripheral);
> +
> +       /*
> +        * I2C and PWM clocks are parented by aclk66_peric which is
> +        * parented by CPLL (initialized in exynos5420_clock_init()).
> +        */
> +       if (bit_info->src_offset < 0)
> +               return get_pll_clk(CPLL);
> +
> +       src = readl(clk_base + bit_info->src_offset);
> +       src = (src >> bit_info->src_bit) & bit_info->src_mask;
> +
> +       switch (src) {
> +       case 0x3:
> +               sclk = get_pll_clk(MPLL);
> +               break;
> +       case 0x6:
> +               sclk = get_pll_clk(EPLL);
> +               break;
> +       case 0x7:
> +               sclk = get_pll_clk(RPLL);
> +               break;
> +       default:
> +               sclk = 0;
> +       }
> +       return sclk;
> +}
> +
> +static long exynos5_src_clk(int peripheral)
> +{
> +       unsigned int src;
> +       unsigned long sclk;
> +       unsigned long clk_base = samsung_get_base_clock();
> +       struct clk_bit_info *bit_info = get_table_index(peripheral);
> +
> +       /*
> +        * I2C clocks are parented by aclk66 which is always parented by
> +        * MPLL on 5250.
> +        */
> +       if (bit_info->src_offset < 0)
> +               return get_pll_clk(MPLL);
> +
> +       src = readl(clk_base + bit_info->src_offset);
> +       src = (src >> bit_info->src_bit) & bit_info->src_mask;
> +
> +       switch (src) {
> +       case 0x6:
> +               sclk = get_pll_clk(MPLL);
> +               break;
> +       case 0x7:
> +               sclk = get_pll_clk(EPLL);
> +               break;
> +       case 0x8:
> +               sclk = get_pll_clk(RPLL);
> +               break;
> +       default:
> +               sclk = -1;
> +       }
> +       return sclk;
> +}
> +
> +static unsigned long get_src_clk(int peripheral)
> +{
> +       if (proid_is_exynos5420())
> +               return exynos5420_src_clk(peripheral);
> +       else if (proid_is_exynos5250())
> +               return exynos5_src_clk(peripheral);
> +       else
> +               return 0;
> +}
> +
> +long clock_get_periph_rate(int peripheral)
> +{
> +       struct clk_bit_info *bit_info = NULL;
> +       unsigned long sclk, sub_clk;
> +       unsigned int div, sub_div = 0;
> +       unsigned long clk_base = samsung_get_base_clock();
> +
> +       bit_info = get_table_index(peripheral);
> +       if (!bit_info) {
> +               debug("Invalid peripheral id\n");
> +               return -1;
> +       }
> +
> +       sclk = get_src_clk(peripheral);
> +       if (sclk < 0) {
> +               debug("Unknown source clock\n");
> +               return -1;
> +       }
> +
> +       div = readl(clk_base + bit_info->div_offset);
> +
> +       /* Ratio clock division for this peripheral */
> +       div = (div >> bit_info->div_bit) & bit_info->div_mask;
> +       sub_clk = sclk / (div + 1);
> +
> +       if (bit_info->prediv_offset >= 0) {
> +               sub_div = readl(clk_base + bit_info->prediv_offset);
> +               sub_div = (sub_div >> bit_info->pre_div_bit) &
> +                               bit_info->pre_div_mask;
> +               return sub_clk / (sub_div + 1);
> +       }
> +
> +       return sub_clk;
> +}
> +
> +/**
> + * Linearly searches for the most accurate main and fine stage clock scalars
> + * (divisors) for a specified target frequency and scalar bit sizes by checking
> + * all multiples of main_scalar_bits values. Will always return scalars up to or
> + * slower than target.
> + *
> + * @param main_scalar_bits     Number of main scalar bits, must be > 0 and < 32
> + * @param fine_scalar_bits     Number of fine scalar bits, must be > 0 and < 32
> + * @param input_freq           Clock frequency to be scaled in Hz
> + * @param target_freq          Desired clock frequency in Hz
> + * @param best_fine_scalar     Pointer to store the fine stage divisor
> + *
> + * @return best_main_scalar    Main scalar for desired frequency or -1 if none
> + * found
> + */
> +static int clock_calc_best_scalar(unsigned int main_scaler_bits,
> +       unsigned int fine_scalar_bits, unsigned int input_rate,
> +       unsigned int target_rate, unsigned int *best_fine_scalar)
> +{
> +       int i;
> +       int best_main_scalar = -1;
> +       unsigned int best_error = target_rate;
> +       const unsigned int cap = (1 << fine_scalar_bits) - 1;
> +       const unsigned int loops = 1 << main_scaler_bits;
> +
> +       debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
> +             target_rate, cap);
> +
> +       assert(best_fine_scalar != NULL);
> +       assert(main_scaler_bits <= fine_scalar_bits);
> +
> +       *best_fine_scalar = 1;
> +
> +       if (input_rate == 0 || target_rate == 0)
> +               return -1;
> +
> +       if (target_rate >= input_rate)
> +               return 1;
> +
> +       for (i = 1; i <= loops; i++) {
> +               const unsigned int effective_div = max(min(input_rate / i /
> +                                                       target_rate, cap), 1);
> +               const unsigned int effective_rate = input_rate / i /
> +                                                       effective_div;
> +               const int error = target_rate - effective_rate;
> +
> +               debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
> +                     effective_rate, error);
> +
> +               if (error >= 0 && error <= best_error) {
> +                       best_error = error;
> +                       best_main_scalar = i;
> +                       *best_fine_scalar = effective_div;
> +               }
> +       }
> +
> +       return best_main_scalar;
> +}
> +
> +int clock_set_periph_source(int periph_id, int src)
> +{
> +       struct clk_bit_info *bit_info = NULL;
> +       unsigned long clk_base = samsung_get_base_clock();
> +
> +       bit_info = get_table_index(periph_id);
> +       if (!bit_info) {
> +               debug("Invalid peripheral id\n");
> +               return -1;
> +       }
> +
> +       clrsetbits_le32(clk_base + bit_info->src_offset,
> +                       bit_info->src_mask << bit_info->src_bit,
> +                       (src & bit_info->src_mask) << bit_info->src_bit);
> +
> +       return 0;
> +}
> +
> +int clock_set_periph_rate(int periph_id, unsigned long rate)
> +{
> +       struct clk_bit_info *bit_info = NULL;
> +       int div;
> +       unsigned int pre_div = 0;
> +       unsigned long sclk, sub_clk;
> +       unsigned long clk_base = samsung_get_base_clock();
> +
> +       bit_info = get_table_index(periph_id);
> +       if (!bit_info) {
> +               debug("Invalid peripheral id\n");
> +               return -1;
> +       }
> +
> +       if ((PERIPH_ID_SPI0 <= periph_id && periph_id <= PERIPH_ID_SPI2) ||
> +           PERIPH_ID_SPI3 == periph_id || periph_id == PERIPH_ID_SPI4) {
> +               div = clock_calc_best_scalar(4, 8, 400000000, rate, &pre_div);
> +               if (div < 0) {
> +                       debug("%s: Cannot set clock rate %lu for periph %d",
> +                             __func__, rate, periph_id);
> +                       return -1;
> +               }
> +               div = div - 1;
> +               pre_div = pre_div - 1;
> +       } else {
> +               sclk = get_src_clk(periph_id);
> +               div = DIV_ROUND_UP(sclk, rate);
> +               if (bit_info->prediv_offset >= 0) {
> +                       sub_clk = sclk / (div + 1);
> +                       pre_div =  DIV_ROUND_UP(sub_clk, rate);
> +               }
> +       }
> +
> +       clrsetbits_le32(clk_base + bit_info->div_offset,
> +                       bit_info->div_mask << bit_info->div_bit,
> +                       (div & bit_info->div_mask) << bit_info->div_bit);
> +
> +       if (bit_info->prediv_offset >= 0)
> +               clrsetbits_le32(clk_base + bit_info->prediv_offset,
> +                               bit_info->pre_div_mask << bit_info->pre_div_bit,
> +                               (pre_div & bit_info->pre_div_mask) <<
> +                               bit_info->pre_div_bit);
> +
> +       return 0;
> +}
> +
>  /* exynos4: return ARM clock frequency */
>  static unsigned long exynos4_get_arm_clk(void)
>  {
> @@ -522,27 +732,6 @@ static unsigned long exynos4x12_get_pwm_clk(void)
>         return pclk;
>  }
>
> -/* exynos5420: return pwm clock frequency */
> -static unsigned long exynos5420_get_pwm_clk(void)
> -{
> -       struct exynos5420_clock *clk =
> -               (struct exynos5420_clock *)samsung_get_base_clock();
> -       unsigned long pclk, sclk;
> -       unsigned int ratio;
> -
> -       /*
> -        * CLK_DIV_PERIC3
> -        * PWM_RATIO [3:0]
> -        */
> -       ratio = readl(&clk->div_peric0);
> -       ratio = (ratio >> 28) & 0xf;
> -       sclk = get_pll_clk(MPLL);
> -
> -       pclk = sclk / (ratio + 1);
> -
> -       return pclk;
> -}
> -
>  /* exynos4: return uart clock frequency */
>  static unsigned long exynos4_get_uart_clk(int dev_index)
>  {
> @@ -635,100 +824,6 @@ static unsigned long exynos4x12_get_uart_clk(int dev_index)
>         return uclk;
>  }
>
> -/* exynos5: return uart clock frequency */
> -static unsigned long exynos5_get_uart_clk(int dev_index)
> -{
> -       struct exynos5_clock *clk =
> -               (struct exynos5_clock *)samsung_get_base_clock();
> -       unsigned long uclk, sclk;
> -       unsigned int sel;
> -       unsigned int ratio;
> -
> -       /*
> -        * CLK_SRC_PERIC0
> -        * UART0_SEL [3:0]
> -        * UART1_SEL [7:4]
> -        * UART2_SEL [8:11]
> -        * UART3_SEL [12:15]
> -        * UART4_SEL [16:19]
> -        * UART5_SEL [23:20]
> -        */
> -       sel = readl(&clk->src_peric0);
> -       sel = (sel >> (dev_index << 2)) & 0xf;
> -
> -       if (sel == 0x6)
> -               sclk = get_pll_clk(MPLL);
> -       else if (sel == 0x7)
> -               sclk = get_pll_clk(EPLL);
> -       else if (sel == 0x8)
> -               sclk = get_pll_clk(VPLL);
> -       else
> -               return 0;
> -
> -       /*
> -        * CLK_DIV_PERIC0
> -        * UART0_RATIO [3:0]
> -        * UART1_RATIO [7:4]
> -        * UART2_RATIO [8:11]
> -        * UART3_RATIO [12:15]
> -        * UART4_RATIO [16:19]
> -        * UART5_RATIO [23:20]
> -        */
> -       ratio = readl(&clk->div_peric0);
> -       ratio = (ratio >> (dev_index << 2)) & 0xf;
> -
> -       uclk = sclk / (ratio + 1);
> -
> -       return uclk;
> -}
> -
> -/* exynos5420: return uart clock frequency */
> -static unsigned long exynos5420_get_uart_clk(int dev_index)
> -{
> -       struct exynos5420_clock *clk =
> -               (struct exynos5420_clock *)samsung_get_base_clock();
> -       unsigned long uclk, sclk;
> -       unsigned int sel;
> -       unsigned int ratio;
> -
> -       /*
> -        * CLK_SRC_PERIC0
> -        * UART0_SEL [3:0]
> -        * UART1_SEL [7:4]
> -        * UART2_SEL [8:11]
> -        * UART3_SEL [12:15]
> -        * UART4_SEL [16:19]
> -        * UART5_SEL [23:20]
> -        */
> -       sel = readl(&clk->src_peric0);
> -       sel = (sel >> ((dev_index * 4) + 4)) & 0x7;
> -
> -       if (sel == 0x3)
> -               sclk = get_pll_clk(MPLL);
> -       else if (sel == 0x6)
> -               sclk = get_pll_clk(EPLL);
> -       else if (sel == 0x7)
> -               sclk = get_pll_clk(RPLL);
> -       else
> -               return 0;
> -
> -       /*
> -        * CLK_DIV_PERIC0
> -        * UART0_RATIO [3:0]
> -        * UART1_RATIO [7:4]
> -        * UART2_RATIO [8:11]
> -        * UART3_RATIO [12:15]
> -        * UART4_RATIO [16:19]
> -        * UART5_RATIO [23:20]
> -        */
> -       ratio = readl(&clk->div_peric0);
> -       ratio = (ratio >> ((dev_index * 4) + 8)) & 0xf;
> -
> -       uclk = sclk / (ratio + 1);
> -
> -       return uclk;
> -}
> -
>  static unsigned long exynos4_get_mmc_clk(int dev_index)
>  {
>         struct exynos4_clock *clk =
> @@ -778,79 +873,6 @@ static unsigned long exynos4_get_mmc_clk(int dev_index)
>         return uclk;
>  }
>
> -static unsigned long exynos5_get_mmc_clk(int dev_index)
> -{
> -       struct exynos5_clock *clk =
> -               (struct exynos5_clock *)samsung_get_base_clock();
> -       unsigned long uclk, sclk;
> -       unsigned int sel, ratio, pre_ratio;
> -       int shift = 0;
> -
> -       sel = readl(&clk->src_fsys);
> -       sel = (sel >> (dev_index << 2)) & 0xf;
> -
> -       if (sel == 0x6)
> -               sclk = get_pll_clk(MPLL);
> -       else if (sel == 0x7)
> -               sclk = get_pll_clk(EPLL);
> -       else if (sel == 0x8)
> -               sclk = get_pll_clk(VPLL);
> -       else
> -               return 0;
> -
> -       switch (dev_index) {
> -       case 0:
> -       case 1:
> -               ratio = readl(&clk->div_fsys1);
> -               pre_ratio = readl(&clk->div_fsys1);
> -               break;
> -       case 2:
> -       case 3:
> -               ratio = readl(&clk->div_fsys2);
> -               pre_ratio = readl(&clk->div_fsys2);
> -               break;
> -       default:
> -               return 0;
> -       }
> -
> -       if (dev_index == 1 || dev_index == 3)
> -               shift = 16;
> -
> -       ratio = (ratio >> shift) & 0xf;
> -       pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
> -       uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
> -
> -       return uclk;
> -}
> -
> -static unsigned long exynos5420_get_mmc_clk(int dev_index)
> -{
> -       struct exynos5420_clock *clk =
> -               (struct exynos5420_clock *)samsung_get_base_clock();
> -       unsigned long uclk, sclk;
> -       unsigned int sel, ratio;
> -       int shift = 0;
> -
> -       sel = readl(&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->div_fsys1);
> -
> -       shift = dev_index * 10;
> -
> -       ratio = (ratio >> shift) & 0x3ff;
> -       uclk = (sclk / (ratio + 1));
> -
> -       return uclk;
> -}
> -
>  /* exynos4: set the mmc clock */
>  static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
>  {
> @@ -910,50 +932,6 @@ static void exynos4x12_set_mmc_clk(int dev_index, unsigned int div)
>         writel(val, addr);
>  }
>
> -/* exynos5: set the mmc clock */
> -static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
> -{
> -       struct exynos5_clock *clk =
> -               (struct exynos5_clock *)samsung_get_base_clock();
> -       unsigned int addr;
> -       unsigned int val;
> -
> -       /*
> -        * CLK_DIV_FSYS1
> -        * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
> -        * CLK_DIV_FSYS2
> -        * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
> -        */
> -       if (dev_index < 2) {
> -               addr = (unsigned int)&clk->div_fsys1;
> -       } else {
> -               addr = (unsigned int)&clk->div_fsys2;
> -               dev_index -= 2;
> -       }
> -
> -       val = readl(addr);
> -       val &= ~(0xff << ((dev_index << 4) + 8));
> -       val |= (div & 0xff) << ((dev_index << 4) + 8);
> -       writel(val, addr);
> -}
> -
> -/* exynos5: set the mmc clock */
> -static void exynos5420_set_mmc_clk(int dev_index, unsigned int div)
> -{
> -       struct exynos5420_clock *clk =
> -               (struct exynos5420_clock *)samsung_get_base_clock();
> -       unsigned int addr;
> -       unsigned int val, shift;
> -
> -       addr = (unsigned int)&clk->div_fsys1;
> -       shift = dev_index * 10;
> -
> -       val = readl(addr);
> -       val &= ~(0x3ff << shift);
> -       val |= (div & 0x3ff) << shift;
> -       writel(val, addr);
> -}
> -
>  /* get_lcd_clk: return lcd clock frequency */
>  static unsigned long exynos4_get_lcd_clk(void)
>  {
> @@ -1222,28 +1200,6 @@ void exynos4_set_mipi_clk(void)
>         writel(cfg, &clk->div_lcd0);
>  }
>
> -/*
> - * I2C
> - *
> - * exynos5: obtaining the I2C clock
> - */
> -static unsigned long exynos5_get_i2c_clk(void)
> -{
> -       struct exynos5_clock *clk =
> -               (struct exynos5_clock *)samsung_get_base_clock();
> -       unsigned long aclk_66, aclk_66_pre, sclk;
> -       unsigned int ratio;
> -
> -       sclk = get_pll_clk(MPLL);
> -
> -       ratio = (readl(&clk->div_top1)) >> 24;
> -       ratio &= 0x7;
> -       aclk_66_pre = sclk / (ratio + 1);
> -       ratio = readl(&clk->div_top0);
> -       ratio &= 0x7;
> -       aclk_66 = aclk_66_pre / (ratio + 1);
> -       return aclk_66;
> -}
>
>  int exynos5_set_epll_clk(unsigned long rate)
>  {
> @@ -1358,200 +1314,6 @@ int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
>         return 0;
>  }
>
> -/**
> - * Linearly searches for the most accurate main and fine stage clock scalars
> - * (divisors) for a specified target frequency and scalar bit sizes by checking
> - * all multiples of main_scalar_bits values. Will always return scalars up to or
> - * slower than target.
> - *
> - * @param main_scalar_bits     Number of main scalar bits, must be > 0 and < 32
> - * @param fine_scalar_bits     Number of fine scalar bits, must be > 0 and < 32
> - * @param input_freq           Clock frequency to be scaled in Hz
> - * @param target_freq          Desired clock frequency in Hz
> - * @param best_fine_scalar     Pointer to store the fine stage divisor
> - *
> - * @return best_main_scalar    Main scalar for desired frequency or -1 if none
> - * found
> - */
> -static int clock_calc_best_scalar(unsigned int main_scaler_bits,
> -       unsigned int fine_scalar_bits, unsigned int input_rate,
> -       unsigned int target_rate, unsigned int *best_fine_scalar)
> -{
> -       int i;
> -       int best_main_scalar = -1;
> -       unsigned int best_error = target_rate;
> -       const unsigned int cap = (1 << fine_scalar_bits) - 1;
> -       const unsigned int loops = 1 << main_scaler_bits;
> -
> -       debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
> -                       target_rate, cap);
> -
> -       assert(best_fine_scalar != NULL);
> -       assert(main_scaler_bits <= fine_scalar_bits);
> -
> -       *best_fine_scalar = 1;
> -
> -       if (input_rate == 0 || target_rate == 0)
> -               return -1;
> -
> -       if (target_rate >= input_rate)
> -               return 1;
> -
> -       for (i = 1; i <= loops; i++) {
> -               const unsigned int effective_div = max(min(input_rate / i /
> -                                                       target_rate, cap), 1);
> -               const unsigned int effective_rate = input_rate / i /
> -                                                       effective_div;
> -               const int error = target_rate - effective_rate;
> -
> -               debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
> -                               effective_rate, error);
> -
> -               if (error >= 0 && error <= best_error) {
> -                       best_error = error;
> -                       best_main_scalar = i;
> -                       *best_fine_scalar = effective_div;
> -               }
> -       }
> -
> -       return best_main_scalar;
> -}
> -
> -static int exynos5_set_spi_clk(enum periph_id periph_id,
> -                                       unsigned int rate)
> -{
> -       struct exynos5_clock *clk =
> -               (struct exynos5_clock *)samsung_get_base_clock();
> -       int main;
> -       unsigned int fine;
> -       unsigned shift, pre_shift;
> -       unsigned mask = 0xff;
> -       u32 *reg;
> -
> -       main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
> -       if (main < 0) {
> -               debug("%s: Cannot set clock rate for periph %d",
> -                               __func__, periph_id);
> -               return -1;
> -       }
> -       main = main - 1;
> -       fine = fine - 1;
> -
> -       switch (periph_id) {
> -       case PERIPH_ID_SPI0:
> -               reg = &clk->div_peric1;
> -               shift = 0;
> -               pre_shift = 8;
> -               break;
> -       case PERIPH_ID_SPI1:
> -               reg = &clk->div_peric1;
> -               shift = 16;
> -               pre_shift = 24;
> -               break;
> -       case PERIPH_ID_SPI2:
> -               reg = &clk->div_peric2;
> -               shift = 0;
> -               pre_shift = 8;
> -               break;
> -       case PERIPH_ID_SPI3:
> -               reg = &clk->sclk_div_isp;
> -               shift = 0;
> -               pre_shift = 4;
> -               break;
> -       case PERIPH_ID_SPI4:
> -               reg = &clk->sclk_div_isp;
> -               shift = 12;
> -               pre_shift = 16;
> -               break;
> -       default:
> -               debug("%s: Unsupported peripheral ID %d\n", __func__,
> -                     periph_id);
> -               return -1;
> -       }
> -       clrsetbits_le32(reg, mask << shift, (main & mask) << shift);
> -       clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift);
> -
> -       return 0;
> -}
> -
> -static int exynos5420_set_spi_clk(enum periph_id periph_id,
> -                                       unsigned int rate)
> -{
> -       struct exynos5420_clock *clk =
> -               (struct exynos5420_clock *)samsung_get_base_clock();
> -       int main;
> -       unsigned int fine, val;
> -       unsigned shift, pre_shift;
> -       unsigned div_mask = 0xf, pre_div_mask = 0xff;
> -
> -       main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
> -       if (main < 0) {
> -               debug("%s: Cannot set clock rate for periph %d",
> -                     __func__, periph_id);
> -               return -1;
> -       }
> -       main = main - 1;
> -       fine = fine - 1;
> -
> -       switch (periph_id) {
> -       case PERIPH_ID_SPI0:
> -               val = readl(&clk->div_peric1);
> -               val &= ~(div_mask << 20);
> -               val |= (main << 20);
> -               writel(val, &clk->div_peric1);
> -
> -               val = readl(&clk->div_peric4);
> -               val &= ~(pre_div_mask << 8);
> -               val |= (fine << 8);
> -               writel(val, &clk->div_peric4);
> -               break;
> -       case PERIPH_ID_SPI1:
> -               val = readl(&clk->div_peric1);
> -               val &= ~(div_mask << 24);
> -               val |= (main << 24);
> -               writel(val, &clk->div_peric1);
> -
> -               val = readl(&clk->div_peric4);
> -               val &= ~(pre_div_mask << 16);
> -               val |= (fine << 16);
> -               writel(val, &clk->div_peric4);
> -               break;
> -       case PERIPH_ID_SPI2:
> -               val = readl(&clk->div_peric1);
> -               val &= ~(div_mask << 28);
> -               val |= (main << 28);
> -               writel(val, &clk->div_peric1);
> -
> -               val = readl(&clk->div_peric4);
> -               val &= ~(pre_div_mask << 24);
> -               val |= (fine << 24);
> -               writel(val, &clk->div_peric4);
> -               break;
> -       case PERIPH_ID_SPI3:
> -               shift = 16;
> -               pre_shift = 0;
> -               clrsetbits_le32(&clk->div_isp1, div_mask << shift,
> -                               (main & div_mask) << shift);
> -               clrsetbits_le32(&clk->div_isp1, pre_div_mask << pre_shift,
> -                               (fine & pre_div_mask) << pre_shift);
> -               break;
> -       case PERIPH_ID_SPI4:
> -               shift = 20;
> -               pre_shift = 8;
> -               clrsetbits_le32(&clk->div_isp1, div_mask << shift,
> -                               (main & div_mask) << shift);
> -               clrsetbits_le32(&clk->div_isp1, pre_div_mask << pre_shift,
> -                               (fine & pre_div_mask) << pre_shift);
> -               break;
> -       default:
> -               debug("%s: Unsupported peripheral ID %d\n", __func__,
> -                     periph_id);
> -               return -1;
> -       }
> -
> -       return 0;
> -}
> -
>  static unsigned long exynos4_get_i2c_clk(void)
>  {
>         struct exynos4_clock *clk =
> @@ -1594,7 +1356,7 @@ unsigned long get_arm_clk(void)
>  unsigned long get_i2c_clk(void)
>  {
>         if (cpu_is_exynos5()) {
> -               return exynos5_get_i2c_clk();
> +               return clock_get_periph_rate(PERIPH_ID_I2C0);
>         } else if (cpu_is_exynos4()) {
>                 return exynos4_get_i2c_clk();
>         } else {
> @@ -1606,8 +1368,6 @@ unsigned long get_i2c_clk(void)
>  unsigned long get_pwm_clk(void)
>  {
>         if (cpu_is_exynos5()) {
> -               if (proid_is_exynos5420())
> -                       return exynos5420_get_pwm_clk();
>                 return clock_get_periph_rate(PERIPH_ID_PWM0);
>         } else {
>                 if (proid_is_exynos4412())
> @@ -1619,9 +1379,7 @@ unsigned long get_pwm_clk(void)
>  unsigned long get_uart_clk(int dev_index)
>  {
>         if (cpu_is_exynos5()) {
> -               if (proid_is_exynos5420())
> -                       return exynos5420_get_uart_clk(dev_index);
> -               return exynos5_get_uart_clk(dev_index);
> +               return clock_get_periph_rate(PERIPH_ID_UART0 + dev_index);
>         } else {
>                 if (proid_is_exynos4412())
>                         return exynos4x12_get_uart_clk(dev_index);
> @@ -1632,9 +1390,7 @@ unsigned long get_uart_clk(int dev_index)
>  unsigned long get_mmc_clk(int dev_index)
>  {
>         if (cpu_is_exynos5()) {
> -               if (proid_is_exynos5420())
> -                       return exynos5420_get_mmc_clk(dev_index);
> -               return exynos5_get_mmc_clk(dev_index);
> +               return clock_get_periph_rate(PERIPH_ID_SDMMC0 + dev_index);
>         } else {
>                 return exynos4_get_mmc_clk(dev_index);
>         }
> @@ -1642,15 +1398,9 @@ unsigned long get_mmc_clk(int dev_index)
>
>  void set_mmc_clk(int dev_index, unsigned int div)
>  {
> -       if (cpu_is_exynos5()) {
> -               if (proid_is_exynos5420())
> -                       return exynos5420_set_mmc_clk(dev_index, div);
> -               exynos5_set_mmc_clk(dev_index, div);
> -       } else {
>                 if (proid_is_exynos4412())
>                         exynos4x12_set_mmc_clk(dev_index, div);
>                 exynos4_set_mmc_clk(dev_index, div);
> -       }
>  }
>
>  unsigned long get_lcd_clk(void)
> @@ -1678,9 +1428,7 @@ void set_mipi_clk(void)
>  int set_spi_clk(int periph_id, unsigned int rate)
>  {
>         if (cpu_is_exynos5()) {
> -               if (proid_is_exynos5420())
> -                       return exynos5420_set_spi_clk(periph_id, rate);
> -               return exynos5_set_spi_clk(periph_id, rate);
> +               return clock_set_periph_rate(periph_id, rate);
>         } else {
>                 return 0;
>         }
> diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h
> index cdeef32..a717805 100644
> --- a/arch/arm/include/asm/arch-exynos/clk.h
> +++ b/arch/arm/include/asm/arch-exynos/clk.h
> @@ -15,12 +15,9 @@
>  #define VPLL   4
>  #define BPLL   5
>  #define RPLL   6
> -
> -enum pll_src_bit {
> -       EXYNOS_SRC_MPLL = 6,
> -       EXYNOS_SRC_EPLL,
> -       EXYNOS_SRC_VPLL,
> -};
> +#define SPLL   7
> +#define CPLL   8
> +#define DPLL   9
>
>  unsigned long get_pll_clk(int pllreg);
>  unsigned long get_arm_clk(void);
> @@ -45,6 +42,25 @@ int set_spi_clk(int periph_id, unsigned int rate);
>   *
>   * @return frequency of the peripheral clk
>   */
> -unsigned long clock_get_periph_rate(int peripheral);
> +long clock_get_periph_rate(int peripheral);
> +
> +/**
> + * set the clk frequency rate of the required peripheral
> + *
> + * @param peripheral   Peripheral id
> + * @param rate         frequency to be set
> + *
> + * @return 0 if success else -1
> + */
> +int clock_set_periph_rate(int periph_id, unsigned long rate);
>
> +/**
> + * set the clk source mux value of the required peripheral
> + *
> + * @param peripheral   Peripheral id
> + * @param src          source to be set
> + *
> + * @return 0 if success else -1
> + */
> +int clock_set_periph_source(int periph_id, int src);
>  #endif
> diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
> index f7439a0..2290330 100644
> --- a/drivers/mmc/exynos_dw_mmc.c
> +++ b/drivers/mmc/exynos_dw_mmc.c
> @@ -45,19 +45,22 @@ unsigned int exynos_dwmci_get_clk(int dev_index)
>  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;
> +       int ret;
> +       unsigned long freq;
>         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);
> +       /* set the clock rate for mmc */
> +       ret = clock_set_periph_rate(PERIPH_ID_SDMMC0 + index, freq);
> +       if (ret < 0) {
> +               debug("Clock rate not set\n");
> +               return -1;
> +       }
>
>         host->name = "EXYNOS DWMMC";
>         host->ioaddr = (void *)regbase;
> --
> 1.7.12.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot


More information about the U-Boot mailing list