83ee43f02834d949e7da22d97611c0056ac8debb
[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-3.0 / pm-wip / voltdm / 0006-omap-Make-a-subset-of-dmtimer-functions-into-inline-.patch
1 From 494286a1785de2342d92c78ba26803cdcfccecfb Mon Sep 17 00:00:00 2001
2 From: Tony Lindgren <tony@atomide.com>
3 Date: Tue, 29 Mar 2011 15:54:48 -0700
4 Subject: [PATCH 006/149] omap: Make a subset of dmtimer functions into inline functions
6 This will allow us to share the code between system timer and
7 dmtimer device driver code without having to initialize all the
8 dmtimers early. This change will also make the timer_set_next_event
9 more efficient as the inline functions will optimize the code
10 better for the timer reprogramming.
12 Signed-off-by: Tony Lindgren <tony@atomide.com>
13 Reviewed-by: Kevin Hilman <khilman@ti.com>
14 ---
15 arch/arm/plat-omap/dmtimer.c | 78 ++++---------------
16 arch/arm/plat-omap/include/plat/dmtimer.h | 119 +++++++++++++++++++++++++++++
17 2 files changed, 136 insertions(+), 61 deletions(-)
19 diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
20 index dfdc3b2..7c5cb4e 100644
21 --- a/arch/arm/plat-omap/dmtimer.c
22 +++ b/arch/arm/plat-omap/dmtimer.c
23 @@ -170,11 +170,7 @@ static spinlock_t dm_timer_lock;
24 */
25 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
26 {
27 - if (timer->posted)
28 - while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
29 - & (reg >> WPSHIFT))
30 - cpu_relax();
31 - return readl(timer->io_base + (reg & 0xff));
32 + return __omap_dm_timer_read(timer->io_base, reg, timer->posted);
33 }
35 /*
36 @@ -186,11 +182,7 @@ static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
37 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
38 u32 value)
39 {
40 - if (timer->posted)
41 - while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
42 - & (reg >> WPSHIFT))
43 - cpu_relax();
44 - writel(value, timer->io_base + (reg & 0xff));
45 + __omap_dm_timer_write(timer->io_base, reg, value, timer->posted);
46 }
48 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
49 @@ -209,7 +201,7 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
51 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
52 {
53 - u32 l;
54 + int autoidle = 0, wakeup = 0;
56 if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
57 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
58 @@ -217,28 +209,21 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
59 }
60 omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
62 - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
63 - l |= 0x02 << 3; /* Set to smart-idle mode */
64 - l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
65 -
66 /* Enable autoidle on OMAP2 / OMAP3 */
67 if (cpu_is_omap24xx() || cpu_is_omap34xx())
68 - l |= 0x1 << 0;
69 + autoidle = 1;
71 /*
72 * Enable wake-up on OMAP2 CPUs.
73 */
74 if (cpu_class_is_omap2())
75 - l |= 1 << 2;
76 - omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
77 + wakeup = 1;
79 - /* Match hardware reset default of posted mode */
80 - omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
81 - OMAP_TIMER_CTRL_POSTED);
82 + __omap_dm_timer_reset(timer->io_base, autoidle, wakeup);
83 timer->posted = 1;
84 }
86 -static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
87 +void omap_dm_timer_prepare(struct omap_dm_timer *timer)
88 {
89 omap_dm_timer_enable(timer);
90 omap_dm_timer_reset(timer);
91 @@ -410,25 +395,13 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_start);
93 void omap_dm_timer_stop(struct omap_dm_timer *timer)
94 {
95 - u32 l;
96 + unsigned long rate = 0;
98 - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
99 - if (l & OMAP_TIMER_CTRL_ST) {
100 - l &= ~0x1;
101 - omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
102 #ifdef CONFIG_ARCH_OMAP2PLUS
103 - /* Readback to make sure write has completed */
104 - omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
105 - /*
106 - * Wait for functional clock period x 3.5 to make sure that
107 - * timer is stopped
108 - */
109 - udelay(3500000 / clk_get_rate(timer->fclk) + 1);
110 + rate = clk_get_rate(timer->fclk);
111 #endif
112 - }
113 - /* Ack possibly pending interrupt */
114 - omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
115 - OMAP_TIMER_INT_OVERFLOW);
116 +
117 + __omap_dm_timer_stop(timer->io_base, timer->posted, rate);
118 }
119 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
121 @@ -451,22 +424,11 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
123 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
124 {
125 - int ret = -EINVAL;
126 -
127 if (source < 0 || source >= 3)
128 return -EINVAL;
130 - clk_disable(timer->fclk);
131 - ret = clk_set_parent(timer->fclk, dm_source_clocks[source]);
132 - clk_enable(timer->fclk);
133 -
134 - /*
135 - * When the functional clock disappears, too quick writes seem
136 - * to cause an abort. XXX Is this still necessary?
137 - */
138 - __delay(300000);
139 -
140 - return ret;
141 + return __omap_dm_timer_set_source(timer->fclk,
142 + dm_source_clocks[source]);
143 }
144 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
146 @@ -504,8 +466,7 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
147 }
148 l |= OMAP_TIMER_CTRL_ST;
150 - omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load);
151 - omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
152 + __omap_dm_timer_load_start(timer->io_base, l, load, timer->posted);
153 }
154 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
156 @@ -558,8 +519,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
157 void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
158 unsigned int value)
159 {
160 - omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
161 - omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value);
162 + __omap_dm_timer_int_enable(timer->io_base, value);
163 }
164 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
166 @@ -575,17 +535,13 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
168 void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
169 {
170 - omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
171 + __omap_dm_timer_write_status(timer->io_base, value);
172 }
173 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
175 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
176 {
177 - unsigned int l;
178 -
179 - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
180 -
181 - return l;
182 + return __omap_dm_timer_read_counter(timer->io_base, timer->posted);
183 }
184 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
186 diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
187 index 3203105..54664a7 100644
188 --- a/arch/arm/plat-omap/include/plat/dmtimer.h
189 +++ b/arch/arm/plat-omap/include/plat/dmtimer.h
190 @@ -32,6 +32,9 @@
191 * 675 Mass Ave, Cambridge, MA 02139, USA.
192 */
194 +#include <linux/clk.h>
195 +#include <linux/delay.h>
196 +
197 #ifndef __ASM_ARCH_DMTIMER_H
198 #define __ASM_ARCH_DMTIMER_H
200 @@ -218,4 +221,120 @@ struct omap_dm_timer {
201 unsigned posted:1;
202 };
204 +void omap_dm_timer_prepare(struct omap_dm_timer *timer);
205 +
206 +static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg,
207 + int posted)
208 +{
209 + if (posted)
210 + while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
211 + & (reg >> WPSHIFT))
212 + cpu_relax();
213 +
214 + return __raw_readl(base + (reg & 0xff));
215 +}
216 +
217 +static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
218 + int posted)
219 +{
220 + if (posted)
221 + while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
222 + & (reg >> WPSHIFT))
223 + cpu_relax();
224 +
225 + __raw_writel(val, base + (reg & 0xff));
226 +}
227 +
228 +/* Assumes the source clock has been set by caller */
229 +static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
230 + int wakeup)
231 +{
232 + u32 l;
233 +
234 + l = __omap_dm_timer_read(base, OMAP_TIMER_OCP_CFG_REG, 0);
235 + l |= 0x02 << 3; /* Set to smart-idle mode */
236 + l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
237 +
238 + if (autoidle)
239 + l |= 0x1 << 0;
240 +
241 + if (wakeup)
242 + l |= 1 << 2;
243 +
244 + __omap_dm_timer_write(base, OMAP_TIMER_OCP_CFG_REG, l, 0);
245 +
246 + /* Match hardware reset default of posted mode */
247 + __omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG,
248 + OMAP_TIMER_CTRL_POSTED, 0);
249 +}
250 +
251 +static inline int __omap_dm_timer_set_source(struct clk *timer_fck,
252 + struct clk *parent)
253 +{
254 + int ret;
255 +
256 + clk_disable(timer_fck);
257 + ret = clk_set_parent(timer_fck, parent);
258 + clk_enable(timer_fck);
259 +
260 + /*
261 + * When the functional clock disappears, too quick writes seem
262 + * to cause an abort. XXX Is this still necessary?
263 + */
264 + __delay(300000);
265 +
266 + return ret;
267 +}
268 +
269 +static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
270 + unsigned long rate)
271 +{
272 + u32 l;
273 +
274 + l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
275 + if (l & OMAP_TIMER_CTRL_ST) {
276 + l &= ~0x1;
277 + __omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, l, posted);
278 +#ifdef CONFIG_ARCH_OMAP2PLUS
279 + /* Readback to make sure write has completed */
280 + __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
281 + /*
282 + * Wait for functional clock period x 3.5 to make sure that
283 + * timer is stopped
284 + */
285 + udelay(3500000 / rate + 1);
286 +#endif
287 + }
288 +
289 + /* Ack possibly pending interrupt */
290 + __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG,
291 + OMAP_TIMER_INT_OVERFLOW, 0);
292 +}
293 +
294 +static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl,
295 + unsigned int load, int posted)
296 +{
297 + __omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG, load, posted);
298 + __omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, ctrl, posted);
299 +}
300 +
301 +static inline void __omap_dm_timer_int_enable(void __iomem *base,
302 + unsigned int value)
303 +{
304 + __omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG, value, 0);
305 + __omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
306 +}
307 +
308 +static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base,
309 + int posted)
310 +{
311 + return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG, posted);
312 +}
313 +
314 +static inline void __omap_dm_timer_write_status(void __iomem *base,
315 + unsigned int value)
316 +{
317 + __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, value, 0);
318 +}
319 +
320 #endif /* __ASM_ARCH_DMTIMER_H */
321 --
322 1.6.6.1