[8/9,V2] EXYNOS: Add clock for I2S

Message ID 1345617865-14199-9-git-send-email-rajeshwari.s@samsung.com
State New
Headers show

Commit Message

Rajeshwari Shinde Aug. 22, 2012, 6:44 a.m.
This patch adds clock support for I2S

Signed-off-by: R. Chandrasekar <rcsekar@samsung.com>
Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
---
Changes in V2:
- None
 arch/arm/cpu/armv7/exynos/clock.c        |  119 ++++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-exynos/clk.h   |    3 +
 arch/arm/include/asm/arch-exynos/clock.h |   29 +++++++
 3 files changed, 151 insertions(+), 0 deletions(-)

Comments

Chander Kashyap Oct. 17, 2012, 7:17 a.m. | #1
On 22 August 2012 12:14, Rajeshwari Shinde <rajeshwari.s@samsung.com> wrote:
> This patch adds clock support for I2S
>
> Signed-off-by: R. Chandrasekar <rcsekar@samsung.com>
> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
> ---
> Changes in V2:
> - None
>  arch/arm/cpu/armv7/exynos/clock.c        |  119 ++++++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-exynos/clk.h   |    3 +
>  arch/arm/include/asm/arch-exynos/clock.h |   29 +++++++
>  3 files changed, 151 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
> index 44dff2b..691f6d4 100644
> --- a/arch/arm/cpu/armv7/exynos/clock.c
> +++ b/arch/arm/cpu/armv7/exynos/clock.c
> @@ -26,6 +26,16 @@
>  #include <asm/arch/clock.h>
>  #include <asm/arch/clk.h>
>
> +/* Epll Clock division values to achive different frequency output */
> +static struct st_epll_con_val epll_div[] = {
> +       { 192000000, 0, 48, 3, 1, 0 },
> +       { 180000000, 0, 45, 3, 1, 0 },
> +       {  73728000, 1, 73, 3, 3, 47710 },
> +       {  67737600, 1, 90, 4, 3, 20762 },
> +       {  49152000, 0, 49, 3, 3, 9961 },
> +       {  45158400, 0, 45, 3, 3, 10381 },
> +       { 180633600, 0, 45, 3, 1, 10381 }
> +};
Are these division values common to Exynos or only for exynos-5.

