aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-07-03 13:49:45 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-07-03 13:49:45 -0400
commit026477c1141b67e98e3bd8bdedb7d4b88a3ecd09 (patch)
tree2624a44924c625c367f3cebf937853b9da2de282 /drivers/rtc
parent9f2fa466383ce100b90fe52cb4489d7a26bf72a9 (diff)
parent29454dde27d8e340bb1987bad9aa504af7081eba (diff)
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig18
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-at91.c2
-rw-r--r--drivers/rtc/rtc-ds1553.c2
-rw-r--r--drivers/rtc/rtc-pl031.c2
-rw-r--r--drivers/rtc/rtc-s3c.c607
-rw-r--r--drivers/rtc/rtc-sa1100.c6
-rw-r--r--drivers/rtc/rtc-vr41xx.c4
8 files changed, 633 insertions, 9 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index f2fc81a9074d..f5b9f187a930 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -15,7 +15,7 @@ config RTC_CLASS
15 help 15 help
16 Generic RTC class support. If you say yes here, you will 16 Generic RTC class support. If you say yes here, you will
17 be allowed to plug one or more RTCs to your system. You will 17 be allowed to plug one or more RTCs to your system. You will
18 probably want to enable one of more of the interfaces below. 18 probably want to enable one or more of the interfaces below.
19 19
20 This driver can also be built as a module. If so, the module 20 This driver can also be built as a module. If so, the module
21 will be called rtc-class. 21 will be called rtc-class.
@@ -182,6 +182,22 @@ config RTC_DRV_RS5C372
182 This driver can also be built as a module. If so, the module 182 This driver can also be built as a module. If so, the module
183 will be called rtc-rs5c372. 183 will be called rtc-rs5c372.
184 184
185config RTC_DRV_S3C
186 tristate "Samsung S3C series SoC RTC"
187 depends on RTC_CLASS && ARCH_S3C2410
188 help
189 RTC (Realtime Clock) driver for the clock inbuilt into the
190 Samsung S3C24XX series of SoCs. This can provide periodic
191 interrupt rates from 1Hz to 64Hz for user programs, and
192 wakeup from Alarm.
193
194 The driver currently supports the common features on all the
195 S3C24XX range, such as the S3C2410, S3C2412, S3C2413, S3C2440
196 and S3C2442.
197
198 This driver can also be build as a module. If so, the module
199 will be called rtc-s3c.
200
185config RTC_DRV_M48T86 201config RTC_DRV_M48T86
186 tristate "ST M48T86/Dallas DS12887" 202 tristate "ST M48T86/Dallas DS12887"
187 depends on RTC_CLASS 203 depends on RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index da5e38774e13..54220714ff49 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o
19obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o 19obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
20obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o 20obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
21obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o 21obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
22obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
22obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o 23obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
23obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o 24obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
24obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o 25obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o
diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91.c
index b676f443c17e..dfd0ce86f6a0 100644
--- a/drivers/rtc/rtc-at91.c
+++ b/drivers/rtc/rtc-at91.c
@@ -293,7 +293,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
293 AT91_RTC_CALEV); 293 AT91_RTC_CALEV);
294 294
295 ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, 295 ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
296 SA_SHIRQ, "at91_rtc", pdev); 296 IRQF_SHARED, "at91_rtc", pdev);
297 if (ret) { 297 if (ret) {
298 printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", 298 printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n",
299 AT91_ID_SYS); 299 AT91_ID_SYS);
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 762521a1419c..209001495474 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -341,7 +341,7 @@ static int __init ds1553_rtc_probe(struct platform_device *pdev)
341 341
342 if (pdata->irq >= 0) { 342 if (pdata->irq >= 0) {
343 writeb(0, ioaddr + RTC_INTERRUPTS); 343 writeb(0, ioaddr + RTC_INTERRUPTS);
344 if (request_irq(pdata->irq, ds1553_rtc_interrupt, SA_SHIRQ, 344 if (request_irq(pdata->irq, ds1553_rtc_interrupt, IRQF_SHARED,
345 pdev->name, pdev) < 0) { 345 pdev->name, pdev) < 0) {
346 dev_warn(&pdev->dev, "interrupt not available.\n"); 346 dev_warn(&pdev->dev, "interrupt not available.\n");
347 pdata->irq = -1; 347 pdata->irq = -1;
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index ee538632660b..d6d1c5726b0e 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -173,7 +173,7 @@ static int pl031_probe(struct amba_device *adev, void *id)
173 goto out_no_remap; 173 goto out_no_remap;
174 } 174 }
175 175
176 if (request_irq(adev->irq[0], pl031_interrupt, SA_INTERRUPT, 176 if (request_irq(adev->irq[0], pl031_interrupt, IRQF_DISABLED,
177 "rtc-pl031", ldata->rtc)) { 177 "rtc-pl031", ldata->rtc)) {
178 ret = -EIO; 178 ret = -EIO;
179 goto out_no_irq; 179 goto out_no_irq;
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
new file mode 100644
index 000000000000..d6d1bff52b8e
--- /dev/null
+++ b/drivers/rtc/rtc-s3c.c
@@ -0,0 +1,607 @@
1/* drivers/rtc/rtc-s3c.c
2 *
3 * Copyright (c) 2004,2006 Simtec Electronics
4 * Ben Dooks, <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * S3C2410/S3C2440/S3C24XX Internal RTC Driver
12*/
13
14#include <linux/module.h>
15#include <linux/fs.h>
16#include <linux/string.h>
17#include <linux/init.h>
18#include <linux/platform_device.h>
19#include <linux/interrupt.h>
20#include <linux/rtc.h>
21#include <linux/bcd.h>
22#include <linux/clk.h>
23
24#include <asm/hardware.h>
25#include <asm/uaccess.h>
26#include <asm/io.h>
27#include <asm/irq.h>
28#include <asm/rtc.h>
29
30#include <asm/mach/time.h>
31
32#include <asm/arch/regs-rtc.h>
33
34/* I have yet to find an S3C implementation with more than one
35 * of these rtc blocks in */
36
37static struct resource *s3c_rtc_mem;
38
39static void __iomem *s3c_rtc_base;
40static int s3c_rtc_alarmno = NO_IRQ;
41static int s3c_rtc_tickno = NO_IRQ;
42static int s3c_rtc_freq = 1;
43
44static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
45static unsigned int tick_count;
46
47/* IRQ Handlers */
48
49static irqreturn_t s3c_rtc_alarmirq(int irq, void *id, struct pt_regs *r)
50{
51 struct rtc_device *rdev = id;
52
53 rtc_update_irq(&rdev->class_dev, 1, RTC_AF | RTC_IRQF);
54 return IRQ_HANDLED;
55}
56
57static irqreturn_t s3c_rtc_tickirq(int irq, void *id, struct pt_regs *r)
58{
59 struct rtc_device *rdev = id;
60
61 rtc_update_irq(&rdev->class_dev, tick_count++, RTC_PF | RTC_IRQF);
62 return IRQ_HANDLED;
63}
64
65/* Update control registers */
66static void s3c_rtc_setaie(int to)
67{
68 unsigned int tmp;
69
70 pr_debug("%s: aie=%d\n", __FUNCTION__, to);
71
72 tmp = readb(S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
73
74 if (to)
75 tmp |= S3C2410_RTCALM_ALMEN;
76
77 writeb(tmp, S3C2410_RTCALM);
78}
79
80static void s3c_rtc_setpie(int to)
81{
82 unsigned int tmp;
83
84 pr_debug("%s: pie=%d\n", __FUNCTION__, to);
85
86 spin_lock_irq(&s3c_rtc_pie_lock);
87 tmp = readb(S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
88
89 if (to)
90 tmp |= S3C2410_TICNT_ENABLE;
91
92 writeb(tmp, S3C2410_TICNT);
93 spin_unlock_irq(&s3c_rtc_pie_lock);
94}
95
96static void s3c_rtc_setfreq(int freq)
97{
98 unsigned int tmp;
99
100 spin_lock_irq(&s3c_rtc_pie_lock);
101 tmp = readb(S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
102
103 s3c_rtc_freq = freq;
104
105 tmp |= (128 / freq)-1;
106
107 writeb(tmp, S3C2410_TICNT);
108 spin_unlock_irq(&s3c_rtc_pie_lock);
109}
110
111/* Time read/write */
112
113static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
114{
115 unsigned int have_retried = 0;
116
117 retry_get_time:
118 rtc_tm->tm_min = readb(S3C2410_RTCMIN);
119 rtc_tm->tm_hour = readb(S3C2410_RTCHOUR);
120 rtc_tm->tm_mday = readb(S3C2410_RTCDATE);
121 rtc_tm->tm_mon = readb(S3C2410_RTCMON);
122 rtc_tm->tm_year = readb(S3C2410_RTCYEAR);
123 rtc_tm->tm_sec = readb(S3C2410_RTCSEC);
124
125 /* the only way to work out wether the system was mid-update
126 * when we read it is to check the second counter, and if it
127 * is zero, then we re-try the entire read
128 */
129
130 if (rtc_tm->tm_sec == 0 && !have_retried) {
131 have_retried = 1;
132 goto retry_get_time;
133 }
134
135 pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
136 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
137 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
138
139 BCD_TO_BIN(rtc_tm->tm_sec);
140 BCD_TO_BIN(rtc_tm->tm_min);
141 BCD_TO_BIN(rtc_tm->tm_hour);
142 BCD_TO_BIN(rtc_tm->tm_mday);
143 BCD_TO_BIN(rtc_tm->tm_mon);
144 BCD_TO_BIN(rtc_tm->tm_year);
145
146 rtc_tm->tm_year += 100;
147 rtc_tm->tm_mon -= 1;
148
149 return 0;
150}
151
152static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
153{
154 /* the rtc gets round the y2k problem by just not supporting it */
155
156 if (tm->tm_year < 100)
157 return -EINVAL;
158
159 writeb(BIN2BCD(tm->tm_sec), S3C2410_RTCSEC);
160 writeb(BIN2BCD(tm->tm_min), S3C2410_RTCMIN);
161 writeb(BIN2BCD(tm->tm_hour), S3C2410_RTCHOUR);
162 writeb(BIN2BCD(tm->tm_mday), S3C2410_RTCDATE);
163 writeb(BIN2BCD(tm->tm_mon + 1), S3C2410_RTCMON);
164 writeb(BIN2BCD(tm->tm_year - 100), S3C2410_RTCYEAR);
165
166 return 0;
167}
168
169static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
170{
171 struct rtc_time *alm_tm = &alrm->time;
172 unsigned int alm_en;
173
174 alm_tm->tm_sec = readb(S3C2410_ALMSEC);
175 alm_tm->tm_min = readb(S3C2410_ALMMIN);
176 alm_tm->tm_hour = readb(S3C2410_ALMHOUR);
177 alm_tm->tm_mon = readb(S3C2410_ALMMON);
178 alm_tm->tm_mday = readb(S3C2410_ALMDATE);
179 alm_tm->tm_year = readb(S3C2410_ALMYEAR);
180
181 alm_en = readb(S3C2410_RTCALM);
182
183 pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
184 alm_en,
185 alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
186 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
187
188
189 /* decode the alarm enable field */
190
191 if (alm_en & S3C2410_RTCALM_SECEN)
192 BCD_TO_BIN(alm_tm->tm_sec);
193 else
194 alm_tm->tm_sec = 0xff;
195
196 if (alm_en & S3C2410_RTCALM_MINEN)
197 BCD_TO_BIN(alm_tm->tm_min);
198 else
199 alm_tm->tm_min = 0xff;
200
201 if (alm_en & S3C2410_RTCALM_HOUREN)
202 BCD_TO_BIN(alm_tm->tm_hour);
203 else
204 alm_tm->tm_hour = 0xff;
205
206 if (alm_en & S3C2410_RTCALM_DAYEN)
207 BCD_TO_BIN(alm_tm->tm_mday);
208 else
209 alm_tm->tm_mday = 0xff;
210
211 if (alm_en & S3C2410_RTCALM_MONEN) {
212 BCD_TO_BIN(alm_tm->tm_mon);
213 alm_tm->tm_mon -= 1;
214 } else {
215 alm_tm->tm_mon = 0xff;
216 }
217
218 if (alm_en & S3C2410_RTCALM_YEAREN)
219 BCD_TO_BIN(alm_tm->tm_year);
220 else
221 alm_tm->tm_year = 0xffff;
222
223 return 0;
224}
225
226static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
227{
228 struct rtc_time *tm = &alrm->time;
229 unsigned int alrm_en;
230
231 pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
232 alrm->enabled,
233 tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff,
234 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
235
236
237 alrm_en = readb(S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
238 writeb(0x00, S3C2410_RTCALM);
239
240 if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
241 alrm_en |= S3C2410_RTCALM_SECEN;
242 writeb(BIN2BCD(tm->tm_sec), S3C2410_ALMSEC);
243 }
244
245 if (tm->tm_min < 60 && tm->tm_min >= 0) {
246 alrm_en |= S3C2410_RTCALM_MINEN;
247 writeb(BIN2BCD(tm->tm_min), S3C2410_ALMMIN);
248 }
249
250 if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
251 alrm_en |= S3C2410_RTCALM_HOUREN;
252 writeb(BIN2BCD(tm->tm_hour), S3C2410_ALMHOUR);
253 }
254
255 pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en);
256
257 writeb(alrm_en, S3C2410_RTCALM);
258
259 if (0) {
260 alrm_en = readb(S3C2410_RTCALM);
261 alrm_en &= ~S3C2410_RTCALM_ALMEN;
262 writeb(alrm_en, S3C2410_RTCALM);
263 disable_irq_wake(s3c_rtc_alarmno);
264 }
265
266 if (alrm->enabled)
267 enable_irq_wake(s3c_rtc_alarmno);
268 else
269 disable_irq_wake(s3c_rtc_alarmno);
270
271 return 0;
272}
273
274static int s3c_rtc_ioctl(struct device *dev,
275 unsigned int cmd, unsigned long arg)
276{
277 unsigned int ret = -ENOIOCTLCMD;
278
279 switch (cmd) {
280 case RTC_AIE_OFF:
281 case RTC_AIE_ON:
282 s3c_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0);
283 ret = 0;
284 break;
285
286 case RTC_PIE_OFF:
287 case RTC_PIE_ON:
288 tick_count = 0;
289 s3c_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0);
290 ret = 0;
291 break;
292
293 case RTC_IRQP_READ:
294 ret = put_user(s3c_rtc_freq, (unsigned long __user *)arg);
295 break;
296
297 case RTC_IRQP_SET:
298 /* check for power of 2 */
299
300 if ((arg & (arg-1)) != 0 || arg < 1) {
301 ret = -EINVAL;
302 goto exit;
303 }
304
305 pr_debug("s3c2410_rtc: setting frequency %ld\n", arg);
306
307 s3c_rtc_setfreq(arg);
308 ret = 0;
309 break;
310
311 case RTC_UIE_ON:
312 case RTC_UIE_OFF:
313 ret = -EINVAL;
314 }
315
316 exit:
317 return ret;
318}
319
320static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
321{
322 unsigned int rtcalm = readb(S3C2410_RTCALM);
323 unsigned int ticnt = readb (S3C2410_TICNT);
324
325 seq_printf(seq, "alarm_IRQ\t: %s\n",
326 (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" );
327
328 seq_printf(seq, "periodic_IRQ\t: %s\n",
329 (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" );
330
331 seq_printf(seq, "periodic_freq\t: %d\n", s3c_rtc_freq);
332
333 return 0;
334}
335
336static int s3c_rtc_open(struct device *dev)
337{
338 struct platform_device *pdev = to_platform_device(dev);
339 struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
340 int ret;
341
342 ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq,
343 SA_INTERRUPT, "s3c2410-rtc alarm", rtc_dev);
344
345 if (ret) {
346 dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);
347 return ret;
348 }
349
350 ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,
351 SA_INTERRUPT, "s3c2410-rtc tick", rtc_dev);
352
353 if (ret) {
354 dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
355 goto tick_err;
356 }
357
358 return ret;
359
360 tick_err:
361 free_irq(s3c_rtc_alarmno, rtc_dev);
362 return ret;
363}
364
365static void s3c_rtc_release(struct device *dev)
366{
367 struct platform_device *pdev = to_platform_device(dev);
368 struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
369
370 /* do not clear AIE here, it may be needed for wake */
371
372 s3c_rtc_setpie(0);
373 free_irq(s3c_rtc_alarmno, rtc_dev);
374 free_irq(s3c_rtc_tickno, rtc_dev);
375}
376
377static struct rtc_class_ops s3c_rtcops = {
378 .open = s3c_rtc_open,
379 .release = s3c_rtc_release,
380 .ioctl = s3c_rtc_ioctl,
381 .read_time = s3c_rtc_gettime,
382 .set_time = s3c_rtc_settime,
383 .read_alarm = s3c_rtc_getalarm,
384 .set_alarm = s3c_rtc_setalarm,
385 .proc = s3c_rtc_proc,
386};
387
388static void s3c_rtc_enable(struct platform_device *pdev, int en)
389{
390 unsigned int tmp;
391
392 if (s3c_rtc_base == NULL)
393 return;
394
395 if (!en) {
396 tmp = readb(S3C2410_RTCCON);
397 writeb(tmp & ~S3C2410_RTCCON_RTCEN, S3C2410_RTCCON);
398
399 tmp = readb(S3C2410_TICNT);
400 writeb(tmp & ~S3C2410_TICNT_ENABLE, S3C2410_TICNT);
401 } else {
402 /* re-enable the device, and check it is ok */
403
404 if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){
405 dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
406
407 tmp = readb(S3C2410_RTCCON);
408 writeb(tmp | S3C2410_RTCCON_RTCEN , S3C2410_RTCCON);
409 }
410
411 if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){
412 dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n");
413
414 tmp = readb(S3C2410_RTCCON);
415 writeb(tmp& ~S3C2410_RTCCON_CNTSEL , S3C2410_RTCCON);
416 }
417
418 if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){
419 dev_info(&pdev->dev, "removing RTCCON_CLKRST\n");
420
421 tmp = readb(S3C2410_RTCCON);
422 writeb(tmp & ~S3C2410_RTCCON_CLKRST, S3C2410_RTCCON);
423 }
424 }
425}
426
427static int s3c_rtc_remove(struct platform_device *dev)
428{
429 struct rtc_device *rtc = platform_get_drvdata(dev);
430
431 platform_set_drvdata(dev, NULL);
432 rtc_device_unregister(rtc);
433
434 s3c_rtc_setpie(0);
435 s3c_rtc_setaie(0);
436
437 iounmap(s3c_rtc_base);
438 release_resource(s3c_rtc_mem);
439 kfree(s3c_rtc_mem);
440
441 return 0;
442}
443
444static int s3c_rtc_probe(struct platform_device *pdev)
445{
446 struct rtc_device *rtc;
447 struct resource *res;
448 int ret;
449
450 pr_debug("%s: probe=%p\n", __FUNCTION__, pdev);
451
452 /* find the IRQs */
453
454 s3c_rtc_tickno = platform_get_irq(pdev, 1);
455 if (s3c_rtc_tickno < 0) {
456 dev_err(&pdev->dev, "no irq for rtc tick\n");
457 return -ENOENT;
458 }
459
460 s3c_rtc_alarmno = platform_get_irq(pdev, 0);
461 if (s3c_rtc_alarmno < 0) {
462 dev_err(&pdev->dev, "no irq for alarm\n");
463 return -ENOENT;
464 }
465
466 pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n",
467 s3c_rtc_tickno, s3c_rtc_alarmno);
468
469 /* get the memory region */
470
471 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
472 if (res == NULL) {
473 dev_err(&pdev->dev, "failed to get memory region resource\n");
474 return -ENOENT;
475 }
476
477 s3c_rtc_mem = request_mem_region(res->start,
478 res->end-res->start+1,
479 pdev->name);
480
481 if (s3c_rtc_mem == NULL) {
482 dev_err(&pdev->dev, "failed to reserve memory region\n");
483 ret = -ENOENT;
484 goto err_nores;
485 }
486
487 s3c_rtc_base = ioremap(res->start, res->end - res->start + 1);
488 if (s3c_rtc_base == NULL) {
489 dev_err(&pdev->dev, "failed ioremap()\n");
490 ret = -EINVAL;
491 goto err_nomap;
492 }
493
494 /* check to see if everything is setup correctly */
495
496 s3c_rtc_enable(pdev, 1);
497
498 pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON));
499
500 s3c_rtc_setfreq(s3c_rtc_freq);
501
502 /* register RTC and exit */
503
504 rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops,
505 THIS_MODULE);
506
507 if (IS_ERR(rtc)) {
508 dev_err(&pdev->dev, "cannot attach rtc\n");
509 ret = PTR_ERR(rtc);
510 goto err_nortc;
511 }
512
513 rtc->max_user_freq = 128;
514
515 platform_set_drvdata(pdev, rtc);
516 return 0;
517
518 err_nortc:
519 s3c_rtc_enable(pdev, 0);
520 iounmap(s3c_rtc_base);
521
522 err_nomap:
523 release_resource(s3c_rtc_mem);
524
525 err_nores:
526 return ret;
527}
528
529#ifdef CONFIG_PM
530
531/* RTC Power management control */
532
533static struct timespec s3c_rtc_delta;
534
535static int ticnt_save;
536
537static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
538{
539 struct rtc_time tm;
540 struct timespec time;
541
542 time.tv_nsec = 0;
543
544 /* save TICNT for anyone using periodic interrupts */
545
546 ticnt_save = readb(S3C2410_TICNT);
547
548 /* calculate time delta for suspend */
549
550 s3c_rtc_gettime(&pdev->dev, &tm);
551 rtc_tm_to_time(&tm, &time.tv_sec);
552 save_time_delta(&s3c_rtc_delta, &time);
553 s3c_rtc_enable(pdev, 0);
554
555 return 0;
556}
557
558static int s3c_rtc_resume(struct platform_device *pdev)
559{
560 struct rtc_time tm;
561 struct timespec time;
562
563 time.tv_nsec = 0;
564
565 s3c_rtc_enable(pdev, 1);
566 s3c_rtc_gettime(&pdev->dev, &tm);
567 rtc_tm_to_time(&tm, &time.tv_sec);
568 restore_time_delta(&s3c_rtc_delta, &time);
569
570 writeb(ticnt_save, S3C2410_TICNT);
571 return 0;
572}
573#else
574#define s3c_rtc_suspend NULL
575#define s3c_rtc_resume NULL
576#endif
577
578static struct platform_driver s3c2410_rtcdrv = {
579 .probe = s3c_rtc_probe,
580 .remove = s3c_rtc_remove,
581 .suspend = s3c_rtc_suspend,
582 .resume = s3c_rtc_resume,
583 .driver = {
584 .name = "s3c2410-rtc",
585 .owner = THIS_MODULE,
586 },
587};
588
589static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n";
590
591static int __init s3c_rtc_init(void)
592{
593 printk(banner);
594 return platform_driver_register(&s3c2410_rtcdrv);
595}
596
597static void __exit s3c_rtc_exit(void)
598{
599 platform_driver_unregister(&s3c2410_rtcdrv);
600}
601
602module_init(s3c_rtc_init);
603module_exit(s3c_rtc_exit);
604
605MODULE_DESCRIPTION("Samsung S3C RTC Driver");
606MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
607MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 9cd1cb304bb2..ee4b61ee67b0 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -157,19 +157,19 @@ static int sa1100_rtc_open(struct device *dev)
157{ 157{
158 int ret; 158 int ret;
159 159
160 ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, SA_INTERRUPT, 160 ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
161 "rtc 1Hz", dev); 161 "rtc 1Hz", dev);
162 if (ret) { 162 if (ret) {
163 dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); 163 dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
164 goto fail_ui; 164 goto fail_ui;
165 } 165 }
166 ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, SA_INTERRUPT, 166 ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED,
167 "rtc Alrm", dev); 167 "rtc Alrm", dev);
168 if (ret) { 168 if (ret) {
169 dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); 169 dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
170 goto fail_ai; 170 goto fail_ai;
171 } 171 }
172 ret = request_irq(IRQ_OST1, timer1_interrupt, SA_INTERRUPT, 172 ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED,
173 "rtc timer", dev); 173 "rtc timer", dev);
174 if (ret) { 174 if (ret) {
175 dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1); 175 dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index 4b9291dd4443..bb6d5ff24fd0 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -345,11 +345,11 @@ static int __devinit rtc_probe(struct platform_device *pdev)
345 spin_unlock_irq(&rtc_lock); 345 spin_unlock_irq(&rtc_lock);
346 346
347 irq = ELAPSEDTIME_IRQ; 347 irq = ELAPSEDTIME_IRQ;
348 retval = request_irq(irq, elapsedtime_interrupt, SA_INTERRUPT, 348 retval = request_irq(irq, elapsedtime_interrupt, IRQF_DISABLED,
349 "elapsed_time", pdev); 349 "elapsed_time", pdev);
350 if (retval == 0) { 350 if (retval == 0) {
351 irq = RTCLONG1_IRQ; 351 irq = RTCLONG1_IRQ;
352 retval = request_irq(irq, rtclong1_interrupt, SA_INTERRUPT, 352 retval = request_irq(irq, rtclong1_interrupt, IRQF_DISABLED,
353 "rtclong1", pdev); 353 "rtclong1", pdev);
354 } 354 }
355 355