GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / arch / arm / plat-brcm / mpcore_gtimer.c
blobe38dac0e1dc45bf3b6d7b8d2fcd81dbbdf69501e
1 /*
2 * Copyright (C) 1999 - 2003 ARM Limited
3 * Copyright (C) 2000 Deep Blue Solutions Ltd
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <linux/kernel.h>
20 #include <linux/init.h>
21 #include <linux/clockchips.h>
22 #include <linux/interrupt.h>
23 #include <linux/irq.h>
24 #include <linux/io.h>
26 #include <plat/mpcore.h>
27 #if defined(CONFIG_BUZZZ)
28 #include <asm/buzzz.h>
29 #endif /* CONFIG_BUZZZ */
32 * The ARM9 MPCORE Global Timer is a continously-running 64-bit timer,
33 * which is used both as a "clock source" and as a "clock event" -
34 * there is a banked per-cpu compare and reload registers that are
35 * used to generated either one-shot or periodic interrupts on the cpu
36 * that calls the mode_set function.
38 * NOTE: This code does not support dynamic change of the source clock
39 * frequency. The interrupt interval is only calculated once during
40 * initialization.
44 * Global Timer Registers
46 #define GTIMER_COUNT_LO 0x00 /* Lower 32 of 64 bits counter */
47 #define GTIMER_COUNT_HI 0x04 /* Higher 32 of 64 bits counter */
48 #define GTIMER_CTRL 0x08 /* Control (partially banked) */
49 #define GTIMER_CTRL_EN (1<<0) /* Timer enable bit */
50 #define GTIMER_CTRL_CMP_EN (1<<1) /* Comparator enable */
51 #define GTIMER_CTRL_IRQ_EN (1<<2) /* Interrupt enable */
52 #define GTIMER_CTRL_AUTO_EN (1<<3) /* Auto-increment enable */
53 #define GTIMER_INT_STAT 0x0C /* Interrupt Status (banked) */
54 #define GTIMER_COMP_LO 0x10 /* Lower half comparator (banked) */
55 #define GTIMER_COMP_HI 0x14 /* Upper half comparator (banked) */
56 #define GTIMER_RELOAD 0x18 /* Auto-increment (banked) */
58 #define GTIMER_MIN_RANGE 30 /* Minimum wrap-around time in sec */
60 /* Gobal variables */
61 static void __iomem *gtimer_base;
62 static u32 ticks_per_jiffy;
64 extern void soc_watchdog(void);
67 static cycle_t gptimer_count_read(struct clocksource *cs)
69 u32 count_hi, count_ho, count_lo;
70 u64 count;
72 /* Avoid unexpected rollover with double-read of upper half */
73 do {
74 count_hi = readl( gtimer_base + GTIMER_COUNT_HI );
75 count_lo = readl( gtimer_base + GTIMER_COUNT_LO );
76 count_ho = readl( gtimer_base + GTIMER_COUNT_HI );
77 } while( count_hi != count_ho );
79 count = (u64) count_hi << 32 | count_lo ;
80 return count;
83 static struct clocksource clocksource_gptimer = {
84 .name = "mpcore_gtimer",
85 .rating = 300,
86 .read = gptimer_count_read,
87 .mask = CLOCKSOURCE_MASK(64),
88 .shift = 20,
89 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
92 static void __init gptimer_clocksource_init(u32 freq)
94 struct clocksource *cs = &clocksource_gptimer;
96 /* <freq> is timer clock in Hz */
97 clocksource_calc_mult_shift(cs, freq, GTIMER_MIN_RANGE);
99 clocksource_register(cs);
103 * IRQ handler for the global timer
104 * This interrupt is banked per CPU so is handled identically
106 static irqreturn_t gtimer_interrupt(int irq, void *dev_id)
108 struct clock_event_device *evt = dev_id;
110 /* clear the interrupt */
111 writel(1, gtimer_base + GTIMER_INT_STAT);
113 #if defined(BUZZZ_KEVT_LVL) && (BUZZZ_KEVT_LVL >= 2)
114 buzzz_kevt_log1(BUZZZ_KEVT_ID_GTIMER_EVENT, (u32)evt->event_handler);
115 #endif /* BUZZZ_KEVT_LVL */
117 evt->event_handler(evt);
119 soc_watchdog();
121 return IRQ_HANDLED;
124 static void gtimer_set_mode(
125 enum clock_event_mode mode,
126 struct clock_event_device *evt
129 u32 ctrl, period;
130 u64 count;
132 /* Get current register with global enable and prescaler */
133 ctrl = readl( gtimer_base + GTIMER_CTRL );
135 /* Clear the mode-related bits */
136 ctrl &= ~( GTIMER_CTRL_CMP_EN |
137 GTIMER_CTRL_IRQ_EN |
138 GTIMER_CTRL_AUTO_EN);
140 switch (mode) {
141 case CLOCK_EVT_MODE_PERIODIC:
142 period = ticks_per_jiffy;
143 count = gptimer_count_read( NULL );
144 count += period ;
145 writel(ctrl, gtimer_base + GTIMER_CTRL);
146 writel(count & 0xffffffffUL, gtimer_base + GTIMER_COMP_LO);
147 writel(count >> 32, gtimer_base + GTIMER_COMP_HI);
148 writel(period, gtimer_base + GTIMER_RELOAD);
149 ctrl |= GTIMER_CTRL_CMP_EN |
150 GTIMER_CTRL_IRQ_EN |
151 GTIMER_CTRL_AUTO_EN ;
152 break;
154 case CLOCK_EVT_MODE_ONESHOT:
155 /* period set, and timer enabled in 'next_event' hook */
156 break;
158 case CLOCK_EVT_MODE_UNUSED:
159 case CLOCK_EVT_MODE_SHUTDOWN:
160 default:
161 break;
163 /* Apply the new mode */
164 writel(ctrl, gtimer_base + GTIMER_CTRL);
167 static int gtimer_set_next_event(
168 unsigned long next,
169 struct clock_event_device *evt
172 u32 ctrl;
173 u64 count;
175 #if defined(BUZZZ_KEVT_LVL) && (BUZZZ_KEVT_LVL >= 2)
176 buzzz_kevt_log1(BUZZZ_KEVT_ID_GTIMER_NEXT, (u32)next);
177 #endif /* BUZZZ_KEVT_LVL */
179 ctrl = readl(gtimer_base + GTIMER_CTRL);
180 count = gptimer_count_read( NULL );
182 ctrl &= ~GTIMER_CTRL_CMP_EN ;
183 writel(ctrl, gtimer_base + GTIMER_CTRL);
185 count += next ;
187 writel(count & 0xffffffffUL, gtimer_base + GTIMER_COMP_LO);
188 writel(count >> 32, gtimer_base + GTIMER_COMP_HI);
190 /* enable IRQ for the same cpu that loaded comparator */
191 ctrl |= GTIMER_CTRL_CMP_EN ;
192 ctrl |= GTIMER_CTRL_IRQ_EN ;
194 writel(ctrl, gtimer_base + GTIMER_CTRL);
196 return 0;
199 static struct clock_event_device gtimer_clockevent = {
200 .name = "mpcore_gtimer",
201 .shift = 20,
202 .features = CLOCK_EVT_FEAT_PERIODIC,
203 .set_mode = gtimer_set_mode,
204 .set_next_event = gtimer_set_next_event,
205 .rating = 300,
206 .cpumask = cpu_all_mask,
209 static struct irqaction gtimer_irq = {
210 .name = "mpcore_gtimer",
211 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_PERCPU,
212 .handler = gtimer_interrupt,
213 .dev_id = &gtimer_clockevent,
216 static void __init gtimer_clockevents_init(u32 freq, unsigned timer_irq)
218 struct clock_event_device *evt = &gtimer_clockevent;
220 evt->irq = timer_irq;
221 ticks_per_jiffy = DIV_ROUND_CLOSEST(freq, HZ);
223 clockevents_calc_mult_shift(evt, freq, GTIMER_MIN_RANGE);
225 evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt);
226 evt->min_delta_ns = clockevent_delta2ns(0xf, evt);
228 /* Register the device to install handler before enabing IRQ */
229 clockevents_register_device(evt);
230 setup_irq(timer_irq, &gtimer_irq);
234 * MPCORE Global Timer initialization function
236 void __init mpcore_gtimer_init(
237 void __iomem *base,
238 unsigned long freq,
239 unsigned int timer_irq)
241 u32 ctrl ;
242 u64 count;
244 gtimer_base = base;
246 printk(KERN_INFO "MPCORE Global Timer Clock %luHz\n",
247 (unsigned long) freq);
249 /* Prescaler = 0; let the Global Timer run at native PERIPHCLK rate */
251 ctrl = GTIMER_CTRL_EN;
253 /* Enable the free-running global counter */
255 writel(ctrl, gtimer_base + GTIMER_CTRL);
257 /* Self-test the timer is running */
258 count = gptimer_count_read(NULL);
260 /* Register as time source */
261 gptimer_clocksource_init(freq);
263 /* Register as system timer */
264 gtimer_clockevents_init(freq, timer_irq);
266 count = gptimer_count_read(NULL) - count ;
267 if( count == 0 )
268 printk(KERN_CRIT "MPCORE Global Timer Dead!!\n");