diff options
author | Timo Teras <timo.teras@solidboot.com> | 2006-06-26 19:16:12 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2006-06-26 19:16:12 -0400 |
commit | 77900a2fc3bfb1eb6eaa6d43eef4591e1f7c600d (patch) | |
tree | 6d6278f833a6057b1b951e4e9bded234aa6459e2 /arch/arm/plat-omap/timer32k.c | |
parent | 6e711ec6d249c0d3f8bc225066738d064ed90032 (diff) |
ARM: OMAP: Port dmtimers to OMAP2 and implement PWM support
Port dmtimer framework to OMAP2.
Modify the dmtimers API to support setting of PWM configuration and prescaler.
Convert 32 kHz timer and GP timer to use the dmtimer framework.
Signed-off-by: Timo Teras <timo.teras@solidboot.com>
Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
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 | ||