diff options
author | Zhou Jingyu <b02241@freescale.com> | 2010-03-31 13:52:20 +0800 |
---|---|---|
committer | Alejandro Gonzalez <alex.gonzalez@digi.com> | 2010-05-25 11:20:19 +0200 |
commit | 1a62b28fe79e53da45263dff1602ab122f9dbe11 (patch) | |
tree | 234a16989bbd4aef4d75bc1760a7b84915371379 /arch/arm/mach-mx23/clock.c | |
parent | c926b11e1ea998a51265088f73f2fa880a7e95c8 (diff) |
ENGR00122161 Add imx23 low power mode
Add imx23 low power mode
Signed-off-by: Zhou Jingyu <Jingyu.Zhou@freescale.com>
Signed-off-by: Alejandro Gonzalez <alex.gonzalez@digi.com>
Diffstat (limited to 'arch/arm/mach-mx23/clock.c')
-rw-r--r-- | arch/arm/mach-mx23/clock.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/arch/arm/mach-mx23/clock.c b/arch/arm/mach-mx23/clock.c index 97b005a5f9f0..da3d4556e45b 100644 --- a/arch/arm/mach-mx23/clock.c +++ b/arch/arm/mach-mx23/clock.c @@ -359,6 +359,68 @@ static struct clk lcdif_clk = { .set_parent = lcdif_set_parent, }; +static struct clk cpu_clk, h_clk; +static int clkseq_set_parent(struct clk *clk, struct clk *parent) +{ + int ret = -EINVAL; + int shift = 8; + + /* bypass? */ + if (parent == &ref_xtal_clk) + shift = 4; + + if (clk->bypass_reg) { + u32 hbus_val, cpu_val; + + if (clk == &cpu_clk && shift == 4) { + hbus_val = __raw_readl(CLKCTRL_BASE_ADDR + + HW_CLKCTRL_HBUS); + cpu_val = __raw_readl(CLKCTRL_BASE_ADDR + + HW_CLKCTRL_CPU); + + hbus_val &= ~(BM_CLKCTRL_HBUS_DIV_FRAC_EN | + BM_CLKCTRL_HBUS_DIV); + hbus_val |= 1; + + cpu_val &= ~BM_CLKCTRL_CPU_DIV_CPU; + cpu_val |= 1; + + __raw_writel(1 << clk->bypass_bits, + clk->bypass_reg + shift); + + __raw_writel(hbus_val, + CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS); + __raw_writel(cpu_val, + CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU); + /* h_clk.rate = 0; */ + } else if (clk == &cpu_clk && shift == 8) { + hbus_val = __raw_readl(CLKCTRL_BASE_ADDR + + HW_CLKCTRL_HBUS); + cpu_val = __raw_readl(CLKCTRL_BASE_ADDR + + HW_CLKCTRL_CPU); + hbus_val &= ~(BM_CLKCTRL_HBUS_DIV_FRAC_EN | + BM_CLKCTRL_HBUS_DIV); + hbus_val |= 2; + cpu_val &= ~BM_CLKCTRL_CPU_DIV_CPU; + cpu_val |= 2; + + __raw_writel(hbus_val, + CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS); + __raw_writel(cpu_val, + CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU); + /* h_clk.rate = 0; */ + + __raw_writel(1 << clk->bypass_bits, + clk->bypass_reg + shift); + } else + __raw_writel(1 << clk->bypass_bits, + clk->bypass_reg + shift); + ret = 0; + } + + return ret; +} + static unsigned long cpu_get_rate(struct clk *clk) { unsigned long reg; @@ -373,7 +435,15 @@ static unsigned long cpu_get_rate(struct clk *clk) static struct clk cpu_clk = { .parent = &ref_cpu_clk, + .scale_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC, + .scale_bits = 0, + .bypass_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ, + .bypass_bits = 7, + .busy_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU, + .busy_bits = 28, +/* .flags = RATE_PROPAGATES | ENABLED,*/ .get_rate = cpu_get_rate, + .set_parent = clkseq_set_parent, }; static unsigned long uart_get_rate(struct clk *clk) |