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