diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-10-31 20:24:50 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-11-02 12:13:47 -0400 |
commit | f3f9ad0edcc1b7bf154bb34fe3b3f71e5379c9f0 (patch) | |
tree | d553ebebfad8bf083342e6af704ae62ae252d0f2 /arch/mips/sibyte/bcm1480 | |
parent | faf2782bf3903391936aba0b575fd39b1da10d00 (diff) |
[MIPS] Sibyte: Fixes for oneshot timer mode.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/sibyte/bcm1480')
-rw-r--r-- | arch/mips/sibyte/bcm1480/time.c | 51 |
1 files changed, 26 insertions, 25 deletions
diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c index 39e77d9bd944..2bcaf5419ac1 100644 --- a/arch/mips/sibyte/bcm1480/time.c +++ b/arch/mips/sibyte/bcm1480/time.c | |||
@@ -17,13 +17,11 @@ | |||
17 | */ | 17 | */ |
18 | #include <linux/clockchips.h> | 18 | #include <linux/clockchips.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/irq.h> | ||
21 | #include <linux/percpu.h> | 20 | #include <linux/percpu.h> |
22 | #include <linux/spinlock.h> | ||
23 | 21 | ||
24 | #include <asm/addrspace.h> | 22 | #include <asm/addrspace.h> |
25 | #include <asm/time.h> | ||
26 | #include <asm/io.h> | 23 | #include <asm/io.h> |
24 | #include <asm/time.h> | ||
27 | 25 | ||
28 | #include <asm/sibyte/bcm1480_regs.h> | 26 | #include <asm/sibyte/bcm1480_regs.h> |
29 | #include <asm/sibyte/sb1250_regs.h> | 27 | #include <asm/sibyte/sb1250_regs.h> |
@@ -45,23 +43,23 @@ static void sibyte_set_mode(enum clock_event_mode mode, | |||
45 | struct clock_event_device *evt) | 43 | struct clock_event_device *evt) |
46 | { | 44 | { |
47 | unsigned int cpu = smp_processor_id(); | 45 | unsigned int cpu = smp_processor_id(); |
48 | void __iomem *timer_cfg, *timer_init; | 46 | void __iomem *cfg, *init; |
49 | 47 | ||
50 | timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); | 48 | cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); |
51 | timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); | 49 | init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); |
52 | 50 | ||
53 | switch (mode) { | 51 | switch (mode) { |
54 | case CLOCK_EVT_MODE_PERIODIC: | 52 | case CLOCK_EVT_MODE_PERIODIC: |
55 | __raw_writeq(0, timer_cfg); | 53 | __raw_writeq(0, cfg); |
56 | __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, timer_init); | 54 | __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init); |
57 | __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, | 55 | __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, |
58 | timer_cfg); | 56 | cfg); |
59 | break; | 57 | break; |
60 | 58 | ||
61 | case CLOCK_EVT_MODE_ONESHOT: | 59 | case CLOCK_EVT_MODE_ONESHOT: |
62 | /* Stop the timer until we actually program a shot */ | 60 | /* Stop the timer until we actually program a shot */ |
63 | case CLOCK_EVT_MODE_SHUTDOWN: | 61 | case CLOCK_EVT_MODE_SHUTDOWN: |
64 | __raw_writeq(0, timer_cfg); | 62 | __raw_writeq(0, cfg); |
65 | break; | 63 | break; |
66 | 64 | ||
67 | case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ | 65 | case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ |
@@ -73,30 +71,33 @@ static void sibyte_set_mode(enum clock_event_mode mode, | |||
73 | static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) | 71 | static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) |
74 | { | 72 | { |
75 | unsigned int cpu = smp_processor_id(); | 73 | unsigned int cpu = smp_processor_id(); |
76 | void __iomem *timer_init; | 74 | void __iomem *cfg, *init; |
77 | unsigned int cnt; | ||
78 | int res; | ||
79 | 75 | ||
80 | timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); | 76 | cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); |
81 | cnt = __raw_readq(timer_init); | 77 | init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); |
82 | cnt += delta; | ||
83 | __raw_writeq(cnt, timer_init); | ||
84 | res = ((long)(__raw_readq(timer_init) - cnt ) > 0) ? -ETIME : 0; | ||
85 | 78 | ||
86 | return res; | 79 | __raw_writeq(delta - 1, init); |
80 | __raw_writeq(M_SCD_TIMER_ENABLE, cfg); | ||
81 | |||
82 | return 0; | ||
87 | } | 83 | } |
88 | 84 | ||
89 | static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) | 85 | static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) |
90 | { | 86 | { |
91 | unsigned int cpu = smp_processor_id(); | 87 | unsigned int cpu = smp_processor_id(); |
92 | struct clock_event_device *cd = dev_id; | 88 | struct clock_event_device *cd = dev_id; |
93 | void __iomem *timer_cfg; | 89 | void __iomem *cfg; |
90 | unsigned long tmode; | ||
91 | |||
92 | if (cd->mode == CLOCK_EVT_MODE_PERIODIC) | ||
93 | tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS; | ||
94 | else | ||
95 | tmode = 0; | ||
94 | 96 | ||
95 | timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); | 97 | /* ACK interrupt */ |
98 | cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); | ||
99 | ____raw_writeq(tmode, cfg); | ||
96 | 100 | ||
97 | /* Reset the timer */ | ||
98 | __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, | ||
99 | timer_cfg); | ||
100 | cd->event_handler(cd); | 101 | cd->event_handler(cd); |
101 | 102 | ||
102 | return IRQ_HANDLED; | 103 | return IRQ_HANDLED; |
@@ -133,7 +134,7 @@ void __cpuinit sb1480_clockevent_init(void) | |||
133 | bcm1480_mask_irq(cpu, irq); | 134 | bcm1480_mask_irq(cpu, irq); |
134 | 135 | ||
135 | /* | 136 | /* |
136 | * Map timer interrupt to IP[4] of this cpu | 137 | * Map the timer interrupt to IP[4] of this cpu |
137 | */ | 138 | */ |
138 | __raw_writeq(IMR_IP4_VAL, | 139 | __raw_writeq(IMR_IP4_VAL, |
139 | IOADDR(A_BCM1480_IMR_REGISTER(cpu, | 140 | IOADDR(A_BCM1480_IMR_REGISTER(cpu, |