aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sgi-ip27
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-10-18 08:34:12 -0400
committerRalf Baechle <ralf@linux-mips.org>2007-10-18 13:11:47 -0400
commite887b24592c5ddf46d37e592b2ee6bd2188257e1 (patch)
tree802956f841441d87dc472240c9eee87f6a574f46 /arch/mips/sgi-ip27
parent832348ff0bf1538e026ff862f91ab6db06e73499 (diff)
[MIPS] IP27: Convert to clock_event_device.
This separates the tick timer stuff from the generic MIPS time.c. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/sgi-ip27')
-rw-r--r--arch/mips/sgi-ip27/ip27-irq.c5
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c155
2 files changed, 94 insertions, 66 deletions
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 856649cf9f1..1bb692a3b31 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -374,14 +374,13 @@ int __devinit request_bridge_irq(struct bridge_controller *bc)
374 return irq; 374 return irq;
375} 375}
376 376
377extern void ip27_rt_timer_interrupt(void);
378
379asmlinkage void plat_irq_dispatch(void) 377asmlinkage void plat_irq_dispatch(void)
380{ 378{
381 unsigned long pending = read_c0_cause() & read_c0_status(); 379 unsigned long pending = read_c0_cause() & read_c0_status();
380 extern unsigned int rt_timer_irq;
382 381
383 if (pending & CAUSEF_IP4) 382 if (pending & CAUSEF_IP4)
384 ip27_rt_timer_interrupt(); 383 do_IRQ(rt_timer_irq);
385 else if (pending & CAUSEF_IP2) /* PI_INT_PEND_0 or CC_PEND_{A|B} */ 384 else if (pending & CAUSEF_IP2) /* PI_INT_PEND_0 or CC_PEND_{A|B} */
386 ip27_do_irq_mask0(); 385 ip27_do_irq_mask0();
387 else if (pending & CAUSEF_IP3) /* PI_INT_PEND_1 */ 386 else if (pending & CAUSEF_IP3) /* PI_INT_PEND_1 */
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index b7b3479b6bc..d467bf4f6c3 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -3,6 +3,7 @@
3 * Copytight (C) 1999, 2000 Silicon Graphics, Inc. 3 * Copytight (C) 1999, 2000 Silicon Graphics, Inc.
4 */ 4 */
5#include <linux/bcd.h> 5#include <linux/bcd.h>
6#include <linux/clockchips.h>
6#include <linux/init.h> 7#include <linux/init.h>
7#include <linux/kernel.h> 8#include <linux/kernel.h>
8#include <linux/sched.h> 9#include <linux/sched.h>
@@ -25,22 +26,8 @@
25#include <asm/sn/sn0/ip27.h> 26#include <asm/sn/sn0/ip27.h>
26#include <asm/sn/sn0/hub.h> 27#include <asm/sn/sn0/hub.h>
27 28
28/*
29 * This is a hack; we really need to figure these values out dynamically
30 *
31 * Since 800 ns works very well with various HUB frequencies, such as
32 * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time.
33 *
34 * Ralf: which clock rate is used to feed the counter?
35 */
36#define NSEC_PER_CYCLE 800
37#define CYCLES_PER_SEC (NSEC_PER_SEC/NSEC_PER_CYCLE)
38#define CYCLES_PER_JIFFY (CYCLES_PER_SEC/HZ)
39
40#define TICK_SIZE (tick_nsec / 1000) 29#define TICK_SIZE (tick_nsec / 1000)
41 30
42static unsigned long ct_cur[NR_CPUS]; /* What counter should be at next timer irq */
43
44#if 0 31#if 0
45static int set_rtc_mmss(unsigned long nowtime) 32static int set_rtc_mmss(unsigned long nowtime)
46{ 33{
@@ -86,36 +73,6 @@ static int set_rtc_mmss(unsigned long nowtime)
86} 73}
87#endif 74#endif
88 75
89static unsigned int rt_timer_irq;
90
91void ip27_rt_timer_interrupt(void)
92{
93 int cpu = smp_processor_id();
94 int cpuA = cputoslice(cpu) == 0;
95 unsigned int irq = rt_timer_irq;
96
97 irq_enter();
98 write_seqlock(&xtime_lock);
99
100again:
101 LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */
102 ct_cur[cpu] += CYCLES_PER_JIFFY;
103 LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]);
104
105 if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu])
106 goto again;
107
108 kstat_this_cpu.irqs[irq]++; /* kstat only for bootcpu? */
109
110 if (cpu == 0)
111 do_timer(1);
112
113 update_process_times(user_mode(get_irq_regs()));
114
115 write_sequnlock(&xtime_lock);
116 irq_exit();
117}
118
119/* Includes for ioc3_init(). */ 76/* Includes for ioc3_init(). */
120#include <asm/sn/types.h> 77#include <asm/sn/types.h>
121#include <asm/sn/sn0/addrs.h> 78#include <asm/sn/sn0/addrs.h>
@@ -154,6 +111,46 @@ unsigned long read_persistent_clock(void)
154 return mktime(year, month, date, hour, min, sec); 111 return mktime(year, month, date, hour, min, sec);
155} 112}
156 113
114static int rt_set_next_event(unsigned long delta,
115 struct clock_event_device *evt)
116{
117 unsigned int cpu = smp_processor_id();
118 int slice = cputoslice(cpu) == 0;
119 unsigned long cnt;
120
121 cnt = LOCAL_HUB_L(PI_RT_COUNT);
122 cnt += delta;
123 LOCAL_HUB_S(slice ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, cnt);
124
125 return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0;
126}
127
128static void rt_set_mode(enum clock_event_mode mode,
129 struct clock_event_device *evt)
130{
131 switch (mode) {
132 case CLOCK_EVT_MODE_PERIODIC:
133 /* The only mode supported */
134 break;
135
136 case CLOCK_EVT_MODE_UNUSED:
137 case CLOCK_EVT_MODE_SHUTDOWN:
138 case CLOCK_EVT_MODE_ONESHOT:
139 case CLOCK_EVT_MODE_RESUME:
140 /* Nothing to do */
141 break;
142 }
143}
144
145struct clock_event_device rt_clock_event_device = {
146 .name = "HUB-RT",
147 .features = CLOCK_EVT_FEAT_ONESHOT,
148
149 .rating = 300,
150 .set_next_event = rt_set_next_event,
151 .set_mode = rt_set_mode,
152};
153
157static void enable_rt_irq(unsigned int irq) 154static void enable_rt_irq(unsigned int irq)
158{ 155{
159} 156}
@@ -171,6 +168,20 @@ static struct irq_chip rt_irq_type = {
171 .eoi = enable_rt_irq, 168 .eoi = enable_rt_irq,
172}; 169};
173 170
171unsigned int rt_timer_irq;
172
173static irqreturn_t ip27_rt_timer_interrupt(int irq, void *dev_id)
174{
175 struct clock_event_device *cd = &rt_clock_event_device;
176 unsigned int cpu = smp_processor_id();
177 int slice = cputoslice(cpu) == 0;
178
179 LOCAL_HUB_S(slice ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */
180 cd->event_handler(cd);
181
182 return IRQ_HANDLED;
183}
184
174static struct irqaction rt_irqaction = { 185static struct irqaction rt_irqaction = {
175 .handler = (irq_handler_t) ip27_rt_timer_interrupt, 186 .handler = (irq_handler_t) ip27_rt_timer_interrupt,
176 .flags = IRQF_DISABLED, 187 .flags = IRQF_DISABLED,
@@ -178,26 +189,43 @@ static struct irqaction rt_irqaction = {
178 .name = "timer" 189 .name = "timer"
179}; 190};
180 191
181void __init plat_timer_setup(struct irqaction *irq) 192/*
193 * This is a hack; we really need to figure these values out dynamically
194 *
195 * Since 800 ns works very well with various HUB frequencies, such as
196 * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time.
197 *
198 * Ralf: which clock rate is used to feed the counter?
199 */
200#define NSEC_PER_CYCLE 800
201#define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE)
202
203static void __init ip27_rt_clock_event_init(void)
182{ 204{
183 int irqno = allocate_irqno(); 205 struct clock_event_device *cd = &rt_clock_event_device;
206 unsigned int cpu = smp_processor_id();
207 int irq = allocate_irqno();
184 208
185 if (irqno < 0) 209 if (irq < 0)
186 panic("Can't allocate interrupt number for timer interrupt"); 210 panic("Can't allocate interrupt number for timer interrupt");
187 211
188 set_irq_chip_and_handler(irqno, &rt_irq_type, handle_percpu_irq); 212 rt_timer_irq = irq;
189 213
190 /* over-write the handler, we use our own way */ 214 cd->irq = irq,
191 irq->handler = no_action; 215 cd->cpumask = cpumask_of_cpu(cpu),
192 216
193 /* setup irqaction */
194 irq_desc[irqno].status |= IRQ_PER_CPU;
195
196 rt_timer_irq = irqno;
197 /* 217 /*
198 * Only needed to get /proc/interrupt to display timer irq stats 218 * Calculate the min / max delta
199 */ 219 */
200 setup_irq(irqno, &rt_irqaction); 220 cd->mult =
221 div_sc((unsigned long) CYCLES_PER_SEC, NSEC_PER_SEC, 32);
222 cd->shift = 32;
223 cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
224 cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
225 clockevents_register_device(cd);
226
227 set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq);
228 setup_irq(irq, &rt_irqaction);
201} 229}
202 230
203static cycle_t hub_rt_read(void) 231static cycle_t hub_rt_read(void)
@@ -206,7 +234,7 @@ static cycle_t hub_rt_read(void)
206} 234}
207 235
208struct clocksource ht_rt_clocksource = { 236struct clocksource ht_rt_clocksource = {
209 .name = "HUB", 237 .name = "HUB-RT",
210 .rating = 200, 238 .rating = 200,
211 .read = hub_rt_read, 239 .read = hub_rt_read,
212 .mask = CLOCKSOURCE_MASK(52), 240 .mask = CLOCKSOURCE_MASK(52),
@@ -214,11 +242,17 @@ struct clocksource ht_rt_clocksource = {
214 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 242 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
215}; 243};
216 244
217void __init plat_time_init(void) 245static void __init ip27_rt_clocksource_init(void)
218{ 246{
219 clocksource_register(&ht_rt_clocksource); 247 clocksource_register(&ht_rt_clocksource);
220} 248}
221 249
250void __init plat_time_init(void)
251{
252 ip27_rt_clock_event_init();
253 ip27_rt_clocksource_init();
254}
255
222void __init cpu_time_init(void) 256void __init cpu_time_init(void)
223{ 257{
224 lboard_t *board; 258 lboard_t *board;
@@ -248,17 +282,12 @@ void __init hub_rtc_init(cnodeid_t cnode)
248 * node and timeouts will not happen there. 282 * node and timeouts will not happen there.
249 */ 283 */
250 if (get_compact_nodeid() == cnode) { 284 if (get_compact_nodeid() == cnode) {
251 int cpu = smp_processor_id();
252 LOCAL_HUB_S(PI_RT_EN_A, 1); 285 LOCAL_HUB_S(PI_RT_EN_A, 1);
253 LOCAL_HUB_S(PI_RT_EN_B, 1); 286 LOCAL_HUB_S(PI_RT_EN_B, 1);
254 LOCAL_HUB_S(PI_PROF_EN_A, 0); 287 LOCAL_HUB_S(PI_PROF_EN_A, 0);
255 LOCAL_HUB_S(PI_PROF_EN_B, 0); 288 LOCAL_HUB_S(PI_PROF_EN_B, 0);
256 ct_cur[cpu] = CYCLES_PER_JIFFY;
257 LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]);
258 LOCAL_HUB_S(PI_RT_COUNT, 0); 289 LOCAL_HUB_S(PI_RT_COUNT, 0);
259 LOCAL_HUB_S(PI_RT_PEND_A, 0); 290 LOCAL_HUB_S(PI_RT_PEND_A, 0);
260 LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]);
261 LOCAL_HUB_S(PI_RT_COUNT, 0);
262 LOCAL_HUB_S(PI_RT_PEND_B, 0); 291 LOCAL_HUB_S(PI_RT_PEND_B, 0);
263 } 292 }
264} 293}