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/uaccess.h> 27 #include <linux/io.h> 28 29 #include <asm/irq.h> 30 #include "rtc-s3c.h" 31 32 struct s3c_rtc { 33 struct device *dev; 34 struct rtc_device *rtc; 35 36 void __iomem *base; 37 struct clk *rtc_clk; 38 struct clk *rtc_src_clk; 39 bool alarm_enabled; 40 41 const struct s3c_rtc_data *data; 42 43 int irq_alarm; 44 spinlock_t alarm_lock; 45 46 bool wake_en; 47 }; 48 49 struct s3c_rtc_data { 50 bool needs_src_clk; 51 52 void (*irq_handler) (struct s3c_rtc *info, int mask); 53 void (*enable) (struct s3c_rtc *info); 54 void (*disable) (struct s3c_rtc *info); 55 }; 56 57 static int s3c_rtc_enable_clk(struct s3c_rtc *info) 58 { 59 int ret; 60 61 ret = clk_enable(info->rtc_clk); 62 if (ret) 63 return ret; 64 65 if (info->data->needs_src_clk) { 66 ret = clk_enable(info->rtc_src_clk); 67 if (ret) { 68 clk_disable(info->rtc_clk); 69 return ret; 70 } 71 } 72 return 0; 73 } 74 75 static void s3c_rtc_disable_clk(struct s3c_rtc *info) 76 { 77 if (info->data->needs_src_clk) 78 clk_disable(info->rtc_src_clk); 79 clk_disable(info->rtc_clk); 80 } 81 82 /* IRQ Handler */ 83 static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) 84 { 85 struct s3c_rtc *info = (struct s3c_rtc *)id; 86 87 if (info->data->irq_handler) 88 info->data->irq_handler(info, S3C2410_INTP_ALM); 89 90 return IRQ_HANDLED; 91 } 92 93 /* Update control registers */ 94 static int s3c_rtc_setaie(struct device *dev, unsigned int enabled) 95 { 96 struct s3c_rtc *info = dev_get_drvdata(dev); 97 unsigned long flags; 98 unsigned int tmp; 99 int ret; 100 101 dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled); 102 103 ret = s3c_rtc_enable_clk(info); 104 if (ret) 105 return ret; 106 107 tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; 108 109 if (enabled) 110 tmp |= S3C2410_RTCALM_ALMEN; 111 112 writeb(tmp, info->base + S3C2410_RTCALM); 113 114 spin_lock_irqsave(&info->alarm_lock, flags); 115 116 if (info->alarm_enabled && !enabled) 117 s3c_rtc_disable_clk(info); 118 else if (!info->alarm_enabled && enabled) 119 ret = s3c_rtc_enable_clk(info); 120 121 info->alarm_enabled = enabled; 122 spin_unlock_irqrestore(&info->alarm_lock, flags); 123 124 s3c_rtc_disable_clk(info); 125 126 return ret; 127 } 128 129 /* Read time from RTC and convert it from BCD */ 130 static int s3c_rtc_read_time(struct s3c_rtc *info, struct rtc_time *tm) 131 { 132 unsigned int have_retried = 0; 133 int ret; 134 135 ret = s3c_rtc_enable_clk(info); 136 if (ret) 137 return ret; 138 139 retry_get_time: 140 tm->tm_min = readb(info->base + S3C2410_RTCMIN); 141 tm->tm_hour = readb(info->base + S3C2410_RTCHOUR); 142 tm->tm_mday = readb(info->base + S3C2410_RTCDATE); 143 tm->tm_mon = readb(info->base + S3C2410_RTCMON); 144 tm->tm_year = readb(info->base + S3C2410_RTCYEAR); 145 tm->tm_sec = readb(info->base + S3C2410_RTCSEC); 146 147 /* 148 * The only way to work out whether the system was mid-update 149 * when we read it is to check the second counter, and if it 150 * is zero, then we re-try the entire read 151 */ 152 if (tm->tm_sec == 0 && !have_retried) { 153 have_retried = 1; 154 goto retry_get_time; 155 } 156 157 s3c_rtc_disable_clk(info); 158 159 tm->tm_sec = bcd2bin(tm->tm_sec); 160 tm->tm_min = bcd2bin(tm->tm_min); 161 tm->tm_hour = bcd2bin(tm->tm_hour); 162 tm->tm_mday = bcd2bin(tm->tm_mday); 163 tm->tm_mon = bcd2bin(tm->tm_mon); 164 tm->tm_year = bcd2bin(tm->tm_year); 165 166 return 0; 167 } 168 169 /* Convert time to BCD and write it to RTC */ 170 static int s3c_rtc_write_time(struct s3c_rtc *info, const struct rtc_time *tm) 171 { 172 int ret; 173 174 ret = s3c_rtc_enable_clk(info); 175 if (ret) 176 return ret; 177 178 writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_RTCSEC); 179 writeb(bin2bcd(tm->tm_min), info->base + S3C2410_RTCMIN); 180 writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_RTCHOUR); 181 writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_RTCDATE); 182 writeb(bin2bcd(tm->tm_mon), info->base + S3C2410_RTCMON); 183 writeb(bin2bcd(tm->tm_year), info->base + S3C2410_RTCYEAR); 184 185 s3c_rtc_disable_clk(info); 186 187 return 0; 188 } 189 190 static int s3c_rtc_gettime(struct device *dev, struct rtc_time *tm) 191 { 192 struct s3c_rtc *info = dev_get_drvdata(dev); 193 int ret; 194 195 ret = s3c_rtc_read_time(info, tm); 196 if (ret) 197 return ret; 198 199 /* Convert internal representation to actual date/time */ 200 tm->tm_year += 100; 201 tm->tm_mon -= 1; 202 203 dev_dbg(dev, "read time %ptR\n", tm); 204 return 0; 205 } 206 207 static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) 208 { 209 struct s3c_rtc *info = dev_get_drvdata(dev); 210 struct rtc_time rtc_tm = *tm; 211 212 dev_dbg(dev, "set time %ptR\n", tm); 213 214 /* 215 * Convert actual date/time to internal representation. 216 * We get around Y2K by simply not supporting it. 217 */ 218 rtc_tm.tm_year -= 100; 219 rtc_tm.tm_mon += 1; 220 221 return s3c_rtc_write_time(info, &rtc_tm); 222 } 223 224 static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) 225 { 226 struct s3c_rtc *info = dev_get_drvdata(dev); 227 struct rtc_time *alm_tm = &alrm->time; 228 unsigned int alm_en; 229 int ret; 230 231 ret = s3c_rtc_enable_clk(info); 232 if (ret) 233 return ret; 234 235 alm_tm->tm_sec = readb(info->base + S3C2410_ALMSEC); 236 alm_tm->tm_min = readb(info->base + S3C2410_ALMMIN); 237 alm_tm->tm_hour = readb(info->base + S3C2410_ALMHOUR); 238 alm_tm->tm_mon = readb(info->base + S3C2410_ALMMON); 239 alm_tm->tm_mday = readb(info->base + S3C2410_ALMDATE); 240 alm_tm->tm_year = readb(info->base + S3C2410_ALMYEAR); 241 242 alm_en = readb(info->base + S3C2410_RTCALM); 243 244 s3c_rtc_disable_clk(info); 245 246 alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; 247 248 dev_dbg(dev, "read alarm %d, %ptR\n", alm_en, alm_tm); 249 250 /* decode the alarm enable field */ 251 if (alm_en & S3C2410_RTCALM_SECEN) 252 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); 253 254 if (alm_en & S3C2410_RTCALM_MINEN) 255 alm_tm->tm_min = bcd2bin(alm_tm->tm_min); 256 257 if (alm_en & S3C2410_RTCALM_HOUREN) 258 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); 259 260 if (alm_en & S3C2410_RTCALM_DAYEN) 261 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); 262 263 if (alm_en & S3C2410_RTCALM_MONEN) { 264 alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); 265 alm_tm->tm_mon -= 1; 266 } 267 268 if (alm_en & S3C2410_RTCALM_YEAREN) 269 alm_tm->tm_year = bcd2bin(alm_tm->tm_year); 270 271 return 0; 272 } 273 274 static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) 275 { 276 struct s3c_rtc *info = dev_get_drvdata(dev); 277 struct rtc_time *tm = &alrm->time; 278 unsigned int alrm_en; 279 int ret; 280 281 dev_dbg(dev, "s3c_rtc_setalarm: %d, %ptR\n", alrm->enabled, tm); 282 283 ret = s3c_rtc_enable_clk(info); 284 if (ret) 285 return ret; 286 287 alrm_en = readb(info->base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; 288 writeb(0x00, info->base + S3C2410_RTCALM); 289 290 if (tm->tm_sec < 60 && tm->tm_sec >= 0) { 291 alrm_en |= S3C2410_RTCALM_SECEN; 292 writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_ALMSEC); 293 } 294 295 if (tm->tm_min < 60 && tm->tm_min >= 0) { 296 alrm_en |= S3C2410_RTCALM_MINEN; 297 writeb(bin2bcd(tm->tm_min), info->base + S3C2410_ALMMIN); 298 } 299 300 if (tm->tm_hour < 24 && tm->tm_hour >= 0) { 301 alrm_en |= S3C2410_RTCALM_HOUREN; 302 writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR); 303 } 304 305 if (tm->tm_mon < 12 && tm->tm_mon >= 0) { 306 alrm_en |= S3C2410_RTCALM_MONEN; 307 writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_ALMMON); 308 } 309 310 if (tm->tm_mday <= 31 && tm->tm_mday >= 1) { 311 alrm_en |= S3C2410_RTCALM_DAYEN; 312 writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_ALMDATE); 313 } 314 315 dev_dbg(dev, "setting S3C2410_RTCALM to %08x\n", alrm_en); 316 317 writeb(alrm_en, info->base + S3C2410_RTCALM); 318 319 s3c_rtc_setaie(dev, alrm->enabled); 320 321 s3c_rtc_disable_clk(info); 322 323 return 0; 324 } 325 326 static const struct rtc_class_ops s3c_rtcops = { 327 .read_time = s3c_rtc_gettime, 328 .set_time = s3c_rtc_settime, 329 .read_alarm = s3c_rtc_getalarm, 330 .set_alarm = s3c_rtc_setalarm, 331 .alarm_irq_enable = s3c_rtc_setaie, 332 }; 333 334 static void s3c6410_rtc_enable(struct s3c_rtc *info) 335 { 336 unsigned int con, tmp; 337 338 con = readw(info->base + S3C2410_RTCCON); 339 /* re-enable the device, and check it is ok */ 340 if ((con & S3C2410_RTCCON_RTCEN) == 0) { 341 dev_info(info->dev, "rtc disabled, re-enabling\n"); 342 343 tmp = readw(info->base + S3C2410_RTCCON); 344 writew(tmp | S3C2410_RTCCON_RTCEN, info->base + S3C2410_RTCCON); 345 } 346 347 if (con & S3C2410_RTCCON_CNTSEL) { 348 dev_info(info->dev, "removing RTCCON_CNTSEL\n"); 349 350 tmp = readw(info->base + S3C2410_RTCCON); 351 writew(tmp & ~S3C2410_RTCCON_CNTSEL, 352 info->base + S3C2410_RTCCON); 353 } 354 355 if (con & S3C2410_RTCCON_CLKRST) { 356 dev_info(info->dev, "removing RTCCON_CLKRST\n"); 357 358 tmp = readw(info->base + S3C2410_RTCCON); 359 writew(tmp & ~S3C2410_RTCCON_CLKRST, 360 info->base + S3C2410_RTCCON); 361 } 362 } 363 364 static void s3c6410_rtc_disable(struct s3c_rtc *info) 365 { 366 unsigned int con; 367 368 con = readw(info->base + S3C2410_RTCCON); 369 con &= ~S3C64XX_RTCCON_TICEN; 370 con &= ~S3C2410_RTCCON_RTCEN; 371 writew(con, info->base + S3C2410_RTCCON); 372 } 373 374 static void s3c_rtc_remove(struct platform_device *pdev) 375 { 376 struct s3c_rtc *info = platform_get_drvdata(pdev); 377 378 s3c_rtc_setaie(info->dev, 0); 379 380 if (info->data->needs_src_clk) 381 clk_unprepare(info->rtc_src_clk); 382 clk_unprepare(info->rtc_clk); 383 } 384 385 static int s3c_rtc_probe(struct platform_device *pdev) 386 { 387 struct s3c_rtc *info = NULL; 388 int ret; 389 390 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); 391 if (!info) 392 return -ENOMEM; 393 394 info->dev = &pdev->dev; 395 info->data = of_device_get_match_data(&pdev->dev); 396 if (!info->data) { 397 dev_err(&pdev->dev, "failed getting s3c_rtc_data\n"); 398 return -EINVAL; 399 } 400 spin_lock_init(&info->alarm_lock); 401 402 platform_set_drvdata(pdev, info); 403 404 info->irq_alarm = platform_get_irq(pdev, 0); 405 if (info->irq_alarm < 0) 406 return info->irq_alarm; 407 408 dev_dbg(&pdev->dev, "s3c2410_rtc: alarm irq %d\n", info->irq_alarm); 409 410 /* get the memory region */ 411 info->base = devm_platform_ioremap_resource(pdev, 0); 412 if (IS_ERR(info->base)) 413 return PTR_ERR(info->base); 414 415 info->rtc_clk = devm_clk_get(&pdev->dev, "rtc"); 416 if (IS_ERR(info->rtc_clk)) 417 return dev_err_probe(&pdev->dev, PTR_ERR(info->rtc_clk), 418 "failed to find rtc clock\n"); 419 ret = clk_prepare_enable(info->rtc_clk); 420 if (ret) 421 return ret; 422 423 if (info->data->needs_src_clk) { 424 info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src"); 425 if (IS_ERR(info->rtc_src_clk)) { 426 ret = dev_err_probe(&pdev->dev, PTR_ERR(info->rtc_src_clk), 427 "failed to find rtc source clock\n"); 428 goto err_src_clk; 429 } 430 ret = clk_prepare_enable(info->rtc_src_clk); 431 if (ret) 432 goto err_src_clk; 433 } 434 435 /* disable RTC enable bits potentially set by the bootloader */ 436 if (info->data->disable) 437 info->data->disable(info); 438 439 /* check to see if everything is setup correctly */ 440 if (info->data->enable) 441 info->data->enable(info); 442 443 dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n", 444 readw(info->base + S3C2410_RTCCON)); 445 446 device_init_wakeup(&pdev->dev, true); 447 448 info->rtc = devm_rtc_allocate_device(&pdev->dev); 449 if (IS_ERR(info->rtc)) { 450 ret = PTR_ERR(info->rtc); 451 goto err_nortc; 452 } 453 454 info->rtc->ops = &s3c_rtcops; 455 info->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; 456 info->rtc->range_max = RTC_TIMESTAMP_END_2099; 457 458 ret = devm_rtc_register_device(info->rtc); 459 if (ret) 460 goto err_nortc; 461 462 ret = devm_request_irq(&pdev->dev, info->irq_alarm, s3c_rtc_alarmirq, 463 0, "s3c2410-rtc alarm", info); 464 if (ret) { 465 dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_alarm, ret); 466 goto err_nortc; 467 } 468 469 s3c_rtc_disable_clk(info); 470 471 return 0; 472 473 err_nortc: 474 if (info->data->disable) 475 info->data->disable(info); 476 477 if (info->data->needs_src_clk) 478 clk_disable_unprepare(info->rtc_src_clk); 479 err_src_clk: 480 clk_disable_unprepare(info->rtc_clk); 481 482 return ret; 483 } 484 485 #ifdef CONFIG_PM_SLEEP 486 487 static int s3c_rtc_suspend(struct device *dev) 488 { 489 struct s3c_rtc *info = dev_get_drvdata(dev); 490 int ret; 491 492 ret = s3c_rtc_enable_clk(info); 493 if (ret) 494 return ret; 495 496 if (info->data->disable) 497 info->data->disable(info); 498 499 if (device_may_wakeup(dev) && !info->wake_en) { 500 if (enable_irq_wake(info->irq_alarm) == 0) 501 info->wake_en = true; 502 else 503 dev_err(dev, "enable_irq_wake failed\n"); 504 } 505 506 return 0; 507 } 508 509 static int s3c_rtc_resume(struct device *dev) 510 { 511 struct s3c_rtc *info = dev_get_drvdata(dev); 512 513 if (info->data->enable) 514 info->data->enable(info); 515 516 s3c_rtc_disable_clk(info); 517 518 if (device_may_wakeup(dev) && info->wake_en) { 519 disable_irq_wake(info->irq_alarm); 520 info->wake_en = false; 521 } 522 523 return 0; 524 } 525 #endif 526 static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume); 527 528 static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask) 529 { 530 rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); 531 writeb(mask, info->base + S3C2410_INTP); 532 } 533 534 static const struct s3c_rtc_data s3c6410_rtc_data = { 535 .needs_src_clk = true, 536 .irq_handler = s3c6410_rtc_irq, 537 .enable = s3c6410_rtc_enable, 538 .disable = s3c6410_rtc_disable, 539 }; 540 541 static const __maybe_unused struct of_device_id s3c_rtc_dt_match[] = { 542 { 543 .compatible = "samsung,s3c6410-rtc", 544 .data = &s3c6410_rtc_data, 545 }, { 546 .compatible = "samsung,exynos3250-rtc", 547 .data = &s3c6410_rtc_data, 548 }, 549 { /* sentinel */ }, 550 }; 551 MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match); 552 553 static struct platform_driver s3c_rtc_driver = { 554 .probe = s3c_rtc_probe, 555 .remove = s3c_rtc_remove, 556 .driver = { 557 .name = "s3c-rtc", 558 .pm = &s3c_rtc_pm_ops, 559 .of_match_table = of_match_ptr(s3c_rtc_dt_match), 560 }, 561 }; 562 module_platform_driver(s3c_rtc_driver); 563 564 MODULE_DESCRIPTION("Samsung S3C RTC Driver"); 565 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 566 MODULE_LICENSE("GPL"); 567