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.c122
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
53struct sys_timer omap_timer; 55struct 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
104static inline void omap_32k_timer_write(int val, int reg) 96static 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
113static inline unsigned long omap_32k_timer_read(int reg) 101static 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()) 106static 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/* 112static inline void omap_32k_timer_stop(void)
123 * The 32KHz synchronized timer is an additional timer on 16xx.
124 * It is always running.
125 */
126static 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
121static struct omap_dm_timer *gptimer;
122
131static inline void omap_32k_timer_start(unsigned long load_val) 123static 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
145static inline void omap_32k_timer_stop(void) 130static 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()) 135static 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 */
147static 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
271static struct clk * gpt1_ick;
272static struct clk * gpt1_fck;
273
274static __init void omap_init_32k_timer(void) 265static __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 */
317static void __init omap_timer_init(void) 298static 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