diff options
Diffstat (limited to 'arch/arm/plat-omap/timer32k.c')
-rw-r--r-- | arch/arm/plat-omap/timer32k.c | 121 |
1 files changed, 52 insertions, 69 deletions
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c index 3461a6c9665c..f028e182215a 100644 --- a/arch/arm/plat-omap/timer32k.c +++ b/arch/arm/plat-omap/timer32k.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Partial timer rewrite and additional dynamic tick timer support by | 7 | * Partial timer rewrite and additional dynamic tick timer support by |
8 | * Tony Lindgen <tony@atomide.com> and | 8 | * Tony Lindgen <tony@atomide.com> and |
9 | * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | 9 | * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> |
10 | * OMAP Dual-mode timer framework support by Timo Teras | ||
10 | * | 11 | * |
11 | * MPU timer code based on the older MPU timer code for OMAP | 12 | * MPU timer code based on the older MPU timer code for OMAP |
12 | * Copyright (C) 2000 RidgeRun, Inc. | 13 | * Copyright (C) 2000 RidgeRun, Inc. |
@@ -79,18 +80,6 @@ struct sys_timer omap_timer; | |||
79 | #define OMAP1_32K_TIMER_TVR 0x00 | 80 | #define OMAP1_32K_TIMER_TVR 0x00 |
80 | #define OMAP1_32K_TIMER_TCR 0x04 | 81 | #define OMAP1_32K_TIMER_TCR 0x04 |
81 | 82 | ||
82 | /* 24xx specific defines */ | ||
83 | #define OMAP2_GP_TIMER_BASE 0x48028000 | ||
84 | #define CM_CLKSEL_WKUP 0x48008440 | ||
85 | #define GP_TIMER_TIDR 0x00 | ||
86 | #define GP_TIMER_TISR 0x18 | ||
87 | #define GP_TIMER_TIER 0x1c | ||
88 | #define GP_TIMER_TCLR 0x24 | ||
89 | #define GP_TIMER_TCRR 0x28 | ||
90 | #define GP_TIMER_TLDR 0x2c | ||
91 | #define GP_TIMER_TTGR 0x30 | ||
92 | #define GP_TIMER_TSICR 0x40 | ||
93 | |||
94 | #define OMAP_32K_TICKS_PER_HZ (32768 / HZ) | 83 | #define OMAP_32K_TICKS_PER_HZ (32768 / HZ) |
95 | 84 | ||
96 | /* | 85 | /* |
@@ -102,54 +91,64 @@ struct sys_timer omap_timer; | |||
102 | #define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \ | 91 | #define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \ |
103 | (((nr_jiffies) * (clock_rate)) / HZ) | 92 | (((nr_jiffies) * (clock_rate)) / HZ) |
104 | 93 | ||
94 | #if defined(CONFIG_ARCH_OMAP1) | ||
95 | |||
105 | static inline void omap_32k_timer_write(int val, int reg) | 96 | static inline void omap_32k_timer_write(int val, int reg) |
106 | { | 97 | { |
107 | if (cpu_class_is_omap1()) | 98 | omap_writew(val, OMAP1_32K_TIMER_BASE + reg); |
108 | omap_writew(val, OMAP1_32K_TIMER_BASE + reg); | ||
109 | |||
110 | if (cpu_is_omap24xx()) | ||
111 | omap_writel(val, OMAP2_GP_TIMER_BASE + reg); | ||
112 | } | 99 | } |
113 | 100 | ||
114 | static inline unsigned long omap_32k_timer_read(int reg) | 101 | static inline unsigned long omap_32k_timer_read(int reg) |
115 | { | 102 | { |
116 | if (cpu_class_is_omap1()) | 103 | return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff; |
117 | return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff; | 104 | } |
118 | 105 | ||
119 | if (cpu_is_omap24xx()) | 106 | static inline void omap_32k_timer_start(unsigned long load_val) |
120 | return omap_readl(OMAP2_GP_TIMER_BASE + reg); | 107 | { |
108 | omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR); | ||
109 | omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR); | ||
121 | } | 110 | } |
122 | 111 | ||
123 | /* | 112 | static inline void omap_32k_timer_stop(void) |
124 | * The 32KHz synchronized timer is an additional timer on 16xx. | ||
125 | * It is always running. | ||
126 | */ | ||
127 | static inline unsigned long omap_32k_sync_timer_read(void) | ||
128 | { | 113 | { |
129 | return omap_readl(TIMER_32K_SYNCHRONIZED); | 114 | omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR); |
130 | } | 115 | } |
131 | 116 | ||
117 | #define omap_32k_timer_ack_irq() | ||
118 | |||
119 | #elif defined(CONFIG_ARCH_OMAP2) | ||
120 | |||
121 | #include <asm/arch/dmtimer.h> | ||
122 | |||
123 | static struct omap_dm_timer *gptimer; | ||
124 | |||
132 | static inline void omap_32k_timer_start(unsigned long load_val) | 125 | static inline void omap_32k_timer_start(unsigned long load_val) |
133 | { | 126 | { |
134 | if (cpu_class_is_omap1()) { | 127 | omap_dm_timer_set_load(gptimer, 1, 0xffffffff - load_val); |
135 | omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR); | 128 | omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW); |
136 | omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR); | 129 | omap_dm_timer_start(gptimer); |
137 | } | ||
138 | |||
139 | if (cpu_is_omap24xx()) { | ||
140 | omap_32k_timer_write(0xffffffff - load_val, GP_TIMER_TCRR); | ||
141 | omap_32k_timer_write((1 << 1), GP_TIMER_TIER); | ||
142 | omap_32k_timer_write((1 << 1) | 1, GP_TIMER_TCLR); | ||
143 | } | ||
144 | } | 130 | } |
145 | 131 | ||
146 | static inline void omap_32k_timer_stop(void) | 132 | static inline void omap_32k_timer_stop(void) |
147 | { | 133 | { |
148 | if (cpu_class_is_omap1()) | 134 | omap_dm_timer_stop(gptimer); |
149 | omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR); | 135 | } |
150 | 136 | ||
151 | if (cpu_is_omap24xx()) | 137 | static inline void omap_32k_timer_ack_irq(void) |
152 | omap_32k_timer_write(0x0, GP_TIMER_TCLR); | 138 | { |
139 | u32 status = omap_dm_timer_read_status(gptimer); | ||
140 | omap_dm_timer_write_status(gptimer, status); | ||
141 | } | ||
142 | |||
143 | #endif | ||
144 | |||
145 | /* | ||
146 | * The 32KHz synchronized timer is an additional timer on 16xx. | ||
147 | * It is always running. | ||
148 | */ | ||
149 | static inline unsigned long omap_32k_sync_timer_read(void) | ||
150 | { | ||
151 | return omap_readl(TIMER_32K_SYNCHRONIZED); | ||
153 | } | 152 | } |
154 | 153 | ||
155 | /* | 154 | /* |
@@ -203,11 +202,7 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, | |||
203 | 202 | ||
204 | write_seqlock_irqsave(&xtime_lock, flags); | 203 | write_seqlock_irqsave(&xtime_lock, flags); |
205 | 204 | ||
206 | if (cpu_is_omap24xx()) { | 205 | omap_32k_timer_ack_irq(); |
207 | u32 status = omap_32k_timer_read(GP_TIMER_TISR); | ||
208 | omap_32k_timer_write(status, GP_TIMER_TISR); | ||
209 | } | ||
210 | |||
211 | now = omap_32k_sync_timer_read(); | 206 | now = omap_32k_sync_timer_read(); |
212 | 207 | ||
213 | while ((signed long)(now - omap_32k_last_tick) | 208 | while ((signed long)(now - omap_32k_last_tick) |
@@ -269,9 +264,6 @@ static struct irqaction omap_32k_timer_irq = { | |||
269 | .handler = omap_32k_timer_interrupt, | 264 | .handler = omap_32k_timer_interrupt, |
270 | }; | 265 | }; |
271 | 266 | ||
272 | static struct clk * gpt1_ick; | ||
273 | static struct clk * gpt1_fck; | ||
274 | |||
275 | static __init void omap_init_32k_timer(void) | 267 | static __init void omap_init_32k_timer(void) |
276 | { | 268 | { |
277 | #ifdef CONFIG_NO_IDLE_HZ | 269 | #ifdef CONFIG_NO_IDLE_HZ |
@@ -280,31 +272,19 @@ static __init void omap_init_32k_timer(void) | |||
280 | 272 | ||
281 | if (cpu_class_is_omap1()) | 273 | if (cpu_class_is_omap1()) |
282 | setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); | 274 | setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); |
283 | if (cpu_is_omap24xx()) | ||
284 | setup_irq(37, &omap_32k_timer_irq); | ||
285 | omap_timer.offset = omap_32k_timer_gettimeoffset; | 275 | omap_timer.offset = omap_32k_timer_gettimeoffset; |
286 | omap_32k_last_tick = omap_32k_sync_timer_read(); | 276 | omap_32k_last_tick = omap_32k_sync_timer_read(); |
287 | 277 | ||
288 | /* REVISIT: Check 24xx TIOCP_CFG settings after idle works */ | 278 | /* REVISIT: Check 24xx TIOCP_CFG settings after idle works */ |
289 | if (cpu_is_omap24xx()) { | 279 | if (cpu_is_omap24xx()) { |
290 | omap_32k_timer_write(0, GP_TIMER_TCLR); | 280 | gptimer = omap_dm_timer_request_specific(1); |
291 | omap_writel(0, CM_CLKSEL_WKUP); /* 32KHz clock source */ | 281 | BUG_ON(gptimer == NULL); |
292 | 282 | ||
293 | gpt1_ick = clk_get(NULL, "gpt1_ick"); | 283 | omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ); |
294 | if (IS_ERR(gpt1_ick)) | 284 | setup_irq(omap_dm_timer_get_irq(gptimer), &omap_32k_timer_irq); |
295 | printk(KERN_ERR "Could not get gpt1_ick\n"); | 285 | omap_dm_timer_set_int_enable(gptimer, |
296 | else | 286 | OMAP_TIMER_INT_CAPTURE | OMAP_TIMER_INT_OVERFLOW | |
297 | clk_enable(gpt1_ick); | 287 | OMAP_TIMER_INT_MATCH); |
298 | |||
299 | gpt1_fck = clk_get(NULL, "gpt1_fck"); | ||
300 | if (IS_ERR(gpt1_fck)) | ||
301 | printk(KERN_ERR "Could not get gpt1_fck\n"); | ||
302 | else | ||
303 | clk_enable(gpt1_fck); | ||
304 | |||
305 | mdelay(100); /* Wait for clocks to stabilize */ | ||
306 | |||
307 | omap_32k_timer_write(0x7, GP_TIMER_TISR); | ||
308 | } | 288 | } |
309 | 289 | ||
310 | omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); | 290 | omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); |
@@ -317,6 +297,9 @@ static __init void omap_init_32k_timer(void) | |||
317 | */ | 297 | */ |
318 | static void __init omap_timer_init(void) | 298 | static void __init omap_timer_init(void) |
319 | { | 299 | { |
300 | #ifdef CONFIG_OMAP_DM_TIMER | ||
301 | omap_dm_timer_init(); | ||
302 | #endif | ||
320 | omap_init_32k_timer(); | 303 | omap_init_32k_timer(); |
321 | } | 304 | } |
322 | 305 | ||