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