aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/plat-omap/dmtimer.c75
1 files changed, 62 insertions, 13 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 50524436de63..fb2a23e7c172 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -79,6 +79,9 @@ struct omap_dm_timer {
79 79
80#ifdef CONFIG_ARCH_OMAP1 80#ifdef CONFIG_ARCH_OMAP1
81 81
82#define omap_dm_clk_enable(x)
83#define omap_dm_clk_disable(x)
84
82static struct omap_dm_timer dm_timers[] = { 85static struct omap_dm_timer dm_timers[] = {
83 { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 }, 86 { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
84 { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 }, 87 { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
@@ -92,6 +95,9 @@ static struct omap_dm_timer dm_timers[] = {
92 95
93#elif defined(CONFIG_ARCH_OMAP2) 96#elif defined(CONFIG_ARCH_OMAP2)
94 97
98#define omap_dm_clk_enable(x) clk_enable(x)
99#define omap_dm_clk_disable(x) clk_disable(x)
100
95static struct omap_dm_timer dm_timers[] = { 101static struct omap_dm_timer dm_timers[] = {
96 { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 }, 102 { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
97 { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 }, 103 { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
@@ -168,11 +174,15 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
168 174
169static void omap_dm_timer_prepare(struct omap_dm_timer *timer) 175static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
170{ 176{
171#ifdef CONFIG_ARCH_OMAP2 177 omap_dm_clk_enable(timer->fclk);
172 clk_enable(timer->iclk); 178 omap_dm_clk_enable(timer->iclk);
173 clk_enable(timer->fclk); 179
174#endif
175 omap_dm_timer_reset(timer); 180 omap_dm_timer_reset(timer);
181
182 /* Leave iclk enabled for GPT1 as it is needed for the
183 * system timer to work properly. */
184 if (timer != &dm_timers[0])
185 omap_dm_clk_disable(timer->iclk);
176} 186}
177 187
178struct omap_dm_timer *omap_dm_timer_request(void) 188struct omap_dm_timer *omap_dm_timer_request(void)
@@ -223,11 +233,14 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
223 233
224void omap_dm_timer_free(struct omap_dm_timer *timer) 234void omap_dm_timer_free(struct omap_dm_timer *timer)
225{ 235{
236 omap_dm_clk_enable(timer->iclk);
226 omap_dm_timer_reset(timer); 237 omap_dm_timer_reset(timer);
227#ifdef CONFIG_ARCH_OMAP2 238 omap_dm_clk_disable(timer->iclk);
228 clk_disable(timer->iclk); 239
229 clk_disable(timer->fclk); 240 if (timer == &dm_timers[0])
230#endif 241 omap_dm_clk_disable(timer->iclk);
242 omap_dm_clk_disable(timer->fclk);
243
231 WARN_ON(!timer->reserved); 244 WARN_ON(!timer->reserved);
232 timer->reserved = 0; 245 timer->reserved = 0;
233} 246}
@@ -276,7 +289,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
276 289
277struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) 290struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
278{ 291{
279 return timer->fclk; 292 return timer->fclk;
280} 293}
281 294
282__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) 295__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
@@ -288,29 +301,35 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
288 301
289void omap_dm_timer_trigger(struct omap_dm_timer *timer) 302void omap_dm_timer_trigger(struct omap_dm_timer *timer)
290{ 303{
304 omap_dm_clk_enable(timer->iclk);
291 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); 305 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
306 omap_dm_clk_disable(timer->iclk);
292} 307}
293 308
294void omap_dm_timer_start(struct omap_dm_timer *timer) 309void omap_dm_timer_start(struct omap_dm_timer *timer)
295{ 310{
296 u32 l; 311 u32 l;
297 312
313 omap_dm_clk_enable(timer->iclk);
298 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 314 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
299 if (!(l & OMAP_TIMER_CTRL_ST)) { 315 if (!(l & OMAP_TIMER_CTRL_ST)) {
300 l |= OMAP_TIMER_CTRL_ST; 316 l |= OMAP_TIMER_CTRL_ST;
301 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 317 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
302 } 318 }
319 omap_dm_clk_disable(timer->iclk);
303} 320}
304 321
305void omap_dm_timer_stop(struct omap_dm_timer *timer) 322void omap_dm_timer_stop(struct omap_dm_timer *timer)
306{ 323{
307 u32 l; 324 u32 l;
308 325
326 omap_dm_clk_enable(timer->iclk);
309 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 327 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
310 if (l & OMAP_TIMER_CTRL_ST) { 328 if (l & OMAP_TIMER_CTRL_ST) {
311 l &= ~0x1; 329 l &= ~0x1;
312 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 330 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
313 } 331 }
332 omap_dm_clk_disable(timer->iclk);
314} 333}
315 334
316#ifdef CONFIG_ARCH_OMAP1 335#ifdef CONFIG_ARCH_OMAP1
@@ -348,6 +367,7 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
348{ 367{
349 u32 l; 368 u32 l;
350 369
370 omap_dm_clk_enable(timer->iclk);
351 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 371 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
352 if (autoreload) 372 if (autoreload)
353 l |= OMAP_TIMER_CTRL_AR; 373 l |= OMAP_TIMER_CTRL_AR;
@@ -356,6 +376,7 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
356 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 376 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
357 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); 377 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
358 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); 378 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
379 omap_dm_clk_disable(timer->iclk);
359} 380}
360 381
361void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, 382void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
@@ -363,6 +384,7 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
363{ 384{
364 u32 l; 385 u32 l;
365 386
387 omap_dm_clk_enable(timer->iclk);
366 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 388 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
367 if (enable) 389 if (enable)
368 l |= OMAP_TIMER_CTRL_CE; 390 l |= OMAP_TIMER_CTRL_CE;
@@ -370,6 +392,7 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
370 l &= ~OMAP_TIMER_CTRL_CE; 392 l &= ~OMAP_TIMER_CTRL_CE;
371 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 393 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
372 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); 394 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
395 omap_dm_clk_disable(timer->iclk);
373} 396}
374 397
375 398
@@ -378,6 +401,7 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
378{ 401{
379 u32 l; 402 u32 l;
380 403
404 omap_dm_clk_enable(timer->iclk);
381 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 405 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
382 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM | 406 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
383 OMAP_TIMER_CTRL_PT | (0x03 << 10)); 407 OMAP_TIMER_CTRL_PT | (0x03 << 10));
@@ -387,12 +411,14 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
387 l |= OMAP_TIMER_CTRL_PT; 411 l |= OMAP_TIMER_CTRL_PT;
388 l |= trigger << 10; 412 l |= trigger << 10;
389 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 413 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
414 omap_dm_clk_disable(timer->iclk);
390} 415}
391 416
392void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) 417void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
393{ 418{
394 u32 l; 419 u32 l;
395 420
421 omap_dm_clk_enable(timer->iclk);
396 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 422 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
397 l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2)); 423 l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
398 if (prescaler >= 0x00 && prescaler <= 0x07) { 424 if (prescaler >= 0x00 && prescaler <= 0x07) {
@@ -400,32 +426,51 @@ void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
400 l |= prescaler << 2; 426 l |= prescaler << 2;
401 } 427 }
402 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 428 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
429 omap_dm_clk_disable(timer->iclk);
403} 430}
404 431
405void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, 432void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
406 unsigned int value) 433 unsigned int value)
407{ 434{
435 omap_dm_clk_enable(timer->iclk);
408 omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value); 436 omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
437 omap_dm_clk_disable(timer->iclk);
409} 438}
410 439
411unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) 440unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
412{ 441{
413 return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); 442 unsigned int l;
443
444 omap_dm_clk_enable(timer->iclk);
445 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
446 omap_dm_clk_disable(timer->iclk);
447
448 return l;
414} 449}
415 450
416void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) 451void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
417{ 452{
453 omap_dm_clk_enable(timer->iclk);
418 omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value); 454 omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
455 omap_dm_clk_disable(timer->iclk);
419} 456}
420 457
421unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) 458unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
422{ 459{
423 return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); 460 unsigned int l;
461
462 omap_dm_clk_enable(timer->iclk);
463 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
464 omap_dm_clk_disable(timer->iclk);
465
466 return l;
424} 467}
425 468
426void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) 469void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
427{ 470{
428 return omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); 471 omap_dm_clk_enable(timer->iclk);
472 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
473 omap_dm_clk_disable(timer->iclk);
429} 474}
430 475
431int omap_dm_timers_active(void) 476int omap_dm_timers_active(void)
@@ -436,9 +481,13 @@ int omap_dm_timers_active(void)
436 struct omap_dm_timer *timer; 481 struct omap_dm_timer *timer;
437 482
438 timer = &dm_timers[i]; 483 timer = &dm_timers[i];
484 omap_dm_clk_enable(timer->iclk);
439 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & 485 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
440 OMAP_TIMER_CTRL_ST) 486 OMAP_TIMER_CTRL_ST) {
487 omap_dm_clk_disable(timer->iclk);
441 return 1; 488 return 1;
489 }
490 omap_dm_clk_disable(timer->iclk);
442 } 491 }
443 return 0; 492 return 0;
444} 493}