From 321cd7879f721c2532fc607058253222e91e74de Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=BB=84=E6=B6=9B?= Date: Thu, 30 Dec 2010 13:56:41 +0800 Subject: [PATCH] rk29: gpu clock bump to 552M; support codec pll on/off --- arch/arm/mach-rk29/clock.c | 168 ++++++++++++------ arch/arm/mach-rk29/cpufreq.c | 4 +- .../os/linux/kernel/gc_hal_kernel_driver.c | 2 +- 3 files changed, 112 insertions(+), 62 deletions(-) diff --git a/arch/arm/mach-rk29/clock.c b/arch/arm/mach-rk29/clock.c index 1a21c18e5afa..33bec46d9565 100755 --- a/arch/arm/mach-rk29/clock.c +++ b/arch/arm/mach-rk29/clock.c @@ -58,22 +58,22 @@ #define CRU_CPU_MODE_MASK (0x03u << 0) #define CRU_CPU_MODE_SLOW (0x00u << 0) #define CRU_CPU_MODE_NORMAL (0x01u << 0) -#define CRU_CPU_MODE_DSLOW (0x02u << 0) +#define CRU_CPU_MODE_SLOW27 (0x02u << 0) #define CRU_GENERAL_MODE_MASK (0x03u << 2) #define CRU_GENERAL_MODE_SLOW (0x00u << 2) #define CRU_GENERAL_MODE_NORMAL (0x01u << 2) -#define CRU_GENERAL_MODE_DSLOW (0x02u << 2) +#define CRU_GENERAL_MODE_SLOW27 (0x02u << 2) #define CRU_CODEC_MODE_MASK (0x03u << 4) #define CRU_CODEC_MODE_SLOW (0x00u << 4) #define CRU_CODEC_MODE_NORMAL (0x01u << 4) -#define CRU_CODEC_MODE_DSLOW (0x02u << 4) +#define CRU_CODEC_MODE_SLOW27 (0x02u << 4) #define CRU_DDR_MODE_MASK (0x03u << 6) #define CRU_DDR_MODE_SLOW (0x00u << 6) #define CRU_DDR_MODE_NORMAL (0x01u << 6) -#define CRU_DDR_MODE_DSLOW (0x02u << 6) +#define CRU_DDR_MODE_SLOW27 (0x02u << 6) /* Clock flags */ /* bit 0 is free */ @@ -82,7 +82,6 @@ #define cru_readl(offset) readl(RK29_CRU_BASE + offset) #define cru_writel(v, offset) writel(v, RK29_CRU_BASE + offset) -#define cru_writel_force(v, offset) do { u32 _v = v; u32 _count = 5; do { cru_writel(_v, offset); } while (cru_readl(offset) != _v && _count--); } while (0) /* huangtao: when write CRU_xPLL_CON, first time may failed, so try again. unknown why. */ #define regfile_readl(offset) readl(RK29_GRF_BASE + offset) #define pmu_readl(offset) readl(RK29_PMU_BASE + offset) @@ -298,9 +297,10 @@ static void delay_300us(void) #define DDR_PLL_IDX 3 #define GRF_SOC_CON0 0xbc -static void pll_wait_lock(int pll_idx, int delay) +static void pll_wait_lock(int pll_idx) { u32 bit = 0x2000000u << pll_idx; + int delay = 2400000; while (delay > 0) { if (regfile_readl(GRF_SOC_CON0) & bit) break; @@ -423,7 +423,7 @@ static int arm_pll_clk_set_rate(struct clk *clk, unsigned long rate) cru_writel(ps->apll_con, CRU_APLL_CON); delay_300us(); - pll_wait_lock(ARM_PLL_IDX, 2400000); + pll_wait_lock(ARM_PLL_IDX); /* 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 | ps->clksel0_con, CRU_CLKSEL0_CON); @@ -478,21 +478,31 @@ static struct clk ddr_pll_clk = { }; -static unsigned long codec_pll_clk_recalc(struct clk *clk) +static int codec_pll_clk_mode(struct clk *clk, int on) { - unsigned long rate; - - if ((cru_readl(CRU_MODE_CON) & CRU_CODEC_MODE_MASK) == CRU_CODEC_MODE_NORMAL) { - u32 v = cru_readl(CRU_CPLL_CON); - u64 rate64 = (u64) clk->parent->rate * PLL_NF(v); - do_div(rate64, PLL_NR(v)); - rate = rate64 >> PLL_NO_SHIFT(v); - pr_debug("%s new clock rate is %ld (NF %d NR %d NO %d)\n", clk->name, rate, PLL_NF(v), PLL_NR(v), 1 << PLL_NO_SHIFT(v)); + if (on) { + cru_writel(cru_readl(CRU_CPLL_CON) & ~PLL_PD, CRU_CPLL_CON); + delay_300us(); + pll_wait_lock(CODEC_PLL_IDX); + cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | CRU_CODEC_MODE_NORMAL, CRU_MODE_CON); } else { - rate = clk->parent->rate; - pr_debug("%s new clock rate is %ld (slow mode)\n", clk->name, rate); + cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | CRU_CODEC_MODE_SLOW, CRU_MODE_CON); + cru_writel(cru_readl(CRU_CPLL_CON) | PLL_PD, CRU_CPLL_CON); + delay_500ns(); } + return 0; +} +static unsigned long codec_pll_clk_recalc(struct clk *clk) +{ + unsigned long rate; + u32 v = cru_readl(CRU_CPLL_CON); + u64 rate64 = (u64) clk->parent->rate * PLL_NF(v); + do_div(rate64, PLL_NR(v)); + rate = rate64 >> PLL_NO_SHIFT(v); + pr_debug("%s new clock rate is %ld (NF %d NR %d NO %d)\n", clk->name, rate, PLL_NF(v), PLL_NR(v), 1 << PLL_NO_SHIFT(v)); + if ((cru_readl(CRU_MODE_CON) & CRU_CODEC_MODE_MASK) != CRU_CODEC_MODE_NORMAL) + pr_debug("%s rate is %ld (slow mode) actually\n", clk->name, clk->parent->rate); return rate; } @@ -502,64 +512,73 @@ static unsigned long codec_pll_clk_recalc(struct clk *clk) #define CODEC_PLL_PARENT_DDR_PLL (2 << 11) #define CODEC_PLL_PARENT_GENERAL_PLL (3 << 11) +struct codec_pll_set { + unsigned long rate; + u32 pll_con; + u32 parent_con; +}; + +#define CODEC_PLL(_mhz, _parent, band, nr, nf, no) \ +{ \ + .rate = _mhz * MHZ, \ + .pll_con = PLL_##band##_BAND | PLL_CLKR(nr) | PLL_CLKF(nf) | PLL_NO_##no, \ + .parent_con = CODEC_PLL_PARENT_XIN##_parent##M, \ +} + +static const struct codec_pll_set codec_pll[] = { + // rate parent band NR NF NO + CODEC_PLL(108, 24, LOW, 1, 18, 4), // for TV + CODEC_PLL(648, 24, HIGH, 1, 27, 1), + CODEC_PLL(297, 27, LOW, 1, 22, 2), // for HDMI + CODEC_PLL(594, 27, LOW, 1, 22, 1), + CODEC_PLL(360, 24, LOW, 1, 15, 1), // for GPU + CODEC_PLL(408, 24, LOW, 1, 17, 1), + CODEC_PLL(456, 24, LOW, 1, 19, 1), + CODEC_PLL(504, 24, LOW, 1, 21, 1), + CODEC_PLL(552, 24, LOW, 1, 23, 1), + CODEC_PLL(600, 24, HIGH, 1, 25, 1), +}; + static int codec_pll_clk_set_rate(struct clk *clk, unsigned long rate) { - u32 pll_con; - u32 mode_con; - struct clk *parent; + int i; + u32 work_mode; - switch (rate) { - case 108 * MHZ: - /* 24 * 18 / 4 */ - pll_con = PLL_LOW_BAND | PLL_CLKR(1) | PLL_CLKF(18) | PLL_NO_4; - mode_con = CODEC_PLL_PARENT_XIN24M; - parent = &xin24m; - break; - case 648 * MHZ: - /* 24 * 27 / 1 */ - pll_con = PLL_HIGH_BAND | PLL_CLKR(1) | PLL_CLKF(27) | PLL_NO_1; - mode_con = CODEC_PLL_PARENT_XIN24M; - parent = &xin24m; - break; - case 297 * MHZ: - /* 27 * 22 / 2 */ - pll_con = PLL_LOW_BAND | PLL_CLKR(1) | PLL_CLKF(22) | PLL_NO_2; - mode_con = CODEC_PLL_PARENT_XIN27M; - parent = &xin27m; - break; - case 594 * MHZ: - /* 27 * 22 / 1 */ - pll_con = PLL_LOW_BAND | PLL_CLKR(1) | PLL_CLKF(22) | PLL_NO_1; - mode_con = CODEC_PLL_PARENT_XIN27M; - parent = &xin27m; - break; - default: - return -ENOENT; - break; + const struct codec_pll_set *ps = NULL; + + for (i = 0; i < ARRAY_SIZE(codec_pll); i++) { + if (codec_pll[i].rate == rate) { + ps = &codec_pll[i]; + break; + } } + if (!ps) + return -ENOENT; + + work_mode = cru_readl(CRU_MODE_CON) & CRU_CODEC_MODE_MASK; /* enter slow mode */ - cru_writel((cru_readl(CRU_MODE_CON) & ~(CRU_CODEC_MODE_MASK | CODEC_PLL_PARENT_MASK)) | CRU_CODEC_MODE_SLOW | mode_con, CRU_MODE_CON); + cru_writel((cru_readl(CRU_MODE_CON) & ~(CRU_CODEC_MODE_MASK | CODEC_PLL_PARENT_MASK)) | CRU_CODEC_MODE_SLOW | ps->parent_con, CRU_MODE_CON); /* power down */ cru_writel(cru_readl(CRU_CPLL_CON) | PLL_PD, CRU_CPLL_CON); delay_500ns(); - cru_writel(pll_con | PLL_PD, CRU_CPLL_CON); + cru_writel(ps->pll_con | PLL_PD, CRU_CPLL_CON); delay_500ns(); /* power up */ - cru_writel(pll_con, CRU_CPLL_CON); + cru_writel(ps->pll_con, CRU_CPLL_CON); delay_300us(); - pll_wait_lock(CODEC_PLL_IDX, 2400000); + pll_wait_lock(CODEC_PLL_IDX); /* enter normal mode */ - cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | CRU_CODEC_MODE_NORMAL, CRU_MODE_CON); + cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | work_mode, CRU_MODE_CON); - clk_set_parent_nolock(clk, parent); + clk_set_parent_nolock(clk, ps->parent_con == CODEC_PLL_PARENT_XIN24M ? &xin24m : &xin27m); return 0; } @@ -569,6 +588,7 @@ static struct clk *codec_pll_parents[4] = { &xin24m, &xin27m, &ddr_pll_clk, &gen static struct clk codec_pll_clk = { .name = "codec_pll", .parent = &xin24m, + .mode = codec_pll_clk_mode, .recalc = codec_pll_clk_recalc, .set_rate = codec_pll_clk_set_rate, .clksel_con = CRU_MODE_CON, @@ -630,7 +650,7 @@ static int general_pll_clk_set_rate(struct clk *clk, unsigned long rate) cru_writel(pll_con, CRU_GPLL_CON); delay_300us(); - pll_wait_lock(GENERAL_PLL_IDX, 2400000); + pll_wait_lock(GENERAL_PLL_IDX); /* enter normal mode */ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_GENERAL_MODE_MASK) | CRU_GENERAL_MODE_NORMAL, CRU_MODE_CON); @@ -2219,7 +2239,7 @@ static void __init rk29_clock_common_init(void) clk_set_parent_nolock(&clk_hsadc_div, &general_pll_clk); /* codec pll */ - clk_set_rate_nolock(&codec_pll_clk, 648 * MHZ); + clk_set_rate_nolock(&codec_pll_clk, 552 * MHZ); clk_set_parent_nolock(&clk_gpu, &codec_pll_clk); clk_set_parent_nolock(&clk_mac_ref_div, &codec_pll_clk); @@ -2316,7 +2336,7 @@ static void dump_clock(struct seq_file *s, struct clk *clk, int deep) seq_printf(s, "%-9s ", clk->name); - if (clk->mode && (clk->gate_idx < CLK_GATE_MAX)) { + if ((clk->mode == gate_mode) && (clk->gate_idx < CLK_GATE_MAX)) { u32 reg; int idx = clk->gate_idx; u32 v; @@ -2330,6 +2350,36 @@ static void dump_clock(struct seq_file *s, struct clk *clk, int deep) seq_printf(s, "%s ", v ? "off" : "on "); } + if (clk == &arm_pll_clk) { + switch (cru_readl(CRU_MODE_CON) & CRU_CPU_MODE_MASK) { + case CRU_CPU_MODE_SLOW: seq_printf(s, "slow "); break; + case CRU_CPU_MODE_NORMAL: seq_printf(s, "normal "); break; + case CRU_CPU_MODE_SLOW27: seq_printf(s, "slow27 "); break; + } + if (cru_readl(CRU_APLL_CON) & PLL_BYPASS) seq_printf(s, "bypass "); + } else if (clk == &ddr_pll_clk) { + switch (cru_readl(CRU_MODE_CON) & CRU_DDR_MODE_MASK) { + case CRU_DDR_MODE_SLOW: seq_printf(s, "slow "); break; + case CRU_DDR_MODE_NORMAL: seq_printf(s, "normal "); break; + case CRU_DDR_MODE_SLOW27: seq_printf(s, "slow27 "); break; + } + if (cru_readl(CRU_DPLL_CON) & PLL_BYPASS) seq_printf(s, "bypass "); + } else if (clk == &codec_pll_clk) { + switch (cru_readl(CRU_MODE_CON) & CRU_CODEC_MODE_MASK) { + case CRU_CODEC_MODE_SLOW: seq_printf(s, "slow "); break; + case CRU_CODEC_MODE_NORMAL: seq_printf(s, "normal "); break; + case CRU_CODEC_MODE_SLOW27: seq_printf(s, "slow27 "); break; + } + if (cru_readl(CRU_CPLL_CON) & PLL_BYPASS) seq_printf(s, "bypass "); + } else if (clk == &general_pll_clk) { + switch (cru_readl(CRU_MODE_CON) & CRU_GENERAL_MODE_MASK) { + case CRU_GENERAL_MODE_SLOW: seq_printf(s, "slow "); break; + case CRU_GENERAL_MODE_NORMAL: seq_printf(s, "normal "); break; + case CRU_GENERAL_MODE_SLOW27: seq_printf(s, "slow27 "); break; + } + if (cru_readl(CRU_GPLL_CON) & PLL_BYPASS) seq_printf(s, "bypass "); + } + if (rate >= MHZ) { if (rate % MHZ) seq_printf(s, "%ld.%06ld MHz", rate / MHZ, rate % MHZ); @@ -2365,7 +2415,7 @@ static int proc_clk_show(struct seq_file *s, void *v) } mutex_unlock(&clocks_mutex); - seq_printf(s, "\nRegisters:\n"); + seq_printf(s, "\nCRU Registers:\n"); seq_printf(s, "APLL : 0x%08x\n", cru_readl(CRU_APLL_CON)); seq_printf(s, "DPLL : 0x%08x\n", cru_readl(CRU_DPLL_CON)); seq_printf(s, "CPLL : 0x%08x\n", cru_readl(CRU_CPLL_CON)); diff --git a/arch/arm/mach-rk29/cpufreq.c b/arch/arm/mach-rk29/cpufreq.c index fb8a0b410cf5..907eaa15409b 100755 --- a/arch/arm/mach-rk29/cpufreq.c +++ b/arch/arm/mach-rk29/cpufreq.c @@ -22,9 +22,9 @@ static struct cpufreq_frequency_table freq_table[] = { // { .index = 950000, .frequency = 204000 }, // { .index = 1050000, .frequency = 300000 }, - { .index = 1050000, .frequency = 408000 }, + { .index = 1150000, .frequency = 408000 }, // { .index = 1125000, .frequency = 600000 }, - { .index = 1200000, .frequency = 816000 }, + { .index = 1150000, .frequency = 816000 }, // { .index = 1250000, .frequency = 1008000 }, // { .index = 1300000, .frequency = 1200000 }, { .frequency = CPUFREQ_TABLE_END }, diff --git a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c index b3aa4b627254..5804c10d9e96 100644 --- a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c +++ b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c @@ -501,7 +501,7 @@ static int drv_init(void) return -ENODEV; } /* APMU_GC_156M, APMU_GC_624M, APMU_GC_PLL2, APMU_GC_PLL2_DIV2 currently */ - if (clk_set_rate(clk_gpu, 500000000)) //designed on 500M + if (clk_set_rate(clk_gpu, 552000000)) //designed on 500M { gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER, "[galcore] Can't set core clock."); -- 2.34.1