aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sibyte/sb1250/time.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-10-22 05:38:44 -0400
committerRalf Baechle <ralf@linux-mips.org>2007-10-22 17:09:00 -0400
commitd04533650f64fe3367e180f3e488d92205152cd3 (patch)
tree5f183668d97d9655a8517e61afd46bfa2f80b101 /arch/mips/sibyte/sb1250/time.c
parent06d428d719dece96c01532b62df4140f4e69a308 (diff)
[MIPS] time: SMP-proofing of Sibyte clockevent/clocksource code.
The BCM148 has 4 cores but there are also just 4 generic timers available so use the ZBbus cycle counter instead of it. In addition the ZBbus counter also offers a much higher resolution and 64-bit counting so I'm considering a later complete conversion to it once I figure out if all members of the Sibyte SOC family support it - the docs seem to agree but the headers files seem to disagree ... Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/sibyte/sb1250/time.c')
-rw-r--r--arch/mips/sibyte/sb1250/time.c88
1 files changed, 44 insertions, 44 deletions
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c
index 9ef54628bc9c..a41e908bc218 100644
--- a/arch/mips/sibyte/sb1250/time.c
+++ b/arch/mips/sibyte/sb1250/time.c
@@ -52,26 +52,6 @@
52 52
53extern int sb1250_steal_irq(int irq); 53extern int sb1250_steal_irq(int irq);
54 54
55static cycle_t sb1250_hpt_read(void);
56
57void __init sb1250_hpt_setup(void)
58{
59 int cpu = smp_processor_id();
60
61 if (!cpu) {
62 /* Setup hpt using timer #3 but do not enable irq for it */
63 __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG)));
64 __raw_writeq(SB1250_HPT_VALUE,
65 IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_INIT)));
66 __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
67 IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG)));
68
69 mips_hpt_frequency = V_SCD_TIMER_FREQ;
70 clocksource_mips.read = sb1250_hpt_read;
71 clocksource_mips.mask = M_SCD_TIMER_INIT;
72 }
73}
74
75/* 55/*
76 * The general purpose timer ticks at 1 Mhz independent if 56 * The general purpose timer ticks at 1 Mhz independent if
77 * the rest of the system 57 * the rest of the system
@@ -121,18 +101,14 @@ sibyte_next_event(unsigned long delta, struct clock_event_device *evt)
121 return 0; 101 return 0;
122} 102}
123 103
124struct clock_event_device sibyte_hpt_clockevent = {
125 .name = "sb1250-counter",
126 .features = CLOCK_EVT_FEAT_PERIODIC,
127 .set_mode = sibyte_set_mode,
128 .set_next_event = sibyte_next_event,
129 .shift = 32,
130 .irq = 0,
131};
132
133static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) 104static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
134{ 105{
135 struct clock_event_device *cd = &sibyte_hpt_clockevent; 106 unsigned int cpu = smp_processor_id();
107 struct clock_event_device *cd = dev_id;
108
109 /* ACK interrupt */
110 ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
111 IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
136 112
137 cd->event_handler(cd); 113 cd->event_handler(cd);
138 114
@@ -145,15 +121,35 @@ static struct irqaction sibyte_irqaction = {
145 .name = "timer", 121 .name = "timer",
146}; 122};
147 123
124static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent);
125static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction);
126static DEFINE_PER_CPU(char [18], sibyte_hpt_name);
127
148void __cpuinit sb1250_clockevent_init(void) 128void __cpuinit sb1250_clockevent_init(void)
149{ 129{
150 struct clock_event_device *cd = &sibyte_hpt_clockevent;
151 unsigned int cpu = smp_processor_id(); 130 unsigned int cpu = smp_processor_id();
152 int irq = K_INT_TIMER_0 + cpu; 131 unsigned int irq = K_INT_TIMER_0 + cpu;
132 struct irqaction *action = &per_cpu(sibyte_hpt_irqaction, cpu);
133 struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu);
134 unsigned char *name = per_cpu(sibyte_hpt_name, cpu);
153 135
154 /* Only have 4 general purpose timers, and we use last one as hpt */ 136 /* Only have 4 general purpose timers, and we use last one as hpt */
155 BUG_ON(cpu > 2); 137 BUG_ON(cpu > 2);
156 138
139 sprintf(name, "bcm1480-counter %d", cpu);
140 cd->name = name;
141 cd->features = CLOCK_EVT_FEAT_PERIODIC |
142 CLOCK_EVT_MODE_ONESHOT;
143 clockevent_set_clock(cd, V_SCD_TIMER_FREQ);
144 cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd);
145 cd->min_delta_ns = clockevent_delta2ns(1, cd);
146 cd->rating = 200;
147 cd->irq = irq;
148 cd->cpumask = cpumask_of_cpu(cpu);
149 cd->set_next_event = sibyte_next_event;
150 cd->set_mode = sibyte_set_mode;
151 clockevents_register_device(cd);
152
157 sb1250_mask_irq(cpu, irq); 153 sb1250_mask_irq(cpu, irq);
158 154
159 /* Map the timer interrupt to ip[4] of this cpu */ 155 /* Map the timer interrupt to ip[4] of this cpu */
@@ -165,17 +161,11 @@ void __cpuinit sb1250_clockevent_init(void)
165 sb1250_unmask_irq(cpu, irq); 161 sb1250_unmask_irq(cpu, irq);
166 sb1250_steal_irq(irq); 162 sb1250_steal_irq(irq);
167 163
168 /* 164 action->handler = sibyte_counter_handler;
169 * This interrupt is "special" in that it doesn't use the request_irq 165 action->flags = IRQF_DISABLED | IRQF_PERCPU;
170 * way to hook the irq line. The timer interrupt is initialized early 166 action->name = name;
171 * enough to make this a major pain, and it's also firing enough to 167 action->dev_id = cd;
172 * warrant a bit of special case code. sb1250_timer_interrupt is
173 * called directly from irq_handler.S when IP[4] is set during an
174 * interrupt
175 */
176 setup_irq(irq, &sibyte_irqaction); 168 setup_irq(irq, &sibyte_irqaction);
177
178 clockevents_register_device(cd);
179} 169}
180 170
181/* 171/*
@@ -195,8 +185,7 @@ struct clocksource bcm1250_clocksource = {
195 .name = "MIPS", 185 .name = "MIPS",
196 .rating = 200, 186 .rating = 200,
197 .read = sb1250_hpt_read, 187 .read = sb1250_hpt_read,
198 .mask = CLOCKSOURCE_MASK(32), 188 .mask = CLOCKSOURCE_MASK(23),
199 .shift = 32,
200 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 189 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
201}; 190};
202 191
@@ -204,6 +193,17 @@ void __init sb1250_clocksource_init(void)
204{ 193{
205 struct clocksource *cs = &bcm1250_clocksource; 194 struct clocksource *cs = &bcm1250_clocksource;
206 195
196 /* Setup hpt using timer #3 but do not enable irq for it */
197 __raw_writeq(0,
198 IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM,
199 R_SCD_TIMER_CFG)));
200 __raw_writeq(SB1250_HPT_VALUE,
201 IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM,
202 R_SCD_TIMER_INIT)));
203 __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
204 IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM,
205 R_SCD_TIMER_CFG)));
206
207 clocksource_set_clock(cs, V_SCD_TIMER_FREQ); 207 clocksource_set_clock(cs, V_SCD_TIMER_FREQ);
208 clocksource_register(cs); 208 clocksource_register(cs);
209} 209}