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