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, 60 insertions, 45 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index a0d3ec89d412..cf953ecbfca9 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -100,7 +100,7 @@ static int s3c_rtc_setpie(struct device *dev, int enabled)
100 spin_lock_irq(&s3c_rtc_pie_lock); 100 spin_lock_irq(&s3c_rtc_pie_lock);
101 101
102 if (s3c_rtc_cpu_type == TYPE_S3C64XX) { 102 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
103 tmp = readb(s3c_rtc_base + S3C2410_RTCCON); 103 tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
104 tmp &= ~S3C64XX_RTCCON_TICEN; 104 tmp &= ~S3C64XX_RTCCON_TICEN;
105 105
106 if (enabled) 106 if (enabled)
@@ -171,8 +171,8 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
171 goto retry_get_time; 171 goto retry_get_time;
172 } 172 }
173 173
174 pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", 174 pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n",
175 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, 175 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); 176 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
177 177
178 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); 178 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
@@ -185,7 +185,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
185 rtc_tm->tm_year += 100; 185 rtc_tm->tm_year += 100;
186 rtc_tm->tm_mon -= 1; 186 rtc_tm->tm_mon -= 1;
187 187
188 return 0; 188 return rtc_valid_tm(rtc_tm);
189} 189}
190 190
191static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) 191static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
@@ -193,8 +193,8 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
193 void __iomem *base = s3c_rtc_base; 193 void __iomem *base = s3c_rtc_base;
194 int year = tm->tm_year - 100; 194 int year = tm->tm_year - 100;
195 195
196 pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n", 196 pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n",
197 tm->tm_year, tm->tm_mon, tm->tm_mday, 197 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
198 tm->tm_hour, tm->tm_min, tm->tm_sec); 198 tm->tm_hour, tm->tm_min, tm->tm_sec);
199 199
200 /* we get around y2k by simply not supporting it */ 200 /* we get around y2k by simply not supporting it */
@@ -231,9 +231,9 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
231 231
232 alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; 232 alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
233 233
234 pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", 234 pr_debug("read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n",
235 alm_en, 235 alm_en,
236 alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, 236 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); 237 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
238 238
239 239
@@ -242,34 +242,34 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
242 if (alm_en & S3C2410_RTCALM_SECEN) 242 if (alm_en & S3C2410_RTCALM_SECEN)
243 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); 243 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
244 else 244 else
245 alm_tm->tm_sec = 0xff; 245 alm_tm->tm_sec = -1;
246 246
247 if (alm_en & S3C2410_RTCALM_MINEN) 247 if (alm_en & S3C2410_RTCALM_MINEN)
248 alm_tm->tm_min = bcd2bin(alm_tm->tm_min); 248 alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
249 else 249 else
250 alm_tm->tm_min = 0xff; 250 alm_tm->tm_min = -1;
251 251
252 if (alm_en & S3C2410_RTCALM_HOUREN) 252 if (alm_en & S3C2410_RTCALM_HOUREN)
253 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); 253 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
254 else 254 else
255 alm_tm->tm_hour = 0xff; 255 alm_tm->tm_hour = -1;
256 256
257 if (alm_en & S3C2410_RTCALM_DAYEN) 257 if (alm_en & S3C2410_RTCALM_DAYEN)
258 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); 258 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
259 else 259 else
260 alm_tm->tm_mday = 0xff; 260 alm_tm->tm_mday = -1;
261 261
262 if (alm_en & S3C2410_RTCALM_MONEN) { 262 if (alm_en & S3C2410_RTCALM_MONEN) {
263 alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); 263 alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);
264 alm_tm->tm_mon -= 1; 264 alm_tm->tm_mon -= 1;
265 } else { 265 } else {
266 alm_tm->tm_mon = 0xff; 266 alm_tm->tm_mon = -1;
267 } 267 }
268 268
269 if (alm_en & S3C2410_RTCALM_YEAREN) 269 if (alm_en & S3C2410_RTCALM_YEAREN)
270 alm_tm->tm_year = bcd2bin(alm_tm->tm_year); 270 alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
271 else 271 else
272 alm_tm->tm_year = 0xffff; 272 alm_tm->tm_year = -1;
273 273
274 return 0; 274 return 0;
275} 275}
@@ -280,10 +280,10 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
280 void __iomem *base = s3c_rtc_base; 280 void __iomem *base = s3c_rtc_base;
281 unsigned int alrm_en; 281 unsigned int alrm_en;
282 282
283 pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n", 283 pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
284 alrm->enabled, 284 alrm->enabled,
285 tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff, 285 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
286 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec); 286 tm->tm_hour, tm->tm_min, tm->tm_sec);
287 287
288 288
289 alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; 289 alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
@@ -310,11 +310,6 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
310 310
311 s3c_rtc_setaie(alrm->enabled); 311 s3c_rtc_setaie(alrm->enabled);
312 312
313 if (alrm->enabled)
314 enable_irq_wake(s3c_rtc_alarmno);
315 else
316 disable_irq_wake(s3c_rtc_alarmno);
317
318 return 0; 313 return 0;
319} 314}
320 315
@@ -323,7 +318,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
323 unsigned int ticnt; 318 unsigned int ticnt;
324 319
325 if (s3c_rtc_cpu_type == TYPE_S3C64XX) { 320 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
326 ticnt = readb(s3c_rtc_base + S3C2410_RTCCON); 321 ticnt = readw(s3c_rtc_base + S3C2410_RTCCON);
327 ticnt &= S3C64XX_RTCCON_TICEN; 322 ticnt &= S3C64XX_RTCCON_TICEN;
328 } else { 323 } else {
329 ticnt = readb(s3c_rtc_base + S3C2410_TICNT); 324 ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
@@ -384,7 +379,8 @@ static const struct rtc_class_ops s3c_rtcops = {
384 .set_alarm = s3c_rtc_setalarm, 379 .set_alarm = s3c_rtc_setalarm,
385 .irq_set_freq = s3c_rtc_setfreq, 380 .irq_set_freq = s3c_rtc_setfreq,
386 .irq_set_state = s3c_rtc_setpie, 381 .irq_set_state = s3c_rtc_setpie,
387 .proc = s3c_rtc_proc, 382 .proc = s3c_rtc_proc,
383 .alarm_irq_enable = s3c_rtc_setaie,
388}; 384};
389 385
390static void s3c_rtc_enable(struct platform_device *pdev, int en) 386static void s3c_rtc_enable(struct platform_device *pdev, int en)
@@ -396,11 +392,11 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
396 return; 392 return;
397 393
398 if (!en) { 394 if (!en) {
399 tmp = readb(base + S3C2410_RTCCON); 395 tmp = readw(base + S3C2410_RTCCON);
400 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 396 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
401 tmp &= ~S3C64XX_RTCCON_TICEN; 397 tmp &= ~S3C64XX_RTCCON_TICEN;
402 tmp &= ~S3C2410_RTCCON_RTCEN; 398 tmp &= ~S3C2410_RTCCON_RTCEN;
403 writeb(tmp, base + S3C2410_RTCCON); 399 writew(tmp, base + S3C2410_RTCCON);
404 400
405 if (s3c_rtc_cpu_type == TYPE_S3C2410) { 401 if (s3c_rtc_cpu_type == TYPE_S3C2410) {
406 tmp = readb(base + S3C2410_TICNT); 402 tmp = readb(base + S3C2410_TICNT);
@@ -410,25 +406,28 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
410 } else { 406 } else {
411 /* re-enable the device, and check it is ok */ 407 /* re-enable the device, and check it is ok */
412 408
413 if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){ 409 if ((readw(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) {
414 dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); 410 dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
415 411
416 tmp = readb(base + S3C2410_RTCCON); 412 tmp = readw(base + S3C2410_RTCCON);
417 writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON); 413 writew(tmp | S3C2410_RTCCON_RTCEN,
414 base + S3C2410_RTCCON);
418 } 415 }
419 416
420 if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){ 417 if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) {
421 dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); 418 dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n");
422 419
423 tmp = readb(base + S3C2410_RTCCON); 420 tmp = readw(base + S3C2410_RTCCON);
424 writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON); 421 writew(tmp & ~S3C2410_RTCCON_CNTSEL,
422 base + S3C2410_RTCCON);
425 } 423 }
426 424
427 if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){ 425 if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) {
428 dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); 426 dev_info(&pdev->dev, "removing RTCCON_CLKRST\n");
429 427
430 tmp = readb(base + S3C2410_RTCCON); 428 tmp = readw(base + S3C2410_RTCCON);
431 writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON); 429 writew(tmp & ~S3C2410_RTCCON_CLKRST,
430 base + S3C2410_RTCCON);
432 } 431 }
433 } 432 }
434} 433}
@@ -457,8 +456,8 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
457static int __devinit s3c_rtc_probe(struct platform_device *pdev) 456static int __devinit s3c_rtc_probe(struct platform_device *pdev)
458{ 457{
459 struct rtc_device *rtc; 458 struct rtc_device *rtc;
459 struct rtc_time rtc_tm;
460 struct resource *res; 460 struct resource *res;
461 unsigned int tmp, i;
462 int ret; 461 int ret;
463 462
464 pr_debug("%s: probe=%p\n", __func__, pdev); 463 pr_debug("%s: probe=%p\n", __func__, pdev);
@@ -519,8 +518,8 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
519 518
520 s3c_rtc_enable(pdev, 1); 519 s3c_rtc_enable(pdev, 1);
521 520
522 pr_debug("s3c2410_rtc: RTCCON=%02x\n", 521 pr_debug("s3c2410_rtc: RTCCON=%02x\n",
523 readb(s3c_rtc_base + S3C2410_RTCCON)); 522 readw(s3c_rtc_base + S3C2410_RTCCON));
524 523
525 device_init_wakeup(&pdev->dev, 1); 524 device_init_wakeup(&pdev->dev, 1);
526 525
@@ -539,11 +538,19 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
539 538
540 /* Check RTC Time */ 539 /* Check RTC Time */
541 540
542 for (i = S3C2410_RTCSEC; i <= S3C2410_RTCYEAR; i += 0x4) { 541 s3c_rtc_gettime(NULL, &rtc_tm);
543 tmp = readb(s3c_rtc_base + i); 542
543 if (rtc_valid_tm(&rtc_tm)) {
544 rtc_tm.tm_year = 100;
545 rtc_tm.tm_mon = 0;
546 rtc_tm.tm_mday = 1;
547 rtc_tm.tm_hour = 0;
548 rtc_tm.tm_min = 0;
549 rtc_tm.tm_sec = 0;
544 550
545 if ((tmp & 0xf) > 0x9 || ((tmp >> 4) & 0xf) > 0x9) 551 s3c_rtc_settime(NULL, &rtc_tm);
546 writeb(0, s3c_rtc_base + i); 552
553 dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
547 } 554 }
548 555
549 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 556 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
@@ -583,10 +590,14 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
583 /* save TICNT for anyone using periodic interrupts */ 590 /* save TICNT for anyone using periodic interrupts */
584 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); 591 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
585 if (s3c_rtc_cpu_type == TYPE_S3C64XX) { 592 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
586 ticnt_en_save = readb(s3c_rtc_base + S3C2410_RTCCON); 593 ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON);
587 ticnt_en_save &= S3C64XX_RTCCON_TICEN; 594 ticnt_en_save &= S3C64XX_RTCCON_TICEN;
588 } 595 }
589 s3c_rtc_enable(pdev, 0); 596 s3c_rtc_enable(pdev, 0);
597
598 if (device_may_wakeup(&pdev->dev))
599 enable_irq_wake(s3c_rtc_alarmno);
600
590 return 0; 601 return 0;
591} 602}
592 603
@@ -597,9 +608,13 @@ static int s3c_rtc_resume(struct platform_device *pdev)
597 s3c_rtc_enable(pdev, 1); 608 s3c_rtc_enable(pdev, 1);
598 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); 609 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
599 if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { 610 if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) {
600 tmp = readb(s3c_rtc_base + S3C2410_RTCCON); 611 tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
601 writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); 612 writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON);
602 } 613 }
614
615 if (device_may_wakeup(&pdev->dev))
616 disable_irq_wake(s3c_rtc_alarmno);
617
603 return 0; 618 return 0;
604} 619}
605#else 620#else