Skip to content

Commit df9e26d

Browse files
chanwoochoitorvalds
authored andcommitted
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>
1 parent ae05c95 commit df9e26d

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

Documentation/devicetree/bindings/rtc/s3c-rtc.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Required properties:
66
* "samsung,s3c2416-rtc" - for controllers compatible with s3c2416 rtc.
77
* "samsung,s3c2443-rtc" - for controllers compatible with s3c2443 rtc.
88
* "samsung,s3c6410-rtc" - for controllers compatible with s3c6410 rtc.
9+
* "samsung,exynos3250-rtc" - for controllers compatible with exynos3250 rtc.
910
- reg: physical base address of the controller and length of memory mapped
1011
region.
1112
- interrupts: Two interrupt numbers to the cpu should be specified. First

drivers/rtc/rtc-s3c.c

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct s3c_rtc {
3838

3939
void __iomem *base;
4040
struct clk *rtc_clk;
41+
struct clk *rtc_src_clk;
4142
bool enabled;
4243

4344
struct s3c_rtc_data *data;
@@ -54,6 +55,7 @@ struct s3c_rtc {
5455

5556
struct s3c_rtc_data {
5657
int max_user_freq;
58+
bool needs_src_clk;
5759

5860
void (*irq_handler) (struct s3c_rtc *info, int mask);
5961
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)
7375
if (enable) {
7476
if (!info->enabled) {
7577
clk_enable(info->rtc_clk);
78+
if (info->data->needs_src_clk)
79+
clk_enable(info->rtc_src_clk);
7680
info->enabled = true;
7781
}
7882
} else {
7983
if (info->enabled) {
84+
if (info->data->needs_src_clk)
85+
clk_disable(info->rtc_src_clk);
8086
clk_disable(info->rtc_clk);
8187
info->enabled = false;
8288
}
@@ -114,12 +120,16 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
114120
dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled);
115121

116122
clk_enable(info->rtc_clk);
123+
if (info->data->needs_src_clk)
124+
clk_enable(info->rtc_src_clk);
117125
tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
118126

119127
if (enabled)
120128
tmp |= S3C2410_RTCALM_ALMEN;
121129

122130
writeb(tmp, info->base + S3C2410_RTCALM);
131+
if (info->data->needs_src_clk)
132+
clk_disable(info->rtc_src_clk);
123133
clk_disable(info->rtc_clk);
124134

125135
s3c_rtc_alarm_clk_enable(info, enabled);
@@ -134,12 +144,16 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
134144
return -EINVAL;
135145

136146
clk_enable(info->rtc_clk);
147+
if (info->data->needs_src_clk)
148+
clk_enable(info->rtc_src_clk);
137149
spin_lock_irq(&info->pie_lock);
138150

139151
if (info->data->set_freq)
140152
info->data->set_freq(info, freq);
141153

142154
spin_unlock_irq(&info->pie_lock);
155+
if (info->data->needs_src_clk)
156+
clk_disable(info->rtc_src_clk);
143157
clk_disable(info->rtc_clk);
144158

145159
return 0;
@@ -152,6 +166,9 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
152166
unsigned int have_retried = 0;
153167

154168
clk_enable(info->rtc_clk);
169+
if (info->data->needs_src_clk)
170+
clk_enable(info->rtc_src_clk);
171+
155172
retry_get_time:
156173
rtc_tm->tm_min = readb(info->base + S3C2410_RTCMIN);
157174
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)
185202

186203
rtc_tm->tm_mon -= 1;
187204

205+
if (info->data->needs_src_clk)
206+
clk_disable(info->rtc_src_clk);
188207
clk_disable(info->rtc_clk);
189208

190209
return rtc_valid_tm(rtc_tm);
@@ -207,6 +226,8 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
207226
}
208227

209228
clk_enable(info->rtc_clk);
229+
if (info->data->needs_src_clk)
230+
clk_enable(info->rtc_src_clk);
210231

211232
writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_RTCSEC);
212233
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)
215236
writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON);
216237
writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR);
217238

239+
if (info->data->needs_src_clk)
240+
clk_disable(info->rtc_src_clk);
218241
clk_disable(info->rtc_clk);
219242

