root/drivers/rtc/rtc-s3c.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. s3c_rtc_enable_clk
  2. s3c_rtc_disable_clk
  3. s3c_rtc_tickirq
  4. s3c_rtc_alarmirq
  5. s3c_rtc_setaie
  6. s3c_rtc_setfreq
  7. s3c_rtc_gettime
  8. s3c_rtc_settime
  9. s3c_rtc_getalarm
  10. s3c_rtc_setalarm
  11. s3c_rtc_proc
  12. s3c24xx_rtc_enable
  13. s3c24xx_rtc_disable
  14. s3c6410_rtc_disable
  15. s3c_rtc_remove
  16. s3c_rtc_probe
  17. s3c_rtc_suspend
  18. s3c_rtc_resume
  19. s3c24xx_rtc_irq
  20. s3c6410_rtc_irq
  21. s3c2410_rtc_setfreq
  22. s3c2416_rtc_setfreq
  23. s3c2443_rtc_setfreq
  24. s3c6410_rtc_setfreq
  25. s3c24xx_rtc_enable_tick
  26. s3c2416_rtc_select_tick_clk
  27. s3c6410_rtc_enable_tick
  28. s3c24xx_rtc_save_tick_cnt
  29. s3c24xx_rtc_restore_tick_cnt
  30. s3c6410_rtc_save_tick_cnt
  31. s3c6410_rtc_restore_tick_cnt

   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                 return info->irq_tick;
 458 
 459         info->dev = &pdev->dev;
 460         info->data = of_device_get_match_data(&pdev->dev);
 461         if (!info->data) {
 462                 dev_err(&pdev->dev, "failed getting s3c_rtc_data\n");
 463                 return -EINVAL;
 464         }
 465         spin_lock_init(&info->pie_lock);
 466         spin_lock_init(&info->alarm_lock);
 467 
 468         platform_set_drvdata(pdev, info);
 469 
 470         info->irq_alarm = platform_get_irq(pdev, 0);
 471         if (info->irq_alarm < 0)
 472                 return info->irq_alarm;
 473 
 474         dev_dbg(&pdev->dev, "s3c2410_rtc: tick irq %d, alarm irq %d\n",
 475                 info->irq_tick, info->irq_alarm);
 476 
 477         /* get the memory region */
 478         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 479         info->base = devm_ioremap_resource(&pdev->dev, res);
 480         if (IS_ERR(info->base))
 481                 return PTR_ERR(info->base);
 482 
 483         info->rtc_clk = devm_clk_get(&pdev->dev, "rtc");
 484         if (IS_ERR(info->rtc_clk)) {
 485                 ret = PTR_ERR(info->rtc_clk);
 486                 if (ret != -EPROBE_DEFER)
 487                         dev_err(&pdev->dev, "failed to find rtc clock\n");
 488                 else
 489                         dev_dbg(&pdev->dev, "probe deferred due to missing rtc clk\n");
 490                 return ret;
 491         }
 492         ret = clk_prepare_enable(info->rtc_clk);
 493         if (ret)
 494                 return ret;
 495 
 496         if (info->data->needs_src_clk) {
 497                 info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src");
 498                 if (IS_ERR(info->rtc_src_clk)) {
 499                         ret = PTR_ERR(info->rtc_src_clk);
 500                         if (ret != -EPROBE_DEFER)
 501                                 dev_err(&pdev->dev,
 502                                         "failed to find rtc source clock\n");
 503                         else
 504                                 dev_dbg(&pdev->dev,
 505                                         "probe deferred due to missing rtc src clk\n");
 506                         goto err_src_clk;
 507                 }
 508                 ret = clk_prepare_enable(info->rtc_src_clk);
 509                 if (ret)
 510                         goto err_src_clk;
 511         }
 512 
 513         /* check to see if everything is setup correctly */
 514         if (info->data->enable)
 515                 info->data->enable(info);
 516 
 517         dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n",
 518                 readw(info->base + S3C2410_RTCCON));
 519 
 520         device_init_wakeup(&pdev->dev, 1);
 521 
 522         /* Check RTC Time */
 523         if (s3c_rtc_gettime(&pdev->dev, &rtc_tm)) {
 524                 rtc_tm.tm_year  = 100;
 525                 rtc_tm.tm_mon   = 0;
 526                 rtc_tm.tm_mday  = 1;
 527                 rtc_tm.tm_hour  = 0;
 528                 rtc_tm.tm_min   = 0;
 529                 rtc_tm.tm_sec   = 0;
 530 
 531                 s3c_rtc_settime(&pdev->dev, &rtc_tm);
 532 
 533                 dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
 534         }
 535 
 536         /* register RTC and exit */
 537         info->rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops,
 538                                              THIS_MODULE);
 539         if (IS_ERR(info->rtc)) {
 540                 dev_err(&pdev->dev, "cannot attach rtc\n");
 541                 ret = PTR_ERR(info->rtc);
 542                 goto err_nortc;
 543         }
 544 
 545         ret = devm_request_irq(&pdev->dev, info->irq_alarm, s3c_rtc_alarmirq,
 546                                0, "s3c2410-rtc alarm", info);
 547         if (ret) {
 548                 dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_alarm, ret);
 549                 goto err_nortc;
 550         }
 551 
 552         ret = devm_request_irq(&pdev->dev, info->irq_tick, s3c_rtc_tickirq,
 553                                0, "s3c2410-rtc tick", info);
 554         if (ret) {
 555                 dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_tick, ret);
 556                 goto err_nortc;
 557         }
 558 
 559         if (info->data->select_tick_clk)
 560                 info->data->select_tick_clk(info);
 561 
 562         s3c_rtc_setfreq(info, 1);
 563 
 564         s3c_rtc_disable_clk(info);
 565 
 566         return 0;
 567 
 568 err_nortc:
 569         if (info->data->disable)
 570                 info->data->disable(info);
 571 
 572         if (info->data->needs_src_clk)
 573                 clk_disable_unprepare(info->rtc_src_clk);
 574 err_src_clk:
 575         clk_disable_unprepare(info->rtc_clk);
 576 
 577         return ret;
 578 }
 579 
 580 #ifdef CONFIG_PM_SLEEP
 581 
 582 static int s3c_rtc_suspend(struct device *dev)
 583 {
 584         struct s3c_rtc *info = dev_get_drvdata(dev);
 585         int ret;
 586 
 587         ret = s3c_rtc_enable_clk(info);
 588         if (ret)
 589                 return ret;
 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, info->base + S3C2410_RTCCON);
 751         }
 752 }
 753 
 754 static struct s3c_rtc_data const s3c2410_rtc_data = {
 755         .max_user_freq          = 128,
 756         .irq_handler            = s3c24xx_rtc_irq,
 757         .set_freq               = s3c2410_rtc_setfreq,
 758         .enable_tick            = s3c24xx_rtc_enable_tick,
 759         .save_tick_cnt          = s3c24xx_rtc_save_tick_cnt,
 760         .restore_tick_cnt       = s3c24xx_rtc_restore_tick_cnt,
 761         .enable                 = s3c24xx_rtc_enable,
 762         .disable                = s3c24xx_rtc_disable,
 763 };
 764 
 765 static struct s3c_rtc_data const s3c2416_rtc_data = {
 766         .max_user_freq          = 32768,
 767         .irq_handler            = s3c24xx_rtc_irq,
 768         .set_freq               = s3c2416_rtc_setfreq,
 769         .enable_tick            = s3c24xx_rtc_enable_tick,
 770         .select_tick_clk        = s3c2416_rtc_select_tick_clk,
 771         .save_tick_cnt          = s3c24xx_rtc_save_tick_cnt,
 772         .restore_tick_cnt       = s3c24xx_rtc_restore_tick_cnt,
 773         .enable                 = s3c24xx_rtc_enable,
 774         .disable                = s3c24xx_rtc_disable,
 775 };
 776 
 777 static struct s3c_rtc_data const s3c2443_rtc_data = {
 778         .max_user_freq          = 32768,
 779         .irq_handler            = s3c24xx_rtc_irq,
 780         .set_freq               = s3c2443_rtc_setfreq,
 781         .enable_tick            = s3c24xx_rtc_enable_tick,
 782         .select_tick_clk        = s3c2416_rtc_select_tick_clk,
 783         .save_tick_cnt          = s3c24xx_rtc_save_tick_cnt,
 784         .restore_tick_cnt       = s3c24xx_rtc_restore_tick_cnt,
 785         .enable                 = s3c24xx_rtc_enable,
 786         .disable                = s3c24xx_rtc_disable,
 787 };
 788 
 789 static struct s3c_rtc_data const s3c6410_rtc_data = {
 790         .max_user_freq          = 32768,
 791         .needs_src_clk          = true,
 792         .irq_handler            = s3c6410_rtc_irq,
 793         .set_freq               = s3c6410_rtc_setfreq,
 794         .enable_tick            = s3c6410_rtc_enable_tick,
 795         .save_tick_cnt          = s3c6410_rtc_save_tick_cnt,
 796         .restore_tick_cnt       = s3c6410_rtc_restore_tick_cnt,
 797         .enable                 = s3c24xx_rtc_enable,
 798         .disable                = s3c6410_rtc_disable,
 799 };
 800 
 801 static const struct of_device_id s3c_rtc_dt_match[] = {
 802         {
 803                 .compatible = "samsung,s3c2410-rtc",
 804                 .data = &s3c2410_rtc_data,
 805         }, {
 806                 .compatible = "samsung,s3c2416-rtc",
 807                 .data = &s3c2416_rtc_data,
 808         }, {
 809                 .compatible = "samsung,s3c2443-rtc",
 810                 .data = &s3c2443_rtc_data,
 811         }, {
 812                 .compatible = "samsung,s3c6410-rtc",
 813                 .data = &s3c6410_rtc_data,
 814         }, {
 815                 .compatible = "samsung,exynos3250-rtc",
 816                 .data = &s3c6410_rtc_data,
 817         },
 818         { /* sentinel */ },
 819 };
 820 MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
 821 
 822 static struct platform_driver s3c_rtc_driver = {
 823         .probe          = s3c_rtc_probe,
 824         .remove         = s3c_rtc_remove,
 825         .driver         = {
 826                 .name   = "s3c-rtc",
 827                 .pm     = &s3c_rtc_pm_ops,
 828                 .of_match_table = of_match_ptr(s3c_rtc_dt_match),
 829         },
 830 };
 831 module_platform_driver(s3c_rtc_driver);
 832 
 833 MODULE_DESCRIPTION("Samsung S3C RTC Driver");
 834 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 835 MODULE_LICENSE("GPL");
 836 MODULE_ALIAS("platform:s3c2410-rtc");

/* [<][>][^][v][top][bottom][index][help] */