summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRichard Zhao <richard.zhao@freescale.com>2010-07-22 17:18:53 +0800
committerAlan Tull <r80115@freescale.com>2010-07-23 09:54:06 -0500
commit2da9a13f709d5b08f51e243dc9a65a0f6f73c596 (patch)
treeabb8790ee18115eacad21f43752d3eadeaa35a4e /arch
parentef272cfdb014d4bb7aa8cebb3270aa3f34a77296 (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.c189
-rw-r--r--arch/arm/mach-mx5/crm_regs.h50
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)