diff options
Diffstat (limited to 'drivers/rtc/rtc-s3c.c')
-rw-r--r-- | drivers/rtc/rtc-s3c.c | 93 |
1 files changed, 19 insertions, 74 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index f26e0cad8f16..54b1ebb01502 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -26,10 +26,6 @@ | |||
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/io.h> | 27 | #include <asm/io.h> |
28 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
29 | #include <asm/rtc.h> | ||
30 | |||
31 | #include <asm/mach/time.h> | ||
32 | |||
33 | #include <asm/plat-s3c/regs-rtc.h> | 29 | #include <asm/plat-s3c/regs-rtc.h> |
34 | 30 | ||
35 | /* I have yet to find an S3C implementation with more than one | 31 | /* I have yet to find an S3C implementation with more than one |
@@ -40,10 +36,8 @@ static struct resource *s3c_rtc_mem; | |||
40 | static void __iomem *s3c_rtc_base; | 36 | static void __iomem *s3c_rtc_base; |
41 | static int s3c_rtc_alarmno = NO_IRQ; | 37 | static int s3c_rtc_alarmno = NO_IRQ; |
42 | static int s3c_rtc_tickno = NO_IRQ; | 38 | static int s3c_rtc_tickno = NO_IRQ; |
43 | static int s3c_rtc_freq = 1; | ||
44 | 39 | ||
45 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); | 40 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); |
46 | static unsigned int tick_count; | ||
47 | 41 | ||
48 | /* IRQ Handlers */ | 42 | /* IRQ Handlers */ |
49 | 43 | ||
@@ -59,7 +53,7 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | |||
59 | { | 53 | { |
60 | struct rtc_device *rdev = id; | 54 | struct rtc_device *rdev = id; |
61 | 55 | ||
62 | rtc_update_irq(rdev, tick_count++, RTC_PF | RTC_IRQF); | 56 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); |
63 | return IRQ_HANDLED; | 57 | return IRQ_HANDLED; |
64 | } | 58 | } |
65 | 59 | ||
@@ -78,35 +72,37 @@ static void s3c_rtc_setaie(int to) | |||
78 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); | 72 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); |
79 | } | 73 | } |
80 | 74 | ||
81 | static void s3c_rtc_setpie(int to) | 75 | static int s3c_rtc_setpie(struct device *dev, int enabled) |
82 | { | 76 | { |
83 | unsigned int tmp; | 77 | unsigned int tmp; |
84 | 78 | ||
85 | pr_debug("%s: pie=%d\n", __func__, to); | 79 | pr_debug("%s: pie=%d\n", __func__, enabled); |
86 | 80 | ||
87 | spin_lock_irq(&s3c_rtc_pie_lock); | 81 | spin_lock_irq(&s3c_rtc_pie_lock); |
88 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; | 82 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; |
89 | 83 | ||
90 | if (to) | 84 | if (enabled) |
91 | tmp |= S3C2410_TICNT_ENABLE; | 85 | tmp |= S3C2410_TICNT_ENABLE; |
92 | 86 | ||
93 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 87 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); |
94 | spin_unlock_irq(&s3c_rtc_pie_lock); | 88 | spin_unlock_irq(&s3c_rtc_pie_lock); |
89 | |||
90 | return 0; | ||
95 | } | 91 | } |
96 | 92 | ||
97 | static void s3c_rtc_setfreq(int freq) | 93 | static int s3c_rtc_setfreq(struct device *dev, int freq) |
98 | { | 94 | { |
99 | unsigned int tmp; | 95 | unsigned int tmp; |
100 | 96 | ||
101 | spin_lock_irq(&s3c_rtc_pie_lock); | 97 | spin_lock_irq(&s3c_rtc_pie_lock); |
102 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; | ||
103 | |||
104 | s3c_rtc_freq = freq; | ||
105 | 98 | ||
99 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; | ||
106 | tmp |= (128 / freq)-1; | 100 | tmp |= (128 / freq)-1; |
107 | 101 | ||
108 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 102 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); |
109 | spin_unlock_irq(&s3c_rtc_pie_lock); | 103 | spin_unlock_irq(&s3c_rtc_pie_lock); |
104 | |||
105 | return 0; | ||
110 | } | 106 | } |
111 | 107 | ||
112 | /* Time read/write */ | 108 | /* Time read/write */ |
@@ -271,12 +267,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
271 | 267 | ||
272 | writeb(alrm_en, base + S3C2410_RTCALM); | 268 | writeb(alrm_en, base + S3C2410_RTCALM); |
273 | 269 | ||
274 | if (0) { | 270 | s3c_rtc_setaie(alrm->enabled); |
275 | alrm_en = readb(base + S3C2410_RTCALM); | ||
276 | alrm_en &= ~S3C2410_RTCALM_ALMEN; | ||
277 | writeb(alrm_en, base + S3C2410_RTCALM); | ||
278 | disable_irq_wake(s3c_rtc_alarmno); | ||
279 | } | ||
280 | 271 | ||
281 | if (alrm->enabled) | 272 | if (alrm->enabled) |
282 | enable_irq_wake(s3c_rtc_alarmno); | 273 | enable_irq_wake(s3c_rtc_alarmno); |
@@ -286,59 +277,12 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
286 | return 0; | 277 | return 0; |
287 | } | 278 | } |
288 | 279 | ||
289 | static int s3c_rtc_ioctl(struct device *dev, | ||
290 | unsigned int cmd, unsigned long arg) | ||
291 | { | ||
292 | unsigned int ret = -ENOIOCTLCMD; | ||
293 | |||
294 | switch (cmd) { | ||
295 | case RTC_AIE_OFF: | ||
296 | case RTC_AIE_ON: | ||
297 | s3c_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0); | ||
298 | ret = 0; | ||
299 | break; | ||
300 | |||
301 | case RTC_PIE_OFF: | ||
302 | case RTC_PIE_ON: | ||
303 | tick_count = 0; | ||
304 | s3c_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0); | ||
305 | ret = 0; | ||
306 | break; | ||
307 | |||
308 | case RTC_IRQP_READ: | ||
309 | ret = put_user(s3c_rtc_freq, (unsigned long __user *)arg); | ||
310 | break; | ||
311 | |||
312 | case RTC_IRQP_SET: | ||
313 | if (!is_power_of_2(arg)) { | ||
314 | ret = -EINVAL; | ||
315 | goto exit; | ||
316 | } | ||
317 | |||
318 | pr_debug("s3c2410_rtc: setting frequency %ld\n", arg); | ||
319 | |||
320 | s3c_rtc_setfreq(arg); | ||
321 | ret = 0; | ||
322 | break; | ||
323 | |||
324 | case RTC_UIE_ON: | ||
325 | case RTC_UIE_OFF: | ||
326 | ret = -EINVAL; | ||
327 | } | ||
328 | |||
329 | exit: | ||
330 | return ret; | ||
331 | } | ||
332 | |||
333 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | 280 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) |
334 | { | 281 | { |
335 | unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | 282 | unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); |
336 | 283 | ||
337 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 284 | seq_printf(seq, "periodic_IRQ\t: %s\n", |
338 | (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); | 285 | (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); |
339 | |||
340 | seq_printf(seq, "periodic_freq\t: %d\n", s3c_rtc_freq); | ||
341 | |||
342 | return 0; | 286 | return 0; |
343 | } | 287 | } |
344 | 288 | ||
@@ -378,7 +322,7 @@ static void s3c_rtc_release(struct device *dev) | |||
378 | 322 | ||
379 | /* do not clear AIE here, it may be needed for wake */ | 323 | /* do not clear AIE here, it may be needed for wake */ |
380 | 324 | ||
381 | s3c_rtc_setpie(0); | 325 | s3c_rtc_setpie(dev, 0); |
382 | free_irq(s3c_rtc_alarmno, rtc_dev); | 326 | free_irq(s3c_rtc_alarmno, rtc_dev); |
383 | free_irq(s3c_rtc_tickno, rtc_dev); | 327 | free_irq(s3c_rtc_tickno, rtc_dev); |
384 | } | 328 | } |
@@ -386,11 +330,12 @@ static void s3c_rtc_release(struct device *dev) | |||
386 | static const struct rtc_class_ops s3c_rtcops = { | 330 | static const struct rtc_class_ops s3c_rtcops = { |
387 | .open = s3c_rtc_open, | 331 | .open = s3c_rtc_open, |
388 | .release = s3c_rtc_release, | 332 | .release = s3c_rtc_release, |
389 | .ioctl = s3c_rtc_ioctl, | ||
390 | .read_time = s3c_rtc_gettime, | 333 | .read_time = s3c_rtc_gettime, |
391 | .set_time = s3c_rtc_settime, | 334 | .set_time = s3c_rtc_settime, |
392 | .read_alarm = s3c_rtc_getalarm, | 335 | .read_alarm = s3c_rtc_getalarm, |
393 | .set_alarm = s3c_rtc_setalarm, | 336 | .set_alarm = s3c_rtc_setalarm, |
337 | .irq_set_freq = s3c_rtc_setfreq, | ||
338 | .irq_set_state = s3c_rtc_setpie, | ||
394 | .proc = s3c_rtc_proc, | 339 | .proc = s3c_rtc_proc, |
395 | }; | 340 | }; |
396 | 341 | ||
@@ -434,14 +379,14 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
434 | } | 379 | } |
435 | } | 380 | } |
436 | 381 | ||
437 | static int s3c_rtc_remove(struct platform_device *dev) | 382 | static int __devexit s3c_rtc_remove(struct platform_device *dev) |
438 | { | 383 | { |
439 | struct rtc_device *rtc = platform_get_drvdata(dev); | 384 | struct rtc_device *rtc = platform_get_drvdata(dev); |
440 | 385 | ||
441 | platform_set_drvdata(dev, NULL); | 386 | platform_set_drvdata(dev, NULL); |
442 | rtc_device_unregister(rtc); | 387 | rtc_device_unregister(rtc); |
443 | 388 | ||
444 | s3c_rtc_setpie(0); | 389 | s3c_rtc_setpie(&dev->dev, 0); |
445 | s3c_rtc_setaie(0); | 390 | s3c_rtc_setaie(0); |
446 | 391 | ||
447 | iounmap(s3c_rtc_base); | 392 | iounmap(s3c_rtc_base); |
@@ -451,7 +396,7 @@ static int s3c_rtc_remove(struct platform_device *dev) | |||
451 | return 0; | 396 | return 0; |
452 | } | 397 | } |
453 | 398 | ||
454 | static int s3c_rtc_probe(struct platform_device *pdev) | 399 | static int __devinit s3c_rtc_probe(struct platform_device *pdev) |
455 | { | 400 | { |
456 | struct rtc_device *rtc; | 401 | struct rtc_device *rtc; |
457 | struct resource *res; | 402 | struct resource *res; |
@@ -508,7 +453,7 @@ static int s3c_rtc_probe(struct platform_device *pdev) | |||
508 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", | 453 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", |
509 | readb(s3c_rtc_base + S3C2410_RTCCON)); | 454 | readb(s3c_rtc_base + S3C2410_RTCCON)); |
510 | 455 | ||
511 | s3c_rtc_setfreq(s3c_rtc_freq); | 456 | s3c_rtc_setfreq(&pdev->dev, 1); |
512 | 457 | ||
513 | /* register RTC and exit */ | 458 | /* register RTC and exit */ |
514 | 459 | ||
@@ -564,7 +509,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
564 | 509 | ||
565 | static struct platform_driver s3c2410_rtcdrv = { | 510 | static struct platform_driver s3c2410_rtcdrv = { |
566 | .probe = s3c_rtc_probe, | 511 | .probe = s3c_rtc_probe, |
567 | .remove = s3c_rtc_remove, | 512 | .remove = __devexit_p(s3c_rtc_remove), |
568 | .suspend = s3c_rtc_suspend, | 513 | .suspend = s3c_rtc_suspend, |
569 | .resume = s3c_rtc_resume, | 514 | .resume = s3c_rtc_resume, |
570 | .driver = { | 515 | .driver = { |