1 // SPDX-License-Identifier: GPL-2.0-only 2 /* drivers/rtc/rtc-s3c.c 3 * 4 * Copyright (c) 2010 Samsung Electronics Co., Ltd. 5 * http://www.samsung.com/ 6 * 7 * Copyright (c) 2004,2006 Simtec Electronics 8 * Ben Dooks, <ben@simtec.co.uk> 9 * http://armlinux.simtec.co.uk/ 10 * 11 * S3C2410/S3C2440/S3C24XX Internal RTC Driver 12 */ 13 14 #include <linux/module.h> 15 #include <linux/fs.h> 16 #include <linux/string.h> 17 #include <linux/init.h> 18 #include <linux/platform_device.h> 19 #include <linux/interrupt.h> 20 #include <linux/rtc.h> 21 #include <linux/bcd.h> 22 #include <linux/clk.h> 23 #include <linux/log2.h> 24 #include <linux/slab.h> 25 #include <linux/of.h> 26 #include <linux/of_device.h> 27 #include <linux/uaccess.h> 28 #include <linux/io.h> 29 30 #include <asm/irq.h> 31 #include "rtc-s3c.h" 32 33 struct s3c_rtc { 34 struct device *dev; 35 struct rtc_device *rtc; 36 37 void __iomem *base; 38 struct clk *rtc_clk; 39 struct clk *rtc_src_clk; 40 bool alarm_enabled; 41 42 const struct s3c_rtc_data *data; 43 44 int irq_alarm; 45 int irq_tick; 46 47 spinlock_t pie_lock; 48 spinlock_t alarm_lock; 49 50 int ticnt_save; 51 int ticnt_en_save; 52 bool wake_en; 53 }; 54 55 struct s3c_rtc_data { 56 int max_user_freq; 57 bool needs_src_clk; 58 59 void (*irq_handler) (struct s3c_rtc *info, int mask); 60 void (*set_freq) (struct s3c_rtc *info, int freq); 61 void (*enable_tick) (struct s3c_rtc *info, struct seq_file *seq); 62 void (*select_tick_clk) (struct s3c_rtc *info); 63 void (*save_tick_cnt) (struct s3c_rtc *info); 64 void (*restore_tick_cnt) (struct s3c_rtc *info); 65 void (*enable) (struct s3c_rtc *info); 66 void (*disable) (struct s3c_rtc *info); 67 }; 68 69 static int s3c_rtc_enable_clk(struct s3c_rtc *info) 70 { 71 int ret; 72 73 ret = clk_enable(info->rtc_clk); 74 if (ret) 75 return ret; 76 77 if (info->data->needs_src_clk) { 78 ret = clk_enable(info->rtc_src_clk); 79 if (ret) { 80 clk_disable(info->rtc_clk); 81 return ret; 82 } 83 } 84 return 0; 85 } 86 87 static void s3c_rtc_disable_clk(struct s3c_rtc *info) 88 { 89 if (info->data->needs_src_clk) 90 clk_disable(info->rtc_src_clk); 91 clk_disable(info->rtc_clk); 92 } 93 94 /* IRQ Handlers */ 95 static irqreturn_t s3c_rtc_tickirq(int irq, void *id) 96 { 97 struct s3c_rtc *info = (struct s3c_rtc *)id; 98 99 if (info->data->irq_handler) 100 info->data->irq_handler(info, S3C2410_INTP_TIC); 101 102 return IRQ_HANDLED; 103 } 104 105 static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) 106 { 107 struct s3c_rtc *info = (struct s3c_rtc *)id; 108 109 if (info->data->irq_handler) 110 info->data->irq_handler(info, S3C2410_INTP_ALM); 111 112 return IRQ_HANDLED; 113 } 114 115 /* Update control registers */ 116 static int s3c_rtc_setaie(struct device *dev, unsigned int enabled) 117 { 118 struct s3c_rtc *info = dev_get_drvdata(dev); 119 unsigned long flags; 120 unsigned int tmp; 121 int ret; 122 123 dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled); 124 125 ret = s3c_rtc_enable_clk(info); 126 if (ret) 127 return ret; 128 129 tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; 130 131 if (enabled) 132 tmp |= S3C2410_RTCALM_ALMEN; 133 134 writeb(tmp, info->base + S3C2410_RTCALM); 135 136 spin_lock_irqsave(&info->alarm_lock, flags); 137 138 if (info->alarm_enabled && !enabled) 139 s3c_rtc_disable_clk(info); 140 else if (!info->alarm_enabled && enabled) 141 ret = s3c_rtc_enable_clk(info); 142 143 info->alarm_enabled = enabled; 144 spin_unlock_irqrestore(&info->alarm_lock, flags); 145 146 s3c_rtc_disable_clk(info); 147 148 return ret; 149 } 150 151 /* Set RTC frequency */ 152 static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) 153 { 154 int ret; 155 156 if (!is_power_of_2(freq)) 157 return -EINVAL; 158 159 ret = s3c_rtc_enable_clk(info); 160 if (ret) 161 return ret; 162 spin_lock_irq(&info->pie_lock); 163 164 if (info->data->set_freq) 165 info->data->set_freq(info, freq); 166 167 spin_unlock_irq(&info->pie_lock); 168 s3c_rtc_disable_clk(info); 169 170 return 0; 171 } 172 173 /* Time read/write */ 174 static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) 175 { 176 struct s3c_rtc *info = dev_get_drvdata(dev); 177 unsigned int have_retried = 0; 178 int ret; 179 180 ret = s3c_rtc_enable_clk(info); 181 if (ret) 182 return ret; 183 184 retry_get_time: 185 rtc_tm->tm_min = readb(info->base + S3C2410_RTCMIN); 186 rtc_tm->tm_hour = readb(info->base + S3C2410_RTCHOUR); 187 rtc_tm->tm_mday = readb(info->base + S3C2410_RTCDATE); 188 rtc_tm->tm_mon = readb(info->base + S3C2410_RTCMON); 189 rtc_tm->tm_year = readb(info->base + S3C2410_RTCYEAR); 190 rtc_tm->tm_sec = readb(info->base + S3C2410_RTCSEC); 191 192 /* the only way to work out whether the system was mid-update 193 * when we read it is to check the second counter, and if it 194 * is zero, then we re-try the entire read 195 */ 196 197 if (rtc_tm->tm_sec == 0 && !have_retried) { 198 have_retried = 1; 199 goto retry_get_time; 200 } 201 202 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); 203 rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); 204 rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); 205 rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday); 206 rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon); 207 rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); 208 209 s3c_rtc_disable_clk(info); 210 211 rtc_tm->tm_year += 100; 212 rtc_tm->tm_mon -= 1; 213 214 dev_dbg(dev, "read time %ptR\n", rtc_tm); 215 return 0; 216 } 217 218 static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) 219 { 220 struct s3c_rtc *info = dev_get_drvdata(dev); 221 int year = tm->tm_year - 100; 222 int ret; 223 224 dev_dbg(dev, "set time %ptR\n", tm); 225 226 /* we get around y2k by simply not supporting it */ 227 228 if (year < 0 || year >= 100) { 229 dev_err(dev, "rtc only supports 100 years\n"); 230 return -EINVAL; 231 } 232 233 ret = s3c_rtc_enable_clk(info); 234 if (ret) 235 return ret; 236 237 writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_RTCSEC); 238 writeb(bin2bcd(tm->tm_min), info->base + S3C2410_RTCMIN); 239 writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_RTCHOUR); 240 writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_RTCDATE); 241 writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON); 242 writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR); 243 244 s3c_rtc_disable_clk(info); 245 246 return 0; 247 } 248 249 static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) 250 { 251 struct s3c_rtc *info = dev_get_drvdata(dev); 252 struct rtc_time *alm_tm = &alrm->time; 253 unsigned int alm_en; 254 int ret; 255 256 ret = s3c_rtc_enable_clk(info); 257 if (ret) 258 return ret; 259 260 alm_tm->tm_sec = readb(info->base + S3C2410_ALMSEC); 261 alm_tm->tm_min = readb(info->base + S3C2410_ALMMIN); 262 alm_tm->tm_hour = readb(info->base + S3C2410_ALMHOUR); 263 alm_tm->tm_mon = readb(info->base + S3C2410_ALMMON); 264 alm_tm->tm_mday = readb(info->base + S3C2410_ALMDATE); 265 alm_tm->tm_year = readb(info->base + S3C2410_ALMYEAR); 266 267 alm_en = readb(info->base + S3C2410_RTCALM); 268 269 s3c_rtc_disable_clk(info); 270 271 alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; 272 273 dev_dbg(dev, "read alarm %d, %ptR\n", alm_en, alm_tm); 274 275 /* decode the alarm enable field */ 276 if (alm_en & S3C2410_RTCALM_SECEN) 277 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); 278 279 if (alm_en & S3C2410_RTCALM_MINEN) 280 alm_tm->tm_min = bcd2bin(alm_tm->tm_min); 281 282 if (alm_en & S3C2410_RTCALM_HOUREN) 283 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); 284 285 if (alm_en & S3C2410_RTCALM_DAYEN) 286 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); 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 } 292 293 if (alm_en & S3C2410_RTCALM_YEAREN) 294 alm_tm->tm_year = bcd2bin(alm_tm->tm_year); 295 296 return 0; 297 } 298 299 static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) 300 { 301 struct s3c_rtc *info = dev_get_drvdata(dev); 302 struct rtc_time *tm = &alrm->time; 303 unsigned int alrm_en; 304 int ret; 305 306 dev_dbg(dev, "s3c_rtc_setalarm: %d, %ptR\n", alrm->enabled, tm); 307 308 ret = s3c_rtc_enable_clk(info); 309 if (ret) 310 return ret; 311 312 alrm_en = readb(info->base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; 313 writeb(0x00, info->base + S3C2410_RTCALM); 314 315 if (tm->tm_sec < 60 && tm->tm_sec >= 0) { 316 alrm_en |= S3C2410_RTCALM_SECEN; 317 writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_ALMSEC); 318 } 319 320 if (tm->tm_min < 60 && tm->tm_min >= 0) { 321 alrm_en |= S3C2410_RTCALM_MINEN; 322 writeb(bin2bcd(tm->tm_min), info->base + S3C2410_ALMMIN); 323 } 324 325 if (tm->tm_hour < 24 && tm->tm_hour >= 0) { 326 alrm_en |= S3C2410_RTCALM_HOUREN; 327 writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR); 328 } 329 330 if (tm->tm_mon < 12 && tm->tm_mon >= 0) { 331 alrm_en |= S3C2410_RTCALM_MONEN; 332 writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_ALMMON); 333 } 334 335 if (tm->tm_mday <= 31 && tm->tm_mday >= 1) { 336 alrm_en |= S3C2410_RTCALM_DAYEN; 337 writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_ALMDATE); 338 } 339 340 dev_dbg(dev, "setting S3C2410_RTCALM to %08x\n", alrm_en); 341 342 writeb(alrm_en, info->base + S3C2410_RTCALM); 343 344 s3c_rtc_setaie(dev, alrm->enabled); 345 346 s3c_rtc_disable_clk(info); 347 348 return 0; 349 } 350 351 static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) 352 { 353 struct s3c_rtc *info = dev_get_drvdata(dev); 354 int ret; 355 356 ret = s3c_rtc_enable_clk(info); 357 if (ret) 358 return ret; 359 360 if (info->data->enable_tick) 361 info->data->enable_tick(info, seq); 362 363 s3c_rtc_disable_clk(info); 364 365 return 0; 366 } 367 368 static const struct rtc_class_ops s3c_rtcops = { 369 .read_time = s3c_rtc_gettime, 370 .set_time = s3c_rtc_settime, 371 .read_alarm = s3c_rtc_getalarm, 372 .set_alarm = s3c_rtc_setalarm, 373 .proc = s3c_rtc_proc, 374 .alarm_irq_enable = s3c_rtc_setaie, 375 }; 376 377 static void s3c24xx_rtc_enable(struct s3c_rtc *info) 378 { 379 unsigned int con, tmp; 380 381 con = readw(info->base + S3C2410_RTCCON); 382 /* re-enable the device, and check it is ok */ 383 if ((con & S3C2410_RTCCON_RTCEN) == 0) { 384 dev_info(info->dev, "rtc disabled, re-enabling\n"); 385 386 tmp = readw(info->base + S3C2410_RTCCON); 387 writew(tmp | S3C2410_RTCCON_RTCEN, info->base + S3C2410_RTCCON); 388 } 389 390 if (con & S3C2410_RTCCON_CNTSEL) { 391 dev_info(info->dev, "removing RTCCON_CNTSEL\n"); 392 393 tmp = readw(info->base + S3C2410_RTCCON); 394 writew(tmp & ~S3C2410_RTCCON_CNTSEL, 395 info->base + S3C2410_RTCCON); 396 } 397 398 if (con & S3C2410_RTCCON_CLKRST) { 399 dev_info(info->dev, "removing RTCCON_CLKRST\n"); 400 401 tmp = readw(info->base + S3C2410_RTCCON); 402 writew(tmp & ~S3C2410_RTCCON_CLKRST, 403 info->base + S3C2410_RTCCON); 404 } 405 } 406 407 static void s3c24xx_rtc_disable(struct s3c_rtc *info) 408 { 409 unsigned int con; 410 411 con = readw(info->base + S3C2410_RTCCON); 412 con &= ~S3C2410_RTCCON_RTCEN; 413 writew(con, info->base + S3C2410_RTCCON); 414 415 con = readb(info->base + S3C2410_TICNT); 416 con &= ~S3C2410_TICNT_ENABLE; 417 writeb(con, info->base + S3C2410_TICNT); 418 } 419 420 static void s3c6410_rtc_disable(struct s3c_rtc *info) 421 { 422 unsigned int con; 423 424 con = readw(info->base + S3C2410_RTCCON); 425 con &= ~S3C64XX_RTCCON_TICEN; 426 con &= ~S3C2410_RTCCON_RTCEN; 427 writew(con, info->base + S3C2410_RTCCON); 428 } 429 430 static int s3c_rtc_remove(struct platform_device *pdev) 431 { 432 struct s3c_rtc *info = platform_get_drvdata(pdev); 433 434 s3c_rtc_setaie(info->dev, 0); 435 436 if (info->data->needs_src_clk) 437 clk_unprepare(info->rtc_src_clk); 438 clk_unprepare(info->rtc_clk); 439 440 return 0; 441 } 442 443 static int s3c_rtc_probe(struct platform_device *pdev) 444 { 445 struct s3c_rtc *info = NULL; 446 struct rtc_time rtc_tm; 447 struct resource *res; 448 int ret; 449 450 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); 451 if (!info) 452 return -ENOMEM; 453 454 /* find the IRQs */ 455 info->irq_tick = platform_get_irq(pdev, 1); 456 if (info->irq_tick < 0) { 457 dev_err(&pdev->dev, "no irq for rtc tick\n"); 458 return info->irq_tick; 459 } 460 461 info->dev = &pdev->dev; 462 info->data = of_device_get_match_data(&pdev->dev); 463 if (!info->data) { 464 dev_err(&pdev->dev, "failed getting s3c_rtc_data\n"); 465 return -EINVAL; 466 } 467 spin_lock_init(&info->pie_lock); 468 spin_lock_init(&info->alarm_lock); 469 470 platform_set_drvdata(pdev, info); 471 472 info->irq_alarm = platform_get_irq(pdev, 0); 473 if (info->irq_alarm < 0) { 474 dev_err(&pdev->dev, "no irq for alarm\n"); 475 return info->irq_alarm; 476 } 477 478 dev_dbg(&pdev->dev, "s3c2410_rtc: tick irq %d, alarm irq %d\n", 479 info->irq_tick, info->irq_alarm); 480 481 /* get the memory region */ 482 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 483 info->base = devm_ioremap_resource(&pdev->dev, res); 484 if (IS_ERR(info->base)) 485 return PTR_ERR(info->base); 486 487 info->rtc_clk = devm_clk_get(&pdev->dev, "rtc"); 488 if (IS_ERR(info->rtc_clk)) { 489 ret = PTR_ERR(info->rtc_clk); 490 if (ret != -EPROBE_DEFER) 491 dev_err(&pdev->dev, "failed to find rtc clock\n"); 492 else 493 dev_dbg(&pdev->dev, "probe deferred due to missing rtc clk\n"); 494 return ret; 495 } 496 ret = clk_prepare_enable(info->rtc_clk); 497 if (ret) 498 return ret; 499 500 if (info->data->needs_src_clk) { 501 info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src"); 502 if (IS_ERR(info->rtc_src_clk)) { 503 ret = PTR_ERR(info->rtc_src_clk); 504 if (ret != -EPROBE_DEFER) 505 dev_err(&pdev->dev, 506 "failed to find rtc source clock\n"); 507 else 508 dev_dbg(&pdev->dev, 509 "probe deferred due to missing rtc src clk\n"); 510 goto err_src_clk; 511 } 512 ret = clk_prepare_enable(info->rtc_src_clk); 513 if (ret) 514 goto err_src_clk; 515 } 516 517 /* check to see if everything is setup correctly */ 518 if (info->data->enable) 519 info->data->enable(info); 520 521 dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n", 522 readw(info->base + S3C2410_RTCCON)); 523 524 device_init_wakeup(&pdev->dev, 1); 525 526 /* Check RTC Time */ 527 if (s3c_rtc_gettime(&pdev->dev, &rtc_tm)) { 528 rtc_tm.tm_year = 100; 529 rtc_tm.tm_mon = 0; 530 rtc_tm.tm_mday = 1; 531 rtc_tm.tm_hour = 0; 532 rtc_tm.tm_min = 0; 533 rtc_tm.tm_sec = 0; 534 535 s3c_rtc_settime(&pdev->dev, &rtc_tm); 536 537 dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); 538 } 539 540 /* register RTC and exit */ 541 info->rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops, 542 THIS_MODULE); 543 if (IS_ERR(info->rtc)) { 544 dev_err(&pdev->dev, "cannot attach rtc\n"); 545 ret = PTR_ERR(info->rtc); 546 goto err_nortc; 547 } 548 549 ret = devm_request_irq(&pdev->dev, info->irq_alarm, s3c_rtc_alarmirq, 550 0, "s3c2410-rtc alarm", info); 551 if (ret) { 552 dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_alarm, ret); 553 goto err_nortc; 554 } 555 556 ret = devm_request_irq(&pdev->dev, info->irq_tick, s3c_rtc_tickirq, 557 0, "s3c2410-rtc tick", info); 558 if (ret) { 559 dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_tick, ret); 560 goto err_nortc; 561 } 562 563 if (info->data->select_tick_clk) 564 info->data->select_tick_clk(info); 565 566 s3c_rtc_setfreq(info, 1); 567 568 s3c_rtc_disable_clk(info); 569 570 return 0; 571 572 err_nortc: 573 if (info->data->disable) 574 info->data->disable(info); 575 576 if (info->data->needs_src_clk) 577 clk_disable_unprepare(info->rtc_src_clk); 578 err_src_clk: 579 clk_disable_unprepare(info->rtc_clk); 580 581 return ret; 582 } 583 584 #ifdef CONFIG_PM_SLEEP 585 586 static int s3c_rtc_suspend(struct device *dev) 587 { 588 struct s3c_rtc *info = dev_get_drvdata(dev); 589 int ret; 590 591 ret = s3c_rtc_enable_clk(info); 592 if (ret) 593 return ret; 594 595 /* save TICNT for anyone using periodic interrupts */ 596 if (info->data->save_tick_cnt) 597 info->data->save_tick_cnt(info); 598 599 if (info->data->disable) 600 info->data->disable(info); 601 602 if (device_may_wakeup(dev) && !info->wake_en) { 603 if (enable_irq_wake(info->irq_alarm) == 0) 604 info->wake_en = true; 605 else 606 dev_err(dev, "enable_irq_wake failed\n"); 607 } 608 609 return 0; 610 } 611 612 static int s3c_rtc_resume(struct device *dev) 613 { 614 struct s3c_rtc *info = dev_get_drvdata(dev); 615 616 if (info->data->enable) 617 info->data->enable(info); 618 619 if (info->data->restore_tick_cnt) 620 info->data->restore_tick_cnt(info); 621 622 s3c_rtc_disable_clk(info); 623 624 if (device_may_wakeup(dev) && info->wake_en) { 625 disable_irq_wake(info->irq_alarm); 626 info->wake_en = false; 627 } 628 629 return 0; 630 } 631 #endif 632 static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume); 633 634 static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask) 635 { 636 rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); 637 } 638 639 static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask) 640 { 641 rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); 642 writeb(mask, info->base + S3C2410_INTP); 643 } 644 645 static void s3c2410_rtc_setfreq(struct s3c_rtc *info, int freq) 646 { 647 unsigned int tmp = 0; 648 int val; 649 650 tmp = readb(info->base + S3C2410_TICNT); 651 tmp &= S3C2410_TICNT_ENABLE; 652 653 val = (info->rtc->max_user_freq / freq) - 1; 654 tmp |= val; 655 656 writel(tmp, info->base + S3C2410_TICNT); 657 } 658 659 static void s3c2416_rtc_setfreq(struct s3c_rtc *info, int freq) 660 { 661 unsigned int tmp = 0; 662 int val; 663 664 tmp = readb(info->base + S3C2410_TICNT); 665 tmp &= S3C2410_TICNT_ENABLE; 666 667 val = (info->rtc->max_user_freq / freq) - 1; 668 669 tmp |= S3C2443_TICNT_PART(val); 670 writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1); 671 672 writel(S3C2416_TICNT2_PART(val), info->base + S3C2416_TICNT2); 673 674 writel(tmp, info->base + S3C2410_TICNT); 675 } 676 677 static void s3c2443_rtc_setfreq(struct s3c_rtc *info, int freq) 678 { 679 unsigned int tmp = 0; 680 int val; 681 682 tmp = readb(info->base + S3C2410_TICNT); 683 tmp &= S3C2410_TICNT_ENABLE; 684 685 val = (info->rtc->max_user_freq / freq) - 1; 686 687 tmp |= S3C2443_TICNT_PART(val); 688 writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1); 689 690 writel(tmp, info->base + S3C2410_TICNT); 691 } 692 693 static void s3c6410_rtc_setfreq(struct s3c_rtc *info, int freq) 694 { 695 int val; 696 697 val = (info->rtc->max_user_freq / freq) - 1; 698 writel(val, info->base + S3C2410_TICNT); 699 } 700 701 static void s3c24xx_rtc_enable_tick(struct s3c_rtc *info, struct seq_file *seq) 702 { 703 unsigned int ticnt; 704 705 ticnt = readb(info->base + S3C2410_TICNT); 706 ticnt &= S3C2410_TICNT_ENABLE; 707 708 seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); 709 } 710 711 static void s3c2416_rtc_select_tick_clk(struct s3c_rtc *info) 712 { 713 unsigned int con; 714 715 con = readw(info->base + S3C2410_RTCCON); 716 con |= S3C2443_RTCCON_TICSEL; 717 writew(con, info->base + S3C2410_RTCCON); 718 } 719 720 static void s3c6410_rtc_enable_tick(struct s3c_rtc *info, struct seq_file *seq) 721 { 722 unsigned int ticnt; 723 724 ticnt = readw(info->base + S3C2410_RTCCON); 725 ticnt &= S3C64XX_RTCCON_TICEN; 726 727 seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); 728 } 729 730 static void s3c24xx_rtc_save_tick_cnt(struct s3c_rtc *info) 731 { 732 info->ticnt_save = readb(info->base + S3C2410_TICNT); 733 } 734 735 static void s3c24xx_rtc_restore_tick_cnt(struct s3c_rtc *info) 736 { 737 writeb(info->ticnt_save, info->base + S3C2410_TICNT); 738 } 739 740 static void s3c6410_rtc_save_tick_cnt(struct s3c_rtc *info) 741 { 742 info->ticnt_en_save = readw(info->base + S3C2410_RTCCON); 743 info->ticnt_en_save &= S3C64XX_RTCCON_TICEN; 744 info->ticnt_save = readl(info->base + S3C2410_TICNT); 745 } 746 747 static void s3c6410_rtc_restore_tick_cnt(struct s3c_rtc *info) 748 { 749 unsigned int con; 750 751 writel(info->ticnt_save, info->base + S3C2410_TICNT); 752 if (info->ticnt_en_save) { 753 con = readw(info->base + S3C2410_RTCCON); 754 writew(con | info->ticnt_en_save, info->base + S3C2410_RTCCON); 755 } 756 } 757 758 static struct s3c_rtc_data const s3c2410_rtc_data = { 759 .max_user_freq = 128, 760 .irq_handler = s3c24xx_rtc_irq, 761 .set_freq = s3c2410_rtc_setfreq, 762 .enable_tick = s3c24xx_rtc_enable_tick, 763 .save_tick_cnt = s3c24xx_rtc_save_tick_cnt, 764 .restore_tick_cnt = s3c24xx_rtc_restore_tick_cnt, 765 .enable = s3c24xx_rtc_enable, 766 .disable = s3c24xx_rtc_disable, 767 }; 768 769 static struct s3c_rtc_data const s3c2416_rtc_data = { 770 .max_user_freq = 32768, 771 .irq_handler = s3c24xx_rtc_irq, 772 .set_freq = s3c2416_rtc_setfreq, 773 .enable_tick = s3c24xx_rtc_enable_tick, 774 .select_tick_clk = s3c2416_rtc_select_tick_clk, 775 .save_tick_cnt = s3c24xx_rtc_save_tick_cnt, 776 .restore_tick_cnt = s3c24xx_rtc_restore_tick_cnt, 777 .enable = s3c24xx_rtc_enable, 778 .disable = s3c24xx_rtc_disable, 779 }; 780 781 static struct s3c_rtc_data const s3c2443_rtc_data = { 782 .max_user_freq = 32768, 783 .irq_handler = s3c24xx_rtc_irq, 784 .set_freq = s3c2443_rtc_setfreq, 785 .enable_tick = s3c24xx_rtc_enable_tick, 786 .select_tick_clk = s3c2416_rtc_select_tick_clk, 787 .save_tick_cnt = s3c24xx_rtc_save_tick_cnt, 788 .restore_tick_cnt = s3c24xx_rtc_restore_tick_cnt, 789 .enable = s3c24xx_rtc_enable, 790 .disable = s3c24xx_rtc_disable, 791 }; 792 793 static struct s3c_rtc_data const s3c6410_rtc_data = { 794 .max_user_freq = 32768, 795 .needs_src_clk = true, 796 .irq_handler = s3c6410_rtc_irq, 797 .set_freq = s3c6410_rtc_setfreq, 798 .enable_tick = s3c6410_rtc_enable_tick, 799 .save_tick_cnt = s3c6410_rtc_save_tick_cnt, 800 .restore_tick_cnt = s3c6410_rtc_restore_tick_cnt, 801 .enable = s3c24xx_rtc_enable, 802 .disable = s3c6410_rtc_disable, 803 }; 804 805 static const struct of_device_id s3c_rtc_dt_match[] = { 806 { 807 .compatible = "samsung,s3c2410-rtc", 808 .data = &s3c2410_rtc_data, 809 }, { 810 .compatible = "samsung,s3c2416-rtc", 811 .data = &s3c2416_rtc_data, 812 }, { 813 .compatible = "samsung,s3c2443-rtc", 814 .data = &s3c2443_rtc_data, 815 }, { 816 .compatible = "samsung,s3c6410-rtc", 817 .data = &s3c6410_rtc_data, 818 }, { 819 .compatible = "samsung,exynos3250-rtc", 820 .data = &s3c6410_rtc_data, 821 }, 822 { /* sentinel */ }, 823 }; 824 MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match); 825 826 static struct platform_driver s3c_rtc_driver = { 827 .probe = s3c_rtc_probe, 828 .remove = s3c_rtc_remove, 829 .driver = { 830 .name = "s3c-rtc", 831 .pm = &s3c_rtc_pm_ops, 832 .of_match_table = of_match_ptr(s3c_rtc_dt_match), 833 }, 834 }; 835 module_platform_driver(s3c_rtc_driver); 836 837 MODULE_DESCRIPTION("Samsung S3C RTC Driver"); 838 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 839 MODULE_LICENSE("GPL"); 840 MODULE_ALIAS("platform:s3c2410-rtc"); 841