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 pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n", 156 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, 157 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); 158 159 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); 160 rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); 161 rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); 162 rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday); 163 rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon); 164 rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); 165 166 rtc_tm->tm_year += 100; 167 rtc_tm->tm_mon -= 1; 168 169 clk_disable(rtc_clk); 170 return rtc_valid_tm(rtc_tm); 171 } 172 173 static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) 174 { 175 void __iomem *base = s3c_rtc_base; 176 int year = tm->tm_year - 100; 177 178 clk_enable(rtc_clk); 179 pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", 180 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, 181 tm->tm_hour, tm->tm_min, tm->tm_sec); 182 183 /* we get around y2k by simply not supporting it */ 184 185 if (year < 0 || year >= 100) { 186 dev_err(dev, "rtc only supports 100 years\n"); 187 return -EINVAL; 188 } 189 190 writeb(bin2bcd(tm->tm_sec), base + S3C2410_RTCSEC); 191 writeb(bin2bcd(tm->tm_min), base + S3C2410_RTCMIN); 192 writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR); 193 writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE); 194 writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON); 195 writeb(bin2bcd(year), base + S3C2410_RTCYEAR); 196 clk_disable(rtc_clk); 197 198 return 0; 199 } 200 201 static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) 202 { 203 struct rtc_time *alm_tm = &alrm->time; 204 void __iomem *base = s3c_rtc_base; 205 unsigned int alm_en; 206 207 clk_enable(rtc_clk); 208 alm_tm->tm_sec = readb(base + S3C2410_ALMSEC); 209 alm_tm->tm_min = readb(base + S3C2410_ALMMIN); 210 alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); 211 alm_tm->tm_mon = readb(base + S3C2410_ALMMON); 212 alm_tm->tm_mday = readb(base + S3C2410_ALMDATE); 213 alm_tm->tm_year = readb(base + S3C2410_ALMYEAR); 214 215 alm_en = readb(base + S3C2410_RTCALM); 216 217 alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; 218 219 pr_debug("read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n", 220 alm_en, 221 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, 222 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); 223 224 225 /* decode the alarm enable field */ 226 227 if (alm_en & S3C2410_RTCALM_SECEN) 228 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); 229 else 230 alm_tm->tm_sec = -1; 231 232 if (alm_en & S3C2410_RTCALM_MINEN) 233 alm_tm->tm_min = bcd2bin(alm_tm->tm_min); 234 else 235 alm_tm->tm_min = -1; 236 237 if (alm_en & S3C2410_RTCALM_HOUREN) 238 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); 239 else 240 alm_tm->tm_hour = -1; 241 242 if (alm_en & S3C2410_RTCALM_DAYEN) 243 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); 244 else 245 alm_tm->tm_mday = -1; 246 247 if (alm_en & S3C2410_RTCALM_MONEN) { 248 alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); 249 alm_tm->tm_mon -= 1; 250 } else { 251 alm_tm->tm_mon = -1; 252 } 253 254 if (alm_en & S3C2410_RTCALM_YEAREN) 255 alm_tm->tm_year = bcd2bin(alm_tm->tm_year); 256 else 257 alm_tm->tm_year = -1; 258 259 clk_disable(rtc_clk); 260 return 0; 261 } 262 263 static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) 264 { 265 struct rtc_time *tm = &alrm->time; 266 void __iomem *base = s3c_rtc_base; 267 unsigned int alrm_en; 268 269 clk_enable(rtc_clk); 270 pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", 271 alrm->enabled, 272 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, 273 tm->tm_hour, tm->tm_min, tm->tm_sec); 274 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 int s3c_rtc_open(struct device *dev) 323 { 324 struct platform_device *pdev = to_platform_device(dev); 325 struct rtc_device *rtc_dev = platform_get_drvdata(pdev); 326 int ret; 327 328 ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, 329 IRQF_DISABLED, "s3c2410-rtc alarm", rtc_dev); 330 331 if (ret) { 332 dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); 333 return ret; 334 } 335 336 ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, 337 IRQF_DISABLED, "s3c2410-rtc tick", rtc_dev); 338 339 if (ret) { 340 dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); 341 goto tick_err; 342 } 343 344 return ret; 345 346 tick_err: 347 free_irq(s3c_rtc_alarmno, rtc_dev); 348 return ret; 349 } 350 351 static void s3c_rtc_release(struct device *dev) 352 { 353 struct platform_device *pdev = to_platform_device(dev); 354 struct rtc_device *rtc_dev = platform_get_drvdata(pdev); 355 356 /* do not clear AIE here, it may be needed for wake */ 357 358 free_irq(s3c_rtc_alarmno, rtc_dev); 359 free_irq(s3c_rtc_tickno, rtc_dev); 360 } 361 362 static const struct rtc_class_ops s3c_rtcops = { 363 .open = s3c_rtc_open, 364 .release = s3c_rtc_release, 365 .read_time = s3c_rtc_gettime, 366 .set_time = s3c_rtc_settime, 367 .read_alarm = s3c_rtc_getalarm, 368 .set_alarm = s3c_rtc_setalarm, 369 .proc = s3c_rtc_proc, 370 .alarm_irq_enable = s3c_rtc_setaie, 371 }; 372 373 static void s3c_rtc_enable(struct platform_device *pdev, int en) 374 { 375 void __iomem *base = s3c_rtc_base; 376 unsigned int tmp; 377 378 if (s3c_rtc_base == NULL) 379 return; 380 381 clk_enable(rtc_clk); 382 if (!en) { 383 tmp = readw(base + S3C2410_RTCCON); 384 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 385 tmp &= ~S3C64XX_RTCCON_TICEN; 386 tmp &= ~S3C2410_RTCCON_RTCEN; 387 writew(tmp, base + S3C2410_RTCCON); 388 389 if (s3c_rtc_cpu_type == TYPE_S3C2410) { 390 tmp = readb(base + S3C2410_TICNT); 391 tmp &= ~S3C2410_TICNT_ENABLE; 392 writeb(tmp, base + S3C2410_TICNT); 393 } 394 } else { 395 /* re-enable the device, and check it is ok */ 396 397 if ((readw(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) { 398 dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); 399 400 tmp = readw(base + S3C2410_RTCCON); 401 writew(tmp | S3C2410_RTCCON_RTCEN, 402 base + S3C2410_RTCCON); 403 } 404 405 if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) { 406 dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); 407 408 tmp = readw(base + S3C2410_RTCCON); 409 writew(tmp & ~S3C2410_RTCCON_CNTSEL, 410 base + S3C2410_RTCCON); 411 } 412 413 if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) { 414 dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); 415 416 tmp = readw(base + S3C2410_RTCCON); 417 writew(tmp & ~S3C2410_RTCCON_CLKRST, 418 base + S3C2410_RTCCON); 419 } 420 } 421 clk_disable(rtc_clk); 422 } 423 424 static int __devexit s3c_rtc_remove(struct platform_device *dev) 425 { 426 struct rtc_device *rtc = platform_get_drvdata(dev); 427 428 platform_set_drvdata(dev, NULL); 429 rtc_device_unregister(rtc); 430 431 s3c_rtc_setaie(&dev->dev, 0); 432 433 clk_put(rtc_clk); 434 rtc_clk = NULL; 435 436 iounmap(s3c_rtc_base); 437 release_resource(s3c_rtc_mem); 438 kfree(s3c_rtc_mem); 439 440 return 0; 441 } 442 443 static int __devinit s3c_rtc_probe(struct platform_device *pdev) 444 { 445 struct rtc_device *rtc; 446 struct rtc_time rtc_tm; 447 struct resource *res; 448 int ret; 449 450 pr_debug("%s: probe=%p\n", __func__, 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, resource_size(res), 478 pdev->name); 479 480 if (s3c_rtc_mem == NULL) { 481 dev_err(&pdev->dev, "failed to reserve memory region\n"); 482 ret = -ENOENT; 483 goto err_nores; 484 } 485 486 s3c_rtc_base = ioremap(res->start, resource_size(res)); 487 if (s3c_rtc_base == NULL) { 488 dev_err(&pdev->dev, "failed ioremap()\n"); 489 ret = -EINVAL; 490 goto err_nomap; 491 } 492 493 rtc_clk = clk_get(&pdev->dev, "rtc"); 494 if (IS_ERR(rtc_clk)) { 495 dev_err(&pdev->dev, "failed to find rtc clock source\n"); 496 ret = PTR_ERR(rtc_clk); 497 rtc_clk = NULL; 498 goto err_clk; 499 } 500 501 clk_enable(rtc_clk); 502 503 /* check to see if everything is setup correctly */ 504 505 s3c_rtc_enable(pdev, 1); 506 507 pr_debug("s3c2410_rtc: RTCCON=%02x\n", 508 readw(s3c_rtc_base + S3C2410_RTCCON)); 509 510 device_init_wakeup(&pdev->dev, 1); 511 512 /* register RTC and exit */ 513 514 rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops, 515 THIS_MODULE); 516 517 if (IS_ERR(rtc)) { 518 dev_err(&pdev->dev, "cannot attach rtc\n"); 519 ret = PTR_ERR(rtc); 520 goto err_nortc; 521 } 522 523 s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data; 524 525 /* Check RTC Time */ 526 527 s3c_rtc_gettime(NULL, &rtc_tm); 528 529 if (rtc_valid_tm(&rtc_tm)) { 530 rtc_tm.tm_year = 100; 531 rtc_tm.tm_mon = 0; 532 rtc_tm.tm_mday = 1; 533 rtc_tm.tm_hour = 0; 534 rtc_tm.tm_min = 0; 535 rtc_tm.tm_sec = 0; 536 537 s3c_rtc_settime(NULL, &rtc_tm); 538 539 dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); 540 } 541 542 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 543 rtc->max_user_freq = 32768; 544 else 545 rtc->max_user_freq = 128; 546 547 platform_set_drvdata(pdev, rtc); 548 549 s3c_rtc_setfreq(&pdev->dev, 1); 550 551 clk_disable(rtc_clk); 552 553 return 0; 554 555 err_nortc: 556 s3c_rtc_enable(pdev, 0); 557 clk_disable(rtc_clk); 558 clk_put(rtc_clk); 559 560 err_clk: 561 iounmap(s3c_rtc_base); 562 563 err_nomap: 564 release_resource(s3c_rtc_mem); 565 566 err_nores: 567 return ret; 568 } 569 570 #ifdef CONFIG_PM 571 572 /* RTC Power management control */ 573 574 static int ticnt_save, ticnt_en_save; 575 576 static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) 577 { 578 clk_enable(rtc_clk); 579 /* save TICNT for anyone using periodic interrupts */ 580 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); 581 if (s3c_rtc_cpu_type == TYPE_S3C64XX) { 582 ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON); 583 ticnt_en_save &= S3C64XX_RTCCON_TICEN; 584 } 585 s3c_rtc_enable(pdev, 0); 586 587 if (device_may_wakeup(&pdev->dev) && !wake_en) { 588 if (enable_irq_wake(s3c_rtc_alarmno) == 0) 589 wake_en = true; 590 else 591 dev_err(&pdev->dev, "enable_irq_wake failed\n"); 592 } 593 clk_disable(rtc_clk); 594 595 return 0; 596 } 597 598 static int s3c_rtc_resume(struct platform_device *pdev) 599 { 600 unsigned int tmp; 601 602 clk_enable(rtc_clk); 603 s3c_rtc_enable(pdev, 1); 604 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); 605 if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { 606 tmp = readw(s3c_rtc_base + S3C2410_RTCCON); 607 writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); 608 } 609 610 if (device_may_wakeup(&pdev->dev) && wake_en) { 611 disable_irq_wake(s3c_rtc_alarmno); 612 wake_en = false; 613 } 614 clk_disable(rtc_clk); 615 616 return 0; 617 } 618 #else 619 #define s3c_rtc_suspend NULL 620 #define s3c_rtc_resume NULL 621 #endif 622 623 static struct platform_device_id s3c_rtc_driver_ids[] = { 624 { 625 .name = "s3c2410-rtc", 626 .driver_data = TYPE_S3C2410, 627 }, { 628 .name = "s3c64xx-rtc", 629 .driver_data = TYPE_S3C64XX, 630 }, 631 { } 632 }; 633 634 MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids); 635 636 static struct platform_driver s3c_rtc_driver = { 637 .probe = s3c_rtc_probe, 638 .remove = __devexit_p(s3c_rtc_remove), 639 .suspend = s3c_rtc_suspend, 640 .resume = s3c_rtc_resume, 641 .id_table = s3c_rtc_driver_ids, 642 .driver = { 643 .name = "s3c-rtc", 644 .owner = THIS_MODULE, 645 }, 646 }; 647 648 static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n"; 649 650 static int __init s3c_rtc_init(void) 651 { 652 printk(banner); 653 return platform_driver_register(&s3c_rtc_driver); 654 } 655 656 static void __exit s3c_rtc_exit(void) 657 { 658 platform_driver_unregister(&s3c_rtc_driver); 659 } 660 661 module_init(s3c_rtc_init); 662 module_exit(s3c_rtc_exit); 663 664 MODULE_DESCRIPTION("Samsung S3C RTC Driver"); 665 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 666 MODULE_LICENSE("GPL"); 667 MODULE_ALIAS("platform:s3c2410-rtc"); 668