[ARM] 3340/1: Fix the PCI setup for direct master access to SDRAM
[pv_ops_mirror.git] / arch / arm / plat-omap / dmtimer.c
blob38d7ebf879207cb116ed17fc1c81e2b1ab7ec946
1 /*
2 * linux/arch/arm/plat-omap/dmtimer.c
4 * OMAP Dual-Mode Timers
6 * Copyright (C) 2005 Nokia Corporation
7 * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
9 * 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 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <linux/init.h>
29 #include <asm/hardware.h>
30 #include <asm/arch/dmtimer.h>
31 #include <asm/io.h>
32 #include <asm/arch/irqs.h>
33 #include <linux/spinlock.h>
34 #include <linux/list.h>
36 #define OMAP_TIMER_COUNT 8
38 #define OMAP_TIMER_ID_REG 0x00
39 #define OMAP_TIMER_OCP_CFG_REG 0x10
40 #define OMAP_TIMER_SYS_STAT_REG 0x14
41 #define OMAP_TIMER_STAT_REG 0x18
42 #define OMAP_TIMER_INT_EN_REG 0x1c
43 #define OMAP_TIMER_WAKEUP_EN_REG 0x20
44 #define OMAP_TIMER_CTRL_REG 0x24
45 #define OMAP_TIMER_COUNTER_REG 0x28
46 #define OMAP_TIMER_LOAD_REG 0x2c
47 #define OMAP_TIMER_TRIGGER_REG 0x30
48 #define OMAP_TIMER_WRITE_PEND_REG 0x34
49 #define OMAP_TIMER_MATCH_REG 0x38
50 #define OMAP_TIMER_CAPTURE_REG 0x3c
51 #define OMAP_TIMER_IF_CTRL_REG 0x40
54 static struct dmtimer_info_struct {
55 struct list_head unused_timers;
56 struct list_head reserved_timers;
57 } dm_timer_info;
59 static struct omap_dm_timer dm_timers[] = {
60 { .base=0xfffb1400, .irq=INT_1610_GPTIMER1 },
61 { .base=0xfffb1c00, .irq=INT_1610_GPTIMER2 },
62 { .base=0xfffb2400, .irq=INT_1610_GPTIMER3 },
63 { .base=0xfffb2c00, .irq=INT_1610_GPTIMER4 },
64 { .base=0xfffb3400, .irq=INT_1610_GPTIMER5 },
65 { .base=0xfffb3c00, .irq=INT_1610_GPTIMER6 },
66 { .base=0xfffb4400, .irq=INT_1610_GPTIMER7 },
67 { .base=0xfffb4c00, .irq=INT_1610_GPTIMER8 },
68 { .base=0x0 },
72 static spinlock_t dm_timer_lock;
75 inline void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value)
77 omap_writel(value, timer->base + reg);
78 while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG))
82 u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg)
84 return omap_readl(timer->base + reg);
87 int omap_dm_timers_active(void)
89 struct omap_dm_timer *timer;
91 for (timer = &dm_timers[0]; timer->base; ++timer)
92 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
93 OMAP_TIMER_CTRL_ST)
94 return 1;
96 return 0;
100 void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
102 int n = (timer - dm_timers) << 1;
103 u32 l;
105 l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
106 l |= source << n;
107 omap_writel(l, MOD_CONF_CTRL_1);
111 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
113 /* Reset and set posted mode */
114 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
115 omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, 0x02);
117 omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_ARMXOR);
122 struct omap_dm_timer * omap_dm_timer_request(void)
124 struct omap_dm_timer *timer = NULL;
125 unsigned long flags;
127 spin_lock_irqsave(&dm_timer_lock, flags);
128 if (!list_empty(&dm_timer_info.unused_timers)) {
129 timer = (struct omap_dm_timer *)
130 dm_timer_info.unused_timers.next;
131 list_move_tail((struct list_head *)timer,
132 &dm_timer_info.reserved_timers);
134 spin_unlock_irqrestore(&dm_timer_lock, flags);
136 return timer;
140 void omap_dm_timer_free(struct omap_dm_timer *timer)
142 unsigned long flags;
144 omap_dm_timer_reset(timer);
146 spin_lock_irqsave(&dm_timer_lock, flags);
147 list_move_tail((struct list_head *)timer, &dm_timer_info.unused_timers);
148 spin_unlock_irqrestore(&dm_timer_lock, flags);
151 void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
152 unsigned int value)
154 omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
157 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
159 return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
162 void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
164 omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
167 void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer)
169 u32 l;
170 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
171 l |= OMAP_TIMER_CTRL_AR;
172 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
175 void omap_dm_timer_trigger(struct omap_dm_timer *timer)
177 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 1);
180 void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value)
182 u32 l;
184 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
185 l |= value & 0x3;
186 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
189 void omap_dm_timer_start(struct omap_dm_timer *timer)
191 u32 l;
193 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
194 l |= OMAP_TIMER_CTRL_ST;
195 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
198 void omap_dm_timer_stop(struct omap_dm_timer *timer)
200 u32 l;
202 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
203 l &= ~0x1;
204 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
207 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
209 return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
212 void omap_dm_timer_reset_counter(struct omap_dm_timer *timer)
214 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, 0);
217 void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load)
219 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
222 void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match)
224 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
227 void omap_dm_timer_enable_compare(struct omap_dm_timer *timer)
229 u32 l;
231 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
232 l |= OMAP_TIMER_CTRL_CE;
233 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
237 static inline void __dm_timer_init(void)
239 struct omap_dm_timer *timer;
241 spin_lock_init(&dm_timer_lock);
242 INIT_LIST_HEAD(&dm_timer_info.unused_timers);
243 INIT_LIST_HEAD(&dm_timer_info.reserved_timers);
245 timer = &dm_timers[0];
246 while (timer->base) {
247 list_add_tail((struct list_head *)timer, &dm_timer_info.unused_timers);
248 omap_dm_timer_reset(timer);
249 timer++;
253 static int __init omap_dm_timer_init(void)
255 if (cpu_is_omap16xx())
256 __dm_timer_init();
257 return 0;
260 arch_initcall(omap_dm_timer_init);