diff options
-rw-r--r-- | drivers/rtc/rtc-s3c.c | 83 |
1 files changed, 16 insertions, 67 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index b81ba7020d92..54b1ebb01502 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -36,10 +36,8 @@ static struct resource *s3c_rtc_mem; | |||
36 | static void __iomem *s3c_rtc_base; | 36 | static void __iomem *s3c_rtc_base; |
37 | static int s3c_rtc_alarmno = NO_IRQ; | 37 | static int s3c_rtc_alarmno = NO_IRQ; |
38 | static int s3c_rtc_tickno = NO_IRQ; | 38 | static int s3c_rtc_tickno = NO_IRQ; |
39 | static int s3c_rtc_freq = 1; | ||
40 | 39 | ||
41 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); | 40 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); |
42 | static unsigned int tick_count; | ||
43 | 41 | ||
44 | /* IRQ Handlers */ | 42 | /* IRQ Handlers */ |
45 | 43 | ||
@@ -55,7 +53,7 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | |||
55 | { | 53 | { |
56 | struct rtc_device *rdev = id; | 54 | struct rtc_device *rdev = id; |
57 | 55 | ||
58 | rtc_update_irq(rdev, tick_count++, RTC_PF | RTC_IRQF); | 56 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); |
59 | return IRQ_HANDLED; | 57 | return IRQ_HANDLED; |
60 | } | 58 | } |
61 | 59 | ||
@@ -74,35 +72,37 @@ static void s3c_rtc_setaie(int to) | |||
74 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); | 72 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); |
75 | } | 73 | } |
76 | 74 | ||
77 | static void s3c_rtc_setpie(int to) | 75 | static int s3c_rtc_setpie(struct device *dev, int enabled) |
78 | { | 76 | { |
79 | unsigned int tmp; | 77 | unsigned int tmp; |
80 | 78 | ||
81 | pr_debug("%s: pie=%d\n", __func__, to); | 79 | pr_debug("%s: pie=%d\n", __func__, enabled); |
82 | 80 | ||
83 | spin_lock_irq(&s3c_rtc_pie_lock); | 81 | spin_lock_irq(&s3c_rtc_pie_lock); |
84 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; | 82 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; |
85 | 83 | ||
86 | if (to) | 84 | if (enabled) |
87 | tmp |= S3C2410_TICNT_ENABLE; | 85 | tmp |= S3C2410_TICNT_ENABLE; |
88 | 86 | ||
89 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 87 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); |
90 | spin_unlock_irq(&s3c_rtc_pie_lock); | 88 | spin_unlock_irq(&s3c_rtc_pie_lock); |
89 | |||
90 | return 0; | ||
91 | } | 91 | } |
92 | 92 | ||
93 | static void s3c_rtc_setfreq(int freq) | 93 | static int s3c_rtc_setfreq(struct device *dev, int freq) |
94 | { | 94 | { |
95 | unsigned int tmp; | 95 | unsigned int tmp; |
96 | 96 | ||
97 | spin_lock_irq(&s3c_rtc_pie_lock); | 97 | spin_lock_irq(&s3c_rtc_pie_lock); |
98 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; | ||
99 | |||
100 | s3c_rtc_freq = freq; | ||
101 | 98 | ||
99 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; | ||
102 | tmp |= (128 / freq)-1; | 100 | tmp |= (128 / freq)-1; |
103 | 101 | ||
104 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 102 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); |
105 | spin_unlock_irq(&s3c_rtc_pie_lock); | 103 | spin_unlock_irq(&s3c_rtc_pie_lock); |
104 | |||
105 | return 0; | ||
106 | } | 106 | } |
107 | 107 | ||
108 | /* Time read/write */ | 108 | /* Time read/write */ |
@@ -267,12 +267,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
267 | 267 | ||
268 | writeb(alrm_en, base + S3C2410_RTCALM); | 268 | writeb(alrm_en, base + S3C2410_RTCALM); |
269 | 269 | ||
270 | if (0) { | 270 | s3c_rtc_setaie(alrm->enabled); |
271 | alrm_en = readb(base + S3C2410_RTCALM); | ||
272 | alrm_en &= ~S3C2410_RTCALM_ALMEN; | ||
273 | writeb(alrm_en, base + S3C2410_RTCALM); | ||
274 | disable_irq_wake(s3c_rtc_alarmno); | ||
275 | } | ||
276 | 271 | ||
277 | if (alrm->enabled) | 272 | if (alrm->enabled) |
278 | enable_irq_wake(s3c_rtc_alarmno); | 273 | enable_irq_wake(s3c_rtc_alarmno); |
@@ -282,59 +277,12 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
282 | return 0; | 277 | return 0; |
283 | } | 278 | } |
284 | 279 | ||
285 | static int s3c_rtc_ioctl(struct device *dev, | ||
286 | unsigned int cmd, unsigned long arg) | ||
287 | { | ||
288 | unsigned int ret = -ENOIOCTLCMD; | ||
289 | |||
290 | switch (cmd) { | ||
291 | case RTC_AIE_OFF: | ||
292 | case RTC_AIE_ON: | ||
293 | s3c_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0); | ||
294 | ret = 0; | ||
295 | break; | ||
296 | |||
297 | case RTC_PIE_OFF: | ||
298 | case RTC_PIE_ON: | ||
299 | tick_count = 0; | ||
300 | s3c_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0); | ||
301 | ret = 0; | ||
302 | break; | ||
303 | |||
304 | case RTC_IRQP_READ: | ||
305 | ret = put_user(s3c_rtc_freq, (unsigned long __user *)arg); | ||
306 | break; | ||
307 | |||
308 | case RTC_IRQP_SET: | ||
309 | if (!is_power_of_2(arg)) { | ||
310 | ret = -EINVAL; | ||
311 | goto exit; | ||
312 | } | ||
313 | |||
314 | pr_debug("s3c2410_rtc: setting frequency %ld\n", arg); | ||
315 | |||
316 | s3c_rtc_setfreq(arg); | ||
317 | ret = 0; | ||
318 | break; | ||
319 | |||
320 | case RTC_UIE_ON: | ||
321 | case RTC_UIE_OFF: | ||
322 | ret = -EINVAL; | ||
323 | } | ||
324 | |||
325 | exit: | ||
326 | return ret; | ||
327 | } | ||
328 | |||
329 | 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) |
330 | { | 281 | { |
331 | unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | 282 | unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); |
332 | 283 | ||
333 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 284 | seq_printf(seq, "periodic_IRQ\t: %s\n", |
334 | (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); | 285 | (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); |
335 | |||
336 | seq_printf(seq, "periodic_freq\t: %d\n", s3c_rtc_freq); | ||
337 | |||
338 | return 0; | 286 | return 0; |
339 | } | 287 | } |
340 | 288 | ||
@@ -374,7 +322,7 @@ static void s3c_rtc_release(struct device *dev) | |||
374 | 322 | ||
375 | /* do not clear AIE here, it may be needed for wake */ | 323 | /* do not clear AIE here, it may be needed for wake */ |
376 | 324 | ||
377 | s3c_rtc_setpie(0); | 325 | s3c_rtc_setpie(dev, 0); |
378 | free_irq(s3c_rtc_alarmno, rtc_dev); | 326 | free_irq(s3c_rtc_alarmno, rtc_dev); |
379 | free_irq(s3c_rtc_tickno, rtc_dev); | 327 | free_irq(s3c_rtc_tickno, rtc_dev); |
380 | } | 328 | } |
@@ -382,11 +330,12 @@ static void s3c_rtc_release(struct device *dev) | |||
382 | static const struct rtc_class_ops s3c_rtcops = { | 330 | static const struct rtc_class_ops s3c_rtcops = { |
383 | .open = s3c_rtc_open, | 331 | .open = s3c_rtc_open, |
384 | .release = s3c_rtc_release, | 332 | .release = s3c_rtc_release, |
385 | .ioctl = s3c_rtc_ioctl, | ||
386 | .read_time = s3c_rtc_gettime, | 333 | .read_time = s3c_rtc_gettime, |
387 | .set_time = s3c_rtc_settime, | 334 | .set_time = s3c_rtc_settime, |
388 | .read_alarm = s3c_rtc_getalarm, | 335 | .read_alarm = s3c_rtc_getalarm, |
389 | .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, | ||
390 | .proc = s3c_rtc_proc, | 339 | .proc = s3c_rtc_proc, |
391 | }; | 340 | }; |
392 | 341 | ||
@@ -437,7 +386,7 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) | |||
437 | platform_set_drvdata(dev, NULL); | 386 | platform_set_drvdata(dev, NULL); |
438 | rtc_device_unregister(rtc); | 387 | rtc_device_unregister(rtc); |
439 | 388 | ||
440 | s3c_rtc_setpie(0); | 389 | s3c_rtc_setpie(&dev->dev, 0); |
441 | s3c_rtc_setaie(0); | 390 | s3c_rtc_setaie(0); |
442 | 391 | ||
443 | iounmap(s3c_rtc_base); | 392 | iounmap(s3c_rtc_base); |
@@ -504,7 +453,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
504 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", | 453 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", |
505 | readb(s3c_rtc_base + S3C2410_RTCCON)); | 454 | readb(s3c_rtc_base + S3C2410_RTCCON)); |
506 | 455 | ||
507 | s3c_rtc_setfreq(s3c_rtc_freq); | 456 | s3c_rtc_setfreq(&pdev->dev, 1); |
508 | 457 | ||
509 | /* register RTC and exit */ | 458 | /* register RTC and exit */ |
510 | 459 | ||