aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-s3c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-s3c.c')
-rw-r--r--drivers/rtc/rtc-s3c.c93
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;
40static void __iomem *s3c_rtc_base; 36static void __iomem *s3c_rtc_base;
41static int s3c_rtc_alarmno = NO_IRQ; 37static int s3c_rtc_alarmno = NO_IRQ;
42static int s3c_rtc_tickno = NO_IRQ; 38static int s3c_rtc_tickno = NO_IRQ;
43static int s3c_rtc_freq = 1;
44 39
45static DEFINE_SPINLOCK(s3c_rtc_pie_lock); 40static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
46static 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
81static void s3c_rtc_setpie(int to) 75static 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
97static void s3c_rtc_setfreq(int freq) 93static 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
289static 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
333static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) 280static 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)
386static const struct rtc_class_ops s3c_rtcops = { 330static 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
437static int s3c_rtc_remove(struct platform_device *dev) 382static 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
454static int s3c_rtc_probe(struct platform_device *pdev) 399static 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
565static struct platform_driver s3c2410_rtcdrv = { 510static 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 = {