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 | |
parent | faf2782bf3903391936aba0b575fd39b1da10d00 (diff) |
[MIPS] Sibyte: Fixes for oneshot timer mode.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/sibyte/bcm1480/time.c | 51 | ||||
-rw-r--r-- | arch/mips/sibyte/sb1250/time.c | 66 |
2 files changed, 55 insertions, 62 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, |
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c index f455ac12a210..24b9c8bad62f 100644 --- a/arch/mips/sibyte/sb1250/time.c +++ b/arch/mips/sibyte/sb1250/time.c | |||
@@ -15,33 +15,19 @@ | |||
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software |
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | */ | 17 | */ |
18 | |||
19 | /* | ||
20 | * These are routines to set up and handle interrupts from the | ||
21 | * sb1250 general purpose timer 0. We're using the timer as a | ||
22 | * system clock, so we set it up to run at 100 Hz. On every | ||
23 | * interrupt, we update our idea of what the time of day is, | ||
24 | * then call do_timer() in the architecture-independent kernel | ||
25 | * code to do general bookkeeping (e.g. update jiffies, run | ||
26 | * bottom halves, etc.) | ||
27 | */ | ||
28 | #include <linux/clockchips.h> | 18 | #include <linux/clockchips.h> |
29 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
30 | #include <linux/sched.h> | 20 | #include <linux/percpu.h> |
31 | #include <linux/spinlock.h> | ||
32 | #include <linux/kernel_stat.h> | ||
33 | 21 | ||
34 | #include <asm/irq.h> | ||
35 | #include <asm/addrspace.h> | 22 | #include <asm/addrspace.h> |
36 | #include <asm/time.h> | ||
37 | #include <asm/io.h> | 23 | #include <asm/io.h> |
24 | #include <asm/time.h> | ||
38 | 25 | ||
39 | #include <asm/sibyte/sb1250.h> | 26 | #include <asm/sibyte/sb1250.h> |
40 | #include <asm/sibyte/sb1250_regs.h> | 27 | #include <asm/sibyte/sb1250_regs.h> |
41 | #include <asm/sibyte/sb1250_int.h> | 28 | #include <asm/sibyte/sb1250_int.h> |
42 | #include <asm/sibyte/sb1250_scd.h> | 29 | #include <asm/sibyte/sb1250_scd.h> |
43 | 30 | ||
44 | |||
45 | #define IMR_IP2_VAL K_INT_MAP_I0 | 31 | #define IMR_IP2_VAL K_INT_MAP_I0 |
46 | #define IMR_IP3_VAL K_INT_MAP_I1 | 32 | #define IMR_IP3_VAL K_INT_MAP_I1 |
47 | #define IMR_IP4_VAL K_INT_MAP_I2 | 33 | #define IMR_IP4_VAL K_INT_MAP_I2 |
@@ -49,32 +35,31 @@ | |||
49 | #define SB1250_HPT_NUM 3 | 35 | #define SB1250_HPT_NUM 3 |
50 | #define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */ | 36 | #define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */ |
51 | 37 | ||
52 | |||
53 | /* | 38 | /* |
54 | * The general purpose timer ticks at 1 Mhz independent if | 39 | * The general purpose timer ticks at 1MHz independent if |
55 | * the rest of the system | 40 | * the rest of the system |
56 | */ | 41 | */ |
57 | static void sibyte_set_mode(enum clock_event_mode mode, | 42 | static void sibyte_set_mode(enum clock_event_mode mode, |
58 | struct clock_event_device *evt) | 43 | struct clock_event_device *evt) |
59 | { | 44 | { |
60 | unsigned int cpu = smp_processor_id(); | 45 | unsigned int cpu = smp_processor_id(); |
61 | void __iomem *timer_cfg, *timer_init; | 46 | void __iomem *cfg, *init; |
62 | 47 | ||
63 | timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); | 48 | cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); |
64 | timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); | 49 | init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); |
65 | 50 | ||
66 | switch(mode) { | 51 | switch (mode) { |
67 | case CLOCK_EVT_MODE_PERIODIC: | 52 | case CLOCK_EVT_MODE_PERIODIC: |
68 | __raw_writeq(0, timer_cfg); | 53 | __raw_writeq(0, cfg); |
69 | __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, timer_init); | 54 | __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init); |
70 | __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, | 55 | __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, |
71 | timer_cfg); | 56 | cfg); |
72 | break; | 57 | break; |
73 | 58 | ||
74 | case CLOCK_EVT_MODE_ONESHOT: | 59 | case CLOCK_EVT_MODE_ONESHOT: |
75 | /* Stop the timer until we actually program a shot */ | 60 | /* Stop the timer until we actually program a shot */ |
76 | case CLOCK_EVT_MODE_SHUTDOWN: | 61 | case CLOCK_EVT_MODE_SHUTDOWN: |
77 | __raw_writeq(0, timer_cfg); | 62 | __raw_writeq(0, cfg); |
78 | break; | 63 | break; |
79 | 64 | ||
80 | case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ | 65 | case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ |
@@ -83,18 +68,16 @@ static void sibyte_set_mode(enum clock_event_mode mode, | |||
83 | } | 68 | } |
84 | } | 69 | } |
85 | 70 | ||
86 | static int | 71 | static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) |
87 | sibyte_next_event(unsigned long delta, struct clock_event_device *evt) | ||
88 | { | 72 | { |
89 | unsigned int cpu = smp_processor_id(); | 73 | unsigned int cpu = smp_processor_id(); |
90 | void __iomem *timer_cfg, *timer_init; | 74 | void __iomem *cfg, *init; |
91 | 75 | ||
92 | timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); | 76 | cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); |
93 | timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); | 77 | init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); |
94 | 78 | ||
95 | __raw_writeq(0, timer_cfg); | 79 | __raw_writeq(delta - 1, init); |
96 | __raw_writeq(delta, timer_init); | 80 | __raw_writeq(M_SCD_TIMER_ENABLE, cfg); |
97 | __raw_writeq(M_SCD_TIMER_ENABLE, timer_cfg); | ||
98 | 81 | ||
99 | return 0; | 82 | return 0; |
100 | } | 83 | } |
@@ -103,10 +86,17 @@ static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) | |||
103 | { | 86 | { |
104 | unsigned int cpu = smp_processor_id(); | 87 | unsigned int cpu = smp_processor_id(); |
105 | struct clock_event_device *cd = dev_id; | 88 | struct clock_event_device *cd = dev_id; |
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; | ||
106 | 96 | ||
107 | /* ACK interrupt */ | 97 | /* ACK interrupt */ |
108 | ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, | 98 | cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); |
109 | IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); | 99 | ____raw_writeq(tmode, cfg); |
110 | 100 | ||
111 | cd->event_handler(cd); | 101 | cd->event_handler(cd); |
112 | 102 | ||
@@ -144,7 +134,9 @@ void __cpuinit sb1250_clockevent_init(void) | |||
144 | 134 | ||
145 | sb1250_mask_irq(cpu, irq); | 135 | sb1250_mask_irq(cpu, irq); |
146 | 136 | ||
147 | /* Map the timer interrupt to ip[4] of this cpu */ | 137 | /* |
138 | * Map the timer interrupt to IP[4] of this cpu | ||
139 | */ | ||
148 | __raw_writeq(IMR_IP4_VAL, | 140 | __raw_writeq(IMR_IP4_VAL, |
149 | IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) + | 141 | IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) + |
150 | (irq << 3))); | 142 | (irq << 3))); |