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