diff options
Diffstat (limited to 'drivers/rtc/rtc-s3c.c')
-rw-r--r-- | drivers/rtc/rtc-s3c.c | 57 |
1 files changed, 50 insertions, 7 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 70b68d35f96..f57a87f4ae9 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -1,5 +1,8 @@ /* drivers/rtc/rtc-s3c.c * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * * Copyright (c) 2004,2006 Simtec Electronics * Ben Dooks, <ben@simtec.co.uk> * http://armlinux.simtec.co.uk/ @@ -39,6 +42,7 @@ enum s3c_cpu_type { static struct resource *s3c_rtc_mem; +static struct clk *rtc_clk; static void __iomem *s3c_rtc_base; static int s3c_rtc_alarmno = NO_IRQ; static int s3c_rtc_tickno = NO_IRQ; @@ -53,6 +57,10 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) struct rtc_device *rdev = id; rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); + + if (s3c_rtc_cpu_type == TYPE_S3C64XX) + writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); + return IRQ_HANDLED; } @@ -61,6 +69,10 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) struct rtc_device *rdev = id; rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); + + if (s3c_rtc_cpu_type == TYPE_S3C64XX) + writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); + return IRQ_HANDLED; } @@ -94,7 +106,7 @@ static int s3c_rtc_setpie(struct device *dev, int enabled) if (enabled) tmp |= S3C64XX_RTCCON_TICEN; - writeb(tmp, s3c_rtc_base + S3C2410_RTCCON); + writew(tmp, s3c_rtc_base + S3C2410_RTCCON); } else { tmp = readb(s3c_rtc_base + S3C2410_TICNT); tmp &= ~S3C2410_TICNT_ENABLE; @@ -128,7 +140,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq) tmp |= (rtc_dev->max_user_freq / freq)-1; - writeb(tmp, s3c_rtc_base + S3C2410_TICNT); + writel(tmp, s3c_rtc_base + S3C2410_TICNT); spin_unlock_irq(&s3c_rtc_pie_lock); return 0; @@ -298,11 +310,6 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) s3c_rtc_setaie(alrm->enabled); - if (alrm->enabled) - enable_irq_wake(s3c_rtc_alarmno); - else - disable_irq_wake(s3c_rtc_alarmno); - return 0; } @@ -431,6 +438,10 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) s3c_rtc_setpie(&dev->dev, 0); s3c_rtc_setaie(0); + clk_disable(rtc_clk); + clk_put(rtc_clk); + rtc_clk = NULL; + iounmap(s3c_rtc_base); release_resource(s3c_rtc_mem); kfree(s3c_rtc_mem); @@ -442,6 +453,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; struct resource *res; + unsigned int tmp, i; int ret; pr_debug("%s: probe=%p\n", __func__, pdev); @@ -488,6 +500,16 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) goto err_nomap; } + rtc_clk = clk_get(&pdev->dev, "rtc"); + if (IS_ERR(rtc_clk)) { + dev_err(&pdev->dev, "failed to find rtc clock source\n"); + ret = PTR_ERR(rtc_clk); + rtc_clk = NULL; + goto err_clk; + } + + clk_enable(rtc_clk); + /* check to see if everything is setup correctly */ s3c_rtc_enable(pdev, 1); @@ -510,6 +532,15 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data; + /* Check RTC Time */ + + for (i = S3C2410_RTCSEC; i <= S3C2410_RTCYEAR; i += 0x4) { + tmp = readb(s3c_rtc_base + i); + + if ((tmp & 0xf) > 0x9 || ((tmp >> 4) & 0xf) > 0x9) + writeb(0, s3c_rtc_base + i); + } + if (s3c_rtc_cpu_type == TYPE_S3C64XX) rtc->max_user_freq = 32768; else @@ -523,6 +554,10 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) err_nortc: s3c_rtc_enable(pdev, 0); + clk_disable(rtc_clk); + clk_put(rtc_clk); + + err_clk: iounmap(s3c_rtc_base); err_nomap: @@ -547,6 +582,10 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) ticnt_en_save &= S3C64XX_RTCCON_TICEN; } s3c_rtc_enable(pdev, 0); + + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(s3c_rtc_alarmno); + return 0; } @@ -560,6 +599,10 @@ static int s3c_rtc_resume(struct platform_device *pdev) tmp = readb(s3c_rtc_base + S3C2410_RTCCON); writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); } + + if (device_may_wakeup(&pdev->dev)) + disable_irq_wake(s3c_rtc_alarmno); + return 0; } #else |