diff options
Diffstat (limited to 'drivers/rtc/rtc-sa1100.c')
-rw-r--r-- | drivers/rtc/rtc-sa1100.c | 160 |
1 files changed, 5 insertions, 155 deletions
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 5dfe5ffcb0d..0b40bb88a88 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #define RTC_DEF_TRIM 0 | 43 | #define RTC_DEF_TRIM 0 |
44 | 44 | ||
45 | static const unsigned long RTC_FREQ = 1024; | 45 | static const unsigned long RTC_FREQ = 1024; |
46 | static unsigned long timer_freq; | ||
47 | static struct rtc_time rtc_alarm; | 46 | static struct rtc_time rtc_alarm; |
48 | static DEFINE_SPINLOCK(sa1100_rtc_lock); | 47 | static DEFINE_SPINLOCK(sa1100_rtc_lock); |
49 | 48 | ||
@@ -156,114 +155,11 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
156 | return IRQ_HANDLED; | 155 | return IRQ_HANDLED; |
157 | } | 156 | } |
158 | 157 | ||
159 | static int sa1100_irq_set_freq(struct device *dev, int freq) | ||
160 | { | ||
161 | if (freq < 1 || freq > timer_freq) { | ||
162 | return -EINVAL; | ||
163 | } else { | ||
164 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
165 | |||
166 | rtc->irq_freq = freq; | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static int rtc_timer1_count; | ||
173 | |||
174 | static int sa1100_irq_set_state(struct device *dev, int enabled) | ||
175 | { | ||
176 | spin_lock_irq(&sa1100_rtc_lock); | ||
177 | if (enabled) { | ||
178 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
179 | |||
180 | OSMR1 = timer_freq / rtc->irq_freq + OSCR; | ||
181 | OIER |= OIER_E1; | ||
182 | rtc_timer1_count = 1; | ||
183 | } else { | ||
184 | OIER &= ~OIER_E1; | ||
185 | } | ||
186 | spin_unlock_irq(&sa1100_rtc_lock); | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static inline int sa1100_timer1_retrigger(struct rtc_device *rtc) | ||
192 | { | ||
193 | unsigned long diff; | ||
194 | unsigned long period = timer_freq / rtc->irq_freq; | ||
195 | |||
196 | spin_lock_irq(&sa1100_rtc_lock); | ||
197 | |||
198 | do { | ||
199 | OSMR1 += period; | ||
200 | diff = OSMR1 - OSCR; | ||
201 | /* If OSCR > OSMR1, diff is a very large number (unsigned | ||
202 | * math). This means we have a lost interrupt. */ | ||
203 | } while (diff > period); | ||
204 | OIER |= OIER_E1; | ||
205 | |||
206 | spin_unlock_irq(&sa1100_rtc_lock); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static irqreturn_t timer1_interrupt(int irq, void *dev_id) | ||
212 | { | ||
213 | struct platform_device *pdev = to_platform_device(dev_id); | ||
214 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
215 | |||
216 | /* | ||
217 | * If we match for the first time, rtc_timer1_count will be 1. | ||
218 | * Otherwise, we wrapped around (very unlikely but | ||
219 | * still possible) so compute the amount of missed periods. | ||
220 | * The match reg is updated only when the data is actually retrieved | ||
221 | * to avoid unnecessary interrupts. | ||
222 | */ | ||
223 | OSSR = OSSR_M1; /* clear match on timer1 */ | ||
224 | |||
225 | rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF); | ||
226 | |||
227 | if (rtc_timer1_count == 1) | ||
228 | rtc_timer1_count = | ||
229 | (rtc->irq_freq * ((1 << 30) / (timer_freq >> 2))); | ||
230 | |||
231 | /* retrigger. */ | ||
232 | sa1100_timer1_retrigger(rtc); | ||
233 | |||
234 | return IRQ_HANDLED; | ||
235 | } | ||
236 | |||
237 | static int sa1100_rtc_read_callback(struct device *dev, int data) | ||
238 | { | ||
239 | if (data & RTC_PF) { | ||
240 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
241 | |||
242 | /* interpolate missed periods and set match for the next */ | ||
243 | unsigned long period = timer_freq / rtc->irq_freq; | ||
244 | unsigned long oscr = OSCR; | ||
245 | unsigned long osmr1 = OSMR1; | ||
246 | unsigned long missed = (oscr - osmr1)/period; | ||
247 | data += missed << 8; | ||
248 | OSSR = OSSR_M1; /* clear match on timer 1 */ | ||
249 | OSMR1 = osmr1 + (missed + 1)*period; | ||
250 | /* Ensure we didn't miss another match in the mean time. | ||
251 | * Here we compare (match - OSCR) 8 instead of 0 -- | ||
252 | * see comment in pxa_timer_interrupt() for explanation. | ||
253 | */ | ||
254 | while ((signed long)((osmr1 = OSMR1) - OSCR) <= 8) { | ||
255 | data += 0x100; | ||
256 | OSSR = OSSR_M1; /* clear match on timer 1 */ | ||
257 | OSMR1 = osmr1 + period; | ||
258 | } | ||
259 | } | ||
260 | return data; | ||
261 | } | ||
262 | |||
263 | static int sa1100_rtc_open(struct device *dev) | 158 | static int sa1100_rtc_open(struct device *dev) |
264 | { | 159 | { |
265 | int ret; | 160 | int ret; |
266 | struct rtc_device *rtc = (struct rtc_device *)dev; | 161 | struct platform_device *plat_dev = to_platform_device(dev); |
162 | struct rtc_device *rtc = platform_get_drvdata(plat_dev); | ||
267 | 163 | ||
268 | ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, | 164 | ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, |
269 | "rtc 1Hz", dev); | 165 | "rtc 1Hz", dev); |
@@ -277,19 +173,11 @@ static int sa1100_rtc_open(struct device *dev) | |||
277 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); | 173 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); |
278 | goto fail_ai; | 174 | goto fail_ai; |
279 | } | 175 | } |
280 | ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED, | ||
281 | "rtc timer", dev); | ||
282 | if (ret) { | ||
283 | dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1); | ||
284 | goto fail_pi; | ||
285 | } | ||
286 | rtc->max_user_freq = RTC_FREQ; | 176 | rtc->max_user_freq = RTC_FREQ; |
287 | sa1100_irq_set_freq(dev, RTC_FREQ); | 177 | rtc_irq_set_freq(rtc, NULL, RTC_FREQ); |
288 | 178 | ||
289 | return 0; | 179 | return 0; |
290 | 180 | ||
291 | fail_pi: | ||
292 | free_irq(IRQ_RTCAlrm, dev); | ||
293 | fail_ai: | 181 | fail_ai: |
294 | free_irq(IRQ_RTC1Hz, dev); | 182 | free_irq(IRQ_RTC1Hz, dev); |
295 | fail_ui: | 183 | fail_ui: |
@@ -304,30 +192,10 @@ static void sa1100_rtc_release(struct device *dev) | |||
304 | OSSR = OSSR_M1; | 192 | OSSR = OSSR_M1; |
305 | spin_unlock_irq(&sa1100_rtc_lock); | 193 | spin_unlock_irq(&sa1100_rtc_lock); |
306 | 194 | ||
307 | free_irq(IRQ_OST1, dev); | ||
308 | free_irq(IRQ_RTCAlrm, dev); | 195 | free_irq(IRQ_RTCAlrm, dev); |
309 | free_irq(IRQ_RTC1Hz, dev); | 196 | free_irq(IRQ_RTC1Hz, dev); |
310 | } | 197 | } |
311 | 198 | ||
312 | |||
313 | static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
314 | unsigned long arg) | ||
315 | { | ||
316 | switch (cmd) { | ||
317 | case RTC_UIE_OFF: | ||
318 | spin_lock_irq(&sa1100_rtc_lock); | ||
319 | RTSR &= ~RTSR_HZE; | ||
320 | spin_unlock_irq(&sa1100_rtc_lock); | ||
321 | return 0; | ||
322 | case RTC_UIE_ON: | ||
323 | spin_lock_irq(&sa1100_rtc_lock); | ||
324 | RTSR |= RTSR_HZE; | ||
325 | spin_unlock_irq(&sa1100_rtc_lock); | ||
326 | return 0; | ||
327 | } | ||
328 | return -ENOIOCTLCMD; | ||
329 | } | ||
330 | |||
331 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 199 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
332 | { | 200 | { |
333 | spin_lock_irq(&sa1100_rtc_lock); | 201 | spin_lock_irq(&sa1100_rtc_lock); |
@@ -386,31 +254,20 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
386 | 254 | ||
387 | static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) | 255 | static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) |
388 | { | 256 | { |
389 | struct rtc_device *rtc = (struct rtc_device *)dev; | 257 | seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR); |
390 | 258 | seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR); | |
391 | seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR); | ||
392 | seq_printf(seq, "update_IRQ\t: %s\n", | ||
393 | (RTSR & RTSR_HZE) ? "yes" : "no"); | ||
394 | seq_printf(seq, "periodic_IRQ\t: %s\n", | ||
395 | (OIER & OIER_E1) ? "yes" : "no"); | ||
396 | seq_printf(seq, "periodic_freq\t: %d\n", rtc->irq_freq); | ||
397 | seq_printf(seq, "RTSR\t\t: 0x%08x\n", (u32)RTSR); | ||
398 | 259 | ||
399 | return 0; | 260 | return 0; |
400 | } | 261 | } |
401 | 262 | ||
402 | static const struct rtc_class_ops sa1100_rtc_ops = { | 263 | static const struct rtc_class_ops sa1100_rtc_ops = { |
403 | .open = sa1100_rtc_open, | 264 | .open = sa1100_rtc_open, |
404 | .read_callback = sa1100_rtc_read_callback, | ||
405 | .release = sa1100_rtc_release, | 265 | .release = sa1100_rtc_release, |
406 | .ioctl = sa1100_rtc_ioctl, | ||
407 | .read_time = sa1100_rtc_read_time, | 266 | .read_time = sa1100_rtc_read_time, |
408 | .set_time = sa1100_rtc_set_time, | 267 | .set_time = sa1100_rtc_set_time, |
409 | .read_alarm = sa1100_rtc_read_alarm, | 268 | .read_alarm = sa1100_rtc_read_alarm, |
410 | .set_alarm = sa1100_rtc_set_alarm, | 269 | .set_alarm = sa1100_rtc_set_alarm, |
411 | .proc = sa1100_rtc_proc, | 270 | .proc = sa1100_rtc_proc, |
412 | .irq_set_freq = sa1100_irq_set_freq, | ||
413 | .irq_set_state = sa1100_irq_set_state, | ||
414 | .alarm_irq_enable = sa1100_rtc_alarm_irq_enable, | 271 | .alarm_irq_enable = sa1100_rtc_alarm_irq_enable, |
415 | }; | 272 | }; |
416 | 273 | ||
@@ -418,8 +275,6 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
418 | { | 275 | { |
419 | struct rtc_device *rtc; | 276 | struct rtc_device *rtc; |
420 | 277 | ||
421 | timer_freq = get_clock_tick_rate(); | ||
422 | |||
423 | /* | 278 | /* |
424 | * According to the manual we should be able to let RTTR be zero | 279 | * According to the manual we should be able to let RTTR be zero |
425 | * and then a default diviser for a 32.768KHz clock is used. | 280 | * and then a default diviser for a 32.768KHz clock is used. |
@@ -445,11 +300,6 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
445 | 300 | ||
446 | platform_set_drvdata(pdev, rtc); | 301 | platform_set_drvdata(pdev, rtc); |
447 | 302 | ||
448 | /* Set the irq_freq */ | ||
449 | /*TODO: Find out who is messing with this value after we initialize | ||
450 | * it here.*/ | ||
451 | rtc->irq_freq = RTC_FREQ; | ||
452 | |||
453 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. | 303 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. |
454 | * See also the comments in sa1100_rtc_interrupt(). | 304 | * See also the comments in sa1100_rtc_interrupt(). |
455 | * | 305 | * |