aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sibyte/bcm1480
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-10-31 20:24:50 -0400
committerRalf Baechle <ralf@linux-mips.org>2007-11-02 12:13:47 -0400
commitf3f9ad0edcc1b7bf154bb34fe3b3f71e5379c9f0 (patch)
treed553ebebfad8bf083342e6af704ae62ae252d0f2 /arch/mips/sibyte/bcm1480
parentfaf2782bf3903391936aba0b575fd39b1da10d00 (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.c51
1 files changed, 26 insertions, 25 deletions
diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c
index 39e77d9bd94..2bcaf5419ac 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,
73static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) 71static 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
89static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) 85static 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,