220243
return 0;
@@ -227,6 +250,9 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
227250
unsigned int alm_en;
228251

229252
clk_enable(info->rtc_clk);
253+
if (info->data->needs_src_clk)
254+
clk_enable(info->rtc_src_clk);
255+
230256
alm_tm->tm_sec = readb(info->base + S3C2410_ALMSEC);
231257
alm_tm->tm_min = readb(info->base + S3C2410_ALMMIN);
232258
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)
278304
else
279305
alm_tm->tm_year = -1;
280306

307+
if (info->data->needs_src_clk)
308+
clk_disable(info->rtc_src_clk);
281309
clk_disable(info->rtc_clk);
310+
282311
return 0;
283312
}
284313

@@ -289,6 +318,9 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
289318
unsigned int alrm_en;
290319

291320
clk_enable(info->rtc_clk);
321+
if (info->data->needs_src_clk)
322+
clk_enable(info->rtc_src_clk);
323+
292324
dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
293325
alrm->enabled,
294326
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)
318350

319351
s3c_rtc_setaie(dev, alrm->enabled);
320352

353+
if (info->data->needs_src_clk)
354+
clk_disable(info->rtc_src_clk);
321355
clk_disable(info->rtc_clk);
322356

323357
return 0;
@@ -328,10 +362,14 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
328362
struct s3c_rtc *info = dev_get_drvdata(dev);
329363

330364
clk_enable(info->rtc_clk);
365+
if (info->data->needs_src_clk)
366+
clk_enable(info->rtc_src_clk);
331367

332368
if (info->data->enable_tick)
333369
info->data->enable_tick(info, seq);
334370

371+
if (info->data->needs_src_clk)
372+
clk_disable(info->rtc_src_clk);
335373
clk_disable(info->rtc_clk);
336374

337375
return 0;
@@ -351,6 +389,8 @@ static void s3c24xx_rtc_enable(struct s3c_rtc *info)
351389
unsigned int con, tmp;
352390

353391
clk_enable(info->rtc_clk);
392+
if (info->data->needs_src_clk)
393+
clk_enable(info->rtc_src_clk);
354394

355395
con = readw(info->base + S3C2410_RTCCON);
356396
/* re-enable the device, and check it is ok */
@@ -378,6 +418,8 @@ static void s3c24xx_rtc_enable(struct s3c_rtc *info)
378418
info->base + S3C2410_RTCCON);
379419
}
380420

421+
if (info->data->needs_src_clk)
422+
clk_disable(info->rtc_src_clk);
381423
clk_disable(info->rtc_clk);
382424
}
383425

@@ -386,6 +428,8 @@ static void s3c24xx_rtc_disable(struct s3c_rtc *info)
386428
unsigned int con;
387429

388430
clk_enable(info->rtc_clk);
431+
if (info->data->needs_src_clk)
432+
clk_enable(info->rtc_src_clk);
389433

390434
con = readw(info->base + S3C2410_RTCCON);
391435
con &= ~S3C2410_RTCCON_RTCEN;
@@ -395,6 +439,8 @@ static void s3c24xx_rtc_disable(struct s3c_rtc *info)
395439
con &= ~S3C2410_TICNT_ENABLE;
396440
writeb(con, info->base + S3C2410_TICNT);
397441

442+
if (info->data->needs_src_clk)
443+
clk_disable(info->rtc_src_clk);
398444
clk_disable(info->rtc_clk);
399445
}
400446

@@ -403,12 +449,16 @@ static void s3c6410_rtc_disable(struct s3c_rtc *info)
403449
unsigned int con;
404450

405451
clk_enable(info->rtc_clk);
452+
if (info->data->needs_src_clk)
453+
clk_enable(info->rtc_src_clk);
406454

407455
con = readw(info->base + S3C2410_RTCCON);
408456
con &= ~S3C64XX_RTCCON_TICEN;
409457
con &= ~S3C2410_RTCCON_RTCEN;
410458
writew(con, info->base + S3C2410_RTCCON);
411459

460+
if (info->data->needs_src_clk)
461+
clk_disable(info->rtc_src_clk);
412462
clk_disable(info->rtc_clk);
413463
}
414464

