aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-s3c.c93
1 files changed, 92 insertions, 1 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 0d9089228bb0..a6b1252c9941 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -38,6 +38,7 @@ struct s3c_rtc {
38 38
39 void __iomem *base; 39 void __iomem *base;
40 struct clk *rtc_clk; 40 struct clk *rtc_clk;
41 struct clk *rtc_src_clk;
41 bool enabled; 42 bool enabled;
42 43
43 struct s3c_rtc_data *data; 44 struct s3c_rtc_data *data;
@@ -54,6 +55,7 @@ struct s3c_rtc {
54 55
55struct s3c_rtc_data { 56struct s3c_rtc_data {
56 int max_user_freq; 57 int max_user_freq;
58 bool needs_src_clk;
57 59
58 void (*irq_handler) (struct s3c_rtc *info, int mask); 60 void (*irq_handler) (struct s3c_rtc *info, int mask);
59 void (*set_freq) (struct s3c_rtc *info, int freq); 61 void (*set_freq) (struct s3c_rtc *info, int freq);
@@ -73,10 +75,14 @@ static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable)
73 if (enable) { 75 if (enable) {
74 if (!info->enabled) { 76 if (!info->enabled) {
75 clk_enable(info->rtc_clk); 77 clk_enable(info->rtc_clk);
78 if (info->data->needs_src_clk)
79 clk_enable(info->rtc_src_clk);
76 info->enabled = true; 80 info->enabled = true;
77 } 81 }
78 } else { 82 } else {
79 if (info->enabled) { 83 if (info->enabled) {
84 if (info->data->needs_src_clk)
85 clk_disable(info->rtc_src_clk);
80 clk_disable(info->rtc_clk); 86 clk_disable(info->rtc_clk);
81 info->enabled = false; 87 info->enabled = false;
82 } 88 }
@@ -114,12 +120,16 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
114 dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled); 120 dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled);
115 121
116 clk_enable(info->rtc_clk); 122 clk_enable(info->rtc_clk);
123 if (info->data->needs_src_clk)
124 clk_enable(info->rtc_src_clk);
117 tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; 125 tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
118 126
119 if (enabled) 127 if (enabled)
120 tmp |= S3C2410_RTCALM_ALMEN; 128 tmp |= S3C2410_RTCALM_ALMEN;
121 129
122 writeb(tmp, info->base + S3C2410_RTCALM); 130 writeb(tmp, info->base + S3C2410_RTCALM);
131 if (info->data->needs_src_clk)
132 clk_disable(info->rtc_src_clk);
123 clk_disable(info->rtc_clk); 133 clk_disable(info->rtc_clk);
124 134
125 s3c_rtc_alarm_clk_enable(info, enabled); 135 s3c_rtc_alarm_clk_enable(info, enabled);
@@ -134,12 +144,16 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
134 return -EINVAL; 144 return -EINVAL;
135 145
136 clk_enable(info->rtc_clk); 146 clk_enable(info->rtc_clk);
147 if (info->data->needs_src_clk)
148 clk_enable(info->rtc_src_clk);
137 spin_lock_irq(&info->pie_lock); 149 spin_lock_irq(&info->pie_lock);
138 150
139 if (info->data->set_freq) 151 if (info->data->set_freq)
140 info->data->set_freq(info, freq); 152 info->data->set_freq(info, freq);
141 153
142 spin_unlock_irq(&info->pie_lock); 154 spin_unlock_irq(&info->pie_lock);
155 if (info->data->needs_src_clk)
156 clk_disable(info->rtc_src_clk);
143 clk_disable(info->rtc_clk); 157 clk_disable(info->rtc_clk);
144 158
145 return 0; 159 return 0;
@@ -152,6 +166,9 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
152 unsigned int have_retried = 0; 166 unsigned int have_retried = 0;
153 167
154 clk_enable(info->rtc_clk); 168 clk_enable(info->rtc_clk);
169 if (info->data->needs_src_clk)
170 clk_enable(info->rtc_src_clk);
171
155 retry_get_time: 172 retry_get_time:
156 rtc_tm->tm_min = readb(info->base + S3C2410_RTCMIN); 173 rtc_tm->tm_min = readb(info->base + S3C2410_RTCMIN);
157 rtc_tm->tm_hour = readb(info->base + S3C2410_RTCHOUR); 174 rtc_tm->tm_hour = readb(info->base + S3C2410_RTCHOUR);
@@ -185,6 +202,8 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
185 202
186 rtc_tm->tm_mon -= 1; 203 rtc_tm->tm_mon -= 1;
187 204
205 if (info->data->needs_src_clk)
206 clk_disable(info->rtc_src_clk);
188 clk_disable(info->rtc_clk); 207 clk_disable(info->rtc_clk);
189 208
190 return rtc_valid_tm(rtc_tm); 209 return rtc_valid_tm(rtc_tm);
@@ -207,6 +226,8 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
207 } 226 }
208 227
209 clk_enable(info->rtc_clk); 228 clk_enable(info->rtc_clk);
229 if (info->data->needs_src_clk)
230 clk_enable(info->rtc_src_clk);
210 231
211 writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_RTCSEC); 232 writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_RTCSEC);
212 writeb(bin2bcd(tm->tm_min), info->base + S3C2410_RTCMIN); 233 writeb(bin2bcd(tm->tm_min), info->base + S3C2410_RTCMIN);
@@ -215,6 +236,8 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
215 writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON); 236 writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON);
216 writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR); 237 writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR);
217 238
239 if (info->data->needs_src_clk)
240 clk_disable(info->rtc_src_clk);
218 clk_disable(info->rtc_clk); 241 clk_disable(info->rtc_clk);
219 242
220 return 0; 243 return 0;
@@ -227,6 +250,9 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
227 unsigned int alm_en; 250 unsigned int alm_en;
228 251
229 clk_enable(info->rtc_clk); 252 clk_enable(info->rtc_clk);
253 if (info->data->needs_src_clk)
254 clk_enable(info->rtc_src_clk);
255
230 alm_tm->tm_sec = readb(info->base + S3C2410_ALMSEC); 256 alm_tm->tm_sec = readb(info->base + S3C2410_ALMSEC);
231 alm_tm->tm_min = readb(info->base + S3C2410_ALMMIN); 257 alm_tm->tm_min = readb(info->base + S3C2410_ALMMIN);
232 alm_tm->tm_hour = readb(info->base + S3C2410_ALMHOUR); 258 alm_tm->tm_hour = readb(info->base + S3C2410_ALMHOUR);
@@ -278,7 +304,10 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
278 else 304 else
279 alm_tm->tm_year = -1; 305 alm_tm->tm_year = -1;
280 306
307 if (info->data->needs_src_clk)
308 clk_disable(info->rtc_src_clk);
281 clk_disable(info->rtc_clk); 309 clk_disable(info->rtc_clk);
310
282 return 0; 311 return 0;
283} 312}
284 313
@@ -289,6 +318,9 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
289 unsigned int alrm_en; 318 unsigned int alrm_en;
290 319
291 clk_enable(info->rtc_clk); 320 clk_enable(info->rtc_clk);
321 if (info->data->needs_src_clk)
322 clk_enable(info->rtc_src_clk);
323
292 dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", 324 dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
293 alrm->enabled, 325 alrm->enabled,
294 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, 326 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
@@ -318,6 +350,8 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
318 350
319 s3c_rtc_setaie(dev, alrm->enabled); 351 s3c_rtc_setaie(dev, alrm->enabled);
320 352
353 if (info->data->needs_src_clk)
354 clk_disable(info->rtc_src_clk);
321 clk_disable(info->rtc_clk); 355 clk_disable(info->rtc_clk);
322 356
323 return 0; 357 return 0;
@@ -328,10 +362,14 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
328 struct s3c_rtc *info = dev_get_drvdata(dev); 362 struct s3c_rtc *info = dev_get_drvdata(dev);
329 363
330 clk_enable(info->rtc_clk); 364 clk_enable(info->rtc_clk);
365 if (info->data->needs_src_clk)
366 clk_enable(info->rtc_src_clk);
331 367
332 if (info->data->enable_tick) 368 if (info->data->enable_tick)
333 info->data->enable_tick(info, seq); 369 info->data->enable_tick(info, seq);
334 370
371 if (info->data->needs_src_clk)
372 clk_disable(info->rtc_src_clk);
335 clk_disable(info->rtc_clk); 373 clk_disable(info->rtc_clk);
336 374
337 return 0; 375 return 0;
@@ -351,6 +389,8 @@ static void s3c24xx_rtc_enable(struct s3c_rtc *info)
351 unsigned int con, tmp; 389 unsigned int con, tmp;
352 390
353 clk_enable(info->rtc_clk); 391 clk_enable(info->rtc_clk);
392 if (info->data->needs_src_clk)
393 clk_enable(info->rtc_src_clk);
354 394
355 con = readw(info->base + S3C2410_RTCCON); 395 con = readw(info->base + S3C2410_RTCCON);
356 /* re-enable the device, and check it is ok */ 396 /* re-enable the device, and check it is ok */
@@ -378,6 +418,8 @@ static void s3c24xx_rtc_enable(struct s3c_rtc *info)
378 info->base + S3C2410_RTCCON); 418 info->base + S3C2410_RTCCON);
379 } 419 }
380 420
421 if (info->data->needs_src_clk)
422 clk_disable(info->rtc_src_clk);
381 clk_disable(info->rtc_clk); 423 clk_disable(info->rtc_clk);
382} 424}
383 425
@@ -386,6 +428,8 @@ static void s3c24xx_rtc_disable(struct s3c_rtc *info)
386 unsigned int con; 428 unsigned int con;
387 429
388 clk_enable(info->rtc_clk); 430 clk_enable(info->rtc_clk);
431 if (info->data->needs_src_clk)
432 clk_enable(info->rtc_src_clk);
389 433
390 con = readw(info->base + S3C2410_RTCCON); 434 con = readw(info->base + S3C2410_RTCCON);
391 con &= ~S3C2410_RTCCON_RTCEN; 435 con &= ~S3C2410_RTCCON_RTCEN;
@@ -395,6 +439,8 @@ static void s3c24xx_rtc_disable(struct s3c_rtc *info)
395 con &= ~S3C2410_TICNT_ENABLE; 439 con &= ~S3C2410_TICNT_ENABLE;
396 writeb(con, info->base + S3C2410_TICNT); 440 writeb(con, info->base + S3C2410_TICNT);
397 441
442 if (info->data->needs_src_clk)
443 clk_disable(info->rtc_src_clk);
398 clk_disable(info->rtc_clk); 444 clk_disable(info->rtc_clk);
399} 445}
400 446
@@ -403,12 +449,16 @@ static void s3c6410_rtc_disable(struct s3c_rtc *info)
403 unsigned int con; 449 unsigned int con;
404 450
405 clk_enable(info->rtc_clk); 451 clk_enable(info->rtc_clk);
452 if (info->data->needs_src_clk)
453 clk_enable(info->rtc_src_clk);
406 454
407 con = readw(info->base + S3C2410_RTCCON); 455 con = readw(info->base + S3C2410_RTCCON);
408 con &= ~S3C64XX_RTCCON_TICEN; 456 con &= ~S3C64XX_RTCCON_TICEN;
409 con &= ~S3C2410_RTCCON_RTCEN; 457 con &= ~S3C2410_RTCCON_RTCEN;
410 writew(con, info->base + S3C2410_RTCCON); 458 writew(con, info->base + S3C2410_RTCCON);
411 459
460 if (info->data->needs_src_clk)
461 clk_disable(info->rtc_src_clk);
412 clk_disable(info->rtc_clk); 462 clk_disable(info->rtc_clk);
413} 463}
414 464
@@ -480,11 +530,19 @@ static int s3c_rtc_probe(struct platform_device *pdev)
480 530
481 info->rtc_clk = devm_clk_get(&pdev->dev, "rtc"); 531 info->rtc_clk = devm_clk_get(&pdev->dev, "rtc");
482 if (IS_ERR(info->rtc_clk)) { 532 if (IS_ERR(info->rtc_clk)) {
483 dev_err(&pdev->dev, "failed to find rtc clock source\n"); 533 dev_err(&pdev->dev, "failed to find rtc clock\n");
484 return PTR_ERR(info->rtc_clk); 534 return PTR_ERR(info->rtc_clk);
485 } 535 }
486 clk_prepare_enable(info->rtc_clk); 536 clk_prepare_enable(info->rtc_clk);
487 537
538 info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src");
539 if (IS_ERR(info->rtc_src_clk)) {
540 dev_err(&pdev->dev, "failed to find rtc source clock\n");
541 return PTR_ERR(info->rtc_src_clk);
542 }
543 clk_prepare_enable(info->rtc_src_clk);
544
545
488 /* check to see if everything is setup correctly */ 546 /* check to see if everything is setup correctly */
489 if (info->data->enable) 547 if (info->data->enable)
490 info->data->enable(info); 548 info->data->enable(info);
@@ -538,6 +596,8 @@ static int s3c_rtc_probe(struct platform_device *pdev)
538 596
539 s3c_rtc_setfreq(info, 1); 597 s3c_rtc_setfreq(info, 1);
540 598
599 if (info->data->needs_src_clk)
600 clk_disable(info->rtc_src_clk);
541 clk_disable(info->rtc_clk); 601 clk_disable(info->rtc_clk);
542 602
543 return 0; 603 return 0;
@@ -557,6 +617,8 @@ static int s3c_rtc_suspend(struct device *dev)
557 struct s3c_rtc *info = dev_get_drvdata(dev); 617 struct s3c_rtc *info = dev_get_drvdata(dev);
558 618
559 clk_enable(info->rtc_clk); 619 clk_enable(info->rtc_clk);
620 if (info->data->needs_src_clk)
621 clk_enable(info->rtc_src_clk);
560 622
561 /* save TICNT for anyone using periodic interrupts */ 623 /* save TICNT for anyone using periodic interrupts */
562 if (info->data->save_tick_cnt) 624 if (info->data->save_tick_cnt)
@@ -572,6 +634,8 @@ static int s3c_rtc_suspend(struct device *dev)
572 dev_err(dev, "enable_irq_wake failed\n"); 634 dev_err(dev, "enable_irq_wake failed\n");
573 } 635 }
574 636
637 if (info->data->needs_src_clk)
638 clk_disable(info->rtc_src_clk);
575 clk_disable(info->rtc_clk); 639 clk_disable(info->rtc_clk);
576 640
577 return 0; 641 return 0;
@@ -582,6 +646,8 @@ static int s3c_rtc_resume(struct device *dev)
582 struct s3c_rtc *info = dev_get_drvdata(dev); 646 struct s3c_rtc *info = dev_get_drvdata(dev);
583 647
584 clk_enable(info->rtc_clk); 648 clk_enable(info->rtc_clk);
649 if (info->data->needs_src_clk)
650 clk_enable(info->rtc_src_clk);
585 651
586 if (info->data->enable) 652 if (info->data->enable)
587 info->data->enable(info); 653 info->data->enable(info);
@@ -594,6 +660,8 @@ static int s3c_rtc_resume(struct device *dev)
594 info->wake_en = false; 660 info->wake_en = false;
595 } 661 }
596 662
663 if (info->data->needs_src_clk)
664 clk_disable(info->rtc_src_clk);
597 clk_disable(info->rtc_clk); 665 clk_disable(info->rtc_clk);
598 666
599 return 0; 667 return 0;
@@ -604,7 +672,11 @@ static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume);
604static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask) 672static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask)
605{ 673{
606 clk_enable(info->rtc_clk); 674 clk_enable(info->rtc_clk);
675 if (info->data->needs_src_clk)
676 clk_enable(info->rtc_src_clk);
607 rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); 677 rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
678 if (info->data->needs_src_clk)
679 clk_disable(info->rtc_src_clk);
608 clk_disable(info->rtc_clk); 680 clk_disable(info->rtc_clk);
609 681
610 s3c_rtc_alarm_clk_enable(info, false); 682 s3c_rtc_alarm_clk_enable(info, false);
@@ -613,8 +685,12 @@ static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask)
613static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask) 685static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask)
614{ 686{
615 clk_enable(info->rtc_clk); 687 clk_enable(info->rtc_clk);
688 if (info->data->needs_src_clk)
689 clk_enable(info->rtc_src_clk);
616 rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); 690 rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
617 writeb(mask, info->base + S3C2410_INTP); 691 writeb(mask, info->base + S3C2410_INTP);
692 if (info->data->needs_src_clk)
693 clk_disable(info->rtc_src_clk);
618 clk_disable(info->rtc_clk); 694 clk_disable(info->rtc_clk);
619 695
620 s3c_rtc_alarm_clk_enable(info, false); 696 s3c_rtc_alarm_clk_enable(info, false);
@@ -780,6 +856,18 @@ static struct s3c_rtc_data const s3c6410_rtc_data = {
780 .disable = s3c6410_rtc_disable, 856 .disable = s3c6410_rtc_disable,
781}; 857};
782 858
859static struct s3c_rtc_data const exynos3250_rtc_data = {
860 .max_user_freq = 32768,
861 .needs_src_clk = true,
862 .irq_handler = s3c6410_rtc_irq,
863 .set_freq = s3c6410_rtc_setfreq,
864 .enable_tick = s3c6410_rtc_enable_tick,
865 .save_tick_cnt = s3c6410_rtc_save_tick_cnt,
866 .restore_tick_cnt = s3c6410_rtc_restore_tick_cnt,
867 .enable = s3c24xx_rtc_enable,
868 .disable = s3c6410_rtc_disable,
869};
870
783static const struct of_device_id s3c_rtc_dt_match[] = { 871static const struct of_device_id s3c_rtc_dt_match[] = {
784 { 872 {
785 .compatible = "samsung,s3c2410-rtc", 873 .compatible = "samsung,s3c2410-rtc",
@@ -793,6 +881,9 @@ static const struct of_device_id s3c_rtc_dt_match[] = {
793 }, { 881 }, {
794 .compatible = "samsung,s3c6410-rtc", 882 .compatible = "samsung,s3c6410-rtc",
795 .data = (void *)&s3c6410_rtc_data, 883 .data = (void *)&s3c6410_rtc_data,
884 }, {
885 .compatible = "samsung,exynos3250-rtc",
886 .data = (void *)&exynos3250_rtc_data,
796 }, 887 },
797 { /* sentinel */ }, 888 { /* sentinel */ },
798}; 889};