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.c105
1 files changed, 57 insertions, 48 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 9329dbb9ebab..7639ab906f02 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -51,6 +51,27 @@ static enum s3c_cpu_type s3c_rtc_cpu_type;
51 51
52static DEFINE_SPINLOCK(s3c_rtc_pie_lock); 52static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
53 53
54static void s3c_rtc_alarm_clk_enable(bool enable)
55{
56 static DEFINE_SPINLOCK(s3c_rtc_alarm_clk_lock);
57 static bool alarm_clk_enabled;
58 unsigned long irq_flags;
59
60 spin_lock_irqsave(&s3c_rtc_alarm_clk_lock, irq_flags);
61 if (enable) {
62 if (!alarm_clk_enabled) {
63 clk_enable(rtc_clk);
64 alarm_clk_enabled = true;
65 }
66 } else {
67 if (alarm_clk_enabled) {
68 clk_disable(rtc_clk);
69 alarm_clk_enabled = false;
70 }
71 }
72 spin_unlock_irqrestore(&s3c_rtc_alarm_clk_lock, irq_flags);
73}
74
54/* IRQ Handlers */ 75/* IRQ Handlers */
55 76
56static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) 77static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
@@ -64,6 +85,9 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
64 writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); 85 writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP);
65 86
66 clk_disable(rtc_clk); 87 clk_disable(rtc_clk);
88
89 s3c_rtc_alarm_clk_enable(false);
90
67 return IRQ_HANDLED; 91 return IRQ_HANDLED;
68} 92}
69 93
@@ -97,6 +121,8 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
97 writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); 121 writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
98 clk_disable(rtc_clk); 122 clk_disable(rtc_clk);
99 123
124 s3c_rtc_alarm_clk_enable(enabled);
125
100 return 0; 126 return 0;
101} 127}
102 128
@@ -152,10 +178,6 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
152 goto retry_get_time; 178 goto retry_get_time;
153 } 179 }
154 180
155 pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n",
156 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
157 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
158
159 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); 181 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
160 rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); 182 rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
161 rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); 183 rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
@@ -164,6 +186,11 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
164 rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); 186 rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
165 187
166 rtc_tm->tm_year += 100; 188 rtc_tm->tm_year += 100;
189
190 pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n",
191 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
192 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
193
167 rtc_tm->tm_mon -= 1; 194 rtc_tm->tm_mon -= 1;
168 195
169 clk_disable(rtc_clk); 196 clk_disable(rtc_clk);
@@ -269,10 +296,9 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
269 clk_enable(rtc_clk); 296 clk_enable(rtc_clk);
270 pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", 297 pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
271 alrm->enabled, 298 alrm->enabled,
272 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, 299 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
273 tm->tm_hour, tm->tm_min, tm->tm_sec); 300 tm->tm_hour, tm->tm_min, tm->tm_sec);
274 301
275
276 alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; 302 alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
277 writeb(0x00, base + S3C2410_RTCALM); 303 writeb(0x00, base + S3C2410_RTCALM);
278 304
@@ -319,49 +345,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
319 return 0; 345 return 0;
320} 346}
321 347
322static int s3c_rtc_open(struct device *dev)
323{
324 struct platform_device *pdev = to_platform_device(dev);
325 struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
326 int ret;
327
328 ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq,
329 IRQF_DISABLED, "s3c2410-rtc alarm", rtc_dev);
330
331 if (ret) {
332 dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);
333 return ret;
334 }
335
336 ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,
337 IRQF_DISABLED, "s3c2410-rtc tick", rtc_dev);
338
339 if (ret) {
340 dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
341 goto tick_err;
342 }
343
344 return ret;
345
346 tick_err:
347 free_irq(s3c_rtc_alarmno, rtc_dev);
348 return ret;
349}
350
351static void s3c_rtc_release(struct device *dev)
352{
353 struct platform_device *pdev = to_platform_device(dev);
354 struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
355
356 /* do not clear AIE here, it may be needed for wake */
357
358 free_irq(s3c_rtc_alarmno, rtc_dev);
359 free_irq(s3c_rtc_tickno, rtc_dev);
360}
361
362static const struct rtc_class_ops s3c_rtcops = { 348static const struct rtc_class_ops s3c_rtcops = {
363 .open = s3c_rtc_open,
364 .release = s3c_rtc_release,
365 .read_time = s3c_rtc_gettime, 349 .read_time = s3c_rtc_gettime,
366 .set_time = s3c_rtc_settime, 350 .set_time = s3c_rtc_settime,
367 .read_alarm = s3c_rtc_getalarm, 351 .read_alarm = s3c_rtc_getalarm,
@@ -425,6 +409,9 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
425{ 409{
426 struct rtc_device *rtc = platform_get_drvdata(dev); 410 struct rtc_device *rtc = platform_get_drvdata(dev);
427 411
412 free_irq(s3c_rtc_alarmno, rtc);
413 free_irq(s3c_rtc_tickno, rtc);
414
428 platform_set_drvdata(dev, NULL); 415 platform_set_drvdata(dev, NULL);
429 rtc_device_unregister(rtc); 416 rtc_device_unregister(rtc);
430 417
@@ -548,10 +535,32 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
548 535
549 s3c_rtc_setfreq(&pdev->dev, 1); 536 s3c_rtc_setfreq(&pdev->dev, 1);
550 537
538 ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq,
539 IRQF_DISABLED, "s3c2410-rtc alarm", rtc);
540 if (ret) {
541 dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);
542 goto err_alarm_irq;
543 }
544
545 ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,
546 IRQF_DISABLED, "s3c2410-rtc tick", rtc);
547 if (ret) {
548 dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
549 free_irq(s3c_rtc_alarmno, rtc);
550 goto err_tick_irq;
551 }
552
551 clk_disable(rtc_clk); 553 clk_disable(rtc_clk);
552 554
553 return 0; 555 return 0;
554 556
557 err_tick_irq:
558 free_irq(s3c_rtc_alarmno, rtc);
559
560 err_alarm_irq:
561 platform_set_drvdata(pdev, NULL);
562 rtc_device_unregister(rtc);
563
555 err_nortc: 564 err_nortc:
556 s3c_rtc_enable(pdev, 0); 565 s3c_rtc_enable(pdev, 0);
557 clk_disable(rtc_clk); 566 clk_disable(rtc_clk);