From ce18e9671642ba320e79040fe63532045c9e3003 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=BB=84=E6=B6=9B?= Date: Fri, 10 Dec 2010 15:05:05 +0800 Subject: [PATCH] clock: fix aclk_periph parent setup --- arch/arm/mach-rk29/clock.c | 102 +++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/arch/arm/mach-rk29/clock.c b/arch/arm/mach-rk29/clock.c index 19233e70d5e0..2df7835901c0 100755 --- a/arch/arm/mach-rk29/clock.c +++ b/arch/arm/mach-rk29/clock.c @@ -320,9 +320,9 @@ static unsigned long arm_pll_clk_recalc(struct clk *clk) } struct arm_pll_set { - u32 clk_hz; - u32 pll_con; - u32 clksel0_con; + unsigned long rate; + u32 apll_con; + u32 clksel0_con; }; #define CORE_ACLK_11 (0 << 5) @@ -343,22 +343,23 @@ struct arm_pll_set { #define ACLK_PCLK_81 (3 << 10) #define ACLK_PCLK_MASK (3 << 10) -#define ARM_PLL(_clk_mhz, nr, nf, no, _axi_div, _ahb_div, _apb_div) \ +#define ARM_PLL(_mhz, nr, nf, no, _axi_div, _ahb_div, _apb_div) \ { \ - .clk_hz = _clk_mhz * MHZ, \ - .pll_con = PLL_CLKR(nr) | PLL_CLKF(nf >> 1) | PLL_NO_##no, \ + .rate = _mhz * MHZ, \ + .apll_con = PLL_CLKR(nr) | PLL_CLKF(nf >> 1) | PLL_NO_##no, \ .clksel0_con = CORE_ACLK_##_axi_div | ACLK_HCLK_##_ahb_div | ACLK_PCLK_##_apb_div, \ } static const struct arm_pll_set arm_pll[] = { - // clk_mhz = 24 * NF / (NR * NO) - // mhz NR NF NO adiv hdiv pdiv -// ARM_PLL(600, 1, 50, 2, 21, 21, 41), - ARM_PLL(624, 1, 52, 2, 21, 21, 41), -// ARM_PLL(720, 1, 60, 2, 21, 21, 41), -// ARM_PLL(1008, 1, 42, 1, 31, 21, 41), + // rate = 24 * NF / (NR * NO) + // rate NR NF NO adiv hdiv pdiv + ARM_PLL(1008, 1, 42, 1, 31, 21, 81), + ARM_PLL( 960, 1, 40, 1, 31, 21, 81), + ARM_PLL( 912, 1, 38, 1, 31, 21, 41), + ARM_PLL( 888, 2, 74, 1, 31, 21, 41), + ARM_PLL( 624, 1, 52, 2, 21, 21, 41), // last item, pll power down. - ARM_PLL( 24, 1, 64, 8, 21, 21, 41), + ARM_PLL( 24, 1, 64, 8, 21, 21, 41), }; #define CORE_PARENT_MASK (3 << 23) @@ -367,7 +368,23 @@ static const struct arm_pll_set arm_pll[] = { static int arm_pll_clk_set_rate(struct clk *clk, unsigned long rate) { - u32 v = arm_pll[0].pll_con; + const struct arm_pll_set *ps, *pt; + int i; + + /* find the arm_pll we want. */ + ps = pt = &arm_pll[0]; + while (1) { + if (pt->rate == rate) { + ps = pt; + break; + } + // we are sorted, and ps->rate > pt->rate. + if ((pt->rate > rate || (rate - pt->rate < ps->rate - rate))) + ps = pt; + if (pt->rate < rate || pt->rate == 24 * MHZ) + break; + pt++; + } /* make aclk safe & reparent to periph pll */ cru_writel((cru_readl(CRU_CLKSEL0_CON) & ~(CORE_PARENT_MASK | CORE_ACLK_MASK)) | CORE_PARENT_PERIPH_PLL | CORE_ACLK_21, CRU_CLKSEL0_CON); @@ -375,27 +392,27 @@ static int arm_pll_clk_set_rate(struct clk *clk, unsigned long rate) /* enter slow mode */ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CPU_MODE_MASK) | CRU_CPU_MODE_SLOW, CRU_MODE_CON); - pll_wait_lock(ARM_PLL_IDX, 2400000); - /* power down */ cru_writel(cru_readl(CRU_APLL_CON) | PLL_PD, CRU_APLL_CON); delay_500ns(); - cru_writel(v | PLL_PD, CRU_APLL_CON); + cru_writel(ps->apll_con | PLL_PD, CRU_APLL_CON); delay_500ns(); /* power up */ - cru_writel(v, CRU_APLL_CON); + cru_writel(ps->apll_con, CRU_APLL_CON); + for (i = 0; i < 600; i++) + delay_500ns(); pll_wait_lock(ARM_PLL_IDX, 2400000); /* enter normal mode */ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CPU_MODE_MASK) | CRU_CPU_MODE_NORMAL, CRU_MODE_CON); /* reparent to arm pll & set aclk/hclk/pclk */ - cru_writel((cru_readl(CRU_CLKSEL0_CON) & ~(CORE_PARENT_MASK | CORE_ACLK_MASK | ACLK_HCLK_MASK | ACLK_PCLK_MASK)) | CORE_PARENT_ARM_PLL | arm_pll[0].clksel0_con, CRU_CLKSEL0_CON); + cru_writel((cru_readl(CRU_CLKSEL0_CON) & ~(CORE_PARENT_MASK | CORE_ACLK_MASK | ACLK_HCLK_MASK | ACLK_PCLK_MASK)) | CORE_PARENT_ARM_PLL | ps->clksel0_con, CRU_CLKSEL0_CON); return 0; } @@ -477,14 +494,13 @@ static unsigned long periph_pll_clk_recalc(struct clk *clk) static int periph_pll_clk_set_rate(struct clk *clk, unsigned long rate) { + int i; /* 624M: high-band, NR=1, NF=26, NO=1 */ u32 v = PLL_HIGH_BAND | PLL_CLKR(1) | PLL_CLKF(26) | PLL_NO_1; /* enter slow mode */ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_PERIPH_MODE_MASK) | CRU_PERIPH_MODE_SLOW, CRU_MODE_CON); - pll_wait_lock(PERIPH_PLL_IDX, 2400000); - /* power down */ cru_writel(cru_readl(CRU_PPLL_CON) | PLL_PD, CRU_PPLL_CON); @@ -497,6 +513,8 @@ static int periph_pll_clk_set_rate(struct clk *clk, unsigned long rate) /* power up */ cru_writel(v, CRU_PPLL_CON); + for (i = 0; i < 600; i++) + delay_500ns(); pll_wait_lock(PERIPH_PLL_IDX, 2400000); /* enter normal mode */ @@ -512,6 +530,7 @@ static struct clk periph_pll_clk = { .set_rate = periph_pll_clk_set_rate, }; +static struct clk *clk_core_parents[4] = { &arm_pll_clk, &periph_pll_clk, &codec_pll_clk, &ddr_pll_clk }; static struct clk clk_core = { .name = "core", @@ -520,6 +539,9 @@ static struct clk clk_core = { .clksel_con = CRU_CLKSEL0_CON, .clksel_mask = 0x1F, .clksel_shift = 0, + .clksel_parent_mask = 3, + .clksel_parent_shift = 23, + .parents = clk_core_parents, }; static unsigned long aclk_cpu_recalc(struct clk *clk) @@ -564,16 +586,20 @@ static struct clk pclk_cpu = { .clksel_maxdiv = 8, }; +static struct clk *aclk_periph_parents[4] = { &periph_pll_clk, &arm_pll_clk, &ddr_pll_clk, &codec_pll_clk }; + static struct clk aclk_periph = { .name = "aclk_periph", .mode = gate_mode, .gate_idx = CLK_GATE_PEIRPH_AXI, - .parent = &periph_pll_clk, .recalc = clksel_recalc_div, .set_rate = clksel_set_rate_div, .clksel_con = CRU_CLKSEL0_CON, .clksel_mask = 0x1F, .clksel_shift = 14, + .clksel_parent_mask = 3, + .clksel_parent_shift = 12, + .parents = aclk_periph_parents, }; static struct clk pclk_periph = { @@ -2068,30 +2094,30 @@ static void rk29_clock_common_init(void) { /* periph pll */ clk_set_rate_nolock(&periph_pll_clk, 624 * MHZ); - clk_set_parent_nolock(&aclk_periph, &periph_pll_clk); // default - clk_set_rate_nolock(&aclk_periph, 312 * MHZ); // default - clk_set_rate_nolock(&hclk_periph, 156 * MHZ); // default - clk_set_rate_nolock(&pclk_periph, 78 * MHZ); // default - clk_set_parent_nolock(&clk_uhost, &periph_pll_clk); // default + clk_set_parent_nolock(&aclk_periph, &periph_pll_clk); + clk_set_rate_nolock(&aclk_periph, 312 * MHZ); + clk_set_rate_nolock(&hclk_periph, 156 * MHZ); + clk_set_rate_nolock(&pclk_periph, 78 * MHZ); + clk_set_parent_nolock(&clk_uhost, &periph_pll_clk); clk_set_rate_nolock(&clk_uhost, 48 * MHZ); - clk_set_parent_nolock(&clk_i2s0_div, &periph_pll_clk); // default - clk_set_parent_nolock(&clk_i2s1_div, &periph_pll_clk); // default - clk_set_parent_nolock(&clk_spdif_div, &periph_pll_clk); // default - clk_set_parent_nolock(&clk_spi_src, &periph_pll_clk); // default + clk_set_parent_nolock(&clk_i2s0_div, &periph_pll_clk); + clk_set_parent_nolock(&clk_i2s1_div, &periph_pll_clk); + clk_set_parent_nolock(&clk_spdif_div, &periph_pll_clk); + clk_set_parent_nolock(&clk_spi_src, &periph_pll_clk); clk_set_parent_nolock(&clk_sdmmc_src, &periph_pll_clk); - clk_set_parent_nolock(&clk_uart01_src, &periph_pll_clk); // default - clk_set_parent_nolock(&clk_uart23_src, &periph_pll_clk); // default + clk_set_parent_nolock(&clk_uart01_src, &periph_pll_clk); + clk_set_parent_nolock(&clk_uart23_src, &periph_pll_clk); clk_set_parent_nolock(&dclk_lcdc_div, &periph_pll_clk); clk_set_parent_nolock(&aclk_lcdc, &periph_pll_clk); - clk_set_parent_nolock(&aclk_vepu, &periph_pll_clk); // default - clk_set_parent_nolock(&aclk_vdpu, &periph_pll_clk); // default - clk_set_parent_nolock(&clk_gpu, &periph_pll_clk); // default - clk_set_parent_nolock(&aclk_gpu, &periph_pll_clk); // default + clk_set_parent_nolock(&aclk_vepu, &periph_pll_clk); + clk_set_parent_nolock(&aclk_vdpu, &periph_pll_clk); + clk_set_parent_nolock(&clk_gpu, &periph_pll_clk); + clk_set_parent_nolock(&aclk_gpu, &periph_pll_clk); clk_set_parent_nolock(&clk_mac_ref_div, &periph_pll_clk); clk_set_parent_nolock(&clk_hsadc_div, &periph_pll_clk); /* arm pll */ - clk_set_rate_nolock(&arm_pll_clk, 600 * MHZ); + clk_set_rate_nolock(&arm_pll_clk, 624 * MHZ); } void __init rk29_clock_init(void) -- 2.34.1