diff options
Diffstat (limited to 'arch/mips/sni/time.c')
-rw-r--r-- | arch/mips/sni/time.c | 80 |
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 | ||
14 | static void sni_a20r_timer_ack(void) | 14 | static 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 | ||
43 | static 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 | |||
54 | static 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 | |||
66 | static 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 | */ |
23 | static void __init sni_a20r_timer_setup(struct irqaction *irq) | 76 | static 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 | ||
124 | void __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 | ||