aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-s3c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-s3c.c')
-rw-r--r--drivers/rtc/rtc-s3c.c238
1 files changed, 181 insertions, 57 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index e0d7b9991505..cf953ecbfca9 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -1,5 +1,8 @@
1/* drivers/rtc/rtc-s3c.c 1/* drivers/rtc/rtc-s3c.c
2 * 2 *
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
3 * Copyright (c) 2004,2006 Simtec Electronics 6 * Copyright (c) 2004,2006 Simtec Electronics
4 * Ben Dooks, <ben@simtec.co.uk> 7 * Ben Dooks, <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/ 8 * http://armlinux.simtec.co.uk/
@@ -21,6 +24,7 @@
21#include <linux/bcd.h> 24#include <linux/bcd.h>
22#include <linux/clk.h> 25#include <linux/clk.h>
23#include <linux/log2.h> 26#include <linux/log2.h>
27#include <linux/slab.h>
24 28
25#include <mach/hardware.h> 29#include <mach/hardware.h>
26#include <asm/uaccess.h> 30#include <asm/uaccess.h>
@@ -28,14 +32,21 @@
28#include <asm/irq.h> 32#include <asm/irq.h>
29#include <plat/regs-rtc.h> 33#include <plat/regs-rtc.h>
30 34
35enum s3c_cpu_type {
36 TYPE_S3C2410,
37 TYPE_S3C64XX,
38};
39
31/* I have yet to find an S3C implementation with more than one 40/* I have yet to find an S3C implementation with more than one
32 * of these rtc blocks in */ 41 * of these rtc blocks in */
33 42
34static struct resource *s3c_rtc_mem; 43static struct resource *s3c_rtc_mem;
35 44
45static struct clk *rtc_clk;
36static void __iomem *s3c_rtc_base; 46static void __iomem *s3c_rtc_base;
37static int s3c_rtc_alarmno = NO_IRQ; 47static int s3c_rtc_alarmno = NO_IRQ;
38static int s3c_rtc_tickno = NO_IRQ; 48static int s3c_rtc_tickno = NO_IRQ;
49static enum s3c_cpu_type s3c_rtc_cpu_type;
39 50
40static DEFINE_SPINLOCK(s3c_rtc_pie_lock); 51static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
41 52
@@ -46,6 +57,10 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
46 struct rtc_device *rdev = id; 57 struct rtc_device *rdev = id;
47 58
48 rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); 59 rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
60
61 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
62 writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP);
63
49 return IRQ_HANDLED; 64 return IRQ_HANDLED;
50} 65}
51 66
@@ -54,6 +69,10 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
54 struct rtc_device *rdev = id; 69 struct rtc_device *rdev = id;
55 70
56 rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); 71 rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
72
73 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
74 writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP);
75
57 return IRQ_HANDLED; 76 return IRQ_HANDLED;
58} 77}
59 78
@@ -79,12 +98,25 @@ static int s3c_rtc_setpie(struct device *dev, int enabled)
79 pr_debug("%s: pie=%d\n", __func__, enabled); 98 pr_debug("%s: pie=%d\n", __func__, enabled);
80 99
81 spin_lock_irq(&s3c_rtc_pie_lock); 100 spin_lock_irq(&s3c_rtc_pie_lock);
82 tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
83 101
84 if (enabled) 102 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
85 tmp |= S3C2410_TICNT_ENABLE; 103 tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
104 tmp &= ~S3C64XX_RTCCON_TICEN;
105
106 if (enabled)
107 tmp |= S3C64XX_RTCCON_TICEN;
108
109 writew(tmp, s3c_rtc_base + S3C2410_RTCCON);
110 } else {
111 tmp = readb(s3c_rtc_base + S3C2410_TICNT);
112 tmp &= ~S3C2410_TICNT_ENABLE;
113
114 if (enabled)
115 tmp |= S3C2410_TICNT_ENABLE;
116
117 writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
118 }
86 119
87 writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
88 spin_unlock_irq(&s3c_rtc_pie_lock); 120 spin_unlock_irq(&s3c_rtc_pie_lock);
89 121
90 return 0; 122 return 0;
@@ -92,17 +124,23 @@ static int s3c_rtc_setpie(struct device *dev, int enabled)
92 124
93static int s3c_rtc_setfreq(struct device *dev, int freq) 125static int s3c_rtc_setfreq(struct device *dev, int freq)
94{ 126{
95 unsigned int tmp; 127 struct platform_device *pdev = to_platform_device(dev);
128 struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
129 unsigned int tmp = 0;
96 130
97 if (!is_power_of_2(freq)) 131 if (!is_power_of_2(freq))
98 return -EINVAL; 132 return -EINVAL;
99 133
100 spin_lock_irq(&s3c_rtc_pie_lock); 134 spin_lock_irq(&s3c_rtc_pie_lock);
101 135
102 tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; 136 if (s3c_rtc_cpu_type == TYPE_S3C2410) {
103 tmp |= (128 / freq)-1; 137 tmp = readb(s3c_rtc_base + S3C2410_TICNT);
138 tmp &= S3C2410_TICNT_ENABLE;
139 }
140
141 tmp |= (rtc_dev->max_user_freq / freq)-1;
104 142
105 writeb(tmp, s3c_rtc_base + S3C2410_TICNT); 143 writel(tmp, s3c_rtc_base + S3C2410_TICNT);
106 spin_unlock_irq(&s3c_rtc_pie_lock); 144 spin_unlock_irq(&s3c_rtc_pie_lock);
107 145
108 return 0; 146 return 0;
@@ -133,8 +171,8 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
133 goto retry_get_time; 171 goto retry_get_time;
134 } 172 }
135 173
136 pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", 174 pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n",
137 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, 175 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
138 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); 176 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
139 177
140 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); 178 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
@@ -147,7 +185,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
147 rtc_tm->tm_year += 100; 185 rtc_tm->tm_year += 100;
148 rtc_tm->tm_mon -= 1; 186 rtc_tm->tm_mon -= 1;
149 187
150 return 0; 188 return rtc_valid_tm(rtc_tm);
151} 189}
152 190
153static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) 191static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
@@ -155,8 +193,8 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
155 void __iomem *base = s3c_rtc_base; 193 void __iomem *base = s3c_rtc_base;
156 int year = tm->tm_year - 100; 194 int year = tm->tm_year - 100;
157 195
158 pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n", 196 pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n",
159 tm->tm_year, tm->tm_mon, tm->tm_mday, 197 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
160 tm->tm_hour, tm->tm_min, tm->tm_sec); 198 tm->tm_hour, tm->tm_min, tm->tm_sec);
161 199
162 /* we get around y2k by simply not supporting it */ 200 /* we get around y2k by simply not supporting it */
@@ -193,9 +231,9 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
193 231
194 alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; 232 alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
195 233
196 pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", 234 pr_debug("read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n",
197 alm_en, 235 alm_en,
198 alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, 236 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
199 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); 237 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
200 238
201 239
@@ -204,34 +242,34 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
204 if (alm_en & S3C2410_RTCALM_SECEN) 242 if (alm_en & S3C2410_RTCALM_SECEN)
205 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); 243 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
206 else 244 else
207 alm_tm->tm_sec = 0xff; 245 alm_tm->tm_sec = -1;
208 246
209 if (alm_en & S3C2410_RTCALM_MINEN) 247 if (alm_en & S3C2410_RTCALM_MINEN)
210 alm_tm->tm_min = bcd2bin(alm_tm->tm_min); 248 alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
211 else 249 else
212 alm_tm->tm_min = 0xff; 250 alm_tm->tm_min = -1;
213 251
214 if (alm_en & S3C2410_RTCALM_HOUREN) 252 if (alm_en & S3C2410_RTCALM_HOUREN)
215 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); 253 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
216 else 254 else
217 alm_tm->tm_hour = 0xff; 255 alm_tm->tm_hour = -1;
218 256
219 if (alm_en & S3C2410_RTCALM_DAYEN) 257 if (alm_en & S3C2410_RTCALM_DAYEN)
220 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); 258 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
221 else 259 else
222 alm_tm->tm_mday = 0xff; 260 alm_tm->tm_mday = -1;
223 261
224 if (alm_en & S3C2410_RTCALM_MONEN) { 262 if (alm_en & S3C2410_RTCALM_MONEN) {
225 alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); 263 alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);
226 alm_tm->tm_mon -= 1; 264 alm_tm->tm_mon -= 1;
227 } else { 265 } else {
228 alm_tm->tm_mon = 0xff; 266 alm_tm->tm_mon = -1;
229 } 267 }
230 268
231 if (alm_en & S3C2410_RTCALM_YEAREN) 269 if (alm_en & S3C2410_RTCALM_YEAREN)
232 alm_tm->tm_year = bcd2bin(alm_tm->tm_year); 270 alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
233 else 271 else
234 alm_tm->tm_year = 0xffff; 272 alm_tm->tm_year = -1;
235 273
236 return 0; 274 return 0;
237} 275}
@@ -242,10 +280,10 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
242 void __iomem *base = s3c_rtc_base; 280 void __iomem *base = s3c_rtc_base;
243 unsigned int alrm_en; 281 unsigned int alrm_en;
244 282
245 pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n", 283 pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
246 alrm->enabled, 284 alrm->enabled,
247 tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff, 285 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
248 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec); 286 tm->tm_hour, tm->tm_min, tm->tm_sec);
249 287
250 288
251 alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; 289 alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
@@ -272,20 +310,22 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
272 310
273 s3c_rtc_setaie(alrm->enabled); 311 s3c_rtc_setaie(alrm->enabled);
274 312
275 if (alrm->enabled)
276 enable_irq_wake(s3c_rtc_alarmno);
277 else
278 disable_irq_wake(s3c_rtc_alarmno);
279
280 return 0; 313 return 0;
281} 314}
282 315
283static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) 316static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
284{ 317{
285 unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); 318 unsigned int ticnt;
286 319
287 seq_printf(seq, "periodic_IRQ\t: %s\n", 320 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
288 (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); 321 ticnt = readw(s3c_rtc_base + S3C2410_RTCCON);
322 ticnt &= S3C64XX_RTCCON_TICEN;
323 } else {
324 ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
325 ticnt &= S3C2410_TICNT_ENABLE;
326 }
327
328 seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no");
289 return 0; 329 return 0;
290} 330}
291 331
@@ -339,7 +379,8 @@ static const struct rtc_class_ops s3c_rtcops = {
339 .set_alarm = s3c_rtc_setalarm, 379 .set_alarm = s3c_rtc_setalarm,
340 .irq_set_freq = s3c_rtc_setfreq, 380 .irq_set_freq = s3c_rtc_setfreq,
341 .irq_set_state = s3c_rtc_setpie, 381 .irq_set_state = s3c_rtc_setpie,
342 .proc = s3c_rtc_proc, 382 .proc = s3c_rtc_proc,
383 .alarm_irq_enable = s3c_rtc_setaie,
343}; 384};
344 385
345static void s3c_rtc_enable(struct platform_device *pdev, int en) 386static void s3c_rtc_enable(struct platform_device *pdev, int en)
@@ -351,33 +392,42 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
351 return; 392 return;
352 393
353 if (!en) { 394 if (!en) {
354 tmp = readb(base + S3C2410_RTCCON); 395 tmp = readw(base + S3C2410_RTCCON);
355 writeb(tmp & ~S3C2410_RTCCON_RTCEN, base + S3C2410_RTCCON); 396 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
356 397 tmp &= ~S3C64XX_RTCCON_TICEN;
357 tmp = readb(base + S3C2410_TICNT); 398 tmp &= ~S3C2410_RTCCON_RTCEN;
358 writeb(tmp & ~S3C2410_TICNT_ENABLE, base + S3C2410_TICNT); 399 writew(tmp, base + S3C2410_RTCCON);
400
401 if (s3c_rtc_cpu_type == TYPE_S3C2410) {
402 tmp = readb(base + S3C2410_TICNT);
403 tmp &= ~S3C2410_TICNT_ENABLE;
404 writeb(tmp, base + S3C2410_TICNT);
405 }
359 } else { 406 } else {
360 /* re-enable the device, and check it is ok */ 407 /* re-enable the device, and check it is ok */
361 408
362 if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){ 409 if ((readw(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) {
363 dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); 410 dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
364 411
365 tmp = readb(base + S3C2410_RTCCON); 412 tmp = readw(base + S3C2410_RTCCON);
366 writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON); 413 writew(tmp | S3C2410_RTCCON_RTCEN,
414 base + S3C2410_RTCCON);
367 } 415 }
368 416
369 if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){ 417 if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) {
370 dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); 418 dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n");
371 419
372 tmp = readb(base + S3C2410_RTCCON); 420 tmp = readw(base + S3C2410_RTCCON);
373 writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON); 421 writew(tmp & ~S3C2410_RTCCON_CNTSEL,
422 base + S3C2410_RTCCON);
374 } 423 }
375 424
376 if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){ 425 if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) {
377 dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); 426 dev_info(&pdev->dev, "removing RTCCON_CLKRST\n");
378 427
379 tmp = readb(base + S3C2410_RTCCON); 428 tmp = readw(base + S3C2410_RTCCON);
380 writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON); 429 writew(tmp & ~S3C2410_RTCCON_CLKRST,
430 base + S3C2410_RTCCON);
381 } 431 }
382 } 432 }
383} 433}
@@ -392,6 +442,10 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
392 s3c_rtc_setpie(&dev->dev, 0); 442 s3c_rtc_setpie(&dev->dev, 0);
393 s3c_rtc_setaie(0); 443 s3c_rtc_setaie(0);
394 444
445 clk_disable(rtc_clk);
446 clk_put(rtc_clk);
447 rtc_clk = NULL;
448
395 iounmap(s3c_rtc_base); 449 iounmap(s3c_rtc_base);
396 release_resource(s3c_rtc_mem); 450 release_resource(s3c_rtc_mem);
397 kfree(s3c_rtc_mem); 451 kfree(s3c_rtc_mem);
@@ -402,6 +456,7 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
402static int __devinit s3c_rtc_probe(struct platform_device *pdev) 456static int __devinit s3c_rtc_probe(struct platform_device *pdev)
403{ 457{
404 struct rtc_device *rtc; 458 struct rtc_device *rtc;
459 struct rtc_time rtc_tm;
405 struct resource *res; 460 struct resource *res;
406 int ret; 461 int ret;
407 462
@@ -449,14 +504,22 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
449 goto err_nomap; 504 goto err_nomap;
450 } 505 }
451 506
507 rtc_clk = clk_get(&pdev->dev, "rtc");
508 if (IS_ERR(rtc_clk)) {
509 dev_err(&pdev->dev, "failed to find rtc clock source\n");
510 ret = PTR_ERR(rtc_clk);
511 rtc_clk = NULL;
512 goto err_clk;
513 }
514
515 clk_enable(rtc_clk);
516
452 /* check to see if everything is setup correctly */ 517 /* check to see if everything is setup correctly */
453 518
454 s3c_rtc_enable(pdev, 1); 519 s3c_rtc_enable(pdev, 1);
455 520
456 pr_debug("s3c2410_rtc: RTCCON=%02x\n", 521 pr_debug("s3c2410_rtc: RTCCON=%02x\n",
457 readb(s3c_rtc_base + S3C2410_RTCCON)); 522 readw(s3c_rtc_base + S3C2410_RTCCON));
458
459 s3c_rtc_setfreq(&pdev->dev, 1);
460 523
461 device_init_wakeup(&pdev->dev, 1); 524 device_init_wakeup(&pdev->dev, 1);
462 525
@@ -471,13 +534,42 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
471 goto err_nortc; 534 goto err_nortc;
472 } 535 }
473 536
474 rtc->max_user_freq = 128; 537 s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
538
539 /* Check RTC Time */
540
541 s3c_rtc_gettime(NULL, &rtc_tm);
542
543 if (rtc_valid_tm(&rtc_tm)) {
544 rtc_tm.tm_year = 100;
545 rtc_tm.tm_mon = 0;
546 rtc_tm.tm_mday = 1;
547 rtc_tm.tm_hour = 0;
548 rtc_tm.tm_min = 0;
549 rtc_tm.tm_sec = 0;
550
551 s3c_rtc_settime(NULL, &rtc_tm);
552
553 dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
554 }
555
556 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
557 rtc->max_user_freq = 32768;
558 else
559 rtc->max_user_freq = 128;
475 560
476 platform_set_drvdata(pdev, rtc); 561 platform_set_drvdata(pdev, rtc);
562
563 s3c_rtc_setfreq(&pdev->dev, 1);
564
477 return 0; 565 return 0;
478 566
479 err_nortc: 567 err_nortc:
480 s3c_rtc_enable(pdev, 0); 568 s3c_rtc_enable(pdev, 0);
569 clk_disable(rtc_clk);
570 clk_put(rtc_clk);
571
572 err_clk:
481 iounmap(s3c_rtc_base); 573 iounmap(s3c_rtc_base);
482 574
483 err_nomap: 575 err_nomap:
@@ -491,20 +583,38 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
491 583
492/* RTC Power management control */ 584/* RTC Power management control */
493 585
494static int ticnt_save; 586static int ticnt_save, ticnt_en_save;
495 587
496static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) 588static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
497{ 589{
498 /* save TICNT for anyone using periodic interrupts */ 590 /* save TICNT for anyone using periodic interrupts */
499 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); 591 ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
592 if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
593 ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON);
594 ticnt_en_save &= S3C64XX_RTCCON_TICEN;
595 }
500 s3c_rtc_enable(pdev, 0); 596 s3c_rtc_enable(pdev, 0);
597
598 if (device_may_wakeup(&pdev->dev))
599 enable_irq_wake(s3c_rtc_alarmno);
600
501 return 0; 601 return 0;
502} 602}
503 603
504static int s3c_rtc_resume(struct platform_device *pdev) 604static int s3c_rtc_resume(struct platform_device *pdev)
505{ 605{
606 unsigned int tmp;
607
506 s3c_rtc_enable(pdev, 1); 608 s3c_rtc_enable(pdev, 1);
507 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); 609 writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
610 if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) {
611 tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
612 writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON);
613 }
614
615 if (device_may_wakeup(&pdev->dev))
616 disable_irq_wake(s3c_rtc_alarmno);
617
508 return 0; 618 return 0;
509} 619}
510#else 620#else
@@ -512,13 +622,27 @@ static int s3c_rtc_resume(struct platform_device *pdev)
512#define s3c_rtc_resume NULL 622#define s3c_rtc_resume NULL
513#endif 623#endif
514 624
515static struct platform_driver s3c2410_rtc_driver = { 625static struct platform_device_id s3c_rtc_driver_ids[] = {
626 {
627 .name = "s3c2410-rtc",
628 .driver_data = TYPE_S3C2410,
629 }, {
630 .name = "s3c64xx-rtc",
631 .driver_data = TYPE_S3C64XX,
632 },
633 { }
634};
635
636MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids);
637
638static struct platform_driver s3c_rtc_driver = {
516 .probe = s3c_rtc_probe, 639 .probe = s3c_rtc_probe,
517 .remove = __devexit_p(s3c_rtc_remove), 640 .remove = __devexit_p(s3c_rtc_remove),
518 .suspend = s3c_rtc_suspend, 641 .suspend = s3c_rtc_suspend,
519 .resume = s3c_rtc_resume, 642 .resume = s3c_rtc_resume,
643 .id_table = s3c_rtc_driver_ids,
520 .driver = { 644 .driver = {
521 .name = "s3c2410-rtc", 645 .name = "s3c-rtc",
522 .owner = THIS_MODULE, 646 .owner = THIS_MODULE,
523 }, 647 },
524}; 648};
@@ -528,12 +652,12 @@ static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics
528static int __init s3c_rtc_init(void) 652static int __init s3c_rtc_init(void)
529{ 653{
530 printk(banner); 654 printk(banner);
531 return platform_driver_register(&s3c2410_rtc_driver); 655 return platform_driver_register(&s3c_rtc_driver);
532} 656}
533 657
534static void __exit s3c_rtc_exit(void) 658static void __exit s3c_rtc_exit(void)
535{ 659{
536 platform_driver_unregister(&s3c2410_rtc_driver); 660 platform_driver_unregister(&s3c_rtc_driver);
537} 661}
538 662
539module_init(s3c_rtc_init); 663module_init(s3c_rtc_init);