diff options
Diffstat (limited to 'arch/sh/kernel/timers/timer-cmt.c')
-rw-r--r-- | arch/sh/kernel/timers/timer-cmt.c | 63 |
1 files changed, 5 insertions, 58 deletions
diff --git a/arch/sh/kernel/timers/timer-cmt.c b/arch/sh/kernel/timers/timer-cmt.c index 9eab395cd34..30687383d4b 100644 --- a/arch/sh/kernel/timers/timer-cmt.c +++ b/arch/sh/kernel/timers/timer-cmt.c | |||
@@ -96,8 +96,7 @@ static unsigned long cmt_timer_get_offset(void) | |||
96 | return count; | 96 | return count; |
97 | } | 97 | } |
98 | 98 | ||
99 | static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id, | 99 | static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id) |
100 | struct pt_regs *regs) | ||
101 | { | 100 | { |
102 | unsigned long timer_status; | 101 | unsigned long timer_status; |
103 | 102 | ||
@@ -114,7 +113,7 @@ static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id, | |||
114 | * locally disabled. -arca | 113 | * locally disabled. -arca |
115 | */ | 114 | */ |
116 | write_seqlock(&xtime_lock); | 115 | write_seqlock(&xtime_lock); |
117 | handle_timer_tick(regs); | 116 | handle_timer_tick(); |
118 | write_sequnlock(&xtime_lock); | 117 | write_sequnlock(&xtime_lock); |
119 | 118 | ||
120 | return IRQ_HANDLED; | 119 | return IRQ_HANDLED; |
@@ -123,62 +122,10 @@ static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id, | |||
123 | static struct irqaction cmt_irq = { | 122 | static struct irqaction cmt_irq = { |
124 | .name = "timer", | 123 | .name = "timer", |
125 | .handler = cmt_timer_interrupt, | 124 | .handler = cmt_timer_interrupt, |
126 | .flags = SA_INTERRUPT, | 125 | .flags = IRQF_DISABLED, |
127 | .mask = CPU_MASK_NONE, | 126 | .mask = CPU_MASK_NONE, |
128 | }; | 127 | }; |
129 | 128 | ||
130 | /* | ||
131 | * Hah! We'll see if this works (switching from usecs to nsecs). | ||
132 | */ | ||
133 | static unsigned long cmt_timer_get_frequency(void) | ||
134 | { | ||
135 | u32 freq; | ||
136 | struct timespec ts1, ts2; | ||
137 | unsigned long diff_nsec; | ||
138 | unsigned long factor; | ||
139 | |||
140 | /* Setup the timer: We don't want to generate interrupts, just | ||
141 | * have it count down at its natural rate. | ||
142 | */ | ||
143 | |||
144 | ctrl_outw(ctrl_inw(CMT_CMSTR) & ~0x01, CMT_CMSTR); | ||
145 | ctrl_outw(CMT_CMCSR_CALIB, CMT_CMCSR_0); | ||
146 | ctrl_outw(0xffff, CMT_CMCOR_0); | ||
147 | ctrl_outw(0xffff, CMT_CMCNT_0); | ||
148 | |||
149 | rtc_sh_get_time(&ts2); | ||
150 | |||
151 | do { | ||
152 | rtc_sh_get_time(&ts1); | ||
153 | } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); | ||
154 | |||
155 | /* actually start the timer */ | ||
156 | ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR); | ||
157 | |||
158 | do { | ||
159 | rtc_sh_get_time(&ts2); | ||
160 | } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); | ||
161 | |||
162 | freq = 0xffff - ctrl_inw(CMT_CMCNT_0); | ||
163 | if (ts2.tv_nsec < ts1.tv_nsec) { | ||
164 | ts2.tv_nsec += 1000000000; | ||
165 | ts2.tv_sec--; | ||
166 | } | ||
167 | |||
168 | diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); | ||
169 | |||
170 | /* this should work well if the RTC has a precision of n Hz, where | ||
171 | * n is an integer. I don't think we have to worry about the other | ||
172 | * cases. */ | ||
173 | factor = (1000000000 + diff_nsec/2) / diff_nsec; | ||
174 | |||
175 | if (factor * diff_nsec > 1100000000 || | ||
176 | factor * diff_nsec < 900000000) | ||
177 | panic("weird RTC (diff_nsec %ld)", diff_nsec); | ||
178 | |||
179 | return freq * factor; | ||
180 | } | ||
181 | |||
182 | static void cmt_clk_init(struct clk *clk) | 129 | static void cmt_clk_init(struct clk *clk) |
183 | { | 130 | { |
184 | u8 divisor = CMT_CMCSR_INIT & 0x3; | 131 | u8 divisor = CMT_CMCSR_INIT & 0x3; |
@@ -245,12 +192,12 @@ struct sys_timer_ops cmt_timer_ops = { | |||
245 | .init = cmt_timer_init, | 192 | .init = cmt_timer_init, |
246 | .start = cmt_timer_start, | 193 | .start = cmt_timer_start, |
247 | .stop = cmt_timer_stop, | 194 | .stop = cmt_timer_stop, |
248 | .get_frequency = cmt_timer_get_frequency, | 195 | #ifndef CONFIG_GENERIC_TIME |
249 | .get_offset = cmt_timer_get_offset, | 196 | .get_offset = cmt_timer_get_offset, |
197 | #endif | ||
250 | }; | 198 | }; |
251 | 199 | ||
252 | struct sys_timer cmt_timer = { | 200 | struct sys_timer cmt_timer = { |
253 | .name = "cmt", | 201 | .name = "cmt", |
254 | .ops = &cmt_timer_ops, | 202 | .ops = &cmt_timer_ops, |
255 | }; | 203 | }; |
256 | |||