aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorChanwoo Choi <cw00.choi@samsung.com>2014-10-13 18:52:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-13 20:18:17 -0400
commitdf9e26d093d33a097c5558aab017dd2f540ccfe5 (patch)
treedc9ddf1e5d385a380feb209269b0b75191aded68 /drivers/rtc
parentae05c95074e0ead8a8fda4aca066e10270086e3f (diff)
rtc: s3c: add support for RTC of Exynos3250 SoC
Add support for RTC of Exynos3250 SoC. The Exynos3250 needs source clock(32.768KHz) for RTC block. If source clock of RTC is registerd on clock list of common clk framework, Exynos RTC drvier have to control this clock. Clock list for s3c-rtc device: - rtc : CLK_RTC of CLK_GATE_IP_PERIR is gate clock for RTC. - rtc_src : XrtcXTI is 32.768.kHz source clock for RTC. (XRTCXTI: Specifies a clock from 32.768 kHz crystal pad with XRTCXTI and XRTCXTO pins. RTC uses this clock as the source of a real-time clock.) Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
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};