diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-08-15 12:15:17 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-08-15 12:15:17 -0400 |
| commit | f3efbe582b5396d134024c03a5fa253f2a85d9a6 (patch) | |
| tree | e4e15b7567b82d24cb1e7327398286a2b88df04c /drivers/rtc/rtc-s3c.c | |
| parent | 05d3ed0a1fe3ea05ab9f3b8d32576a0bc2e19660 (diff) | |
| parent | b635acec48bcaa9183fcbf4e3955616b0d4119b5 (diff) | |
Merge branch 'linus' into x86/gart
Diffstat (limited to 'drivers/rtc/rtc-s3c.c')
| -rw-r--r-- | drivers/rtc/rtc-s3c.c | 91 |
1 files changed, 20 insertions, 71 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index fed86e507fdf..e7d19b6c265a 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
| 23 | #include <linux/log2.h> | 23 | #include <linux/log2.h> |
| 24 | 24 | ||
| 25 | #include <asm/hardware.h> | 25 | #include <mach/hardware.h> |
| 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> |
| @@ -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 | ||
| @@ -430,14 +379,14 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
| 430 | } | 379 | } |
| 431 | } | 380 | } |
| 432 | 381 | ||
| 433 | static int s3c_rtc_remove(struct platform_device *dev) | 382 | static int __devexit s3c_rtc_remove(struct platform_device *dev) |
| 434 | { | 383 | { |
| 435 | struct rtc_device *rtc = platform_get_drvdata(dev); | 384 | struct rtc_device *rtc = platform_get_drvdata(dev); |
| 436 | 385 | ||
| 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); |
| @@ -447,7 +396,7 @@ static int s3c_rtc_remove(struct platform_device *dev) | |||
| 447 | return 0; | 396 | return 0; |
| 448 | } | 397 | } |
| 449 | 398 | ||
| 450 | static int s3c_rtc_probe(struct platform_device *pdev) | 399 | static int __devinit s3c_rtc_probe(struct platform_device *pdev) |
| 451 | { | 400 | { |
| 452 | struct rtc_device *rtc; | 401 | struct rtc_device *rtc; |
| 453 | struct resource *res; | 402 | struct resource *res; |
| @@ -504,7 +453,7 @@ static int 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 | ||
| @@ -560,7 +509,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
| 560 | 509 | ||
| 561 | static struct platform_driver s3c2410_rtcdrv = { | 510 | static struct platform_driver s3c2410_rtcdrv = { |
| 562 | .probe = s3c_rtc_probe, | 511 | .probe = s3c_rtc_probe, |
| 563 | .remove = s3c_rtc_remove, | 512 | .remove = __devexit_p(s3c_rtc_remove), |
| 564 | .suspend = s3c_rtc_suspend, | 513 | .suspend = s3c_rtc_suspend, |
| 565 | .resume = s3c_rtc_resume, | 514 | .resume = s3c_rtc_resume, |
| 566 | .driver = { | 515 | .driver = { |
