diff options
author | Juha Yrjola <juha.yrjola@solidboot.com> | 2006-09-25 05:41:50 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2006-09-25 05:41:50 -0400 |
commit | ddc32a87497d8806e361cfe7168f173396fe9219 (patch) | |
tree | 41e4235bb358443fa187b11c49d8d9c418dbff99 /arch/arm | |
parent | dc0d794e488090082b7194738a08f18db0874900 (diff) |
ARM: OMAP2: Make sure peripherals can be accessed after clk_enable
Some peripherals seem to need additional delay until they
can actually be accessed after enabling their FCLK and ICLK.
Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/clock.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index eee273bdd191..26ac49ecb78d 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include "memory.h" | 32 | #include "memory.h" |
33 | #include "clock.h" | 33 | #include "clock.h" |
34 | 34 | ||
35 | #undef DEBUG | ||
36 | |||
35 | //#define DOWN_VARIABLE_DPLL 1 /* Experimental */ | 37 | //#define DOWN_VARIABLE_DPLL 1 /* Experimental */ |
36 | 38 | ||
37 | static struct prcm_config *curr_prcm_set; | 39 | static struct prcm_config *curr_prcm_set; |
@@ -114,9 +116,51 @@ static void omap2_clk_fixed_enable(struct clk *clk) | |||
114 | while (!(CM_IDLEST_CKGEN & cval)) { /* Wait for lock */ | 116 | while (!(CM_IDLEST_CKGEN & cval)) { /* Wait for lock */ |
115 | ++i; | 117 | ++i; |
116 | udelay(1); | 118 | udelay(1); |
117 | if (i == 100000) | 119 | if (i == 100000) { |
120 | printk(KERN_ERR "Clock %s didn't lock\n", clk->name); | ||
121 | break; | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static void omap2_clk_wait_ready(struct clk *clk) | ||
127 | { | ||
128 | unsigned long reg, other_reg, st_reg; | ||
129 | u32 bit; | ||
130 | int i; | ||
131 | |||
132 | reg = (unsigned long) clk->enable_reg; | ||
133 | if (reg == (unsigned long) &CM_FCLKEN1_CORE || | ||
134 | reg == (unsigned long) &CM_FCLKEN2_CORE) | ||
135 | other_reg = (reg & ~0xf0) | 0x10; | ||
136 | else if (reg == (unsigned long) &CM_ICLKEN1_CORE || | ||
137 | reg == (unsigned long) &CM_ICLKEN2_CORE) | ||
138 | other_reg = (reg & ~0xf0) | 0x00; | ||
139 | else | ||
140 | return; | ||
141 | |||
142 | /* No check for DSS or cam clocks */ | ||
143 | if ((reg & 0x0f) == 0) { | ||
144 | if (clk->enable_bit <= 1 || clk->enable_bit == 31) | ||
145 | return; | ||
146 | } | ||
147 | |||
148 | /* Check if both functional and interface clocks | ||
149 | * are running. */ | ||
150 | bit = 1 << clk->enable_bit; | ||
151 | if (!(__raw_readl(other_reg) & bit)) | ||
152 | return; | ||
153 | st_reg = (other_reg & ~0xf0) | 0x20; | ||
154 | i = 0; | ||
155 | while (!(__raw_readl(st_reg) & bit)) { | ||
156 | i++; | ||
157 | if (i == 100000) { | ||
158 | printk(KERN_ERR "Timeout enabling clock %s\n", clk->name); | ||
118 | break; | 159 | break; |
160 | } | ||
119 | } | 161 | } |
162 | if (i) | ||
163 | pr_debug("Clock %s stable after %d loops\n", clk->name, i); | ||
120 | } | 164 | } |
121 | 165 | ||
122 | /* Enables clock without considering parent dependencies or use count | 166 | /* Enables clock without considering parent dependencies or use count |
@@ -150,6 +194,8 @@ static int _omap2_clk_enable(struct clk * clk) | |||
150 | __raw_writel(regval32, clk->enable_reg); | 194 | __raw_writel(regval32, clk->enable_reg); |
151 | wmb(); | 195 | wmb(); |
152 | 196 | ||
197 | omap2_clk_wait_ready(clk); | ||
198 | |||
153 | return 0; | 199 | return 0; |
154 | } | 200 | } |
155 | 201 | ||