aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-s3c.c
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2010-05-24 17:33:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-25 11:07:07 -0400
commit9f4123b78d02ba48e7e6e3cd9de789c9b85b557a (patch)
tree0faf7f318bd90af043c8e9e056697ca38a1281e4 /drivers/rtc/rtc-s3c.c
parent337bbfdbffa5c893e80f96a3bf117743ceb0fefc (diff)
s3c rtc driver: add support for S3C64xx
Add support for the S3C64xx SoC to the generic S3C RTC driver. Signed-off-by: Maurus Cuelenaere <mcuelenaere@gmail.com> Acked-by: Ben Dooks <ben-linux@fluff.org> Cc: Frans Pop <elendil@planet.nl> Cc: Paul Gortmaker <p_gortmaker@yahoo.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc/rtc-s3c.c')
-rw-r--r--drivers/rtc/rtc-s3c.c107
1 files changed, 87 insertions, 20 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 4969b6059c89..e5972b2c17b7 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -29,6 +29,11 @@
29#include <asm/irq.h> 29#include <asm/irq.h>
30#include <plat/regs-rtc.h> 30#include <plat/regs-rtc.h>
31 31
32enum s3c_cpu_type {
33 TYPE_S3C2410,
34 TYPE_S3C64XX,
35};
36
32/* I have yet to find an S3C implementation with more than one 37/* I have yet to find an S3C implementation with more than one
33 * of these rtc blocks in */ 38 * of these rtc blocks in */
34 39
@@ -37,6 +42,7 @@ static struct resource *s3c_rtc_mem;
37static void __iomem *s3c_rtc_base; 42static void __iomem *s3c_rtc_base;
38static int s3c_rtc_alarmno = NO_IRQ; 43static int s3c_rtc_alarmno = NO_IRQ;
39static int s3c_rtc_tickno = NO_IRQ; 44static int s3c_rtc_tickno = NO_IRQ;
45static enum s3c_cpu_type s3c_rtc_cpu_type;
40 46
41static DEFINE_SPINLOCK(s3c_rtc_pie_lock); 47static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
42 48
@@ -80,12 +86,25 @@ static int s3c_rtc_setpie(struct device *dev, int enabled)
80 pr_debug("%s: pie=%d\n", __func__, enabled); 86 pr_debug("%s: pie=%d\n", __func__, enabled);
81 87
82 spin_lock_irq(&s3c_rtc_pie_lock); 88 spin_lock_irq(&s3c_rtc_pie_lock);
83 tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
84 89
85 if (enabled) 90 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
86 tmp |= S3C2410_TICNT_ENABLE; 91 tmp = readb(s3c_rtc_base + S3C2410_RTCCON);
92 tmp &= ~S3C64XX_RTCCON_TICEN;
93
94 if (enabled)
95 tmp |= S3C64XX_RTCCON_TICEN;
96
97 writeb(tmp, s3c_rtc_base + S3C2410_RTCCON);
98 } else {
99 tmp = readb(s3c_rtc_base + S3C2410_TICNT);
100 tmp &= ~S3C2410_TICNT_ENABLE;
101
102 if (enabled)
103 tmp |= S3C2410_TICNT_ENABLE;
104
105 writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
106 }
87 107
88 writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
89 spin_unlock_irq(&s3c_rtc_pie_lock); 108 spin_unlock_irq(&s3c_rtc_pie_lock);
90 109
91 return 0; 110 return 0;
@@ -93,15 +112,21 @@ static int s3c_rtc_setpie(struct device *dev, int enabled)
93 112
94static int s3c_rtc_setfreq(struct device *dev, int freq) 113static int s3c_rtc_setfreq(struct device *dev, int freq)
95{ 114{
96 unsigned int tmp; 115 struct platform_device *pdev = to_platform_device(dev);
116 struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
117 unsigned int tmp = 0;
97 118
98 if (!is_power_of_2(freq)) 119 if (!is_power_of_2(freq))
99 return -EINVAL; 120 return -EINVAL;
100 121
101 spin_lock_irq(&s3c_rtc_pie_lock); 122 spin_lock_irq(&s3c_rtc_pie_lock);
102 123
103 tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; 124 if (s3c_rtc_cpu_type == TYPE_S3C2410) {
104 tmp |= (128 / freq)-1; 125 tmp = readb(s3c_rtc_base + S3C2410_TICNT);
126 tmp &= S3C2410_TICNT_ENABLE;
127 }
128
129 tmp |= (rtc_dev->max_user_freq / freq)-1;
105 130
106 writeb(tmp, s3c_rtc_base + S3C2410_TICNT); 131 writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
107 spin_unlock_irq(&s3c_rtc_pie_lock); 132 spin_unlock_irq(&s3c_rtc_pie_lock);
@@ -283,10 +308,17 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
283 308
284static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) 309static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
285{ 310{
286 unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); 311 unsigned int ticnt;
287 312
288 seq_printf(seq, "periodic_IRQ\t: %s\n", 313 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
289 (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); 314 ticnt = readb(s3c_rtc_base + S3C2410_RTCCON);
315 ticnt &= S3C64XX_RTCCON_TICEN;
316 } else {
317 ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
318 ticnt &= S3C2410_TICNT_ENABLE;
319 }
320
321 seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no");
290 return 0; 322 return 0;
291} 323}
292 324
@@ -353,10 +385,16 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
353 385
354 if (!en) { 386 if (!en) {
355 tmp = readb(base + S3C2410_RTCCON); 387 tmp = readb(base + S3C2410_RTCCON);
356 writeb(tmp & ~S3C2410_RTCCON_RTCEN, base + S3C2410_RTCCON); 388 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
357 389 tmp &= ~S3C64XX_RTCCON_TICEN;
358 tmp = readb(base + S3C2410_TICNT); 390 tmp &= ~S3C2410_RTCCON_RTCEN;
359 writeb(tmp & ~S3C2410_TICNT_ENABLE, base + S3C2410_TICNT); 391 writeb(tmp, base + S3C2410_RTCCON);
392
393 if (s3c_rtc_cpu_type == TYPE_S3C2410) {
394 tmp = readb(base + S3C2410_TICNT);
395 tmp &= ~S3C2410_TICNT_ENABLE;
396 writeb(tmp, base + S3C2410_TICNT);
397 }
360 } else { 398 } else {
361 /* re-enable the device, and check it is ok */ 399 /* re-enable the device, and check it is ok */
362 400
@@ -472,7 +510,12 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
472 goto err_nortc; 510 goto err_nortc;
473 } 511 }
474 512
475 rtc->max_user_freq = 128; 513 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
514 rtc->max_user_freq = 32768;
515 else
516 rtc->max_user_freq = 128;
517
518 s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
476 519
477 platform_set_drvdata(pdev, rtc); 520 platform_set_drvdata(pdev, rtc);
478 return 0; 521 return 0;
@@ -492,20 +535,30 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
492 535
493/* RTC Power management control */ 536/* RTC Power management control */
494 537
495static int ticnt_save; 538static int ticnt_save, ticnt_en_save;
496 539
497static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) 540static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
498{ 541{
499 /* save TICNT for anyone using periodic interrupts */ 542 /* save TICNT for anyone using periodic interrupts */
500 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); 543 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
544 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
545 ticnt_en_save = readb(s3c_rtc_base + S3C2410_RTCCON);
546 ticnt_en_save &= S3C64XX_RTCCON_TICEN;
547 }
501 s3c_rtc_enable(pdev, 0); 548 s3c_rtc_enable(pdev, 0);
502 return 0; 549 return 0;
503} 550}
504 551
505static int s3c_rtc_resume(struct platform_device *pdev) 552static int s3c_rtc_resume(struct platform_device *pdev)
506{ 553{
554 unsigned int tmp;
555
507 s3c_rtc_enable(pdev, 1); 556 s3c_rtc_enable(pdev, 1);
508 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); 557 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
558 if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) {
559 tmp = readb(s3c_rtc_base + S3C2410_RTCCON);
560 writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON);
561 }
509 return 0; 562 return 0;
510} 563}
511#else 564#else
@@ -513,13 +566,27 @@ static int s3c_rtc_resume(struct platform_device *pdev)
513#define s3c_rtc_resume NULL 566#define s3c_rtc_resume NULL
514#endif 567#endif
515 568
516static struct platform_driver s3c2410_rtc_driver = { 569static struct platform_device_id s3c_rtc_driver_ids[] = {
570 {
571 .name = "s3c2410-rtc",
572 .driver_data = TYPE_S3C2410,
573 }, {
574 .name = "s3c64xx-rtc",
575 .driver_data = TYPE_S3C64XX,
576 },
577 { }
578};
579
580MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids);
581
582static struct platform_driver s3c_rtc_driver = {
517 .probe = s3c_rtc_probe, 583 .probe = s3c_rtc_probe,
518 .remove = __devexit_p(s3c_rtc_remove), 584 .remove = __devexit_p(s3c_rtc_remove),
519 .suspend = s3c_rtc_suspend, 585 .suspend = s3c_rtc_suspend,
520 .resume = s3c_rtc_resume, 586 .resume = s3c_rtc_resume,
587 .id_table = s3c_rtc_driver_ids,
521 .driver = { 588 .driver = {
522 .name = "s3c2410-rtc", 589 .name = "s3c-rtc",
523 .owner = THIS_MODULE, 590 .owner = THIS_MODULE,
524 }, 591 },
525}; 592};
@@ -529,12 +596,12 @@ static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics
529static int __init s3c_rtc_init(void) 596static int __init s3c_rtc_init(void)
530{ 597{
531 printk(banner); 598 printk(banner);
532 return platform_driver_register(&s3c2410_rtc_driver); 599 return platform_driver_register(&s3c_rtc_driver);
533} 600}
534 601
535static void __exit s3c_rtc_exit(void) 602static void __exit s3c_rtc_exit(void)
536{ 603{
537 platform_driver_unregister(&s3c2410_rtc_driver); 604 platform_driver_unregister(&s3c_rtc_driver);
538} 605}
539 606
540module_init(s3c_rtc_init); 607module_init(s3c_rtc_init);