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