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