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.c146
1 files changed, 66 insertions, 80 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index f57a87f4ae96..16512ecae31a 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -46,6 +46,7 @@ static struct clk *rtc_clk;
46static void __iomem *s3c_rtc_base; 46static void __iomem *s3c_rtc_base;
47static int s3c_rtc_alarmno = NO_IRQ; 47static int s3c_rtc_alarmno = NO_IRQ;
48static int s3c_rtc_tickno = NO_IRQ; 48static int s3c_rtc_tickno = NO_IRQ;
49static bool wake_en;
49static enum s3c_cpu_type s3c_rtc_cpu_type; 50static enum s3c_cpu_type s3c_rtc_cpu_type;
50 51
51static DEFINE_SPINLOCK(s3c_rtc_pie_lock); 52static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
@@ -77,47 +78,18 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
77} 78}
78 79
79/* Update control registers */ 80/* Update control registers */
80static void s3c_rtc_setaie(int to) 81static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
81{ 82{
82 unsigned int tmp; 83 unsigned int tmp;
83 84
84 pr_debug("%s: aie=%d\n", __func__, to); 85 pr_debug("%s: aie=%d\n", __func__, enabled);
85 86
86 tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; 87 tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
87 88
88 if (to) 89 if (enabled)
89 tmp |= S3C2410_RTCALM_ALMEN; 90 tmp |= S3C2410_RTCALM_ALMEN;
90 91
91 writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); 92 writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
92}
93
94static int s3c_rtc_setpie(struct device *dev, int enabled)
95{
96 unsigned int tmp;
97
98 pr_debug("%s: pie=%d\n", __func__, enabled);
99
100 spin_lock_irq(&s3c_rtc_pie_lock);
101
102 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
103 tmp = readb(s3c_rtc_base + S3C2410_RTCCON);
104 tmp &= ~S3C64XX_RTCCON_TICEN;
105
106 if (enabled)
107 tmp |= S3C64XX_RTCCON_TICEN;
108
109 writew(tmp, s3c_rtc_base + S3C2410_RTCCON);
110 } else {
111 tmp = readb(s3c_rtc_base + S3C2410_TICNT);
112 tmp &= ~S3C2410_TICNT_ENABLE;
113
114 if (enabled)
115 tmp |= S3C2410_TICNT_ENABLE;
116
117 writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
118 }
119
120 spin_unlock_irq(&s3c_rtc_pie_lock);
121 93
122 return 0; 94 return 0;
123} 95}
@@ -171,8 +143,8 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
171 goto retry_get_time; 143 goto retry_get_time;
172 } 144 }
173 145
174 pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", 146 pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n",
175 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, 147 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
176 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); 148 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
177 149
178 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); 150 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
@@ -185,7 +157,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
185 rtc_tm->tm_year += 100; 157 rtc_tm->tm_year += 100;
186 rtc_tm->tm_mon -= 1; 158 rtc_tm->tm_mon -= 1;
187 159
188 return 0; 160 return rtc_valid_tm(rtc_tm);
189} 161}
190 162
191static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) 163static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
@@ -193,8 +165,8 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
193 void __iomem *base = s3c_rtc_base; 165 void __iomem *base = s3c_rtc_base;
194 int year = tm->tm_year - 100; 166 int year = tm->tm_year - 100;
195 167
196 pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n", 168 pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n",
197 tm->tm_year, tm->tm_mon, tm->tm_mday, 169 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
198 tm->tm_hour, tm->tm_min, tm->tm_sec); 170 tm->tm_hour, tm->tm_min, tm->tm_sec);
199 171
200 /* we get around y2k by simply not supporting it */ 172 /* we get around y2k by simply not supporting it */
@@ -231,9 +203,9 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
231 203
232 alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; 204 alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
233 205
234 pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", 206 pr_debug("read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n",
235 alm_en, 207 alm_en,
236 alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, 208 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
237 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); 209 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
238 210
239 211
@@ -242,34 +214,34 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
242 if (alm_en & S3C2410_RTCALM_SECEN) 214 if (alm_en & S3C2410_RTCALM_SECEN)
243 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); 215 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
244 else 216 else
245 alm_tm->tm_sec = 0xff; 217 alm_tm->tm_sec = -1;
246 218
247 if (alm_en & S3C2410_RTCALM_MINEN) 219 if (alm_en & S3C2410_RTCALM_MINEN)
248 alm_tm->tm_min = bcd2bin(alm_tm->tm_min); 220 alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
249 else 221 else
250 alm_tm->tm_min = 0xff; 222 alm_tm->tm_min = -1;
251 223
252 if (alm_en & S3C2410_RTCALM_HOUREN) 224 if (alm_en & S3C2410_RTCALM_HOUREN)
253 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); 225 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
254 else 226 else
255 alm_tm->tm_hour = 0xff; 227 alm_tm->tm_hour = -1;
256 228
257 if (alm_en & S3C2410_RTCALM_DAYEN) 229 if (alm_en & S3C2410_RTCALM_DAYEN)
258 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); 230 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
259 else 231 else
260 alm_tm->tm_mday = 0xff; 232 alm_tm->tm_mday = -1;
261 233
262 if (alm_en & S3C2410_RTCALM_MONEN) { 234 if (alm_en & S3C2410_RTCALM_MONEN) {
263 alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); 235 alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);
264 alm_tm->tm_mon -= 1; 236 alm_tm->tm_mon -= 1;
265 } else { 237 } else {
266 alm_tm->tm_mon = 0xff; 238 alm_tm->tm_mon = -1;
267 } 239 }
268 240
269 if (alm_en & S3C2410_RTCALM_YEAREN) 241 if (alm_en & S3C2410_RTCALM_YEAREN)
270 alm_tm->tm_year = bcd2bin(alm_tm->tm_year); 242 alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
271 else 243 else
272 alm_tm->tm_year = 0xffff; 244 alm_tm->tm_year = -1;
273 245
274 return 0; 246 return 0;
275} 247}
@@ -280,10 +252,10 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
280 void __iomem *base = s3c_rtc_base; 252 void __iomem *base = s3c_rtc_base;
281 unsigned int alrm_en; 253 unsigned int alrm_en;
282 254
283 pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n", 255 pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
284 alrm->enabled, 256 alrm->enabled,
285 tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff, 257 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
286 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec); 258 tm->tm_hour, tm->tm_min, tm->tm_sec);
287 259
288 260
289 alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; 261 alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
@@ -308,7 +280,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
308 280
309 writeb(alrm_en, base + S3C2410_RTCALM); 281 writeb(alrm_en, base + S3C2410_RTCALM);
310 282
311 s3c_rtc_setaie(alrm->enabled); 283 s3c_rtc_setaie(dev, alrm->enabled);
312 284
313 return 0; 285 return 0;
314} 286}
@@ -318,7 +290,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
318 unsigned int ticnt; 290 unsigned int ticnt;
319 291
320 if (s3c_rtc_cpu_type == TYPE_S3C64XX) { 292 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
321 ticnt = readb(s3c_rtc_base + S3C2410_RTCCON); 293 ticnt = readw(s3c_rtc_base + S3C2410_RTCCON);
322 ticnt &= S3C64XX_RTCCON_TICEN; 294 ticnt &= S3C64XX_RTCCON_TICEN;
323 } else { 295 } else {
324 ticnt = readb(s3c_rtc_base + S3C2410_TICNT); 296 ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
@@ -365,7 +337,6 @@ static void s3c_rtc_release(struct device *dev)
365 337
366 /* do not clear AIE here, it may be needed for wake */ 338 /* do not clear AIE here, it may be needed for wake */
367 339
368 s3c_rtc_setpie(dev, 0);
369 free_irq(s3c_rtc_alarmno, rtc_dev); 340 free_irq(s3c_rtc_alarmno, rtc_dev);
370 free_irq(s3c_rtc_tickno, rtc_dev); 341 free_irq(s3c_rtc_tickno, rtc_dev);
371} 342}
@@ -377,9 +348,8 @@ static const struct rtc_class_ops s3c_rtcops = {
377 .set_time = s3c_rtc_settime, 348 .set_time = s3c_rtc_settime,
378 .read_alarm = s3c_rtc_getalarm, 349 .read_alarm = s3c_rtc_getalarm,
379 .set_alarm = s3c_rtc_setalarm, 350 .set_alarm = s3c_rtc_setalarm,
380 .irq_set_freq = s3c_rtc_setfreq, 351 .proc = s3c_rtc_proc,
381 .irq_set_state = s3c_rtc_setpie, 352 .alarm_irq_enable = s3c_rtc_setaie,
382 .proc = s3c_rtc_proc,
383}; 353};
384 354
385static void s3c_rtc_enable(struct platform_device *pdev, int en) 355static void s3c_rtc_enable(struct platform_device *pdev, int en)
@@ -391,11 +361,11 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
391 return; 361 return;
392 362
393 if (!en) { 363 if (!en) {
394 tmp = readb(base + S3C2410_RTCCON); 364 tmp = readw(base + S3C2410_RTCCON);
395 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 365 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
396 tmp &= ~S3C64XX_RTCCON_TICEN; 366 tmp &= ~S3C64XX_RTCCON_TICEN;
397 tmp &= ~S3C2410_RTCCON_RTCEN; 367 tmp &= ~S3C2410_RTCCON_RTCEN;
398 writeb(tmp, base + S3C2410_RTCCON); 368 writew(tmp, base + S3C2410_RTCCON);
399 369
400 if (s3c_rtc_cpu_type == TYPE_S3C2410) { 370 if (s3c_rtc_cpu_type == TYPE_S3C2410) {
401 tmp = readb(base + S3C2410_TICNT); 371 tmp = readb(base + S3C2410_TICNT);
@@ -405,25 +375,28 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
405 } else { 375 } else {
406 /* re-enable the device, and check it is ok */ 376 /* re-enable the device, and check it is ok */
407 377
408 if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){ 378 if ((readw(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) {
409 dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); 379 dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
410 380
411 tmp = readb(base + S3C2410_RTCCON); 381 tmp = readw(base + S3C2410_RTCCON);
412 writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON); 382 writew(tmp | S3C2410_RTCCON_RTCEN,
383 base + S3C2410_RTCCON);
413 } 384 }
414 385
415 if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){ 386 if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) {
416 dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); 387 dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n");
417 388
418 tmp = readb(base + S3C2410_RTCCON); 389 tmp = readw(base + S3C2410_RTCCON);
419 writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON); 390 writew(tmp & ~S3C2410_RTCCON_CNTSEL,
391 base + S3C2410_RTCCON);
420 } 392 }
421 393
422 if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){ 394 if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) {
423 dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); 395 dev_info(&pdev->dev, "removing RTCCON_CLKRST\n");
424 396
425 tmp = readb(base + S3C2410_RTCCON); 397 tmp = readw(base + S3C2410_RTCCON);
426 writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON); 398 writew(tmp & ~S3C2410_RTCCON_CLKRST,
399 base + S3C2410_RTCCON);
427 } 400 }
428 } 401 }
429} 402}
@@ -435,8 +408,7 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
435 platform_set_drvdata(dev, NULL); 408 platform_set_drvdata(dev, NULL);
436 rtc_device_unregister(rtc); 409 rtc_device_unregister(rtc);
437 410
438 s3c_rtc_setpie(&dev->dev, 0); 411 s3c_rtc_setaie(&dev->dev, 0);
439 s3c_rtc_setaie(0);
440 412
441 clk_disable(rtc_clk); 413 clk_disable(rtc_clk);
442 clk_put(rtc_clk); 414 clk_put(rtc_clk);
@@ -452,8 +424,8 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
452static int __devinit s3c_rtc_probe(struct platform_device *pdev) 424static int __devinit s3c_rtc_probe(struct platform_device *pdev)
453{ 425{
454 struct rtc_device *rtc; 426 struct rtc_device *rtc;
427 struct rtc_time rtc_tm;
455 struct resource *res; 428 struct resource *res;
456 unsigned int tmp, i;
457 int ret; 429 int ret;
458 430
459 pr_debug("%s: probe=%p\n", __func__, pdev); 431 pr_debug("%s: probe=%p\n", __func__, pdev);
@@ -514,8 +486,8 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
514 486
515 s3c_rtc_enable(pdev, 1); 487 s3c_rtc_enable(pdev, 1);
516 488
517 pr_debug("s3c2410_rtc: RTCCON=%02x\n", 489 pr_debug("s3c2410_rtc: RTCCON=%02x\n",
518 readb(s3c_rtc_base + S3C2410_RTCCON)); 490 readw(s3c_rtc_base + S3C2410_RTCCON));
519 491
520 device_init_wakeup(&pdev->dev, 1); 492 device_init_wakeup(&pdev->dev, 1);
521 493
@@ -534,11 +506,19 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
534 506
535 /* Check RTC Time */ 507 /* Check RTC Time */
536 508
537 for (i = S3C2410_RTCSEC; i <= S3C2410_RTCYEAR; i += 0x4) { 509 s3c_rtc_gettime(NULL, &rtc_tm);
538 tmp = readb(s3c_rtc_base + i); 510
511 if (rtc_valid_tm(&rtc_tm)) {
512 rtc_tm.tm_year = 100;
513 rtc_tm.tm_mon = 0;
514 rtc_tm.tm_mday = 1;
515 rtc_tm.tm_hour = 0;
516 rtc_tm.tm_min = 0;
517 rtc_tm.tm_sec = 0;
539 518
540 if ((tmp & 0xf) > 0x9 || ((tmp >> 4) & 0xf) > 0x9) 519 s3c_rtc_settime(NULL, &rtc_tm);
541 writeb(0, s3c_rtc_base + i); 520
521 dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
542 } 522 }
543 523
544 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 524 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
@@ -578,13 +558,17 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
578 /* save TICNT for anyone using periodic interrupts */ 558 /* save TICNT for anyone using periodic interrupts */
579 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); 559 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
580 if (s3c_rtc_cpu_type == TYPE_S3C64XX) { 560 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
581 ticnt_en_save = readb(s3c_rtc_base + S3C2410_RTCCON); 561 ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON);
582 ticnt_en_save &= S3C64XX_RTCCON_TICEN; 562 ticnt_en_save &= S3C64XX_RTCCON_TICEN;
583 } 563 }
584 s3c_rtc_enable(pdev, 0); 564 s3c_rtc_enable(pdev, 0);
585 565
586 if (device_may_wakeup(&pdev->dev)) 566 if (device_may_wakeup(&pdev->dev) && !wake_en) {
587 enable_irq_wake(s3c_rtc_alarmno); 567 if (enable_irq_wake(s3c_rtc_alarmno) == 0)
568 wake_en = true;
569 else
570 dev_err(&pdev->dev, "enable_irq_wake failed\n");
571 }
588 572
589 return 0; 573 return 0;
590} 574}
@@ -596,12 +580,14 @@ static int s3c_rtc_resume(struct platform_device *pdev)
596 s3c_rtc_enable(pdev, 1); 580 s3c_rtc_enable(pdev, 1);
597 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); 581 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
598 if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { 582 if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) {
599 tmp = readb(s3c_rtc_base + S3C2410_RTCCON); 583 tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
600 writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); 584 writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON);
601 } 585 }
602 586
603 if (device_may_wakeup(&pdev->dev)) 587 if (device_may_wakeup(&pdev->dev) && wake_en) {
604 disable_irq_wake(s3c_rtc_alarmno); 588 disable_irq_wake(s3c_rtc_alarmno);
589 wake_en = false;
590 }
605 591
606 return 0; 592 return 0;
607} 593}