summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx23/clock.c
diff options
context:
space:
mode:
authorZhou Jingyu <b02241@freescale.com>2010-03-31 13:52:20 +0800
committerAlejandro Gonzalez <alex.gonzalez@digi.com>2010-05-25 11:20:19 +0200
commit1a62b28fe79e53da45263dff1602ab122f9dbe11 (patch)
tree234a16989bbd4aef4d75bc1760a7b84915371379 /arch/arm/mach-mx23/clock.c
parentc926b11e1ea998a51265088f73f2fa880a7e95c8 (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.c70
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)