@@ -480,11 +530,19 @@ static int s3c_rtc_probe(struct platform_device *pdev)
480530

481531
info->rtc_clk = devm_clk_get(&pdev->dev, "rtc");
482532
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");
484534
return PTR_ERR(info->rtc_clk);
485535
}
486536
clk_prepare_enable(info->rtc_clk);
487537

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+
488546
/* check to see if everything is setup correctly */
489547
if (info->data->enable)
490548
info->data->enable(info);
@@ -538,6 +596,8 @@ static int s3c_rtc_probe(struct platform_device *pdev)
538596

539597
s3c_rtc_setfreq(info, 1);
540598

599+
if (info->data->needs_src_clk)
600+
clk_disable(info->rtc_src_clk);
541601
clk_disable(info->rtc_clk);
542602

543603
return 0;
@@ -557,6 +617,8 @@ static int s3c_rtc_suspend(struct device *dev)
557617
struct s3c_rtc *info = dev_get_drvdata(dev);
558618

559619
clk_enable(info->rtc_clk);
620+
if (info->data->needs_src_clk)
621+
clk_enable(info->rtc_src_clk);
560622

561623
/* save TICNT for anyone using periodic interrupts */
562624
if (info->data->save_tick_cnt)
@@ -572,6 +634,8 @@ static int s3c_rtc_suspend(struct device *dev)
572634
dev_err(dev, "enable_irq_wake failed\n");
573635
}
574636

637+
if (info->data->needs_src_clk)
638+
clk_disable(info->rtc_src_clk);
575639
clk_disable(info->rtc_clk);
576640

577641
return 0;
@@ -582,6 +646,8 @@ static int s3c_rtc_resume(struct device *dev)
582646
struct s3c_rtc *info = dev_get_drvdata(dev);
583647

584648
clk_enable(info->rtc_clk);
649+
if (info->data->needs_src_clk)
650+
clk_enable(info->rtc_src_clk);
585651

586652
if (info->data->enable)
587653
info->data->enable(info);
@@ -594,6 +660,8 @@ static int s3c_rtc_resume(struct device *dev)
594660
info->wake_en = false;
595661
}
596662

663+
if (info->data->needs_src_clk)
664+
clk_disable(info->rtc_src_clk);
597665
clk_disable(info->rtc_clk);
598666

599667
return 0;
@@ -604,7 +672,11 @@ static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume);
604672
static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask)
605673
{
606674
clk_enable(info->rtc_clk);
675+
if (info->data->needs_src_clk)
676+
clk_enable(info->rtc_src_clk);
607677
rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
678+
if (info->data->needs_src_clk)
679+
clk_disable(info->rtc_src_clk);
608680
clk_disable(info->rtc_clk);
609681

610682
s3c_rtc_alarm_clk_enable(info, false);
@@ -613,8 +685,12 @@ static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask)
613685
static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask)
614686
{
615687
clk_enable(info->rtc_clk);
688+
if (info->data->needs_src_clk)
689+
clk_enable(info->rtc_src_clk);
616690
rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
617691
writeb(mask, info->base + S3C2410_INTP);
692+
if (info->data->needs_src_clk)
693+
clk_disable(info->rtc_src_clk);
618694
clk_disable(info->rtc_clk);
619695

620696
s3c_rtc_alarm_clk_enable(info, false);
@@ -780,6 +856,18 @@ static struct s3c_rtc_data const s3c6410_rtc_data = {
780856
.disable = s3c6410_rtc_disable,
781857
};
782858

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+
783871
static const struct of_device_id s3c_rtc_dt_match[] = {
784872
{
785873
.compatible = "samsung,s3c2410-rtc",
@@ -793,6 +881,9 @@ static const struct of_device_id s3c_rtc_dt_match[] = {
793881
}, {
794882
.compatible = "samsung,s3c6410-rtc",
795883
.data = (void *)&s3c6410_rtc_data,
884+
}, {
885+
.compatible = "samsung,exynos3250-rtc",
886+
.data = (void *)&exynos3250_rtc_data,
796887
},
797888
{ /* sentinel */ },
798889
};

0 commit comments

Comments
 (0)