aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/timer32k.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap/timer32k.c')
-rw-r--r--arch/arm/plat-omap/timer32k.c121
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
105static inline void omap_32k_timer_write(int val, int reg) 96static 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
114static inline unsigned long omap_32k_timer_read(int reg) 101static 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()) 106static 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/* 112static inline void omap_32k_timer_stop(void)
124 * The 32KHz synchronized timer is an additional timer on 16xx.
125 * It is always running.
126 */
127static 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
123static struct omap_dm_timer *gptimer;
124
132static inline void omap_32k_timer_start(unsigned long load_val) 125static 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
146static inline void omap_32k_timer_stop(void) 132static 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()) 137static 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 */
149static 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
272static struct clk * gpt1_ick;
273static struct clk * gpt1_fck;
274
275static __init void omap_init_32k_timer(void) 267static __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 */
318static void __init omap_timer_init(void) 298static 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