aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/Kconfig1
-rw-r--r--arch/arm/mach-omap2/timer-gp.c86
-rw-r--r--arch/arm/plat-omap/Kconfig2
-rw-r--r--arch/arm/plat-omap/dmtimer.c413
-rw-r--r--arch/arm/plat-omap/timer32k.c121
-rw-r--r--include/asm-arm/arch-omap/dmtimer.h79
-rw-r--r--include/asm-arm/arch-omap/irqs.h12
7 files changed, 412 insertions, 302 deletions
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 537dd2e6d380..aab97ccf1e63 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -8,6 +8,7 @@ config ARCH_OMAP24XX
8config ARCH_OMAP2420 8config ARCH_OMAP2420
9 bool "OMAP2420 support" 9 bool "OMAP2420 support"
10 depends on ARCH_OMAP24XX 10 depends on ARCH_OMAP24XX
11 select OMAP_DM_TIMER
11 12
12comment "OMAP Board Type" 13comment "OMAP Board Type"
13 depends on ARCH_OMAP2 14 depends on ARCH_OMAP2
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 1d2f5ac2f69b..3358c0d47b1a 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -6,6 +6,7 @@
6 * Copyright (C) 2005 Nokia Corporation 6 * Copyright (C) 2005 Nokia Corporation
7 * Author: Paul Mundt <paul.mundt@nokia.com> 7 * Author: Paul Mundt <paul.mundt@nokia.com>
8 * Juha Yrjölä <juha.yrjola@nokia.com> 8 * Juha Yrjölä <juha.yrjola@nokia.com>
9 * OMAP Dual-mode timer framework support by Timo Teras
9 * 10 *
10 * Some parts based off of TI's 24xx code: 11 * Some parts based off of TI's 24xx code:
11 * 12 *
@@ -22,54 +23,18 @@
22#include <linux/interrupt.h> 23#include <linux/interrupt.h>
23#include <linux/err.h> 24#include <linux/err.h>
24#include <linux/clk.h> 25#include <linux/clk.h>
26#include <linux/delay.h>
25 27
26#include <asm/mach/time.h> 28#include <asm/mach/time.h>
27#include <asm/delay.h> 29#include <asm/arch/dmtimer.h>
28#include <asm/io.h>
29 30
30#define OMAP2_GP_TIMER1_BASE 0x48028000 31static struct omap_dm_timer *gptimer;
31#define OMAP2_GP_TIMER2_BASE 0x4802a000
32#define OMAP2_GP_TIMER3_BASE 0x48078000
33#define OMAP2_GP_TIMER4_BASE 0x4807a000
34 32
35#define GP_TIMER_TIDR 0x00 33static inline void omap2_gp_timer_start(unsigned long load_val)
36#define GP_TIMER_TISR 0x18
37#define GP_TIMER_TIER 0x1c
38#define GP_TIMER_TCLR 0x24
39#define GP_TIMER_TCRR 0x28
40#define GP_TIMER_TLDR 0x2c
41#define GP_TIMER_TSICR 0x40
42
43#define OS_TIMER_NR 1 /* GP timer 2 */
44
45static unsigned long timer_base[] = {
46 IO_ADDRESS(OMAP2_GP_TIMER1_BASE),
47 IO_ADDRESS(OMAP2_GP_TIMER2_BASE),
48 IO_ADDRESS(OMAP2_GP_TIMER3_BASE),
49 IO_ADDRESS(OMAP2_GP_TIMER4_BASE),
50};
51
52static inline unsigned int timer_read_reg(int nr, unsigned int reg)
53{
54 return __raw_readl(timer_base[nr] + reg);
55}
56
57static inline void timer_write_reg(int nr, unsigned int reg, unsigned int val)
58{
59 __raw_writel(val, timer_base[nr] + reg);
60}
61
62/* Note that we always enable the clock prescale divider bit */
63static inline void omap2_gp_timer_start(int nr, unsigned long load_val)
64{ 34{
65 unsigned int tmp; 35 omap_dm_timer_set_load(gptimer, 1, 0xffffffff - load_val);
66 36 omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
67 tmp = 0xffffffff - load_val; 37 omap_dm_timer_start(gptimer);
68
69 timer_write_reg(nr, GP_TIMER_TLDR, tmp);
70 timer_write_reg(nr, GP_TIMER_TCRR, tmp);
71 timer_write_reg(nr, GP_TIMER_TIER, 1 << 1);
72 timer_write_reg(nr, GP_TIMER_TCLR, (1 << 5) | (1 << 1) | 1);
73} 38}
74 39
75static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id, 40static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id,
@@ -77,7 +42,7 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id,
77{ 42{
78 write_seqlock(&xtime_lock); 43 write_seqlock(&xtime_lock);
79 44
80 timer_write_reg(OS_TIMER_NR, GP_TIMER_TISR, 1 << 1); 45 omap_dm_timer_write_status(gptimer, OMAP_TIMER_INT_OVERFLOW);
81 timer_tick(regs); 46 timer_tick(regs);
82 47
83 write_sequnlock(&xtime_lock); 48 write_sequnlock(&xtime_lock);
@@ -87,41 +52,26 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id,
87 52
88static struct irqaction omap2_gp_timer_irq = { 53static struct irqaction omap2_gp_timer_irq = {
89 .name = "gp timer", 54 .name = "gp timer",
90 .flags = SA_INTERRUPT, 55 .flags = SA_INTERRUPT | SA_TIMER,
91 .handler = omap2_gp_timer_interrupt, 56 .handler = omap2_gp_timer_interrupt,
92}; 57};
93 58
94static void __init omap2_gp_timer_init(void) 59static void __init omap2_gp_timer_init(void)
95{ 60{
96 struct clk * sys_ck; 61 u32 tick_period;
97 u32 tick_period = 120000;
98 u32 l;
99 62
100 /* Reset clock and prescale value */ 63 omap_dm_timer_init();
101 timer_write_reg(OS_TIMER_NR, GP_TIMER_TCLR, 0); 64 gptimer = omap_dm_timer_request_specific(2);
65 BUG_ON(gptimer == NULL);
102 66
103 sys_ck = clk_get(NULL, "sys_ck"); 67 omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK);
104 if (IS_ERR(sys_ck)) 68 tick_period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / 100;
105 printk(KERN_ERR "Could not get sys_ck\n");
106 else {
107 clk_enable(sys_ck);
108 tick_period = clk_get_rate(sys_ck) / 100;
109 clk_put(sys_ck);
110 }
111
112 tick_period /= 2; /* Minimum prescale divider is 2 */
113 tick_period -= 1; 69 tick_period -= 1;
114 70
115 l = timer_read_reg(OS_TIMER_NR, GP_TIMER_TIDR); 71 setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq);
116 printk(KERN_INFO "OMAP2 GP timer (HW version %d.%d)\n", 72 omap2_gp_timer_start(tick_period);
117 (l >> 4) & 0x0f, l & 0x0f);
118
119 setup_irq(38, &omap2_gp_timer_irq);
120
121 omap2_gp_timer_start(OS_TIMER_NR, tick_period);
122} 73}
123 74
124struct sys_timer omap_timer = { 75struct sys_timer omap_timer = {
125 .init = omap2_gp_timer_init, 76 .init = omap2_gp_timer_init,
126}; 77};
127
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index ec49495e651e..ec752e16d618 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -91,7 +91,7 @@ config OMAP_32K_TIMER_HZ
91 91
92config OMAP_DM_TIMER 92config OMAP_DM_TIMER
93 bool "Use dual-mode timer" 93 bool "Use dual-mode timer"
94 depends on ARCH_OMAP16XX 94 depends on ARCH_OMAP16XX || ARCH_OMAP24XX
95 help 95 help
96 Select this option if you want to use OMAP Dual-Mode timers. 96 Select this option if you want to use OMAP Dual-Mode timers.
97 97
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index eba3cb52ad87..c25a1a6d2b03 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -4,7 +4,8 @@
4 * OMAP Dual-Mode Timers 4 * OMAP Dual-Mode Timers
5 * 5 *
6 * Copyright (C) 2005 Nokia Corporation 6 * Copyright (C) 2005 Nokia Corporation
7 * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com> 7 * OMAP2 support by Juha Yrjola
8 * API improvements and OMAP2 clock framework support by Timo Teras
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the 11 * under the terms of the GNU General Public License as published by the
@@ -26,15 +27,17 @@
26 */ 27 */
27 28
28#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/spinlock.h>
31#include <linux/errno.h>
32#include <linux/list.h>
33#include <linux/clk.h>
34#include <linux/delay.h>
29#include <asm/hardware.h> 35#include <asm/hardware.h>
30#include <asm/arch/dmtimer.h> 36#include <asm/arch/dmtimer.h>
31#include <asm/io.h> 37#include <asm/io.h>
32#include <asm/arch/irqs.h> 38#include <asm/arch/irqs.h>
33#include <linux/spinlock.h>
34#include <linux/list.h>
35
36#define OMAP_TIMER_COUNT 8
37 39
40/* register offsets */
38#define OMAP_TIMER_ID_REG 0x00 41#define OMAP_TIMER_ID_REG 0x00
39#define OMAP_TIMER_OCP_CFG_REG 0x10 42#define OMAP_TIMER_OCP_CFG_REG 0x10
40#define OMAP_TIMER_SYS_STAT_REG 0x14 43#define OMAP_TIMER_SYS_STAT_REG 0x14
@@ -50,52 +53,184 @@
50#define OMAP_TIMER_CAPTURE_REG 0x3c 53#define OMAP_TIMER_CAPTURE_REG 0x3c
51#define OMAP_TIMER_IF_CTRL_REG 0x40 54#define OMAP_TIMER_IF_CTRL_REG 0x40
52 55
56/* timer control reg bits */
57#define OMAP_TIMER_CTRL_GPOCFG (1 << 14)
58#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13)
59#define OMAP_TIMER_CTRL_PT (1 << 12)
60#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8)
61#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8)
62#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8)
63#define OMAP_TIMER_CTRL_SCPWM (1 << 7)
64#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */
65#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */
66#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* how much to shift the prescaler value */
67#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */
68#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */
69
70struct omap_dm_timer {
71 unsigned long phys_base;
72 int irq;
73#ifdef CONFIG_ARCH_OMAP2
74 struct clk *iclk, *fclk;
75#endif
76 void __iomem *io_base;
77 unsigned reserved:1;
78};
79
80#ifdef CONFIG_ARCH_OMAP1
81
82static struct omap_dm_timer dm_timers[] = {
83 { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
84 { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
85 { .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
86 { .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
87 { .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
88 { .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
89 { .phys_base = 0xfffb4400, .irq = INT_1610_GPTIMER7 },
90 { .phys_base = 0xfffb4c00, .irq = INT_1610_GPTIMER8 },
91};
53 92
54static struct dmtimer_info_struct { 93#elif defined(CONFIG_ARCH_OMAP2)
55 struct list_head unused_timers;
56 struct list_head reserved_timers;
57} dm_timer_info;
58 94
59static struct omap_dm_timer dm_timers[] = { 95static struct omap_dm_timer dm_timers[] = {
60 { .base=0xfffb1400, .irq=INT_1610_GPTIMER1 }, 96 { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
61 { .base=0xfffb1c00, .irq=INT_1610_GPTIMER2 }, 97 { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
62 { .base=0xfffb2400, .irq=INT_1610_GPTIMER3 }, 98 { .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
63 { .base=0xfffb2c00, .irq=INT_1610_GPTIMER4 }, 99 { .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
64 { .base=0xfffb3400, .irq=INT_1610_GPTIMER5 }, 100 { .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
65 { .base=0xfffb3c00, .irq=INT_1610_GPTIMER6 }, 101 { .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
66 { .base=0xfffb4400, .irq=INT_1610_GPTIMER7 }, 102 { .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
67 { .base=0xfffb4c00, .irq=INT_1610_GPTIMER8 }, 103 { .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
68 { .base=0x0 }, 104 { .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
105 { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
106 { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
107 { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
69}; 108};
70 109
110#else
111
112#error OMAP architecture not supported!
113
114#endif
115
116static const int dm_timer_count = ARRAY_SIZE(dm_timers);
71 117
72static spinlock_t dm_timer_lock; 118static spinlock_t dm_timer_lock;
73 119
120static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg)
121{
122 return readl(timer->io_base + reg);
123}
74 124
75inline void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value) 125static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value)
76{ 126{
77 omap_writel(value, timer->base + reg); 127 writel(value, timer->io_base + reg);
78 while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG)) 128 while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG))
79 ; 129 ;
80} 130}
81 131
82u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg) 132static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
83{ 133{
84 return omap_readl(timer->base + reg); 134 int c;
135
136 c = 0;
137 while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
138 c++;
139 if (c > 100000) {
140 printk(KERN_ERR "Timer failed to reset\n");
141 return;
142 }
143 }
85} 144}
86 145
87int omap_dm_timers_active(void) 146static void omap_dm_timer_reset(struct omap_dm_timer *timer)
147{
148 u32 l;
149
150 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
151 omap_dm_timer_wait_for_reset(timer);
152
153 omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_SYS_CLK);
154
155 /* Set to smart-idle mode */
156 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
157 l |= 0x02 << 3;
158 omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
159}
160
161static void omap_dm_timer_reserve(struct omap_dm_timer *timer)
162{
163 timer->reserved = 1;
164#ifdef CONFIG_ARCH_OMAP2
165 clk_enable(timer->iclk);
166 clk_enable(timer->fclk);
167#endif
168 omap_dm_timer_reset(timer);
169}
170
171struct omap_dm_timer *omap_dm_timer_request(void)
172{
173 struct omap_dm_timer *timer = NULL;
174 unsigned long flags;
175 int i;
176
177 spin_lock_irqsave(&dm_timer_lock, flags);
178 for (i = 0; i < dm_timer_count; i++) {
179 if (dm_timers[i].reserved)
180 continue;
181
182 timer = &dm_timers[i];
183 omap_dm_timer_reserve(timer);
184 break;
185 }
186 spin_unlock_irqrestore(&dm_timer_lock, flags);
187
188 return timer;
189}
190
191struct omap_dm_timer *omap_dm_timer_request_specific(int id)
88{ 192{
89 struct omap_dm_timer *timer; 193 struct omap_dm_timer *timer;
194 unsigned long flags;
90 195
91 for (timer = &dm_timers[0]; timer->base; ++timer) 196 spin_lock_irqsave(&dm_timer_lock, flags);
92 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & 197 if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
93 OMAP_TIMER_CTRL_ST) 198 spin_unlock_irqrestore(&dm_timer_lock, flags);
94 return 1; 199 printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
200 __FILE__, __LINE__, __FUNCTION__, id);
201 dump_stack();
202 return NULL;
203 }
95 204
96 return 0; 205 timer = &dm_timers[id-1];
206 omap_dm_timer_reserve(timer);
207 spin_unlock_irqrestore(&dm_timer_lock, flags);
208
209 return timer;
97} 210}
98 211
212void omap_dm_timer_free(struct omap_dm_timer *timer)
213{
214 omap_dm_timer_reset(timer);
215#ifdef CONFIG_ARCH_OMAP2
216 clk_disable(timer->iclk);
217 clk_disable(timer->fclk);
218#endif
219 WARN_ON(!timer->reserved);
220 timer->reserved = 0;
221}
222
223int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
224{
225 return timer->irq;
226}
227
228#if defined(CONFIG_ARCH_OMAP1)
229
230struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
231{
232 BUG();
233}
99 234
100/** 235/**
101 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR 236 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
@@ -103,184 +238,226 @@ int omap_dm_timers_active(void)
103 */ 238 */
104__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) 239__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
105{ 240{
106 int n; 241 int i;
107 242
108 /* If ARMXOR cannot be idled this function call is unnecessary */ 243 /* If ARMXOR cannot be idled this function call is unnecessary */
109 if (!(inputmask & (1 << 1))) 244 if (!(inputmask & (1 << 1)))
110 return inputmask; 245 return inputmask;
111 246
112 /* If any active timer is using ARMXOR return modified mask */ 247 /* If any active timer is using ARMXOR return modified mask */
113 for (n = 0; dm_timers[n].base; ++n) 248 for (i = 0; i < dm_timer_count; i++) {
114 if (omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG)& 249 u32 l;
115 OMAP_TIMER_CTRL_ST) { 250
116 if (((omap_readl(MOD_CONF_CTRL_1)>>(n*2)) & 0x03) == 0) 251 l = omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG);
252 if (l & OMAP_TIMER_CTRL_ST) {
253 if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
117 inputmask &= ~(1 << 1); 254 inputmask &= ~(1 << 1);
118 else 255 else
119 inputmask &= ~(1 << 2); 256 inputmask &= ~(1 << 2);
120 } 257 }
258 }
121 259
122 return inputmask; 260 return inputmask;
123} 261}
124 262
263#elif defined(CONFIG_ARCH_OMAP2)
125 264
126void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) 265struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
127{ 266{
128 int n = (timer - dm_timers) << 1; 267 return timer->fclk;
129 u32 l; 268}
130 269
131 l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n); 270__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
132 l |= source << n; 271{
133 omap_writel(l, MOD_CONF_CTRL_1); 272 BUG();
134} 273}
135 274
275#endif
136 276
137static void omap_dm_timer_reset(struct omap_dm_timer *timer) 277void omap_dm_timer_trigger(struct omap_dm_timer *timer)
138{ 278{
139 /* Reset and set posted mode */ 279 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
140 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
141 omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, 0x02);
142
143 omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_ARMXOR);
144} 280}
145 281
282void omap_dm_timer_start(struct omap_dm_timer *timer)
283{
284 u32 l;
146 285
286 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
287 if (!(l & OMAP_TIMER_CTRL_ST)) {
288 l |= OMAP_TIMER_CTRL_ST;
289 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
290 }
291}
147 292
148struct omap_dm_timer * omap_dm_timer_request(void) 293void omap_dm_timer_stop(struct omap_dm_timer *timer)
149{ 294{
150 struct omap_dm_timer *timer = NULL; 295 u32 l;
151 unsigned long flags;
152 296
153 spin_lock_irqsave(&dm_timer_lock, flags); 297 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
154 if (!list_empty(&dm_timer_info.unused_timers)) { 298 if (l & OMAP_TIMER_CTRL_ST) {
155 timer = (struct omap_dm_timer *) 299 l &= ~0x1;
156 dm_timer_info.unused_timers.next; 300 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
157 list_move_tail((struct list_head *)timer,
158 &dm_timer_info.reserved_timers);
159 } 301 }
160 spin_unlock_irqrestore(&dm_timer_lock, flags);
161
162 return timer;
163} 302}
164 303
304#ifdef CONFIG_ARCH_OMAP1
165 305
166void omap_dm_timer_free(struct omap_dm_timer *timer) 306void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
167{ 307{
168 unsigned long flags; 308 int n = (timer - dm_timers) << 1;
169 309 u32 l;
170 omap_dm_timer_reset(timer);
171 310
172 spin_lock_irqsave(&dm_timer_lock, flags); 311 l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
173 list_move_tail((struct list_head *)timer, &dm_timer_info.unused_timers); 312 l |= source << n;
174 spin_unlock_irqrestore(&dm_timer_lock, flags); 313 omap_writel(l, MOD_CONF_CTRL_1);
175} 314}
176 315
177void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, 316#else
178 unsigned int value)
179{
180 omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
181}
182 317
183unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) 318void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
184{ 319{
185 return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); 320 static const char *source_timers[] = {
321 "sys_ck",
322 "func_32k_ck",
323 "alt_ck"
324 };
325 struct clk *parent;
326
327 if (source < 0 || source >= 3)
328 return;
329
330 parent = clk_get(NULL, source_timers[source]);
331 clk_disable(timer->fclk);
332 clk_set_parent(timer->fclk, parent);
333 clk_enable(timer->fclk);
334 clk_put(parent);
335
336 /* When the functional clock disappears, too quick writes seem to
337 * cause an abort. */
338 udelay(50);
186} 339}
187 340
188void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) 341#endif
189{
190 omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
191}
192 342
193void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer) 343void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
344 unsigned int load)
194{ 345{
195 u32 l; 346 u32 l;
347
196 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 348 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
197 l |= OMAP_TIMER_CTRL_AR; 349 if (autoreload)
350 l |= OMAP_TIMER_CTRL_AR;
351 else
352 l &= ~OMAP_TIMER_CTRL_AR;
198 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 353 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
354 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
355 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
199} 356}
200 357
201void omap_dm_timer_trigger(struct omap_dm_timer *timer) 358void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
202{ 359 unsigned int match)
203 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 1);
204}
205
206void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value)
207{ 360{
208 u32 l; 361 u32 l;
209 362
210 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 363 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
211 l |= value & 0x3; 364 if (enable)
365 l |= OMAP_TIMER_CTRL_CE;
366 else
367 l &= ~OMAP_TIMER_CTRL_CE;
212 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 368 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
369 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
213} 370}
214 371
215void omap_dm_timer_start(struct omap_dm_timer *timer) 372
373void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
374 int toggle, int trigger)
216{ 375{
217 u32 l; 376 u32 l;
218 377
219 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 378 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
220 l |= OMAP_TIMER_CTRL_ST; 379 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
380 OMAP_TIMER_CTRL_PT | (0x03 << 10));
381 if (def_on)
382 l |= OMAP_TIMER_CTRL_SCPWM;
383 if (toggle)
384 l |= OMAP_TIMER_CTRL_PT;
385 l |= trigger << 10;
221 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 386 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
222} 387}
223 388
224void omap_dm_timer_stop(struct omap_dm_timer *timer) 389void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
225{ 390{
226 u32 l; 391 u32 l;
227 392
228 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 393 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
229 l &= ~0x1; 394 l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
395 if (prescaler >= 0x00 && prescaler <= 0x07) {
396 l |= OMAP_TIMER_CTRL_PRE;
397 l |= prescaler << 2;
398 }
230 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 399 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
231} 400}
232 401
233unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) 402void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
403 unsigned int value)
234{ 404{
235 return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); 405 omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
236} 406}
237 407
238void omap_dm_timer_reset_counter(struct omap_dm_timer *timer) 408unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
239{ 409{
240 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, 0); 410 return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
241} 411}
242 412
243void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load) 413void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
244{ 414{
245 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); 415 omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
246} 416}
247 417
248void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match) 418unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
249{ 419{
250 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); 420 return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
251} 421}
252 422
253void omap_dm_timer_enable_compare(struct omap_dm_timer *timer) 423int omap_dm_timers_active(void)
254{ 424{
255 u32 l; 425 int i;
256 426
257 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 427 for (i = 0; i < dm_timer_count; i++) {
258 l |= OMAP_TIMER_CTRL_CE; 428 struct omap_dm_timer *timer;
259 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
260}
261 429
430 timer = &dm_timers[i];
431 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
432 OMAP_TIMER_CTRL_ST)
433 return 1;
434 }
435 return 0;
436}
262 437
263static inline void __dm_timer_init(void) 438int omap_dm_timer_init(void)
264{ 439{
265 struct omap_dm_timer *timer; 440 struct omap_dm_timer *timer;
441 int i;
442
443 if (!(cpu_is_omap16xx() || cpu_is_omap24xx()))
444 return -ENODEV;
266 445
267 spin_lock_init(&dm_timer_lock); 446 spin_lock_init(&dm_timer_lock);
268 INIT_LIST_HEAD(&dm_timer_info.unused_timers); 447 for (i = 0; i < dm_timer_count; i++) {
269 INIT_LIST_HEAD(&dm_timer_info.reserved_timers); 448#ifdef CONFIG_ARCH_OMAP2
270 449 char clk_name[16];
271 timer = &dm_timers[0]; 450#endif
272 while (timer->base) { 451
273 list_add_tail((struct list_head *)timer, &dm_timer_info.unused_timers); 452 timer = &dm_timers[i];
274 omap_dm_timer_reset(timer); 453 timer->io_base = (void __iomem *) io_p2v(timer->phys_base);
275 timer++; 454#ifdef CONFIG_ARCH_OMAP2
455 sprintf(clk_name, "gpt%d_ick", i + 1);
456 timer->iclk = clk_get(NULL, clk_name);
457 sprintf(clk_name, "gpt%d_fck", i + 1);
458 timer->fclk = clk_get(NULL, clk_name);
459#endif
276 } 460 }
277}
278 461
279static int __init omap_dm_timer_init(void)
280{
281 if (cpu_is_omap16xx())
282 __dm_timer_init();
283 return 0; 462 return 0;
284} 463}
285
286arch_initcall(omap_dm_timer_init);
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
diff --git a/include/asm-arm/arch-omap/dmtimer.h b/include/asm-arm/arch-omap/dmtimer.h
index e6522e6a3834..5b58e3d62742 100644
--- a/include/asm-arm/arch-omap/dmtimer.h
+++ b/include/asm-arm/arch-omap/dmtimer.h
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (C) 2005 Nokia Corporation 6 * Copyright (C) 2005 Nokia Corporation
7 * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com> 7 * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
8 * PWM and clock framwork support by Timo Teras.
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the 11 * under the terms of the GNU General Public License as published by the
@@ -25,69 +26,55 @@
25 * 675 Mass Ave, Cambridge, MA 02139, USA. 26 * 675 Mass Ave, Cambridge, MA 02139, USA.
26 */ 27 */
27 28
28#ifndef __ASM_ARCH_TIMER_H 29#ifndef __ASM_ARCH_DMTIMER_H
29#define __ASM_ARCH_TIMER_H 30#define __ASM_ARCH_DMTIMER_H
30
31#include <linux/list.h>
32
33#define OMAP_TIMER_SRC_ARMXOR 0x00
34#define OMAP_TIMER_SRC_32_KHZ 0x01
35#define OMAP_TIMER_SRC_EXT_CLK 0x02
36
37/* timer control reg bits */
38#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13)
39#define OMAP_TIMER_CTRL_PT (1 << 12)
40#define OMAP_TIMER_CTRL_TRG_OVERFLOW (0x1 << 10)
41#define OMAP_TIMER_CTRL_TRG_OFANDMATCH (0x2 << 10)
42#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8)
43#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8)
44#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8)
45#define OMAP_TIMER_CTRL_SCPWM (1 << 7)
46#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */
47#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */
48#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* how much to shift the prescaler value */
49#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */
50#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */
51 31
52/* timer interrupt enable bits */ 32/* clock sources */
53#define OMAP_TIMER_INT_CAPTURE (1 << 2) 33#define OMAP_TIMER_SRC_SYS_CLK 0x00
54#define OMAP_TIMER_INT_OVERFLOW (1 << 1) 34#define OMAP_TIMER_SRC_32_KHZ 0x01
55#define OMAP_TIMER_INT_MATCH (1 << 0) 35#define OMAP_TIMER_SRC_EXT_CLK 0x02
56 36
37/* timer interrupt enable bits */
38#define OMAP_TIMER_INT_CAPTURE (1 << 2)
39#define OMAP_TIMER_INT_OVERFLOW (1 << 1)
40#define OMAP_TIMER_INT_MATCH (1 << 0)
57 41
58struct omap_dm_timer { 42/* trigger types */
59 struct list_head timer_list; 43#define OMAP_TIMER_TRIGGER_NONE 0x00
44#define OMAP_TIMER_TRIGGER_OVERFLOW 0x01
45#define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE 0x02
60 46
61 u32 base; 47struct omap_dm_timer;
62 unsigned int irq; 48struct clk;
63};
64 49
65u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg); 50int omap_dm_timer_init(void);
66void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value);
67 51
68struct omap_dm_timer * omap_dm_timer_request(void); 52struct omap_dm_timer *omap_dm_timer_request(void);
53struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
69void omap_dm_timer_free(struct omap_dm_timer *timer); 54void omap_dm_timer_free(struct omap_dm_timer *timer);
70void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
71 55
72void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value); 56int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
73void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value); 57
74void omap_dm_timer_enable_compare(struct omap_dm_timer *timer); 58u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
75void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer); 59struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
76 60
77void omap_dm_timer_trigger(struct omap_dm_timer *timer); 61void omap_dm_timer_trigger(struct omap_dm_timer *timer);
78void omap_dm_timer_start(struct omap_dm_timer *timer); 62void omap_dm_timer_start(struct omap_dm_timer *timer);
79void omap_dm_timer_stop(struct omap_dm_timer *timer); 63void omap_dm_timer_stop(struct omap_dm_timer *timer);
80 64
81void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load); 65void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
82void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match); 66void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
67void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
68void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
69void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
70
71void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
83 72
84unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer); 73unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
85void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value); 74void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
86
87unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer); 75unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
88void omap_dm_timer_reset_counter(struct omap_dm_timer *timer);
89 76
90int omap_dm_timers_active(void); 77int omap_dm_timers_active(void);
91u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
92 78
93#endif /* __ASM_ARCH_TIMER_H */ 79
80#endif /* __ASM_ARCH_DMTIMER_H */
diff --git a/include/asm-arm/arch-omap/irqs.h b/include/asm-arm/arch-omap/irqs.h
index 42098d99f302..46f2f06eae0c 100644
--- a/include/asm-arm/arch-omap/irqs.h
+++ b/include/asm-arm/arch-omap/irqs.h
@@ -242,6 +242,18 @@
242#define INT_24XX_GPIO_BANK2 30 242#define INT_24XX_GPIO_BANK2 30
243#define INT_24XX_GPIO_BANK3 31 243#define INT_24XX_GPIO_BANK3 31
244#define INT_24XX_GPIO_BANK4 32 244#define INT_24XX_GPIO_BANK4 32
245#define INT_24XX_GPTIMER1 37
246#define INT_24XX_GPTIMER2 38
247#define INT_24XX_GPTIMER3 39
248#define INT_24XX_GPTIMER4 40
249#define INT_24XX_GPTIMER5 41
250#define INT_24XX_GPTIMER6 42
251#define INT_24XX_GPTIMER7 43
252#define INT_24XX_GPTIMER8 44
253#define INT_24XX_GPTIMER9 45
254#define INT_24XX_GPTIMER10 46
255#define INT_24XX_GPTIMER11 47
256#define INT_24XX_GPTIMER12 48
245#define INT_24XX_MCBSP1_IRQ_TX 59 257#define INT_24XX_MCBSP1_IRQ_TX 59
246#define INT_24XX_MCBSP1_IRQ_RX 60 258#define INT_24XX_MCBSP1_IRQ_RX 60
247#define INT_24XX_MCBSP2_IRQ_TX 62 259#define INT_24XX_MCBSP2_IRQ_TX 62