diff options
Diffstat (limited to 'arch/arm/mach-omap2/timer-gp.c')
-rw-r--r-- | arch/arm/mach-omap2/timer-gp.c | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index 9fc13a2cc3f4..f36aba12090e 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * | 3 | * |
4 | * OMAP2 GP timer support. | 4 | * OMAP2 GP timer support. |
5 | * | 5 | * |
6 | * Copyright (C) 2009 Nokia Corporation | ||
7 | * | ||
6 | * Update to use new clocksource/clockevent layers | 8 | * Update to use new clocksource/clockevent layers |
7 | * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com> | 9 | * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com> |
8 | * Copyright (C) 2007 MontaVista Software, Inc. | 10 | * Copyright (C) 2007 MontaVista Software, Inc. |
@@ -36,8 +38,13 @@ | |||
36 | #include <asm/mach/time.h> | 38 | #include <asm/mach/time.h> |
37 | #include <mach/dmtimer.h> | 39 | #include <mach/dmtimer.h> |
38 | 40 | ||
41 | /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */ | ||
42 | #define MAX_GPTIMER_ID 12 | ||
43 | |||
39 | static struct omap_dm_timer *gptimer; | 44 | static struct omap_dm_timer *gptimer; |
40 | static struct clock_event_device clockevent_gpt; | 45 | static struct clock_event_device clockevent_gpt; |
46 | static u8 __initdata gptimer_id = 1; | ||
47 | static u8 __initdata inited; | ||
41 | 48 | ||
42 | static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id) | 49 | static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id) |
43 | { | 50 | { |
@@ -95,20 +102,53 @@ static struct clock_event_device clockevent_gpt = { | |||
95 | .set_mode = omap2_gp_timer_set_mode, | 102 | .set_mode = omap2_gp_timer_set_mode, |
96 | }; | 103 | }; |
97 | 104 | ||
105 | /** | ||
106 | * omap2_gp_clockevent_set_gptimer - set which GPTIMER is used for clockevents | ||
107 | * @id: GPTIMER to use (1..MAX_GPTIMER_ID) | ||
108 | * | ||
109 | * Define the GPTIMER that the system should use for the tick timer. | ||
110 | * Meant to be called from board-*.c files in the event that GPTIMER1, the | ||
111 | * default, is unsuitable. Returns -EINVAL on error or 0 on success. | ||
112 | */ | ||
113 | int __init omap2_gp_clockevent_set_gptimer(u8 id) | ||
114 | { | ||
115 | if (id < 1 || id > MAX_GPTIMER_ID) | ||
116 | return -EINVAL; | ||
117 | |||
118 | BUG_ON(inited); | ||
119 | |||
120 | gptimer_id = id; | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
98 | static void __init omap2_gp_clockevent_init(void) | 125 | static void __init omap2_gp_clockevent_init(void) |
99 | { | 126 | { |
100 | u32 tick_rate; | 127 | u32 tick_rate; |
128 | int src; | ||
129 | |||
130 | inited = 1; | ||
101 | 131 | ||
102 | gptimer = omap_dm_timer_request_specific(1); | 132 | gptimer = omap_dm_timer_request_specific(gptimer_id); |
103 | BUG_ON(gptimer == NULL); | 133 | BUG_ON(gptimer == NULL); |
104 | 134 | ||
105 | #if defined(CONFIG_OMAP_32K_TIMER) | 135 | #if defined(CONFIG_OMAP_32K_TIMER) |
106 | omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ); | 136 | src = OMAP_TIMER_SRC_32_KHZ; |
107 | #else | 137 | #else |
108 | omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK); | 138 | src = OMAP_TIMER_SRC_SYS_CLK; |
139 | WARN(gptimer_id == 12, "WARNING: GPTIMER12 can only use the " | ||
140 | "secure 32KiHz clock source\n"); | ||
109 | #endif | 141 | #endif |
142 | |||
143 | if (gptimer_id != 12) | ||
144 | WARN(IS_ERR_VALUE(omap_dm_timer_set_source(gptimer, src)), | ||
145 | "timer-gp: omap_dm_timer_set_source() failed\n"); | ||
146 | |||
110 | tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer)); | 147 | tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer)); |
111 | 148 | ||
149 | pr_info("OMAP clockevent source: GPTIMER%d at %u Hz\n", | ||
150 | gptimer_id, tick_rate); | ||
151 | |||
112 | omap2_gp_timer_irq.dev_id = (void *)gptimer; | 152 | omap2_gp_timer_irq.dev_id = (void *)gptimer; |
113 | setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq); | 153 | setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq); |
114 | omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW); | 154 | omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW); |
@@ -125,6 +165,8 @@ static void __init omap2_gp_clockevent_init(void) | |||
125 | clockevents_register_device(&clockevent_gpt); | 165 | clockevents_register_device(&clockevent_gpt); |
126 | } | 166 | } |
127 | 167 | ||
168 | /* Clocksource code */ | ||
169 | |||
128 | #ifdef CONFIG_OMAP_32K_TIMER | 170 | #ifdef CONFIG_OMAP_32K_TIMER |
129 | /* | 171 | /* |
130 | * When 32k-timer is enabled, don't use GPTimer for clocksource | 172 | * When 32k-timer is enabled, don't use GPTimer for clocksource |
@@ -138,7 +180,7 @@ static inline void __init omap2_gp_clocksource_init(void) {} | |||
138 | * clocksource | 180 | * clocksource |
139 | */ | 181 | */ |
140 | static struct omap_dm_timer *gpt_clocksource; | 182 | static struct omap_dm_timer *gpt_clocksource; |
141 | static cycle_t clocksource_read_cycles(void) | 183 | static cycle_t clocksource_read_cycles(struct clocksource *cs) |
142 | { | 184 | { |
143 | return (cycle_t)omap_dm_timer_read_counter(gpt_clocksource); | 185 | return (cycle_t)omap_dm_timer_read_counter(gpt_clocksource); |
144 | } | 186 | } |