1 /* drivers/rtc/rtc-s3c.c 2 * 3 * Copyright (c) 2004,2006 Simtec Electronics 4 * Ben Dooks, <ben@simtec.co.uk> 5 * http://armlinux.simtec.co.uk/ 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * S3C2410/S3C2440/S3C24XX Internal RTC Driver 12 */ 13 14 #include <linux/module.h> 15 #include <linux/fs.h> 16 #include <linux/string.h> 17 #include <linux/init.h> 18 #include <linux/platform_device.h> 19 #include <linux/interrupt.h> 20 #include <linux/rtc.h> 21 #include <linux/bcd.h> 22 #include <linux/clk.h> 23 24 #include <asm/hardware.h> 25 #include <asm/uaccess.h> 26 #include <asm/io.h> 27 #include <asm/irq.h> 28 #include <asm/rtc.h> 29 30 #include <asm/mach/time.h> 31 32 #include <asm/arch/regs-rtc.h> 33 34 /* I have yet to find an S3C implementation with more than one 35 * of these rtc blocks in */ 36 37 static struct resource *s3c_rtc_mem; 38 39 static void __iomem *s3c_rtc_base; 40 static int s3c_rtc_alarmno = NO_IRQ; 41 static int s3c_rtc_tickno = NO_IRQ; 42 static int s3c_rtc_freq = 1; 43 44 static DEFINE_SPINLOCK(s3c_rtc_pie_lock); 45 static unsigned int tick_count; 46 47 /* IRQ Handlers */ 48 49 static irqreturn_t s3c_rtc_alarmirq(int irq, void *id, struct pt_regs *r) 50 { 51 struct rtc_device *rdev = id; 52 53 rtc_update_irq(&rdev->class_dev, 1, RTC_AF | RTC_IRQF); 54 return IRQ_HANDLED; 55 } 56 57 static irqreturn_t s3c_rtc_tickirq(int irq, void *id, struct pt_regs *r) 58 { 59 struct rtc_device *rdev = id; 60 61 rtc_update_irq(&rdev->class_dev, tick_count++, RTC_PF | RTC_IRQF); 62 return IRQ_HANDLED; 63 } 64 65 /* Update control registers */ 66 static void s3c_rtc_setaie(int to) 67 { 68 unsigned int tmp; 69 70 pr_debug("%s: aie=%d\n", __FUNCTION__, to); 71 72 tmp = readb(S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; 73 74 if (to) 75 tmp |= S3C2410_RTCALM_ALMEN; 76 77 writeb(tmp, S3C2410_RTCALM); 78 } 79 80 static void s3c_rtc_setpie(int to) 81 { 82 unsigned int tmp; 83 84 pr_debug("%s: pie=%d\n", __FUNCTION__, to); 85 86 spin_lock_irq(&s3c_rtc_pie_lock); 87 tmp = readb(S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; 88 89 if (to) 90 tmp |= S3C2410_TICNT_ENABLE; 91 92 writeb(tmp, S3C2410_TICNT); 93 spin_unlock_irq(&s3c_rtc_pie_lock); 94 } 95 96 static void s3c_rtc_setfreq(int freq) 97 { 98 unsigned int tmp; 99 100 spin_lock_irq(&s3c_rtc_pie_lock); 101 tmp = readb(S3C2410_TICNT) & S3C2410_TICNT_ENABLE; 102 103 s3c_rtc_freq = freq; 104 105 tmp |= (128 / freq)-1; 106 107 writeb(tmp, S3C2410_TICNT); 108 spin_unlock_irq(&s3c_rtc_pie_lock); 109 } 110 111 /* Time read/write */ 112 113 static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) 114 { 115 unsigned int have_retried = 0; 116 117 retry_get_time: 118 rtc_tm->tm_min = readb(S3C2410_RTCMIN); 119 rtc_tm->tm_hour = readb(S3C2410_RTCHOUR); 120 rtc_tm->tm_mday = readb(S3C2410_RTCDATE); 121 rtc_tm->tm_mon = readb(S3C2410_RTCMON); 122 rtc_tm->tm_year = readb(S3C2410_RTCYEAR); 123 rtc_tm->tm_sec = readb(S3C2410_RTCSEC); 124 125 /* the only way to work out wether the system was mid-update 126 * when we read it is to check the second counter, and if it 127 * is zero, then we re-try the entire read 128 */ 129 130 if (rtc_tm->tm_sec == 0 && !have_retried) { 131 have_retried = 1; 132 goto retry_get_time; 133 } 134 135 pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", 136 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, 137 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); 138 139 BCD_TO_BIN(rtc_tm->tm_sec); 140 BCD_TO_BIN(rtc_tm->tm_min); 141 BCD_TO_BIN(rtc_tm->tm_hour); 142 BCD_TO_BIN(rtc_tm->tm_mday); 143 BCD_TO_BIN(rtc_tm->tm_mon); 144 BCD_TO_BIN(rtc_tm->tm_year); 145 146 rtc_tm->tm_year += 100; 147 rtc_tm->tm_mon -= 1; 148 149 return 0; 150 } 151 152 static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) 153 { 154 /* the rtc gets round the y2k problem by just not supporting it */ 155 156 if (tm->tm_year < 100) 157 return -EINVAL; 158 159 writeb(BIN2BCD(tm->tm_sec), S3C2410_RTCSEC); 160 writeb(BIN2BCD(tm->tm_min), S3C2410_RTCMIN); 161 writeb(BIN2BCD(tm->tm_hour), S3C2410_RTCHOUR); 162 writeb(BIN2BCD(tm->tm_mday), S3C2410_RTCDATE); 163 writeb(BIN2BCD(tm->tm_mon + 1), S3C2410_RTCMON); 164 writeb(BIN2BCD(tm->tm_year - 100), S3C2410_RTCYEAR); 165 166 return 0; 167 } 168 169 static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) 170 { 171 struct rtc_time *alm_tm = &alrm->time; 172 unsigned int alm_en; 173 174 alm_tm->tm_sec = readb(S3C2410_ALMSEC); 175 alm_tm->tm_min = readb(S3C2410_ALMMIN); 176 alm_tm->tm_hour = readb(S3C2410_ALMHOUR); 177 alm_tm->tm_mon = readb(S3C2410_ALMMON); 178 alm_tm->tm_mday = readb(S3C2410_ALMDATE); 179 alm_tm->tm_year = readb(S3C2410_ALMYEAR); 180 181 alm_en = readb(S3C2410_RTCALM); 182 183 pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", 184 alm_en, 185 alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, 186 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); 187 188 189 /* decode the alarm enable field */ 190 191 if (alm_en & S3C2410_RTCALM_SECEN) 192 BCD_TO_BIN(alm_tm->tm_sec); 193 else 194 alm_tm->tm_sec = 0xff; 195 196 if (alm_en & S3C2410_RTCALM_MINEN) 197 BCD_TO_BIN(alm_tm->tm_min); 198 else 199 alm_tm->tm_min = 0xff; 200 201 if (alm_en & S3C2410_RTCALM_HOUREN) 202 BCD_TO_BIN(alm_tm->tm_hour); 203 else 204 alm_tm->tm_hour = 0xff; 205 206 if (alm_en & S3C2410_RTCALM_DAYEN) 207 BCD_TO_BIN(alm_tm->tm_mday); 208 else 209 alm_tm->tm_mday = 0xff; 210 211 if (alm_en & S3C2410_RTCALM_MONEN) { 212 BCD_TO_BIN(alm_tm->tm_mon); 213 alm_tm->tm_mon -= 1; 214 } else { 215 alm_tm->tm_mon = 0xff; 216 } 217 218 if (alm_en & S3C2410_RTCALM_YEAREN) 219 BCD_TO_BIN(alm_tm->tm_year); 220 else 221 alm_tm->tm_year = 0xffff; 222 223 return 0; 224 } 225 226 static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) 227 { 228 struct rtc_time *tm = &alrm->time; 229 unsigned int alrm_en; 230 231 pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n", 232 alrm->enabled, 233 tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff, 234 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec); 235 236 237 alrm_en = readb(S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; 238 writeb(0x00, S3C2410_RTCALM); 239 240 if (tm->tm_sec < 60 && tm->tm_sec >= 0) { 241 alrm_en |= S3C2410_RTCALM_SECEN; 242 writeb(BIN2BCD(tm->tm_sec), S3C2410_ALMSEC); 243 } 244 245 if (tm->tm_min < 60 && tm->tm_min >= 0) { 246 alrm_en |= S3C2410_RTCALM_MINEN; 247 writeb(BIN2BCD(tm->tm_min), S3C2410_ALMMIN); 248 } 249 250 if (tm->tm_hour < 24 && tm->tm_hour >= 0) { 251 alrm_en |= S3C2410_RTCALM_HOUREN; 252 writeb(BIN2BCD(tm->tm_hour), S3C2410_ALMHOUR); 253 } 254 255 pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en); 256 257 writeb(alrm_en, S3C2410_RTCALM); 258 259 if (0) { 260 alrm_en = readb(S3C2410_RTCALM); 261 alrm_en &= ~S3C2410_RTCALM_ALMEN; 262 writeb(alrm_en, S3C2410_RTCALM); 263 disable_irq_wake(s3c_rtc_alarmno); 264 } 265 266 if (alrm->enabled) 267 enable_irq_wake(s3c_rtc_alarmno); 268 else 269 disable_irq_wake(s3c_rtc_alarmno); 270 271 return 0; 272 } 273 274 static int s3c_rtc_ioctl(struct device *dev, 275 unsigned int cmd, unsigned long arg) 276 { 277 unsigned int ret = -ENOIOCTLCMD; 278 279 switch (cmd) { 280 case RTC_AIE_OFF: 281 case RTC_AIE_ON: 282 s3c_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0); 283 ret = 0; 284 break; 285 286 case RTC_PIE_OFF: 287 case RTC_PIE_ON: 288 tick_count = 0; 289 s3c_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0); 290 ret = 0; 291 break; 292 293 case RTC_IRQP_READ: 294 ret = put_user(s3c_rtc_freq, (unsigned long __user *)arg); 295 break; 296 297 case RTC_IRQP_SET: 298 /* check for power of 2 */ 299 300 if ((arg & (arg-1)) != 0 || arg < 1) { 301 ret = -EINVAL; 302 goto exit; 303 } 304 305 pr_debug("s3c2410_rtc: setting frequency %ld\n", arg); 306 307 s3c_rtc_setfreq(arg); 308 ret = 0; 309 break; 310 311 case RTC_UIE_ON: 312 case RTC_UIE_OFF: 313 ret = -EINVAL; 314 } 315 316 exit: 317 return ret; 318 } 319 320 static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) 321 { 322 unsigned int rtcalm = readb(S3C2410_RTCALM); 323 unsigned int ticnt = readb (S3C2410_TICNT); 324 325 seq_printf(seq, "alarm_IRQ\t: %s\n", 326 (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" ); 327 328 seq_printf(seq, "periodic_IRQ\t: %s\n", 329 (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); 330 331 seq_printf(seq, "periodic_freq\t: %d\n", s3c_rtc_freq); 332 333 return 0; 334 } 335 336 static int s3c_rtc_open(struct device *dev) 337 { 338 struct platform_device *pdev = to_platform_device(dev); 339 struct rtc_device *rtc_dev = platform_get_drvdata(pdev); 340 int ret; 341 342 ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, 343 SA_INTERRUPT, "s3c2410-rtc alarm", rtc_dev); 344 345 if (ret) { 346 dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); 347 return ret; 348 } 349 350 ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, 351 SA_INTERRUPT, "s3c2410-rtc tick", rtc_dev); 352 353 if (ret) { 354 dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); 355 goto tick_err; 356 } 357 358 return ret; 359 360 tick_err: 361 free_irq(s3c_rtc_alarmno, rtc_dev); 362 return ret; 363 } 364 365 static void s3c_rtc_release(struct device *dev) 366 { 367 struct platform_device *pdev = to_platform_device(dev); 368 struct rtc_device *rtc_dev = platform_get_drvdata(pdev); 369 370 /* do not clear AIE here, it may be needed for wake */ 371 372 s3c_rtc_setpie(0); 373 free_irq(s3c_rtc_alarmno, rtc_dev); 374 free_irq(s3c_rtc_tickno, rtc_dev); 375 } 376 377 static struct rtc_class_ops s3c_rtcops = { 378 .open = s3c_rtc_open, 379 .release = s3c_rtc_release, 380 .ioctl = s3c_rtc_ioctl, 381 .read_time = s3c_rtc_gettime, 382 .set_time = s3c_rtc_settime, 383 .read_alarm = s3c_rtc_getalarm, 384 .set_alarm = s3c_rtc_setalarm, 385 .proc = s3c_rtc_proc, 386 }; 387 388 static void s3c_rtc_enable(struct platform_device *pdev, int en) 389 { 390 unsigned int tmp; 391 392 if (s3c_rtc_base == NULL) 393 return; 394 395 if (!en) { 396 tmp = readb(S3C2410_RTCCON); 397 writeb(tmp & ~S3C2410_RTCCON_RTCEN, S3C2410_RTCCON); 398 399 tmp = readb(S3C2410_TICNT); 400 writeb(tmp & ~S3C2410_TICNT_ENABLE, S3C2410_TICNT); 401 } else { 402 /* re-enable the device, and check it is ok */ 403 404 if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){ 405 dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); 406 407 tmp = readb(S3C2410_RTCCON); 408 writeb(tmp | S3C2410_RTCCON_RTCEN , S3C2410_RTCCON); 409 } 410 411 if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){ 412 dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); 413 414 tmp = readb(S3C2410_RTCCON); 415 writeb(tmp& ~S3C2410_RTCCON_CNTSEL , S3C2410_RTCCON); 416 } 417 418 if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){ 419 dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); 420 421 tmp = readb(S3C2410_RTCCON); 422 writeb(tmp & ~S3C2410_RTCCON_CLKRST, S3C2410_RTCCON); 423 } 424 } 425 } 426 427 static int s3c_rtc_remove(struct platform_device *dev) 428 { 429 struct rtc_device *rtc = platform_get_drvdata(dev); 430 431 platform_set_drvdata(dev, NULL); 432 rtc_device_unregister(rtc); 433 434 s3c_rtc_setpie(0); 435 s3c_rtc_setaie(0); 436 437 iounmap(s3c_rtc_base); 438 release_resource(s3c_rtc_mem); 439 kfree(s3c_rtc_mem); 440 441 return 0; 442 } 443 444 static int s3c_rtc_probe(struct platform_device *pdev) 445 { 446 struct rtc_device *rtc; 447 struct resource *res; 448 int ret; 449 450 pr_debug("%s: probe=%p\n", __FUNCTION__, pdev); 451 452 /* find the IRQs */ 453 454 s3c_rtc_tickno = platform_get_irq(pdev, 1); 455 if (s3c_rtc_tickno < 0) { 456 dev_err(&pdev->dev, "no irq for rtc tick\n"); 457 return -ENOENT; 458 } 459 460 s3c_rtc_alarmno = platform_get_irq(pdev, 0); 461 if (s3c_rtc_alarmno < 0) { 462 dev_err(&pdev->dev, "no irq for alarm\n"); 463 return -ENOENT; 464 } 465 466 pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n", 467 s3c_rtc_tickno, s3c_rtc_alarmno); 468 469 /* get the memory region */ 470 471 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 472 if (res == NULL) { 473 dev_err(&pdev->dev, "failed to get memory region resource\n"); 474 return -ENOENT; 475 } 476 477 s3c_rtc_mem = request_mem_region(res->start, 478 res->end-res->start+1, 479 pdev->name); 480 481 if (s3c_rtc_mem == NULL) { 482 dev_err(&pdev->dev, "failed to reserve memory region\n"); 483 ret = -ENOENT; 484 goto err_nores; 485 } 486 487 s3c_rtc_base = ioremap(res->start, res->end - res->start + 1); 488 if (s3c_rtc_base == NULL) { 489 dev_err(&pdev->dev, "failed ioremap()\n"); 490 ret = -EINVAL; 491 goto err_nomap; 492 } 493 494 /* check to see if everything is setup correctly */ 495 496 s3c_rtc_enable(pdev, 1); 497 498 pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON)); 499 500 s3c_rtc_setfreq(s3c_rtc_freq); 501 502 /* register RTC and exit */ 503 504 rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops, 505 THIS_MODULE); 506 507 if (IS_ERR(rtc)) { 508 dev_err(&pdev->dev, "cannot attach rtc\n"); 509 ret = PTR_ERR(rtc); 510 goto err_nortc; 511 } 512 513 rtc->max_user_freq = 128; 514 515 platform_set_drvdata(pdev, rtc); 516 return 0; 517 518 err_nortc: 519 s3c_rtc_enable(pdev, 0); 520 iounmap(s3c_rtc_base); 521 522 err_nomap: 523 release_resource(s3c_rtc_mem); 524 525 err_nores: 526 return ret; 527 } 528 529 #ifdef CONFIG_PM 530 531 /* RTC Power management control */ 532 533 static struct timespec s3c_rtc_delta; 534 535 static int ticnt_save; 536 537 static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) 538 { 539 struct rtc_time tm; 540 struct timespec time; 541 542 time.tv_nsec = 0; 543 544 /* save TICNT for anyone using periodic interrupts */ 545 546 ticnt_save = readb(S3C2410_TICNT); 547 548 /* calculate time delta for suspend */ 549 550 s3c_rtc_gettime(&pdev->dev, &tm); 551 rtc_tm_to_time(&tm, &time.tv_sec); 552 save_time_delta(&s3c_rtc_delta, &time); 553 s3c_rtc_enable(pdev, 0); 554 555 return 0; 556 } 557 558 static int s3c_rtc_resume(struct platform_device *pdev) 559 { 560 struct rtc_time tm; 561 struct timespec time; 562 563 time.tv_nsec = 0; 564 565 s3c_rtc_enable(pdev, 1); 566 s3c_rtc_gettime(&pdev->dev, &tm); 567 rtc_tm_to_time(&tm, &time.tv_sec); 568 restore_time_delta(&s3c_rtc_delta, &time); 569 570 writeb(ticnt_save, S3C2410_TICNT); 571 return 0; 572 } 573 #else 574 #define s3c_rtc_suspend NULL 575 #define s3c_rtc_resume NULL 576 #endif 577 578 static struct platform_driver s3c2410_rtcdrv = { 579 .probe = s3c_rtc_probe, 580 .remove = s3c_rtc_remove, 581 .suspend = s3c_rtc_suspend, 582 .resume = s3c_rtc_resume, 583 .driver = { 584 .name = "s3c2410-rtc", 585 .owner = THIS_MODULE, 586 }, 587 }; 588 589 static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n"; 590 591 static int __init s3c_rtc_init(void) 592 { 593 printk(banner); 594 return platform_driver_register(&s3c2410_rtcdrv); 595 } 596 597 static void __exit s3c_rtc_exit(void) 598 { 599 platform_driver_unregister(&s3c2410_rtcdrv); 600 } 601 602 module_init(s3c_rtc_init); 603 module_exit(s3c_rtc_exit); 604 605 MODULE_DESCRIPTION("Samsung S3C RTC Driver"); 606 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 607 MODULE_LICENSE("GPL"); 608