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.c137
1 files changed, 85 insertions, 52 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 16512ecae31a..7639ab906f02 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -51,17 +51,43 @@ 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)
57{ 78{
58 struct rtc_device *rdev = id; 79 struct rtc_device *rdev = id;
59 80
81 clk_enable(rtc_clk);
60 rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); 82 rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
61 83
62 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 84 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
63 writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); 85 writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP);
64 86
87 clk_disable(rtc_clk);
88
89 s3c_rtc_alarm_clk_enable(false);
90
65 return IRQ_HANDLED; 91 return IRQ_HANDLED;
66} 92}
67 93
@@ -69,11 +95,13 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
69{ 95{
70 struct rtc_device *rdev = id; 96 struct rtc_device *rdev = id;
71 97
98 clk_enable(rtc_clk);
72 rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); 99 rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
73 100
74 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 101 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
75 writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); 102 writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP);
76 103
104 clk_disable(rtc_clk);
77 return IRQ_HANDLED; 105 return IRQ_HANDLED;
78} 106}
79 107
@@ -84,12 +112,16 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
84 112
85 pr_debug("%s: aie=%d\n", __func__, enabled); 113 pr_debug("%s: aie=%d\n", __func__, enabled);
86 114
115 clk_enable(rtc_clk);
87 tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; 116 tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
88 117
89 if (enabled) 118 if (enabled)
90 tmp |= S3C2410_RTCALM_ALMEN; 119 tmp |= S3C2410_RTCALM_ALMEN;
91 120
92 writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); 121 writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
122 clk_disable(rtc_clk);
123
124 s3c_rtc_alarm_clk_enable(enabled);
93 125
94 return 0; 126 return 0;
95} 127}
@@ -103,6 +135,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
103 if (!is_power_of_2(freq)) 135 if (!is_power_of_2(freq))
104 return -EINVAL; 136 return -EINVAL;
105 137
138 clk_enable(rtc_clk);
106 spin_lock_irq(&s3c_rtc_pie_lock); 139 spin_lock_irq(&s3c_rtc_pie_lock);
107 140
108 if (s3c_rtc_cpu_type == TYPE_S3C2410) { 141 if (s3c_rtc_cpu_type == TYPE_S3C2410) {
@@ -114,6 +147,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
114 147
115 writel(tmp, s3c_rtc_base + S3C2410_TICNT); 148 writel(tmp, s3c_rtc_base + S3C2410_TICNT);
116 spin_unlock_irq(&s3c_rtc_pie_lock); 149 spin_unlock_irq(&s3c_rtc_pie_lock);
150 clk_disable(rtc_clk);
117 151
118 return 0; 152 return 0;
119} 153}
@@ -125,6 +159,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
125 unsigned int have_retried = 0; 159 unsigned int have_retried = 0;
126 void __iomem *base = s3c_rtc_base; 160 void __iomem *base = s3c_rtc_base;
127 161
162 clk_enable(rtc_clk);
128 retry_get_time: 163 retry_get_time:
129 rtc_tm->tm_min = readb(base + S3C2410_RTCMIN); 164 rtc_tm->tm_min = readb(base + S3C2410_RTCMIN);
130 rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR); 165 rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);
@@ -143,10 +178,6 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
143 goto retry_get_time; 178 goto retry_get_time;
144 } 179 }
145 180
146 pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n",
147 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
148 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
149
150 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); 181 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
151 rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); 182 rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
152 rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); 183 rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
@@ -155,8 +186,14 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
155 rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); 186 rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
156 187
157 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
158 rtc_tm->tm_mon -= 1; 194 rtc_tm->tm_mon -= 1;
159 195
196 clk_disable(rtc_clk);
160 return rtc_valid_tm(rtc_tm); 197 return rtc_valid_tm(rtc_tm);
161} 198}
162 199
@@ -165,6 +202,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
165 void __iomem *base = s3c_rtc_base; 202 void __iomem *base = s3c_rtc_base;
166 int year = tm->tm_year - 100; 203 int year = tm->tm_year - 100;
167 204
205 clk_enable(rtc_clk);
168 pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", 206 pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n",
169 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, 207 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
170 tm->tm_hour, tm->tm_min, tm->tm_sec); 208 tm->tm_hour, tm->tm_min, tm->tm_sec);
@@ -182,6 +220,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
182 writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE); 220 writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);
183 writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON); 221 writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);
184 writeb(bin2bcd(year), base + S3C2410_RTCYEAR); 222 writeb(bin2bcd(year), base + S3C2410_RTCYEAR);
223 clk_disable(rtc_clk);
185 224
186 return 0; 225 return 0;
187} 226}
@@ -192,6 +231,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
192 void __iomem *base = s3c_rtc_base; 231 void __iomem *base = s3c_rtc_base;
193 unsigned int alm_en; 232 unsigned int alm_en;
194 233
234 clk_enable(rtc_clk);
195 alm_tm->tm_sec = readb(base + S3C2410_ALMSEC); 235 alm_tm->tm_sec = readb(base + S3C2410_ALMSEC);
196 alm_tm->tm_min = readb(base + S3C2410_ALMMIN); 236 alm_tm->tm_min = readb(base + S3C2410_ALMMIN);
197 alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); 237 alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR);
@@ -243,6 +283,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
243 else 283 else
244 alm_tm->tm_year = -1; 284 alm_tm->tm_year = -1;
245 285
286 clk_disable(rtc_clk);
246 return 0; 287 return 0;
247} 288}
248 289
@@ -252,12 +293,12 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
252 void __iomem *base = s3c_rtc_base; 293 void __iomem *base = s3c_rtc_base;
253 unsigned int alrm_en; 294 unsigned int alrm_en;
254 295
296 clk_enable(rtc_clk);
255 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",
256 alrm->enabled, 298 alrm->enabled,
257 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, 299 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
258 tm->tm_hour, tm->tm_min, tm->tm_sec); 300 tm->tm_hour, tm->tm_min, tm->tm_sec);
259 301
260
261 alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; 302 alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
262 writeb(0x00, base + S3C2410_RTCALM); 303 writeb(0x00, base + S3C2410_RTCALM);
263 304
@@ -282,6 +323,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
282 323
283 s3c_rtc_setaie(dev, alrm->enabled); 324 s3c_rtc_setaie(dev, alrm->enabled);
284 325
326 clk_disable(rtc_clk);
285 return 0; 327 return 0;
286} 328}
287 329
@@ -289,6 +331,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
289{ 331{
290 unsigned int ticnt; 332 unsigned int ticnt;
291 333
334 clk_enable(rtc_clk);
292 if (s3c_rtc_cpu_type == TYPE_S3C64XX) { 335 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
293 ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); 336 ticnt = readw(s3c_rtc_base + S3C2410_RTCCON);
294 ticnt &= S3C64XX_RTCCON_TICEN; 337 ticnt &= S3C64XX_RTCCON_TICEN;
@@ -298,52 +341,11 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
298 } 341 }
299 342
300 seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); 343 seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no");
344 clk_disable(rtc_clk);
301 return 0; 345 return 0;
302} 346}
303 347
304static int s3c_rtc_open(struct device *dev)
305{
306 struct platform_device *pdev = to_platform_device(dev);
307 struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
308 int ret;
309
310 ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq,
311 IRQF_DISABLED, "s3c2410-rtc alarm", rtc_dev);
312
313 if (ret) {
314 dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);
315 return ret;
316 }
317
318 ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,
319 IRQF_DISABLED, "s3c2410-rtc tick", rtc_dev);
320
321 if (ret) {
322 dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
323 goto tick_err;
324 }
325
326 return ret;
327
328 tick_err:
329 free_irq(s3c_rtc_alarmno, rtc_dev);
330 return ret;
331}
332
333static void s3c_rtc_release(struct device *dev)
334{
335 struct platform_device *pdev = to_platform_device(dev);
336 struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
337
338 /* do not clear AIE here, it may be needed for wake */
339
340 free_irq(s3c_rtc_alarmno, rtc_dev);
341 free_irq(s3c_rtc_tickno, rtc_dev);
342}
343
344static const struct rtc_class_ops s3c_rtcops = { 348static const struct rtc_class_ops s3c_rtcops = {
345 .open = s3c_rtc_open,
346 .release = s3c_rtc_release,
347 .read_time = s3c_rtc_gettime, 349 .read_time = s3c_rtc_gettime,
348 .set_time = s3c_rtc_settime, 350 .set_time = s3c_rtc_settime,
349 .read_alarm = s3c_rtc_getalarm, 351 .read_alarm = s3c_rtc_getalarm,
@@ -360,6 +362,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
360 if (s3c_rtc_base == NULL) 362 if (s3c_rtc_base == NULL)
361 return; 363 return;
362 364
365 clk_enable(rtc_clk);
363 if (!en) { 366 if (!en) {
364 tmp = readw(base + S3C2410_RTCCON); 367 tmp = readw(base + S3C2410_RTCCON);
365 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 368 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
@@ -399,18 +402,21 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
399 base + S3C2410_RTCCON); 402 base + S3C2410_RTCCON);
400 } 403 }
401 } 404 }
405 clk_disable(rtc_clk);
402} 406}
403 407
404static int __devexit s3c_rtc_remove(struct platform_device *dev) 408static int __devexit s3c_rtc_remove(struct platform_device *dev)
405{ 409{
406 struct rtc_device *rtc = platform_get_drvdata(dev); 410 struct rtc_device *rtc = platform_get_drvdata(dev);
407 411
412 free_irq(s3c_rtc_alarmno, rtc);
413 free_irq(s3c_rtc_tickno, rtc);
414
408 platform_set_drvdata(dev, NULL); 415 platform_set_drvdata(dev, NULL);
409 rtc_device_unregister(rtc); 416 rtc_device_unregister(rtc);
410 417
411 s3c_rtc_setaie(&dev->dev, 0); 418 s3c_rtc_setaie(&dev->dev, 0);
412 419
413 clk_disable(rtc_clk);
414 clk_put(rtc_clk); 420 clk_put(rtc_clk);
415 rtc_clk = NULL; 421 rtc_clk = NULL;
416 422
@@ -455,8 +461,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
455 return -ENOENT; 461 return -ENOENT;
456 } 462 }
457 463
458 s3c_rtc_mem = request_mem_region(res->start, 464 s3c_rtc_mem = request_mem_region(res->start, resource_size(res),
459 res->end-res->start+1,
460 pdev->name); 465 pdev->name);
461 466
462 if (s3c_rtc_mem == NULL) { 467 if (s3c_rtc_mem == NULL) {
@@ -465,7 +470,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
465 goto err_nores; 470 goto err_nores;
466 } 471 }
467 472
468 s3c_rtc_base = ioremap(res->start, res->end - res->start + 1); 473 s3c_rtc_base = ioremap(res->start, resource_size(res));
469 if (s3c_rtc_base == NULL) { 474 if (s3c_rtc_base == NULL) {
470 dev_err(&pdev->dev, "failed ioremap()\n"); 475 dev_err(&pdev->dev, "failed ioremap()\n");
471 ret = -EINVAL; 476 ret = -EINVAL;
@@ -530,8 +535,32 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
530 535
531 s3c_rtc_setfreq(&pdev->dev, 1); 536 s3c_rtc_setfreq(&pdev->dev, 1);
532 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
553 clk_disable(rtc_clk);
554
533 return 0; 555 return 0;
534 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
535 err_nortc: 564 err_nortc:
536 s3c_rtc_enable(pdev, 0); 565 s3c_rtc_enable(pdev, 0);
537 clk_disable(rtc_clk); 566 clk_disable(rtc_clk);
@@ -555,6 +584,7 @@ static int ticnt_save, ticnt_en_save;
555 584
556static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) 585static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
557{ 586{
587 clk_enable(rtc_clk);
558 /* save TICNT for anyone using periodic interrupts */ 588 /* save TICNT for anyone using periodic interrupts */
559 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); 589 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
560 if (s3c_rtc_cpu_type == TYPE_S3C64XX) { 590 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
@@ -569,6 +599,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
569 else 599 else
570 dev_err(&pdev->dev, "enable_irq_wake failed\n"); 600 dev_err(&pdev->dev, "enable_irq_wake failed\n");
571 } 601 }
602 clk_disable(rtc_clk);
572 603
573 return 0; 604 return 0;
574} 605}
@@ -577,6 +608,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
577{ 608{
578 unsigned int tmp; 609 unsigned int tmp;
579 610
611 clk_enable(rtc_clk);
580 s3c_rtc_enable(pdev, 1); 612 s3c_rtc_enable(pdev, 1);
581 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); 613 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
582 if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { 614 if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) {
@@ -588,6 +620,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
588 disable_irq_wake(s3c_rtc_alarmno); 620 disable_irq_wake(s3c_rtc_alarmno);
589 wake_en = false; 621 wake_en = false;
590 } 622 }
623 clk_disable(rtc_clk);
591 624
592 return 0; 625 return 0;
593} 626}