EXYNOS: Add clock for I2S
This patch adds clock support for I2S Signed-off-by: R. Chandrasekar <rcsekar@samsung.com> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com> Acked-by: Simon Glass <sjg@chromium.org> Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
This commit is contained in:
parent
87fa491aee
commit
2e206caaa6
@ -26,6 +26,17 @@
|
|||||||
#include <asm/arch/clock.h>
|
#include <asm/arch/clock.h>
|
||||||
#include <asm/arch/clk.h>
|
#include <asm/arch/clk.h>
|
||||||
|
|
||||||
|
/* Epll Clock division values to achive different frequency output */
|
||||||
|
static struct set_epll_con_val exynos5_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 }
|
||||||
|
};
|
||||||
|
|
||||||
/* exynos: return pll clock frequency */
|
/* exynos: return pll clock frequency */
|
||||||
static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
|
static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
|
||||||
{
|
{
|
||||||
@ -706,6 +717,93 @@ static unsigned long exynos5_get_i2c_clk(void)
|
|||||||
return aclk_66;
|
return aclk_66;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int exynos5_set_epll_clk(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(exynos5_epll_div); i++) {
|
||||||
|
if (exynos5_epll_div[i].freq_out == rate)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == ARRAY_SIZE(exynos5_epll_div))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
epll_con_k = exynos5_epll_div[i].k_dsm << 0;
|
||||||
|
epll_con |= exynos5_epll_div[i].en_lock_det <<
|
||||||
|
EPLL_CON0_LOCK_DET_EN_SHIFT;
|
||||||
|
epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
|
||||||
|
epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
|
||||||
|
epll_con |= exynos5_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 * exynos5_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_set_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_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)
|
unsigned long get_pll_clk(int pllreg)
|
||||||
{
|
{
|
||||||
if (cpu_is_exynos5())
|
if (cpu_is_exynos5())
|
||||||
@ -777,3 +875,26 @@ void set_mipi_clk(void)
|
|||||||
if (cpu_is_exynos4())
|
if (cpu_is_exynos4())
|
||||||
exynos4_set_mipi_clk();
|
exynos4_set_mipi_clk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (cpu_is_exynos5())
|
||||||
|
return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_i2s_clk_source(void)
|
||||||
|
{
|
||||||
|
if (cpu_is_exynos5())
|
||||||
|
exynos5_set_i2s_clk_source();
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_epll_clk(unsigned long rate)
|
||||||
|
{
|
||||||
|
if (cpu_is_exynos5())
|
||||||
|
return exynos5_set_epll_clk(rate);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -38,5 +38,8 @@ void set_mmc_clk(int dev_index, unsigned int div);
|
|||||||
unsigned long get_lcd_clk(void);
|
unsigned long get_lcd_clk(void);
|
||||||
void set_lcd_clk(void);
|
void set_lcd_clk(void);
|
||||||
void set_mipi_clk(void);
|
void set_mipi_clk(void);
|
||||||
|
void set_i2s_clk_source(void);
|
||||||
|
int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq);
|
||||||
|
int set_epll_clk(unsigned long rate);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -595,9 +595,38 @@ struct exynos5_clock {
|
|||||||
unsigned int pll_div2_sel;
|
unsigned int pll_div2_sel;
|
||||||
unsigned char res123[0xf5d8];
|
unsigned char res123[0xf5d8];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* structure for epll configuration used in audio clock configuration */
|
||||||
|
struct set_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
|
#endif
|
||||||
|
|
||||||
#define MPLL_FOUT_SEL_SHIFT 4
|
#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 MPLL_FOUT_SEL_MASK 0x1
|
||||||
#define BPLL_FOUT_SEL_SHIFT 0
|
#define BPLL_FOUT_SEL_SHIFT 0
|
||||||
#define BPLL_FOUT_SEL_MASK 0x1
|
#define BPLL_FOUT_SEL_MASK 0x1
|
||||||
|
Loading…
Reference in New Issue
Block a user