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