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