aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDonggeun Kim <dg77.kim@samsung.com>2011-07-25 20:13:32 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-25 23:57:17 -0400
commitcefe4fbbaab8e20a7581a187db82d33c1e3320c0 (patch)
treea40203a65c87c09136a38d3927c643a119364f7f
parent955dbea3c7133d3ccfaa79c7eba1244c1de42865 (diff)
drivers/rtc/rtc-s3c.c: support clock gating
Add support for clock gating. Power consumption can be reduced by setting rtc_clk disabled state except for when RTC related registers are accessed. Signed-off-by: Donggeun Kim <dg77.kim@samsung.com> Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> Signed-off-by: KyungMin Park <kyungmin.park@samsung.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Ben Dooks <ben@fluff.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/rtc/rtc-s3c.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 16512ecae31a..53c99b1a3c92 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -57,11 +57,13 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
57{ 57{
58 struct rtc_device *rdev = id; 58 struct rtc_device *rdev = id;
59 59
60 clk_enable(rtc_clk);
60 rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); 61 rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
61 62
62 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 63 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
63 writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); 64 writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP);
64 65
66 clk_disable(rtc_clk);
65 return IRQ_HANDLED; 67 return IRQ_HANDLED;
66} 68}
67 69
@@ -69,11 +71,13 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
69{ 71{
70 struct rtc_device *rdev = id; 72 struct rtc_device *rdev = id;
71 73
74 clk_enable(rtc_clk);
72 rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); 75 rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
73 76
74 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 77 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
75 writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); 78 writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP);
76 79
80 clk_disable(rtc_clk);
77 return IRQ_HANDLED; 81 return IRQ_HANDLED;
78} 82}
79 83
@@ -84,12 +88,14 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
84 88
85 pr_debug("%s: aie=%d\n", __func__, enabled); 89 pr_debug("%s: aie=%d\n", __func__, enabled);
86 90
91 clk_enable(rtc_clk);
87 tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; 92 tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
88 93
89 if (enabled) 94 if (enabled)
90 tmp |= S3C2410_RTCALM_ALMEN; 95 tmp |= S3C2410_RTCALM_ALMEN;
91 96
92 writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); 97 writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
98 clk_disable(rtc_clk);
93 99
94 return 0; 100 return 0;
95} 101}
@@ -103,6 +109,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
103 if (!is_power_of_2(freq)) 109 if (!is_power_of_2(freq))
104 return -EINVAL; 110 return -EINVAL;
105 111
112 clk_enable(rtc_clk);
106 spin_lock_irq(&s3c_rtc_pie_lock); 113 spin_lock_irq(&s3c_rtc_pie_lock);
107 114
108 if (s3c_rtc_cpu_type == TYPE_S3C2410) { 115 if (s3c_rtc_cpu_type == TYPE_S3C2410) {
@@ -114,6 +121,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
114 121
115 writel(tmp, s3c_rtc_base + S3C2410_TICNT); 122 writel(tmp, s3c_rtc_base + S3C2410_TICNT);
116 spin_unlock_irq(&s3c_rtc_pie_lock); 123 spin_unlock_irq(&s3c_rtc_pie_lock);
124 clk_disable(rtc_clk);
117 125
118 return 0; 126 return 0;
119} 127}
@@ -125,6 +133,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
125 unsigned int have_retried = 0; 133 unsigned int have_retried = 0;
126 void __iomem *base = s3c_rtc_base; 134 void __iomem *base = s3c_rtc_base;
127 135
136 clk_enable(rtc_clk);
128 retry_get_time: 137 retry_get_time:
129 rtc_tm->tm_min = readb(base + S3C2410_RTCMIN); 138 rtc_tm->tm_min = readb(base + S3C2410_RTCMIN);
130 rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR); 139 rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);
@@ -157,6 +166,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
157 rtc_tm->tm_year += 100; 166 rtc_tm->tm_year += 100;
158 rtc_tm->tm_mon -= 1; 167 rtc_tm->tm_mon -= 1;
159 168
169 clk_disable(rtc_clk);
160 return rtc_valid_tm(rtc_tm); 170 return rtc_valid_tm(rtc_tm);
161} 171}
162 172
@@ -165,6 +175,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
165 void __iomem *base = s3c_rtc_base; 175 void __iomem *base = s3c_rtc_base;
166 int year = tm->tm_year - 100; 176 int year = tm->tm_year - 100;
167 177
178 clk_enable(rtc_clk);
168 pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", 179 pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n",
169 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, 180 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
170 tm->tm_hour, tm->tm_min, tm->tm_sec); 181 tm->tm_hour, tm->tm_min, tm->tm_sec);
@@ -182,6 +193,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
182 writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE); 193 writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);
183 writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON); 194 writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);
184 writeb(bin2bcd(year), base + S3C2410_RTCYEAR); 195 writeb(bin2bcd(year), base + S3C2410_RTCYEAR);
196 clk_disable(rtc_clk);
185 197
186 return 0; 198 return 0;
187} 199}
@@ -192,6 +204,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
192 void __iomem *base = s3c_rtc_base; 204 void __iomem *base = s3c_rtc_base;
193 unsigned int alm_en; 205 unsigned int alm_en;
194 206
207 clk_enable(rtc_clk);
195 alm_tm->tm_sec = readb(base + S3C2410_ALMSEC); 208 alm_tm->tm_sec = readb(base + S3C2410_ALMSEC);
196 alm_tm->tm_min = readb(base + S3C2410_ALMMIN); 209 alm_tm->tm_min = readb(base + S3C2410_ALMMIN);
197 alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); 210 alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR);
@@ -243,6 +256,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
243 else 256 else
244 alm_tm->tm_year = -1; 257 alm_tm->tm_year = -1;
245 258
259 clk_disable(rtc_clk);
246 return 0; 260 return 0;
247} 261}
248 262
@@ -252,6 +266,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
252 void __iomem *base = s3c_rtc_base; 266 void __iomem *base = s3c_rtc_base;
253 unsigned int alrm_en; 267 unsigned int alrm_en;
254 268
269 clk_enable(rtc_clk);
255 pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", 270 pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
256 alrm->enabled, 271 alrm->enabled,
257 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, 272 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
@@ -282,6 +297,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
282 297
283 s3c_rtc_setaie(dev, alrm->enabled); 298 s3c_rtc_setaie(dev, alrm->enabled);
284 299
300 clk_disable(rtc_clk);
285 return 0; 301 return 0;
286} 302}
287 303
@@ -289,6 +305,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
289{ 305{
290 unsigned int ticnt; 306 unsigned int ticnt;
291 307
308 clk_enable(rtc_clk);
292 if (s3c_rtc_cpu_type == TYPE_S3C64XX) { 309 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
293 ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); 310 ticnt = readw(s3c_rtc_base + S3C2410_RTCCON);
294 ticnt &= S3C64XX_RTCCON_TICEN; 311 ticnt &= S3C64XX_RTCCON_TICEN;
@@ -298,6 +315,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
298 } 315 }
299 316
300 seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); 317 seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no");
318 clk_disable(rtc_clk);
301 return 0; 319 return 0;
302} 320}
303 321
@@ -360,6 +378,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
360 if (s3c_rtc_base == NULL) 378 if (s3c_rtc_base == NULL)
361 return; 379 return;
362 380
381 clk_enable(rtc_clk);
363 if (!en) { 382 if (!en) {
364 tmp = readw(base + S3C2410_RTCCON); 383 tmp = readw(base + S3C2410_RTCCON);
365 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 384 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
@@ -399,6 +418,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
399 base + S3C2410_RTCCON); 418 base + S3C2410_RTCCON);
400 } 419 }
401 } 420 }
421 clk_disable(rtc_clk);
402} 422}
403 423
404static int __devexit s3c_rtc_remove(struct platform_device *dev) 424static int __devexit s3c_rtc_remove(struct platform_device *dev)
@@ -410,7 +430,6 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
410 430
411 s3c_rtc_setaie(&dev->dev, 0); 431 s3c_rtc_setaie(&dev->dev, 0);
412 432
413 clk_disable(rtc_clk);
414 clk_put(rtc_clk); 433 clk_put(rtc_clk);
415 rtc_clk = NULL; 434 rtc_clk = NULL;
416 435
@@ -530,6 +549,8 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
530 549
531 s3c_rtc_setfreq(&pdev->dev, 1); 550 s3c_rtc_setfreq(&pdev->dev, 1);
532 551
552 clk_disable(rtc_clk);
553
533 return 0; 554 return 0;
534 555
535 err_nortc: 556 err_nortc:
@@ -555,6 +576,7 @@ static int ticnt_save, ticnt_en_save;
555 576
556static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) 577static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
557{ 578{
579 clk_enable(rtc_clk);
558 /* save TICNT for anyone using periodic interrupts */ 580 /* save TICNT for anyone using periodic interrupts */
559 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); 581 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
560 if (s3c_rtc_cpu_type == TYPE_S3C64XX) { 582 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
@@ -569,6 +591,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
569 else 591 else
570 dev_err(&pdev->dev, "enable_irq_wake failed\n"); 592 dev_err(&pdev->dev, "enable_irq_wake failed\n");
571 } 593 }
594 clk_disable(rtc_clk);
572 595
573 return 0; 596 return 0;
574} 597}
@@ -577,6 +600,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
577{ 600{
578 unsigned int tmp; 601 unsigned int tmp;
579 602
603 clk_enable(rtc_clk);
580 s3c_rtc_enable(pdev, 1); 604 s3c_rtc_enable(pdev, 1);
581 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); 605 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
582 if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { 606 if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) {
@@ -588,6 +612,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
588 disable_irq_wake(s3c_rtc_alarmno); 612 disable_irq_wake(s3c_rtc_alarmno);
589 wake_en = false; 613 wake_en = false;
590 } 614 }
615 clk_disable(rtc_clk);
591 616
592 return 0; 617 return 0;
593} 618}