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