>  /* exynos4: return pll clock frequency */
>  static unsigned long exynos4_get_pll_clk(int pllreg)
>  {
> @@ -848,6 +858,92 @@ static int exynos5_spi_set_clock_rate(enum periph_id periph_id,
>         return 0;
>  }
>
> +int exynos5_clock_epll_set_rate(unsigned long rate)
> +{
> +       unsigned int epll_con, epll_con_k;
> +       unsigned int i;
> +       unsigned int lockcnt;
> +       unsigned int start;
> +       struct exynos5_clock *clk =
> +               (struct exynos5_clock *)samsung_get_base_clock();
> +
> +       epll_con = readl(&clk->epll_con0);
> +       epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
> +                       EPLL_CON0_LOCK_DET_EN_SHIFT) |
> +               EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
> +               EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
> +               EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
> +
> +       for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
> +               if (epll_div[i].freq_out == rate)
> +                       break;
> +       }
> +
> +       if (i == ARRAY_SIZE(epll_div))
> +               return -1;
> +
> +       epll_con_k = epll_div[i].k_dsm << 0;
> +       epll_con |= epll_div[i].en_lock_det << EPLL_CON0_LOCK_DET_EN_SHIFT;
> +       epll_con |= epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
> +       epll_con |= epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
> +       epll_con |= epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
> +
> +       /*
> +        * Required period ( in cycles) to genarate a stable clock output.
> +        * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
> +        * frequency input (as per spec)
> +        */
> +       lockcnt = 3000 * epll_div[i].p_div;
> +
> +       writel(lockcnt, &clk->epll_lock);
> +       writel(epll_con, &clk->epll_con0);
> +       writel(epll_con_k, &clk->epll_con1);
> +
> +       start = get_timer(0);
> +
> +        while (!(readl(&clk->epll_con0) &
> +                       (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
> +               if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
> +                       debug("%s: Timeout waiting for EPLL lock\n", __func__);
> +                       return -1;
> +               }
> +       }
> +       return 0;
> +}
> +
> +void exynos5_clock_select_i2s_clk_source(void)
> +{
> +       struct exynos5_clock *clk =
> +               (struct exynos5_clock *)samsung_get_base_clock();
> +
> +       clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
> +                       (CLK_SRC_SCLK_EPLL));
> +}
> +
> +int exynos5_clock_set_i2s_clk_prescaler(unsigned int src_frq,
> +                                       unsigned int dst_frq)
> +{
> +       struct exynos5_clock *clk =
> +               (struct exynos5_clock *)samsung_get_base_clock();
> +       unsigned int div;
> +
> +       if ((dst_frq == 0) || (src_frq == 0)) {
> +               debug("%s: Invalid requency input for prescaler\n", __func__);
> +               debug("src frq = %d des frq = %d ", src_frq, dst_frq);
> +               return -1;
> +       }
> +
> +       div = (src_frq / dst_frq);
> +       if (div > AUDIO_1_RATIO_MASK) {
> +               debug("%s: Frequency ratio is out of range\n", __func__);
> +               debug("src frq = %d des frq = %d ", src_frq, dst_frq);
> +               return -1;
> +       }
> +       clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
> +                               (div & AUDIO_1_RATIO_MASK));
> +       return 0;
> +}
> +
>  unsigned long get_pll_clk(int pllreg)
>  {
>         if (cpu_is_exynos5())
> @@ -927,3 +1023,26 @@ int spi_set_clock_rate(enum periph_id periph_id, unsigned int rate)
>         else
>                 return 0;
>  }
> +
> +int clock_set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq)
> +{
> +
> +       if (cpu_is_exynos5())
> +               return exynos5_clock_set_i2s_clk_prescaler(src_frq, dst_frq);
> +       else
> +               return 0;
> +}
> +
> +void clock_select_i2s_clk_source(void)
> +{
> +       if (cpu_is_exynos5())
> +               exynos5_clock_select_i2s_clk_source();
> +}
> +
> +int clock_epll_set_rate(unsigned long rate)
> +{
> +       if (cpu_is_exynos5())
> +               return exynos5_clock_epll_set_rate(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 4e51402..f32c634 100644
> --- a/arch/arm/include/asm/arch-exynos/clk.h
> +++ b/arch/arm/include/asm/arch-exynos/clk.h
> @@ -41,4 +41,7 @@ unsigned long get_lcd_clk(void);
>  void set_lcd_clk(void);
>  void set_mipi_clk(void);
>  int spi_set_clock_rate(enum periph_id periph_id, unsigned int rate);
> +void clock_select_i2s_clk_source(void);
> +int clock_set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq);
> +int clock_epll_set_rate(unsigned long rate);
>  #endif
> diff --git a/arch/arm/include/asm/arch-exynos/clock.h b/arch/arm/include/asm/arch-exynos/clock.h
> index fce38ef..1df49a9 100644
> --- a/arch/arm/include/asm/arch-exynos/clock.h
> +++ b/arch/arm/include/asm/arch-exynos/clock.h
> @@ -595,9 +595,38 @@ struct exynos5_clock {
>         unsigned int    pll_div2_sel;
>         unsigned char   res123[0xf5d8];
>  };
> +
> +/* structure for epll configuration used in audio clock configuration */
> +struct st_epll_con_val {
> +       unsigned int freq_out;          /* frequency out */
> +       unsigned int en_lock_det;       /* enable lock detect */
> +       unsigned int m_div;             /* m divider value */
> +       unsigned int p_div;             /* p divider value */
> +       unsigned int s_div;             /* s divider value */
> +       unsigned int k_dsm;             /* k value of delta signal modulator */
> +};
>  #endif
>
>  #define MPLL_FOUT_SEL_SHIFT    4
> +#define EXYNOS5_EPLLCON0_LOCKED_SHIFT  29  /* EPLL Locked bit position*/
> +#define TIMEOUT_EPLL_LOCK              1000
> +
> +#define AUDIO_0_RATIO_MASK             0x0f
> +#define AUDIO_1_RATIO_MASK             0x0f
> +
> +#define AUDIO1_SEL_MASK                        0xf
> +#define CLK_SRC_SCLK_EPLL              0x7
> +
> +/* CON0 bit-fields */
> +#define EPLL_CON0_MDIV_MASK            0x1ff
> +#define EPLL_CON0_PDIV_MASK            0x3f
> +#define EPLL_CON0_SDIV_MASK            0x7
> +#define EPLL_CON0_MDIV_SHIFT           16
> +#define EPLL_CON0_PDIV_SHIFT           8
> +#define EPLL_CON0_SDIV_SHIFT           0
> +#define EPLL_CON0_LOCK_DET_EN_SHIFT    28
> +#define EPLL_CON0_LOCK_DET_EN_MASK     1
> +
>  #define MPLL_FOUT_SEL_MASK     0x1
>  #define BPLL_FOUT_SEL_SHIFT    0
>  #define BPLL_FOUT_SEL_MASK     0x1
> --
> 1.7.4.4
>
Minkyu Kang Oct. 17, 2012, 7:49 a.m. | #2
On 22 August 2012 15:44, Rajeshwari Shinde <rajeshwari.s@samsung.com> wrote:
> This patch adds clock support for I2S
>
> Signed-off-by: R. Chandrasekar <rcsekar@samsung.com>
> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
> ---
> Changes in V2:
> - None
>  arch/arm/cpu/armv7/exynos/clock.c        |  119 ++++++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-exynos/clk.h   |    3 +
>  arch/arm/include/asm/arch-exynos/clock.h |   29 +++++++
>  3 files changed, 151 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
> index 44dff2b..691f6d4 100644
> --- a/arch/arm/cpu/armv7/exynos/clock.c
> +++ b/arch/arm/cpu/armv7/exynos/clock.c
> @@ -26,6 +26,16 @@
>  #include <asm/arch/clock.h>
>  #include <asm/arch/clk.h>
>
> +/* Epll Clock division values to achive different frequency output */
> +static struct st_epll_con_val epll_div[] = {
> +       { 192000000, 0, 48, 3, 1, 0 },
> +       { 180000000, 0, 45, 3, 1, 0 },
> +       {  73728000, 1, 73, 3, 3, 47710 },
> +       {  67737600, 1, 90, 4, 3, 20762 },
> +       {  49152000, 0, 49, 3, 3, 9961 },
> +       {  45158400, 0, 45, 3, 3, 10381 },
> +       { 180633600, 0, 45, 3, 1, 10381 }
> +};
>  /* exynos4: return pll clock frequency */
>  static unsigned long exynos4_get_pll_clk(int pllreg)
>  {
> @@ -848,6 +858,92 @@ static int exynos5_spi_set_clock_rate(enum periph_id periph_id,
>         return 0;
>  }
>
> +int exynos5_clock_epll_set_rate(unsigned long rate)

exynos5_set_epll_clk

> +{
> +       unsigned int epll_con, epll_con_k;
> +       unsigned int i;
> +       unsigned int lockcnt;
> +       unsigned int start;
> +       struct exynos5_clock *clk =
> +               (struct exynos5_clock *)samsung_get_base_clock();
> +
> +       epll_con = readl(&clk->epll_con0);
> +       epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
> +                       EPLL_CON0_LOCK_DET_EN_SHIFT) |
> +               EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
> +               EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
> +               EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
> +
> +       for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
> +               if (epll_div[i].freq_out == rate)
> +                       break;
> +       }
> +
> +       if (i == ARRAY_SIZE(epll_div))
> +               return -1;
> +
> +       epll_con_k = epll_div[i].k_dsm << 0;
> +       epll_con |= epll_div[i].en_lock_det << EPLL_CON0_LOCK_DET_EN_SHIFT;
> +       epll_con |= epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
> +       epll_con |= epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
> +       epll_con |= epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
> +
> +       /*
> +        * Required period ( in cycles) to genarate a stable clock output.
> +        * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
> +        * frequency input (as per spec)
> +        */
> +       lockcnt = 3000 * epll_div[i].p_div;
> +
> +       writel(lockcnt, &clk->epll_lock);
> +       writel(epll_con, &clk->epll_con0);
> +       writel(epll_con_k, &clk->epll_con1);
> +
> +       start = get_timer(0);
> +
> +        while (!(readl(&clk->epll_con0) &
> +                       (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
> +               if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
> +                       debug("%s: Timeout waiting for EPLL lock\n", __func__);
> +                       return -1;
> +               }
> +       }
> +       return 0;
> +}
> +
> +void exynos5_clock_select_i2s_clk_source(void)

exynos5_set_i2s_clk_source

> +{
> +       struct exynos5_clock *clk =
> +               (struct exynos5_clock *)samsung_get_base_clock();
> +
> +       clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
> +                       (CLK_SRC_SCLK_EPLL));
> +}
> +
> +int exynos5_clock_set_i2s_clk_prescaler(unsigned int src_frq,

exynos5_set_i2s_clk_prescaler

> +                                       unsigned int dst_frq)
> +{
> +       struct exynos5_clock *clk =
> +               (struct exynos5_clock *)samsung_get_base_clock();
> +       unsigned int div;
> +
> +       if ((dst_frq == 0) || (src_frq == 0)) {
> +               debug("%s: Invalid requency input for prescaler\n", __func__);
> +               debug("src frq = %d des frq = %d ", src_frq, dst_frq);
> +               return -1;
> +       }
> +
> +       div = (src_frq / dst_frq);
> +       if (div > AUDIO_1_RATIO_MASK) {
> +               debug("%s: Frequency ratio is out of range\n", __func__);
> +               debug("src frq = %d des frq = %d ", src_frq, dst_frq);
> +               return -1;
> +       }
> +       clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
> +                               (div & AUDIO_1_RATIO_MASK));
> +       return 0;
> +}
> +
>  unsigned long get_pll_clk(int pllreg)
>  {
>         if (cpu_is_exynos5())
> @@ -927,3 +1023,26 @@ int spi_set_clock_rate(enum periph_id periph_id, unsigned int rate)
>         else
>                 return 0;
>  }
> +
> +int clock_set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq)

