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