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