aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/timer.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2013-04-08 13:30:48 -0400
committerArnd Bergmann <arnd@arndb.de>2013-04-08 13:30:48 -0400
commitdc2d3db8137fba0f62d7517e1bea8a47f69fcbc4 (patch)
treeaee802680d09fe7c1288138cbfc0db17702e8075 /arch/arm/mach-omap2/timer.c
parent8355ae69afca3b6bcb7b68712f30223455caebda (diff)
parent7f585bbfc54fec9dcf387fd2edb2d6f4908badf8 (diff)
Merge tag 'omap-for-v3.10/timer-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/drivers
From Tony Lindgren <tony@atomide.com>: Clean-up for omap2+ timers from Jon Hunter <jon-hunter@ti.com>: This series consists mainly of clean-ups for clockevents and clocksource timers on OMAP2+ devices. The most significant change in functionality comes from the 5th patch which is changing the selection of the clocksource timer for OMAP3 and AM335x devices when gptimers are used for clocksource. Note that this series depends on 7185684 (ARM: OMAP: use consistent error checking) in RMK's tree and 960cba6 (ARM: OMAP5: timer: Update the clocksource name as per clock data) in omap-for-v3.10/fixes-non-critical. So this branch is based on a merge of 7185684 and omap-for-v3.10/fixes-non-critical to avoid non-trivial merge conflicts. * tag 'omap-for-v3.10/timer-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: ARM: OMAP4+: Fix sparse warning in system timers ARM: OMAP2+: Store ID of system timers in timer structure ARM: OMAP3: Update clocksource timer selection ARM: OMAP2+: Simplify system timers definitions ARM: OMAP2+: Simplify system timer clock definitions ARM: OMAP2+: Remove hard-coded test on timer ID ARM: OMAP2+: Display correct system timer name ARM: OMAP2+: fix typo "CONFIG_BRIDGE_DVFS" ARM: OMAP1: remove "config MACH_OMAP_HTCWIZARD" ARM: OMAP: dpll: enable bypass clock only when attempting dpll bypass ARM: OMAP2+: powerdomain: avoid testing whether an unsigned char is less than 0 ARM: OMAP2+: hwmod: Remove unused _HWMOD_WAKEUP_ENABLED flag ARM: OMAP2+: am335x: Change the wdt1 func clk src to per_32k clk ARM: OMAP2+: AM33xx: hwmod: Add missing sysc definition to wdt1 entry Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arm/mach-omap2/timer.c')
-rw-r--r--arch/arm/mach-omap2/timer.c123
1 files changed, 63 insertions, 60 deletions
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 4fd80257c73e..f12aa6c15da4 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -57,15 +57,6 @@
57#include "common.h" 57#include "common.h"
58#include "powerdomain.h" 58#include "powerdomain.h"
59 59
60/* Parent clocks, eventually these will come from the clock framework */
61
62#define OMAP2_MPU_SOURCE "sys_ck"
63#define OMAP3_MPU_SOURCE OMAP2_MPU_SOURCE
64#define OMAP4_MPU_SOURCE "sys_clkin_ck"
65#define OMAP2_32K_SOURCE "func_32k_ck"
66#define OMAP3_32K_SOURCE "omap_32k_fck"
67#define OMAP4_32K_SOURCE "sys_32k_ck"
68
69#define REALTIME_COUNTER_BASE 0x48243200 60#define REALTIME_COUNTER_BASE 0x48243200
70#define INCREMENTER_NUMERATOR_OFFSET 0x10 61#define INCREMENTER_NUMERATOR_OFFSET 0x10
71#define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14 62#define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14
@@ -129,7 +120,6 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
129} 120}
130 121
131static struct clock_event_device clockevent_gpt = { 122static struct clock_event_device clockevent_gpt = {
132 .name = "gp_timer",
133 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 123 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
134 .rating = 300, 124 .rating = 300,
135 .set_next_event = omap2_gp_timer_set_next_event, 125 .set_next_event = omap2_gp_timer_set_next_event,
@@ -170,6 +160,12 @@ static struct device_node * __init omap_get_timer_dt(struct of_device_id *match,
170 if (property && !of_get_property(np, property, NULL)) 160 if (property && !of_get_property(np, property, NULL))
171 continue; 161 continue;
172 162
163 if (!property && (of_get_property(np, "ti,timer-alwon", NULL) ||
164 of_get_property(np, "ti,timer-dsp", NULL) ||
165 of_get_property(np, "ti,timer-pwm", NULL) ||
166 of_get_property(np, "ti,timer-secure", NULL)))
167 continue;
168
173 of_add_property(np, &device_disabled); 169 of_add_property(np, &device_disabled);
174 return np; 170 return np;
175 } 171 }
@@ -214,16 +210,17 @@ static u32 __init omap_dm_timer_get_errata(void)
214} 210}
215 211
216static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, 212static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
217 int gptimer_id, 213 const char *fck_source,
218 const char *fck_source, 214 const char *property,
219 const char *property, 215 const char **timer_name,
220 int posted) 216 int posted)
221{ 217{
222 char name[10]; /* 10 = sizeof("gptXX_Xck0") */ 218 char name[10]; /* 10 = sizeof("gptXX_Xck0") */
223 const char *oh_name; 219 const char *oh_name;
224 struct device_node *np; 220 struct device_node *np;
225 struct omap_hwmod *oh; 221 struct omap_hwmod *oh;
226 struct resource irq, mem; 222 struct resource irq, mem;
223 struct clk *src;
227 int r = 0; 224 int r = 0;
228 225
229 if (of_have_populated_dt()) { 226 if (of_have_populated_dt()) {
@@ -243,10 +240,10 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
243 240
244 of_node_put(np); 241 of_node_put(np);
245 } else { 242 } else {
246 if (omap_dm_timer_reserve_systimer(gptimer_id)) 243 if (omap_dm_timer_reserve_systimer(timer->id))
247 return -ENODEV; 244 return -ENODEV;
248 245
249 sprintf(name, "timer%d", gptimer_id); 246 sprintf(name, "timer%d", timer->id);
250 oh_name = name; 247 oh_name = name;
251 } 248 }
252 249
@@ -254,6 +251,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
254 if (!oh) 251 if (!oh)
255 return -ENODEV; 252 return -ENODEV;
256 253
254 *timer_name = oh->name;
255
257 if (!of_have_populated_dt()) { 256 if (!of_have_populated_dt()) {
258 r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL, 257 r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL,
259 &irq); 258 &irq);
@@ -276,24 +275,24 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
276 /* After the dmtimer is using hwmod these clocks won't be needed */ 275 /* After the dmtimer is using hwmod these clocks won't be needed */
277 timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh)); 276 timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh));
278 if (IS_ERR(timer->fclk)) 277 if (IS_ERR(timer->fclk))
279 return -ENODEV; 278 return PTR_ERR(timer->fclk);
280 279
281 /* FIXME: Need to remove hard-coded test on timer ID */ 280 src = clk_get(NULL, fck_source);
282 if (gptimer_id != 12) { 281 if (IS_ERR(src))
283 struct clk *src; 282 return PTR_ERR(src);
284 283
285 src = clk_get(NULL, fck_source); 284 if (clk_get_parent(timer->fclk) != src) {
286 if (IS_ERR(src)) { 285 r = clk_set_parent(timer->fclk, src);
287 r = -EINVAL; 286 if (r < 0) {
288 } else { 287 pr_warn("%s: %s cannot set source\n", __func__,
289 r = clk_set_parent(timer->fclk, src); 288 oh->name);
290 if (IS_ERR_VALUE(r))
291 pr_warn("%s: %s cannot set source\n",
292 __func__, oh->name);
293 clk_put(src); 289 clk_put(src);
290 return r;
294 } 291 }
295 } 292 }
296 293
294 clk_put(src);
295
297 omap_hwmod_setup_one(oh_name); 296 omap_hwmod_setup_one(oh_name);
298 omap_hwmod_enable(oh); 297 omap_hwmod_enable(oh);
299 __omap_dm_timer_init_regs(timer); 298 __omap_dm_timer_init_regs(timer);
@@ -317,6 +316,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
317{ 316{
318 int res; 317 int res;
319 318
319 clkev.id = gptimer_id;
320 clkev.errata = omap_dm_timer_get_errata(); 320 clkev.errata = omap_dm_timer_get_errata();
321 321
322 /* 322 /*
@@ -326,8 +326,8 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
326 */ 326 */
327 __omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767); 327 __omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);
328 328
329 res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property, 329 res = omap_dm_timer_init_one(&clkev, fck_source, property,
330 OMAP_TIMER_POSTED); 330 &clockevent_gpt.name, OMAP_TIMER_POSTED);
331 BUG_ON(res); 331 BUG_ON(res);
332 332
333 omap2_gp_timer_irq.dev_id = &clkev; 333 omap2_gp_timer_irq.dev_id = &clkev;
@@ -341,8 +341,8 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
341 3, /* Timer internal resynch latency */ 341 3, /* Timer internal resynch latency */
342 0xffffffff); 342 0xffffffff);
343 343
344 pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n", 344 pr_info("OMAP clockevent source: %s at %lu Hz\n", clockevent_gpt.name,
345 gptimer_id, clkev.rate); 345 clkev.rate);
346} 346}
347 347
348/* Clocksource code */ 348/* Clocksource code */
@@ -359,7 +359,6 @@ static cycle_t clocksource_read_cycles(struct clocksource *cs)
359} 359}
360 360
361static struct clocksource clocksource_gpt = { 361static struct clocksource clocksource_gpt = {
362 .name = "gp_timer",
363 .rating = 300, 362 .rating = 300,
364 .read = clocksource_read_cycles, 363 .read = clocksource_read_cycles,
365 .mask = CLOCKSOURCE_MASK(32), 364 .mask = CLOCKSOURCE_MASK(32),
@@ -442,13 +441,16 @@ static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
442} 441}
443 442
444static void __init omap2_gptimer_clocksource_init(int gptimer_id, 443static void __init omap2_gptimer_clocksource_init(int gptimer_id,
445 const char *fck_source) 444 const char *fck_source,
445 const char *property)
446{ 446{
447 int res; 447 int res;
448 448
449 clksrc.id = gptimer_id;
449 clksrc.errata = omap_dm_timer_get_errata(); 450 clksrc.errata = omap_dm_timer_get_errata();
450 451
451 res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL, 452 res = omap_dm_timer_init_one(&clksrc, fck_source, property,
453 &clocksource_gpt.name,
452 OMAP_TIMER_NONPOSTED); 454 OMAP_TIMER_NONPOSTED);
453 BUG_ON(res); 455 BUG_ON(res);
454 456
@@ -461,8 +463,8 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,
461 pr_err("Could not register clocksource %s\n", 463 pr_err("Could not register clocksource %s\n",
462 clocksource_gpt.name); 464 clocksource_gpt.name);
463 else 465 else
464 pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n", 466 pr_info("OMAP clocksource: %s at %lu Hz\n",
465 gptimer_id, clksrc.rate); 467 clocksource_gpt.name, clksrc.rate);
466} 468}
467 469
468#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER 470#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
@@ -487,7 +489,7 @@ static void __init realtime_counter_init(void)
487 pr_err("%s: ioremap failed\n", __func__); 489 pr_err("%s: ioremap failed\n", __func__);
488 return; 490 return;
489 } 491 }
490 sys_clk = clk_get(NULL, "sys_clkin_ck"); 492 sys_clk = clk_get(NULL, "sys_clkin");
491 if (IS_ERR(sys_clk)) { 493 if (IS_ERR(sys_clk)) {
492 pr_err("%s: failed to get system clock handle\n", __func__); 494 pr_err("%s: failed to get system clock handle\n", __func__);
493 iounmap(base); 495 iounmap(base);
@@ -544,49 +546,52 @@ static inline void __init realtime_counter_init(void)
544#endif 546#endif
545 547
546#define OMAP_SYS_GP_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \ 548#define OMAP_SYS_GP_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \
547 clksrc_nr, clksrc_src) \ 549 clksrc_nr, clksrc_src, clksrc_prop) \
548void __init omap##name##_gptimer_timer_init(void) \ 550void __init omap##name##_gptimer_timer_init(void) \
549{ \ 551{ \
550 omap_dmtimer_init(); \ 552 omap_dmtimer_init(); \
551 omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \ 553 omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \
552 omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src); \ 554 omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src, \
555 clksrc_prop); \
553} 556}
554 557
555#define OMAP_SYS_32K_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \ 558#define OMAP_SYS_32K_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \
556 clksrc_nr, clksrc_src) \ 559 clksrc_nr, clksrc_src, clksrc_prop) \
557void __init omap##name##_sync32k_timer_init(void) \ 560void __init omap##name##_sync32k_timer_init(void) \
558{ \ 561{ \
559 omap_dmtimer_init(); \ 562 omap_dmtimer_init(); \
560 omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \ 563 omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \
561 /* Enable the use of clocksource="gp_timer" kernel parameter */ \ 564 /* Enable the use of clocksource="gp_timer" kernel parameter */ \
562 if (use_gptimer_clksrc) \ 565 if (use_gptimer_clksrc) \
563 omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src);\ 566 omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src, \
567 clksrc_prop); \
564 else \ 568 else \
565 omap2_sync32k_clocksource_init(); \ 569 omap2_sync32k_clocksource_init(); \
566} 570}
567 571
568#ifdef CONFIG_ARCH_OMAP2 572#ifdef CONFIG_ARCH_OMAP2
569OMAP_SYS_32K_TIMER_INIT(2, 1, OMAP2_32K_SOURCE, "ti,timer-alwon", 573OMAP_SYS_32K_TIMER_INIT(2, 1, "timer_32k_ck", "ti,timer-alwon",
570 2, OMAP2_MPU_SOURCE); 574 2, "timer_sys_ck", NULL);
571#endif /* CONFIG_ARCH_OMAP2 */ 575#endif /* CONFIG_ARCH_OMAP2 */
572 576
573#ifdef CONFIG_ARCH_OMAP3 577#ifdef CONFIG_ARCH_OMAP3
574OMAP_SYS_32K_TIMER_INIT(3, 1, OMAP3_32K_SOURCE, "ti,timer-alwon", 578OMAP_SYS_32K_TIMER_INIT(3, 1, "timer_32k_ck", "ti,timer-alwon",
575 2, OMAP3_MPU_SOURCE); 579 2, "timer_sys_ck", NULL);
576OMAP_SYS_32K_TIMER_INIT(3_secure, 12, OMAP3_32K_SOURCE, "ti,timer-secure", 580OMAP_SYS_32K_TIMER_INIT(3_secure, 12, "secure_32k_fck", "ti,timer-secure",
577 2, OMAP3_MPU_SOURCE); 581 2, "timer_sys_ck", NULL);
578OMAP_SYS_GP_TIMER_INIT(3_gp, 1, OMAP3_MPU_SOURCE, "ti,timer-alwon",
579 2, OMAP3_MPU_SOURCE);
580#endif /* CONFIG_ARCH_OMAP3 */ 582#endif /* CONFIG_ARCH_OMAP3 */
581 583
582#ifdef CONFIG_SOC_AM33XX 584#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX)
583OMAP_SYS_GP_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon", 585OMAP_SYS_GP_TIMER_INIT(3, 2, "timer_sys_ck", NULL,
584 2, OMAP4_MPU_SOURCE); 586 1, "timer_sys_ck", "ti,timer-alwon");
585#endif /* CONFIG_SOC_AM33XX */ 587#endif
588
589#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
590static OMAP_SYS_32K_TIMER_INIT(4, 1, "timer_32k_ck", "ti,timer-alwon",
591 2, "sys_clkin_ck", NULL);
592#endif
586 593
587#ifdef CONFIG_ARCH_OMAP4 594#ifdef CONFIG_ARCH_OMAP4
588OMAP_SYS_32K_TIMER_INIT(4, 1, OMAP4_32K_SOURCE, "ti,timer-alwon",
589 2, OMAP4_MPU_SOURCE);
590#ifdef CONFIG_LOCAL_TIMERS 595#ifdef CONFIG_LOCAL_TIMERS
591static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29); 596static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29);
592void __init omap4_local_timer_init(void) 597void __init omap4_local_timer_init(void)
@@ -615,13 +620,11 @@ void __init omap4_local_timer_init(void)
615#endif /* CONFIG_ARCH_OMAP4 */ 620#endif /* CONFIG_ARCH_OMAP4 */
616 621
617#ifdef CONFIG_SOC_OMAP5 622#ifdef CONFIG_SOC_OMAP5
618OMAP_SYS_32K_TIMER_INIT(5, 1, OMAP4_32K_SOURCE, "ti,timer-alwon",
619 2, OMAP4_MPU_SOURCE);
620void __init omap5_realtime_timer_init(void) 623void __init omap5_realtime_timer_init(void)
621{ 624{
622 int err; 625 int err;
623 626
624 omap5_sync32k_timer_init(); 627 omap4_sync32k_timer_init();
625 realtime_counter_init(); 628 realtime_counter_init();
626 629
627 err = arch_timer_of_register(); 630 err = arch_timer_of_register();