set_i2s_clk_prescaler

> +{
> +
> +       if (cpu_is_exynos5())
> +               return exynos5_clock_set_i2s_clk_prescaler(src_frq, dst_frq);
> +       else
> +               return 0;
> +}
> +
> +void clock_select_i2s_clk_source(void)

set_i2s_clk_source

> +{
> +       if (cpu_is_exynos5())
> +               exynos5_clock_select_i2s_clk_source();
> +}
> +
> +int clock_epll_set_rate(unsigned long rate)

set_epll_clk

> +{
> +       if (cpu_is_exynos5())
> +               return exynos5_clock_epll_set_rate(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 4e51402..f32c634 100644
> --- a/arch/arm/include/asm/arch-exynos/clk.h
> +++ b/arch/arm/include/asm/arch-exynos/clk.h
> @@ -41,4 +41,7 @@ unsigned long get_lcd_clk(void);
>  void set_lcd_clk(void);
>  void set_mipi_clk(void);
>  int spi_set_clock_rate(enum periph_id periph_id, unsigned int rate);
> +void clock_select_i2s_clk_source(void);
> +int clock_set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq);
> +int clock_epll_set_rate(unsigned long rate);
>  #endif
> diff --git a/arch/arm/include/asm/arch-exynos/clock.h b/arch/arm/include/asm/arch-exynos/clock.h
> index fce38ef..1df49a9 100644
> --- a/arch/arm/include/asm/arch-exynos/clock.h
> +++ b/arch/arm/include/asm/arch-exynos/clock.h
> @@ -595,9 +595,38 @@ struct exynos5_clock {
>         unsigned int    pll_div2_sel;
>         unsigned char   res123[0xf5d8];
>  };
> +
> +/* structure for epll configuration used in audio clock configuration */
> +struct st_epll_con_val {
> +       unsigned int freq_out;          /* frequency out */
> +       unsigned int en_lock_det;       /* enable lock detect */
> +       unsigned int m_div;             /* m divider value */
> +       unsigned int p_div;             /* p divider value */
> +       unsigned int s_div;             /* s divider value */
> +       unsigned int k_dsm;             /* k value of delta signal modulator */
> +};
>  #endif
>
>  #define MPLL_FOUT_SEL_SHIFT    4
> +#define EXYNOS5_EPLLCON0_LOCKED_SHIFT  29  /* EPLL Locked bit position*/
> +#define TIMEOUT_EPLL_LOCK              1000
> +
> +#define AUDIO_0_RATIO_MASK             0x0f
> +#define AUDIO_1_RATIO_MASK             0x0f
> +
> +#define AUDIO1_SEL_MASK                        0xf
> +#define CLK_SRC_SCLK_EPLL              0x7
> +
> +/* CON0 bit-fields */
> +#define EPLL_CON0_MDIV_MASK            0x1ff
> +#define EPLL_CON0_PDIV_MASK            0x3f
> +#define EPLL_CON0_SDIV_MASK            0x7
> +#define EPLL_CON0_MDIV_SHIFT           16
> +#define EPLL_CON0_PDIV_SHIFT           8
> +#define EPLL_CON0_SDIV_SHIFT           0
> +#define EPLL_CON0_LOCK_DET_EN_SHIFT    28
> +#define EPLL_CON0_LOCK_DET_EN_MASK     1
> +
>  #define MPLL_FOUT_SEL_MASK     0x1
>  #define BPLL_FOUT_SEL_SHIFT    0
>  #define BPLL_FOUT_SEL_MASK     0x1
> --
> 1.7.4.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

Thanks.
Minkyu Kang.

Patch

diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
index 44dff2b..691f6d4 100644
--- a/arch/arm/cpu/armv7/exynos/clock.c
+++ b/arch/arm/cpu/armv7/exynos/clock.c
@@ -26,6 +26,16 @@ 
 #include <asm/arch/clock.h>
 #include <asm/arch/clk.h>
 
+/* Epll Clock division values to achive different frequency output */
+static struct st_epll_con_val epll_div[] = {
+	{ 192000000, 0, 48, 3, 1, 0 },
+	{ 180000000, 0, 45, 3, 1, 0 },
+	{  73728000, 1, 73, 3, 3, 47710 },
+	{  67737600, 1, 90, 4, 3, 20762 },
+	{  49152000, 0, 49, 3, 3, 9961 },
+	{  45158400, 0, 45, 3, 3, 10381 },
+	{ 180633600, 0, 45, 3, 1, 10381 }
+};
 /* exynos4: return pll clock frequency */
 static unsigned long exynos4_get_pll_clk(int pllreg)
 {
@@ -848,6 +858,92 @@  static int exynos5_spi_set_clock_rate(enum periph_id periph_id,
 	return 0;
 }
 
+int exynos5_clock_epll_set_rate(unsigned long rate)
+{
+	unsigned int epll_con, epll_con_k;
+	unsigned int i;
+	unsigned int lockcnt;
+	unsigned int start;
+	struct exynos5_clock *clk =
+		(struct exynos5_clock *)samsung_get_base_clock();
+
+	epll_con = readl(&clk->epll_con0);
+	epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
+			EPLL_CON0_LOCK_DET_EN_SHIFT) |
+		EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
+		EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
+		EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
+
+	for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
+		if (epll_div[i].freq_out == rate)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(epll_div))
+		return -1;
+
+	epll_con_k = epll_div[i].k_dsm << 0;
+	epll_con |= epll_div[i].en_lock_det << EPLL_CON0_LOCK_DET_EN_SHIFT;
+	epll_con |= epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
+	epll_con |= epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
+	epll_con |= epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
+
+	/*
+	 * Required period ( in cycles) to genarate a stable clock output.
+	 * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
+	 * frequency input (as per spec)
+	 */
+	lockcnt = 3000 * epll_div[i].p_div;
+
+	writel(lockcnt, &clk->epll_lock);
+	writel(epll_con, &clk->epll_con0);
+	writel(epll_con_k, &clk->epll_con1);
+
+	start = get_timer(0);
+
+	 while (!(readl(&clk->epll_con0) &
+			(0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
+		if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
+			debug("%s: Timeout waiting for EPLL lock\n", __func__);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+void exynos5_clock_select_i2s_clk_source(void)
+{
+	struct exynos5_clock *clk =
+		(struct exynos5_clock *)samsung_get_base_clock();
+
+	clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
+			(CLK_SRC_SCLK_EPLL));
+}
+
+int exynos5_clock_set_i2s_clk_prescaler(unsigned int src_frq,
+					unsigned int dst_frq)
+{
+	struct exynos5_clock *clk =
+		(struct exynos5_clock *)samsung_get_base_clock();
+	unsigned int div;
+
+	if ((dst_frq == 0) || (src_frq == 0)) {
+		debug("%s: Invalid requency input for prescaler\n", __func__);
+		debug("src frq = %d des frq = %d ", src_frq, dst_frq);
+		return -1;
+	}
+
+	div = (src_frq / dst_frq);
+	if (div > AUDIO_1_RATIO_MASK) {
+		debug("%s: Frequency ratio is out of range\n", __func__);
+		debug("src frq = %d des frq = %d ", src_frq, dst_frq);
+		return -1;
+	}
+	clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
+				(div & AUDIO_1_RATIO_MASK));
+	return 0;
+}
+
 unsigned long get_pll_clk(int pllreg)
 {
 	if (cpu_is_exynos5())
@@ -927,3 +1023,26 @@  int spi_set_clock_rate(enum periph_id periph_id, unsigned int rate)
 	else
 		return 0;
 }
+
+int clock_set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq)
+{
+
+	if (cpu_is_exynos5())
+		return exynos5_clock_set_i2s_clk_prescaler(src_frq, dst_frq);
+	else
+		return 0;
+}
+
+void clock_select_i2s_clk_source(void)
+{
+	if (cpu_is_exynos5())
+		exynos5_clock_select_i2s_clk_source();
+}
+
+int clock_epll_set_rate(unsigned long rate)
+{
+	if (cpu_is_exynos5())
+		return exynos5_clock_epll_set_rate(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 4e51402..f32c634 100644
--- a/arch/arm/include/asm/arch-exynos/clk.h
+++ b/arch/arm/include/asm/arch-exynos/clk.h
@@ -41,4 +41,7 @@  unsigned long get_lcd_clk(void);
 void set_lcd_clk(void);
 void set_mipi_clk(void);
 int spi_set_clock_rate(enum periph_id periph_id, unsigned int rate);
+void clock_select_i2s_clk_source(void);
+int clock_set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq);
+int clock_epll_set_rate(unsigned long rate);
 #endif
diff --git a/arch/arm/include/asm/arch-exynos/clock.h b/arch/arm/include/asm/arch-exynos/clock.h
index fce38ef..1df49a9 100644
--- a/arch/arm/include/asm/arch-exynos/clock.h
+++ b/arch/arm/include/asm/arch-exynos/clock.h
@@ -595,9 +595,38 @@  struct exynos5_clock {
 	unsigned int	pll_div2_sel;
 	unsigned char	res123[0xf5d8];
 };
+
+/* structure for epll configuration used in audio clock configuration */
+struct st_epll_con_val {
+	unsigned int freq_out;		/* frequency out */
+	unsigned int en_lock_det;	/* enable lock detect */
+	unsigned int m_div;		/* m divider value */
+	unsigned int p_div;		/* p divider value */
+	unsigned int s_div;		/* s divider value */
+	unsigned int k_dsm;		/* k value of delta signal modulator */
+};
 #endif
 
 #define MPLL_FOUT_SEL_SHIFT	4
+#define EXYNOS5_EPLLCON0_LOCKED_SHIFT	29  /* EPLL Locked bit position*/
+#define TIMEOUT_EPLL_LOCK		1000
+
+#define AUDIO_0_RATIO_MASK		0x0f
+#define AUDIO_1_RATIO_MASK		0x0f
+
+#define AUDIO1_SEL_MASK			0xf
+#define CLK_SRC_SCLK_EPLL		0x7
+
+/* CON0 bit-fields */
+#define EPLL_CON0_MDIV_MASK		0x1ff
+#define EPLL_CON0_PDIV_MASK		0x3f
+#define EPLL_CON0_SDIV_MASK		0x7
+#define EPLL_CON0_MDIV_SHIFT		16
+#define EPLL_CON0_PDIV_SHIFT		8
+#define EPLL_CON0_SDIV_SHIFT		0
+#define EPLL_CON0_LOCK_DET_EN_SHIFT	28
+#define EPLL_CON0_LOCK_DET_EN_MASK	1
+
 #define MPLL_FOUT_SEL_MASK	0x1
 #define BPLL_FOUT_SEL_SHIFT	0
 #define BPLL_FOUT_SEL_MASK	0x1