aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sgi-ip27/ip27-timer.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-10-22 05:34:13 -0400
committerRalf Baechle <ralf@linux-mips.org>2007-10-22 17:09:00 -0400
commit06d428d719dece96c01532b62df4140f4e69a308 (patch)
tree2e10ca921862366b515404697206f1d0ca68dd56 /arch/mips/sgi-ip27/ip27-timer.c
parent508a775a3c9c6c3f952338f6722ea8bc92899962 (diff)
[MIPS] time: SMP/NUMA-proofing of IP27 HUB RT timer code.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/sgi-ip27/ip27-timer.c')
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c134
1 files changed, 71 insertions, 63 deletions
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index d467bf4f6c3f..f5dccf01da11 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -111,8 +111,24 @@ unsigned long read_persistent_clock(void)
111 return mktime(year, month, date, hour, min, sec); 111 return mktime(year, month, date, hour, min, sec);
112} 112}
113 113
114static int rt_set_next_event(unsigned long delta, 114static void enable_rt_irq(unsigned int irq)
115 struct clock_event_device *evt) 115{
116}
117
118static void disable_rt_irq(unsigned int irq)
119{
120}
121
122static struct irq_chip rt_irq_type = {
123 .name = "SN HUB RT timer",
124 .ack = disable_rt_irq,
125 .mask = disable_rt_irq,
126 .mask_ack = disable_rt_irq,
127 .unmask = enable_rt_irq,
128 .eoi = enable_rt_irq,
129};
130
131static int rt_next_event(unsigned long delta, struct clock_event_device *evt)
116{ 132{
117 unsigned int cpu = smp_processor_id(); 133 unsigned int cpu = smp_processor_id();
118 int slice = cputoslice(cpu) == 0; 134 int slice = cputoslice(cpu) == 0;
@@ -129,50 +145,24 @@ static void rt_set_mode(enum clock_event_mode mode,
129 struct clock_event_device *evt) 145 struct clock_event_device *evt)
130{ 146{
131 switch (mode) { 147 switch (mode) {
132 case CLOCK_EVT_MODE_PERIODIC: 148 case CLOCK_EVT_MODE_ONESHOT:
133 /* The only mode supported */ 149 /* The only mode supported */
134 break; 150 break;
135 151
152 case CLOCK_EVT_MODE_PERIODIC:
136 case CLOCK_EVT_MODE_UNUSED: 153 case CLOCK_EVT_MODE_UNUSED:
137 case CLOCK_EVT_MODE_SHUTDOWN: 154 case CLOCK_EVT_MODE_SHUTDOWN:
138 case CLOCK_EVT_MODE_ONESHOT:
139 case CLOCK_EVT_MODE_RESUME: 155 case CLOCK_EVT_MODE_RESUME:
140 /* Nothing to do */ 156 /* Nothing to do */
141 break; 157 break;
142 } 158 }
143} 159}
144 160
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
154static void enable_rt_irq(unsigned int irq)
155{
156}
157
158static void disable_rt_irq(unsigned int irq)
159{
160}
161
162static struct irq_chip rt_irq_type = {
163 .name = "SN HUB RT timer",
164 .ack = disable_rt_irq,
165 .mask = disable_rt_irq,
166 .mask_ack = disable_rt_irq,
167 .unmask = enable_rt_irq,
168 .eoi = enable_rt_irq,
169};
170
171unsigned int rt_timer_irq; 161unsigned int rt_timer_irq;
172 162
173static irqreturn_t ip27_rt_timer_interrupt(int irq, void *dev_id) 163static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id)
174{ 164{
175 struct clock_event_device *cd = &rt_clock_event_device; 165 struct clock_event_device *cd = dev_id;
176 unsigned int cpu = smp_processor_id(); 166 unsigned int cpu = smp_processor_id();
177 int slice = cputoslice(cpu) == 0; 167 int slice = cputoslice(cpu) == 0;
178 168
@@ -182,11 +172,10 @@ static irqreturn_t ip27_rt_timer_interrupt(int irq, void *dev_id)
182 return IRQ_HANDLED; 172 return IRQ_HANDLED;
183} 173}
184 174
185static struct irqaction rt_irqaction = { 175struct irqaction hub_rt_irqaction = {
186 .handler = (irq_handler_t) ip27_rt_timer_interrupt, 176 .handler = hub_rt_counter_handler,
187 .flags = IRQF_DISABLED, 177 .flags = IRQF_DISABLED | IRQF_PERCPU,
188 .mask = CPU_MASK_NONE, 178 .name = "hub-rt",
189 .name = "timer"
190}; 179};
191 180
192/* 181/*
@@ -200,32 +189,48 @@ static struct irqaction rt_irqaction = {
200#define NSEC_PER_CYCLE 800 189#define NSEC_PER_CYCLE 800
201#define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE) 190#define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE)
202 191
203static void __init ip27_rt_clock_event_init(void) 192static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent);
193static DEFINE_PER_CPU(char [11], hub_rt_name);
194
195static void __cpuinit hub_rt_clock_event_init(void)
204{ 196{
205 struct clock_event_device *cd = &rt_clock_event_device;
206 unsigned int cpu = smp_processor_id(); 197 unsigned int cpu = smp_processor_id();
207 int irq = allocate_irqno(); 198 struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu);
208 199 unsigned char *name = per_cpu(hub_rt_name, cpu);
209 if (irq < 0) 200 int irq = rt_timer_irq;
210 panic("Can't allocate interrupt number for timer interrupt"); 201
211 202 sprintf(name, "hub-rt %d", cpu);
212 rt_timer_irq = irq; 203 cd->name = "HUB-RT",
213 204 cd->features = CLOCK_EVT_FEAT_ONESHOT,
205 clockevent_set_clock(cd, CYCLES_PER_SEC);
206 cd->max_delta_ns = clockevent_delta2ns(0xfffffffffffff, cd);
207 cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
208 cd->rating = 200,
214 cd->irq = irq, 209 cd->irq = irq,
215 cd->cpumask = cpumask_of_cpu(cpu), 210 cd->cpumask = cpumask_of_cpu(cpu),
216 211 cd->rating = 300,
217 /* 212 cd->set_next_event = rt_next_event,
218 * Calculate the min / max delta 213 cd->set_mode = rt_set_mode,
219 */
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); 214 clockevents_register_device(cd);
215}
216
217static void __init hub_rt_clock_event_global_init(void)
218{
219 unsigned int irq;
220
221 do {
222 smp_wmb();
223 irq = rt_timer_irq;
224 if (irq)
225 break;
226
227 irq = allocate_irqno();
228 if (irq < 0)
229 panic("Allocation of irq number for timer failed");
230 } while (xchg(&rt_timer_irq, irq));
226 231
227 set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq); 232 set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq);
228 setup_irq(irq, &rt_irqaction); 233 setup_irq(irq, &hub_rt_irqaction);
229} 234}
230 235
231static cycle_t hub_rt_read(void) 236static cycle_t hub_rt_read(void)
@@ -233,27 +238,29 @@ static cycle_t hub_rt_read(void)
233 return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); 238 return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT);
234} 239}
235 240
236struct clocksource ht_rt_clocksource = { 241struct clocksource hub_rt_clocksource = {
237 .name = "HUB-RT", 242 .name = "HUB-RT",
238 .rating = 200, 243 .rating = 200,
239 .read = hub_rt_read, 244 .read = hub_rt_read,
240 .mask = CLOCKSOURCE_MASK(52), 245 .mask = CLOCKSOURCE_MASK(52),
241 .shift = 32,
242 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 246 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
243}; 247};
244 248
245static void __init ip27_rt_clocksource_init(void) 249static void __init hub_rt_clocksource_init(void)
246{ 250{
247 clocksource_register(&ht_rt_clocksource); 251 struct clocksource *cs = &hub_rt_clocksource;
252
253 clocksource_set_clock(cs, CYCLES_PER_SEC);
254 clocksource_register(cs);
248} 255}
249 256
250void __init plat_time_init(void) 257void __init plat_time_init(void)
251{ 258{
252 ip27_rt_clock_event_init(); 259 hub_rt_clocksource_init();
253 ip27_rt_clocksource_init(); 260 hub_rt_clock_event_global_init();
254} 261}
255 262
256void __init cpu_time_init(void) 263void __cpuinit cpu_time_init(void)
257{ 264{
258 lboard_t *board; 265 lboard_t *board;
259 klcpu_t *cpu; 266 klcpu_t *cpu;
@@ -271,6 +278,7 @@ void __init cpu_time_init(void)
271 278
272 printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); 279 printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed);
273 280
281 hub_rt_clock_event_init();
274 set_c0_status(SRB_TIMOCLK); 282 set_c0_status(SRB_TIMOCLK);
275} 283}
276 284