diff options
author | Richard Zhao <richard.zhao@freescale.com> | 2010-07-22 17:18:53 +0800 |
---|---|---|
committer | Alan Tull <r80115@freescale.com> | 2010-07-23 09:54:06 -0500 |
commit | 2da9a13f709d5b08f51e243dc9a65a0f6f73c596 (patch) | |
tree | abb8790ee18115eacad21f43752d3eadeaa35a4e /arch | |
parent | ef272cfdb014d4bb7aa8cebb3270aa3f34a77296 (diff) |
ENGR00125458 mx50: Add apll and pfd clock
Add apll and pfd support.
Signed-off-by: Richard Zhao <richard.zhao@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-mx5/clock_mx50.c | 189 | ||||
-rw-r--r-- | arch/arm/mach-mx5/crm_regs.h | 50 |
2 files changed, 223 insertions, 16 deletions
diff --git a/arch/arm/mach-mx5/clock_mx50.c b/arch/arm/mach-mx5/clock_mx50.c index 6bd7fd3b96aa..ea7ba9da4ca4 100644 --- a/arch/arm/mach-mx5/clock_mx50.c +++ b/arch/arm/mach-mx5/clock_mx50.c @@ -39,7 +39,15 @@ static struct clk pll1_main_clk; static struct clk pll1_sw_clk; static struct clk pll2_sw_clk; static struct clk pll3_sw_clk; -static struct clk pll4_sw_clk; +static struct clk apll_clk; +static struct clk pfd0_clk; +static struct clk pfd1_clk; +static struct clk pfd2_clk; +static struct clk pfd3_clk; +static struct clk pfd4_clk; +static struct clk pfd5_clk; +static struct clk pfd6_clk; +static struct clk pfd7_clk; static struct clk lp_apm_clk; static struct clk weim_clk; static struct clk ddr_clk; @@ -52,7 +60,7 @@ static struct cpu_wp *cpu_wp_tbl; static void __iomem *pll1_base; static void __iomem *pll2_base; static void __iomem *pll3_base; -static void __iomem *pll4_base; +static void __iomem *apll_base; extern int cpu_wp_nr; extern int lp_high_freq; @@ -223,8 +231,6 @@ static inline void __iomem *_get_pll_base(struct clk *pll) return pll2_base; else if (pll == &pll3_sw_clk) return pll3_base; - else if (pll == &pll4_sw_clk) - return pll4_base; else BUG(); @@ -246,48 +252,197 @@ static struct clk osc_clk = { .flags = RATE_PROPAGATES, }; +static int apll_enable(struct clk *clk) +{ + __raw_writel(1, apll_base + MXC_ANADIG_MISC_SET); + udelay(10); + return 0; +} + +static void apll_disable(struct clk *clk) +{ + __raw_writel(1, apll_base + MXC_ANADIG_MISC_CLR); +} + static struct clk apll_clk = { .name = "apll", + .rate = 480000000, + .enable = apll_enable, + .disable = apll_disable, .flags = RATE_PROPAGATES, }; +static void pfd_recalc(struct clk *clk) +{ + u32 frac; + u64 rate; + frac = __raw_readl(apll_base + + (int)clk->enable_reg) >> clk->enable_shift; + frac &= MXC_ANADIG_PFD_FRAC_MASK; + rate = (u64)clk->parent->rate * 18; + do_div(rate, frac); + clk->rate = rate; +} + +static unsigned long pfd_round_rate(struct clk *clk, unsigned long rate) +{ + u32 frac; + u64 tmp; + tmp = (u64)clk->parent->rate * 18; + do_div(tmp, rate); + frac = tmp; + frac = frac < 18 ? 18 : frac; + frac = frac > 35 ? 35 : frac; + do_div(tmp, frac); + return tmp; +} + +static int pfd_set_rate(struct clk *clk, unsigned long rate) +{ + u32 frac; + u64 tmp; + tmp = (u64)clk->parent->rate * 18; + do_div(tmp, rate); + frac = tmp; + frac = frac < 18 ? 18 : frac; + frac = frac > 35 ? 35 : frac; + /* clear clk frac bits */ + __raw_writel(MXC_ANADIG_PFD_FRAC_MASK << clk->enable_shift, + apll_base + (int)clk->enable_reg + 8); + /* set clk frac bits */ + __raw_writel(frac << clk->enable_shift, + apll_base + (int)clk->enable_reg + 4); + + tmp = (u64)clk->parent->rate * 18; + do_div(tmp, frac); + clk->rate = tmp; + return 0; +} + +static int pfd_enable(struct clk *clk) +{ + int index; + index = _get_mux8(clk, &pfd0_clk, &pfd1_clk, &pfd2_clk, &pfd3_clk, + &pfd4_clk, &pfd5_clk, &pfd6_clk, &pfd7_clk); + __raw_writel(1 << index, apll_base + MXC_ANADIG_PLLCTRL_CLR); + /* clear clk gate bit */ + __raw_writel((1 << (clk->enable_shift + 7)), + apll_base + (int)clk->enable_reg + 8); + return 0; +} + +static void pfd_disable(struct clk *clk) +{ + int index; + index = _get_mux8(clk, &pfd0_clk, &pfd1_clk, &pfd2_clk, &pfd3_clk, + &pfd4_clk, &pfd5_clk, &pfd6_clk, &pfd7_clk); + /* set clk gate bit */ + __raw_writel((1 << (clk->enable_shift + 7)), + apll_base + (int)clk->enable_reg + 4); + __raw_writel(1 << index, apll_base + MXC_ANADIG_PLLCTRL_SET); +} + static struct clk pfd0_clk = { .name = "pfd0", + .parent = &apll_clk, + .enable_reg = (void *)MXC_ANADIG_FRAC0, + .enable_shift = MXC_ANADIG_PFD0_FRAC_OFFSET, + .recalc = pfd_recalc, + .set_rate = pfd_set_rate, + .round_rate = pfd_round_rate, + .enable = pfd_enable, + .disable = pfd_disable, .flags = RATE_PROPAGATES, }; static struct clk pfd1_clk = { .name = "pfd1", + .parent = &apll_clk, + .enable_reg = (void *)MXC_ANADIG_FRAC0, + .enable_shift = MXC_ANADIG_PFD1_FRAC_OFFSET, + .recalc = pfd_recalc, + .set_rate = pfd_set_rate, + .round_rate = pfd_round_rate, + .enable = pfd_enable, + .disable = pfd_disable, .flags = RATE_PROPAGATES, }; static struct clk pfd2_clk = { .name = "pfd2", + .parent = &apll_clk, + .enable_reg = (void *)MXC_ANADIG_FRAC0, + .enable_shift = MXC_ANADIG_PFD2_FRAC_OFFSET, + .recalc = pfd_recalc, + .set_rate = pfd_set_rate, + .round_rate = pfd_round_rate, + .enable = pfd_enable, + .disable = pfd_disable, .flags = RATE_PROPAGATES, }; static struct clk pfd3_clk = { .name = "pfd3", + .parent = &apll_clk, + .enable_reg = (void *)MXC_ANADIG_FRAC0, + .enable_shift = MXC_ANADIG_PFD3_FRAC_OFFSET, + .recalc = pfd_recalc, + .set_rate = pfd_set_rate, + .round_rate = pfd_round_rate, + .enable = pfd_enable, + .disable = pfd_disable, .flags = RATE_PROPAGATES, }; static struct clk pfd4_clk = { .name = "pfd4", + .parent = &apll_clk, + .enable_reg = (void *)MXC_ANADIG_FRAC1, + .enable_shift = MXC_ANADIG_PFD4_FRAC_OFFSET, + .recalc = pfd_recalc, + .set_rate = pfd_set_rate, + .round_rate = pfd_round_rate, + .enable = pfd_enable, + .disable = pfd_disable, .flags = RATE_PROPAGATES, }; static struct clk pfd5_clk = { .name = "pfd5", + .parent = &apll_clk, + .enable_reg = (void *)MXC_ANADIG_FRAC1, + .enable_shift = MXC_ANADIG_PFD5_FRAC_OFFSET, + .recalc = pfd_recalc, + .set_rate = pfd_set_rate, + .round_rate = pfd_round_rate, + .enable = pfd_enable, + .disable = pfd_disable, .flags = RATE_PROPAGATES, }; static struct clk pfd6_clk = { .name = "pfd6", + .parent = &apll_clk, + .enable_reg = (void *)MXC_ANADIG_FRAC1, + .enable_shift = MXC_ANADIG_PFD6_FRAC_OFFSET, + .recalc = pfd_recalc, + .set_rate = pfd_set_rate, + .round_rate = pfd_round_rate, + .enable = pfd_enable, + .disable = pfd_disable, .flags = RATE_PROPAGATES, }; static struct clk pfd7_clk = { .name = "pfd7", + .parent = &apll_clk, + .enable_reg = (void *)MXC_ANADIG_FRAC1, + .enable_shift = MXC_ANADIG_PFD7_FRAC_OFFSET, + .recalc = pfd_recalc, + .set_rate = pfd_set_rate, + .round_rate = pfd_round_rate, + .enable = pfd_enable, + .disable = pfd_disable, .flags = RATE_PROPAGATES, }; @@ -551,17 +706,6 @@ static struct clk pll3_sw_clk = { .flags = RATE_PROPAGATES, }; -/* same as pll4_main_clk. These two clocks should always be the same */ -static struct clk pll4_sw_clk = { - .name = "pll4", - .parent = &osc_clk, - .set_rate = _clk_pll_set_rate, - .recalc = _clk_pll_recalc, - .enable = _clk_pll_enable, - .disable = _clk_pll_disable, - .flags = RATE_PROPAGATES, -}; - static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent) { u32 reg; @@ -2742,6 +2886,15 @@ static struct clk *mxc_clks[] = { &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, + &apll_clk, + &pfd0_clk, + &pfd1_clk, + &pfd2_clk, + &pfd3_clk, + &pfd4_clk, + &pfd5_clk, + &pfd6_clk, + &pfd7_clk, &ipmux1_clk, &ipmux2_clk, &gpc_dvfs_clk, @@ -2877,6 +3030,7 @@ int __init mx50_clocks_init(unsigned long ckil, unsigned long osc, unsigned long pll1_base = ioremap(MX53_BASE_ADDR(PLL1_BASE_ADDR), SZ_4K); pll2_base = ioremap(MX53_BASE_ADDR(PLL2_BASE_ADDR), SZ_4K); pll3_base = ioremap(MX53_BASE_ADDR(PLL3_BASE_ADDR), SZ_4K); + apll_base = ioremap(ANATOP_BASE_ADDR, SZ_4K); /* Turn off all possible clocks */ if (mxc_jtag_enabled) { @@ -2912,7 +3066,8 @@ int __init mx50_clocks_init(unsigned long ckil, unsigned long osc, unsigned long 3 << MXC_CCM_CCGR6_CG8_OFFSET | 3 << MXC_CCM_CCGR6_CG9_OFFSET | 3 << MXC_CCM_CCGR6_CG12_OFFSET | - 3 << MXC_CCM_CCGR6_CG13_OFFSET , MXC_CCM_CCGR6); + 3 << MXC_CCM_CCGR6_CG13_OFFSET | + 2 << MXC_CCM_CCGR6_CG14_OFFSET, MXC_CCM_CCGR6); __raw_writel(0, MXC_CCM_CCGR7); @@ -2979,6 +3134,8 @@ int __init mx50_clocks_init(unsigned long ckil, unsigned long osc, unsigned long clk_enable(&apbh_dma_clk); + propagate_rate(&apll_clk); + /* Initialise the parents to be axi_b, parents are set to * axi_a when the clocks are enabled. */ diff --git a/arch/arm/mach-mx5/crm_regs.h b/arch/arm/mach-mx5/crm_regs.h index c75d100cf749..623fcc09154d 100644 --- a/arch/arm/mach-mx5/crm_regs.h +++ b/arch/arm/mach-mx5/crm_regs.h @@ -70,6 +70,56 @@ #define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31) #define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF +/* Register addresses of apll and pfd*/ +#define MXC_ANADIG_FRAC0 0x10 +#define MXC_ANADIG_FRAC0_SET 0x14 +#define MXC_ANADIG_FRAC0_CLR 0x18 +#define MXC_ANADIG_FRAC1 0x20 +#define MXC_ANADIG_FRAC1_SET 0x24 +#define MXC_ANADIG_FRAC1_CLR 0x28 +#define MXC_ANADIG_MISC 0x60 +#define MXC_ANADIG_MISC_SET 0x64 +#define MXC_ANADIG_MISC_CLR 0x68 +#define MXC_ANADIG_PLLCTRL 0x70 +#define MXC_ANADIG_PLLCTRL_SET 0x74 +#define MXC_ANADIG_PLLCTRL_CLR 0x78 + +/* apll and pfd Register Bit definitions */ + +#define MXC_ANADIG_PFD3_CLKGATE (1 << 31) +#define MXC_ANADIG_PFD3_STABLE (1 << 30) +#define MXC_ANADIG_PFD3_FRAC_OFFSET 24 +#define MXC_ANADIG_PFD_FRAC_MASK 0x3F +#define MXC_ANADIG_PFD2_CLKGATE (1 << 23) +#define MXC_ANADIG_PFD2_STABLE (1 << 22) +#define MXC_ANADIG_PFD2_FRAC_OFFSET 16 +#define MXC_ANADIG_PFD1_CLKGATE (1 << 15) +#define MXC_ANADIG_PFD1_STABLE (1 << 14) +#define MXC_ANADIG_PFD1_FRAC_OFFSET 8 +#define MXC_ANADIG_PFD0_CLKGATE (1 << 7) +#define MXC_ANADIG_PFD0_STABLE (1 << 6) +#define MXC_ANADIG_PFD0_FRAC_OFFSET 0 + +#define MXC_ANADIG_PFD7_CLKGATE (1 << 31) +#define MXC_ANADIG_PFD7_STABLE (1 << 30) +#define MXC_ANADIG_PFD7_FRAC_OFFSET 24 +#define MXC_ANADIG_PFD6_CLKGATE (1 << 23) +#define MXC_ANADIG_PFD6_STABLE (1 << 22) +#define MXC_ANADIG_PFD6_FRAC_OFFSET 16 +#define MXC_ANADIG_PFD5_CLKGATE (1 << 15) +#define MXC_ANADIG_PFD5_STABLE (1 << 14) +#define MXC_ANADIG_PFD5_FRAC_OFFSET 8 +#define MXC_ANADIG_PFD4_CLKGATE (1 << 7) +#define MXC_ANADIG_PFD4_STABLE (1 << 6) +#define MXC_ANADIG_PFD4_FRAC_OFFSET 0 + +#define MXC_ANADIG_APLL_LOCK (1 << 31) +#define MXC_ANADIG_APLL_FORCE_LOCK (1 << 30) +#define MXC_ANADIG_PFD_DIS_OFFSET (1 << 16) +#define MXC_ANADIG_PFD_DIS_MASK 0xff +#define MXC_ANADIG_APLL_LOCK_CNT_OFFSET 0 +#define MXC_ANADIG_APLL_LOCK_CNT_MASK 0xffff + /* Register addresses of CCM*/ #define MXC_CCM_CCR (MXC_CCM_BASE + 0x00) #define MXC_CCM_CCDR (MXC_CCM_BASE + 0x04) |