aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sni/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/sni/time.c')
-rw-r--r--arch/mips/sni/time.c80
1 files changed, 64 insertions, 16 deletions
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
index 0910b35cb71f..60bc62ef0935 100644
--- a/arch/mips/sni/time.c
+++ b/arch/mips/sni/time.c
@@ -11,27 +11,78 @@
11#define SNI_COUNTER2_DIV 64 11#define SNI_COUNTER2_DIV 64
12#define SNI_COUNTER0_DIV ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ) 12#define SNI_COUNTER0_DIV ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ)
13 13
14static void sni_a20r_timer_ack(void) 14static void a20r_set_mode(enum clock_event_mode mode,
15 struct clock_event_device *evt)
15{ 16{
16 *(volatile u8 *)A20R_PT_TIM0_ACK = 0x0; wmb(); 17 switch (mode) {
18 case CLOCK_EVT_MODE_PERIODIC:
19 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34;
20 wmb();
21 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV;
22 wmb();
23 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8;
24 wmb();
25
26 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4;
27 wmb();
28 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV;
29 wmb();
30 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8;
31 wmb();
32
33 break;
34 case CLOCK_EVT_MODE_ONESHOT:
35 case CLOCK_EVT_MODE_UNUSED:
36 case CLOCK_EVT_MODE_SHUTDOWN:
37 break;
38 case CLOCK_EVT_MODE_RESUME:
39 break;
40 }
17} 41}
18 42
43static struct clock_event_device a20r_clockevent_device = {
44 .name = "a20r-timer",
45 .features = CLOCK_EVT_FEAT_PERIODIC,
46
47 /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */
48
49 .rating = 300,
50 .irq = SNI_A20R_IRQ_TIMER,
51 .set_mode = a20r_set_mode,
52};
53
54static irqreturn_t a20r_interrupt(int irq, void *dev_id)
55{
56 struct clock_event_device *cd = dev_id;
57
58 *(volatile u8 *)A20R_PT_TIM0_ACK = 0;
59 wmb();
60
61 cd->event_handler(cd);
62
63 return IRQ_HANDLED;
64}
65
66static struct irqaction a20r_irqaction = {
67 .handler = a20r_interrupt,
68 .flags = IRQF_DISABLED | IRQF_PERCPU,
69 .name = "a20r-timer",
70};
71
19/* 72/*
20 * a20r platform uses 2 counters to divide the input frequency. 73 * a20r platform uses 2 counters to divide the input frequency.
21 * Counter 2 output is connected to Counter 0 & 1 input. 74 * Counter 2 output is connected to Counter 0 & 1 input.
22 */ 75 */
23static void __init sni_a20r_timer_setup(struct irqaction *irq) 76static void __init sni_a20r_timer_setup(void)
24{ 77{
25 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; wmb(); 78 struct clock_event_device *cd = &a20r_clockevent_device;
26 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = (SNI_COUNTER0_DIV) & 0xff; wmb(); 79 struct irqaction *action = &a20r_irqaction;
27 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = (SNI_COUNTER0_DIV >> 8) & 0xff; wmb(); 80 unsigned int cpu = smp_processor_id();
28 81
29 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; wmb(); 82 cd->cpumask = cpumask_of_cpu(cpu);
30 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = (SNI_COUNTER2_DIV) & 0xff; wmb();
31 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = (SNI_COUNTER2_DIV >> 8) & 0xff; wmb();
32 83
33 setup_irq(SNI_A20R_IRQ_TIMER, irq); 84 action->dev_id = cd;
34 mips_timer_ack = sni_a20r_timer_ack; 85 setup_irq(SNI_A20R_IRQ_TIMER, &a20r_irqaction);
35} 86}
36 87
37#define SNI_8254_TICK_RATE 1193182UL 88#define SNI_8254_TICK_RATE 1193182UL
@@ -119,17 +170,14 @@ void __init plat_time_init(void)
119 mips_hpt_frequency = r4k_tick * HZ; 170 mips_hpt_frequency = r4k_tick * HZ;
120 171
121 setup_pit_timer(); 172 setup_pit_timer();
122}
123 173
124void __init plat_timer_setup(struct irqaction *irq)
125{
126 switch (sni_brd_type) { 174 switch (sni_brd_type) {
127 case SNI_BRD_10: 175 case SNI_BRD_10:
128 case SNI_BRD_10NEW: 176 case SNI_BRD_10NEW:
129 case SNI_BRD_TOWER_OASIC: 177 case SNI_BRD_TOWER_OASIC:
130 case SNI_BRD_MINITOWER: 178 case SNI_BRD_MINITOWER:
131 sni_a20r_timer_setup(irq); 179 sni_a20r_timer_setup();
132 break; 180 break;
133 } 181 }
134} 182}
135 183