aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>2006-04-11 01:54:47 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-11 09:18:47 -0400
commit8417eb7a168eee8b9baa744ee5c591868e85529a (patch)
tree24ead87700250799a14f257e7d259b50d550f30c
parent2260a25c93cb356e834f1ab08b419f9897c977b7 (diff)
[PATCH] RTC subsystem: VR41XX driver
This patch updates VR4100 series RTC driver. * This driver supports new RTC subsystem. * Simple set time/read time test worked fine. Signed-off-by: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/char/Kconfig4
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/rtc/Kconfig4
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-vr41xx.c (renamed from drivers/char/vr41xx_rtc.c)404
5 files changed, 84 insertions, 330 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 889cad07774e..402296670d3a 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -805,10 +805,6 @@ config S3C2410_RTC
805 Samsung S3C2410. This can provide periodic interrupt rates 805 Samsung S3C2410. This can provide periodic interrupt rates
806 from 1Hz to 64Hz for user programs, and wakeup from Alarm. 806 from 1Hz to 64Hz for user programs, and wakeup from Alarm.
807 807
808config RTC_VR41XX
809 tristate "NEC VR4100 series Real Time Clock Support"
810 depends on CPU_VR41XX
811
812config COBALT_LCD 808config COBALT_LCD
813 bool "Support for Cobalt LCD" 809 bool "Support for Cobalt LCD"
814 depends on MIPS_COBALT 810 depends on MIPS_COBALT
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index a73cb4956928..f5b01c6d498e 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -67,7 +67,6 @@ obj-$(CONFIG_SGI_DS1286) += ds1286.o
67obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o 67obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
68obj-$(CONFIG_DS1302) += ds1302.o 68obj-$(CONFIG_DS1302) += ds1302.o
69obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o 69obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o
70obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o
71ifeq ($(CONFIG_GENERIC_NVRAM),y) 70ifeq ($(CONFIG_GENERIC_NVRAM),y)
72 obj-$(CONFIG_NVRAM) += generic_nvram.o 71 obj-$(CONFIG_NVRAM) += generic_nvram.o
73else 72else
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 929dd8090578..b4a252b6cdcc 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -147,6 +147,10 @@ config RTC_DRV_SA1100
147 To compile this driver as a module, choose M here: the 147 To compile this driver as a module, choose M here: the
148 module will be called rtc-sa1100. 148 module will be called rtc-sa1100.
149 149
150config RTC_DRV_VR41XX
151 tristate "NEC VR4100 series RTC"
152 depends on RTC_CLASS && CPU_VR41XX
153
150config RTC_DRV_TEST 154config RTC_DRV_TEST
151 tristate "Test driver/device" 155 tristate "Test driver/device"
152 depends on RTC_CLASS 156 depends on RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 8d4c7fe88d58..a9ca0f171686 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
19obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o 19obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
20obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o 20obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
21obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o 21obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
22obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
diff --git a/drivers/char/vr41xx_rtc.c b/drivers/rtc/rtc-vr41xx.c
index b109d9a502d6..4d49fd501198 100644
--- a/drivers/char/vr41xx_rtc.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for NEC VR4100 series Real Time Clock unit. 2 * Driver for NEC VR4100 series Real Time Clock unit.
3 * 3 *
4 * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 4 * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -17,23 +17,18 @@
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */ 19 */
20#include <linux/platform_device.h>
21#include <linux/fs.h> 20#include <linux/fs.h>
22#include <linux/init.h> 21#include <linux/init.h>
23#include <linux/ioport.h> 22#include <linux/ioport.h>
24#include <linux/irq.h> 23#include <linux/irq.h>
25#include <linux/mc146818rtc.h>
26#include <linux/miscdevice.h>
27#include <linux/module.h> 24#include <linux/module.h>
28#include <linux/poll.h> 25#include <linux/platform_device.h>
29#include <linux/rtc.h> 26#include <linux/rtc.h>
30#include <linux/spinlock.h> 27#include <linux/spinlock.h>
31#include <linux/types.h> 28#include <linux/types.h>
32#include <linux/wait.h>
33 29
34#include <asm/div64.h> 30#include <asm/div64.h>
35#include <asm/io.h> 31#include <asm/io.h>
36#include <asm/time.h>
37#include <asm/uaccess.h> 32#include <asm/uaccess.h>
38#include <asm/vr41xx/vr41xx.h> 33#include <asm/vr41xx/vr41xx.h>
39 34
@@ -99,27 +94,11 @@ static void __iomem *rtc2_base;
99 94
100static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */ 95static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */
101 96
102static spinlock_t rtc_task_lock; 97static spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
103static wait_queue_head_t rtc_wait;
104static unsigned long rtc_irq_data;
105static struct fasync_struct *rtc_async_queue;
106static rtc_task_t *rtc_callback;
107static char rtc_name[] = "RTC"; 98static char rtc_name[] = "RTC";
108static unsigned long periodic_frequency; 99static unsigned long periodic_frequency;
109static unsigned long periodic_count; 100static unsigned long periodic_count;
110 101
111typedef enum {
112 RTC_RELEASE,
113 RTC_OPEN,
114} rtc_status_t;
115
116static rtc_status_t rtc_status;
117
118typedef enum {
119 FUNCTION_RTC_IOCTL,
120 FUNCTION_RTC_CONTROL,
121} rtc_callfrom_t;
122
123struct resource rtc_resource[2] = { 102struct resource rtc_resource[2] = {
124 { .name = rtc_name, 103 { .name = rtc_name,
125 .flags = IORESOURCE_MEM, }, 104 .flags = IORESOURCE_MEM, },
@@ -129,7 +108,9 @@ struct resource rtc_resource[2] = {
129 108
130static inline unsigned long read_elapsed_second(void) 109static inline unsigned long read_elapsed_second(void)
131{ 110{
111
132 unsigned long first_low, first_mid, first_high; 112 unsigned long first_low, first_mid, first_high;
113
133 unsigned long second_low, second_mid, second_high; 114 unsigned long second_low, second_mid, second_high;
134 115
135 do { 116 do {
@@ -156,50 +137,36 @@ static inline void write_elapsed_second(unsigned long sec)
156 spin_unlock_irq(&rtc_lock); 137 spin_unlock_irq(&rtc_lock);
157} 138}
158 139
159static void set_alarm(struct rtc_time *time) 140static void vr41xx_rtc_release(struct device *dev)
160{ 141{
161 unsigned long alarm_sec;
162
163 alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
164 time->tm_hour, time->tm_min, time->tm_sec);
165
166 spin_lock_irq(&rtc_lock);
167
168 rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
169 rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
170 rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
171
172 spin_unlock_irq(&rtc_lock);
173}
174
175static void read_alarm(struct rtc_time *time)
176{
177 unsigned long low, mid, high;
178 142
179 spin_lock_irq(&rtc_lock); 143 spin_lock_irq(&rtc_lock);
180 144
181 low = rtc1_read(ECMPLREG); 145 rtc1_write(ECMPLREG, 0);
182 mid = rtc1_read(ECMPMREG); 146 rtc1_write(ECMPMREG, 0);
183 high = rtc1_read(ECMPHREG); 147 rtc1_write(ECMPHREG, 0);
148 rtc1_write(RTCL1LREG, 0);
149 rtc1_write(RTCL1HREG, 0);
184 150
185 spin_unlock_irq(&rtc_lock); 151 spin_unlock_irq(&rtc_lock);
186 152
187 to_tm((high << 17) | (mid << 1) | (low >> 15), time); 153 disable_irq(ELAPSEDTIME_IRQ);
188 time->tm_year -= 1900; 154 disable_irq(RTCLONG1_IRQ);
189} 155}
190 156
191static void read_time(struct rtc_time *time) 157static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time)
192{ 158{
193 unsigned long epoch_sec, elapsed_sec; 159 unsigned long epoch_sec, elapsed_sec;
194 160
195 epoch_sec = mktime(epoch, 1, 1, 0, 0, 0); 161 epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
196 elapsed_sec = read_elapsed_second(); 162 elapsed_sec = read_elapsed_second();
197 163
198 to_tm(epoch_sec + elapsed_sec, time); 164 rtc_time_to_tm(epoch_sec + elapsed_sec, time);
199 time->tm_year -= 1900; 165
166 return 0;
200} 167}
201 168
202static void set_time(struct rtc_time *time) 169static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time)
203{ 170{
204 unsigned long epoch_sec, current_sec; 171 unsigned long epoch_sec, current_sec;
205 172
@@ -208,73 +175,49 @@ static void set_time(struct rtc_time *time)
208 time->tm_hour, time->tm_min, time->tm_sec); 175 time->tm_hour, time->tm_min, time->tm_sec);
209 176
210 write_elapsed_second(current_sec - epoch_sec); 177 write_elapsed_second(current_sec - epoch_sec);
178
179 return 0;
211} 180}
212 181
213static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) 182static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
214{ 183{
215 DECLARE_WAITQUEUE(wait, current); 184 unsigned long low, mid, high;
216 unsigned long irq_data; 185 struct rtc_time *time = &wkalrm->time;
217 int retval = 0;
218
219 if (count != sizeof(unsigned int) && count != sizeof(unsigned long))
220 return -EINVAL;
221
222 add_wait_queue(&rtc_wait, &wait);
223
224 do {
225 __set_current_state(TASK_INTERRUPTIBLE);
226 186
227 spin_lock_irq(&rtc_lock); 187 spin_lock_irq(&rtc_lock);
228 irq_data = rtc_irq_data;
229 rtc_irq_data = 0;
230 spin_unlock_irq(&rtc_lock);
231 188
232 if (irq_data != 0) 189 low = rtc1_read(ECMPLREG);
233 break; 190 mid = rtc1_read(ECMPMREG);
191 high = rtc1_read(ECMPHREG);
234 192
235 if (file->f_flags & O_NONBLOCK) { 193 spin_unlock_irq(&rtc_lock);
236 retval = -EAGAIN;
237 break;
238 }
239 194
240 if (signal_pending(current)) { 195 rtc_time_to_tm((high << 17) | (mid << 1) | (low >> 15), time);
241 retval = -ERESTARTSYS;
242 break;
243 }
244 } while (1);
245 196
246 if (retval == 0) { 197 return 0;
247 if (count == sizeof(unsigned int)) { 198}
248 retval = put_user(irq_data, (unsigned int __user *)buf);
249 if (retval == 0)
250 retval = sizeof(unsigned int);
251 } else {
252 retval = put_user(irq_data, (unsigned long __user *)buf);
253 if (retval == 0)
254 retval = sizeof(unsigned long);
255 }
256 199
257 } 200static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
201{
202 unsigned long alarm_sec;
203 struct rtc_time *time = &wkalrm->time;
258 204
259 __set_current_state(TASK_RUNNING); 205 alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
260 remove_wait_queue(&rtc_wait, &wait); 206 time->tm_hour, time->tm_min, time->tm_sec);
261 207
262 return retval; 208 spin_lock_irq(&rtc_lock);
263}
264 209
265static unsigned int rtc_poll(struct file *file, struct poll_table_struct *table) 210 rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
266{ 211 rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
267 poll_wait(file, &rtc_wait, table); 212 rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
268 213
269 if (rtc_irq_data != 0) 214 spin_unlock_irq(&rtc_lock);
270 return POLLIN | POLLRDNORM;
271 215
272 return 0; 216 return 0;
273} 217}
274 218
275static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from) 219static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
276{ 220{
277 struct rtc_time time;
278 unsigned long count; 221 unsigned long count;
279 222
280 switch (cmd) { 223 switch (cmd) {
@@ -290,33 +233,6 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from
290 case RTC_PIE_OFF: 233 case RTC_PIE_OFF:
291 disable_irq(RTCLONG1_IRQ); 234 disable_irq(RTCLONG1_IRQ);
292 break; 235 break;
293 case RTC_ALM_SET:
294 if (copy_from_user(&time, (struct rtc_time __user *)arg,
295 sizeof(struct rtc_time)))
296 return -EFAULT;
297
298 set_alarm(&time);
299 break;
300 case RTC_ALM_READ:
301 memset(&time, 0, sizeof(struct rtc_time));
302 read_alarm(&time);
303 break;
304 case RTC_RD_TIME:
305 memset(&time, 0, sizeof(struct rtc_time));
306 read_time(&time);
307 if (copy_to_user((void __user *)arg, &time, sizeof(struct rtc_time)))
308 return -EFAULT;
309 break;
310 case RTC_SET_TIME:
311 if (capable(CAP_SYS_TIME) == 0)
312 return -EACCES;
313
314 if (copy_from_user(&time, (struct rtc_time __user *)arg,
315 sizeof(struct rtc_time)))
316 return -EFAULT;
317
318 set_time(&time);
319 break;
320 case RTC_IRQP_READ: 236 case RTC_IRQP_READ:
321 return put_user(periodic_frequency, (unsigned long __user *)arg); 237 return put_user(periodic_frequency, (unsigned long __user *)arg);
322 break; 238 break;
@@ -324,8 +240,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from
324 if (arg > MAX_PERIODIC_RATE) 240 if (arg > MAX_PERIODIC_RATE)
325 return -EINVAL; 241 return -EINVAL;
326 242
327 if (from == FUNCTION_RTC_IOCTL && arg > MAX_USER_PERIODIC_RATE && 243 if (arg > MAX_USER_PERIODIC_RATE && capable(CAP_SYS_RESOURCE) == 0)
328 capable(CAP_SYS_RESOURCE) == 0)
329 return -EACCES; 244 return -EACCES;
330 245
331 periodic_frequency = arg; 246 periodic_frequency = arg;
@@ -361,205 +276,46 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from
361 return 0; 276 return 0;
362} 277}
363 278
364static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
365 unsigned long arg)
366{
367 return rtc_do_ioctl(cmd, arg, FUNCTION_RTC_IOCTL);
368}
369
370static int rtc_open(struct inode *inode, struct file *file)
371{
372 spin_lock_irq(&rtc_lock);
373
374 if (rtc_status == RTC_OPEN) {
375 spin_unlock_irq(&rtc_lock);
376 return -EBUSY;
377 }
378
379 rtc_status = RTC_OPEN;
380 rtc_irq_data = 0;
381
382 spin_unlock_irq(&rtc_lock);
383
384 return 0;
385}
386
387static int rtc_release(struct inode *inode, struct file *file)
388{
389 if (file->f_flags & FASYNC)
390 (void)fasync_helper(-1, file, 0, &rtc_async_queue);
391
392 spin_lock_irq(&rtc_lock);
393
394 rtc1_write(ECMPLREG, 0);
395 rtc1_write(ECMPMREG, 0);
396 rtc1_write(ECMPHREG, 0);
397 rtc1_write(RTCL1LREG, 0);
398 rtc1_write(RTCL1HREG, 0);
399
400 rtc_status = RTC_RELEASE;
401
402 spin_unlock_irq(&rtc_lock);
403
404 disable_irq(ELAPSEDTIME_IRQ);
405 disable_irq(RTCLONG1_IRQ);
406
407 return 0;
408}
409
410static int rtc_fasync(int fd, struct file *file, int on)
411{
412 return fasync_helper(fd, file, on, &rtc_async_queue);
413}
414
415static struct file_operations rtc_fops = {
416 .owner = THIS_MODULE,
417 .llseek = no_llseek,
418 .read = rtc_read,
419 .poll = rtc_poll,
420 .ioctl = rtc_ioctl,
421 .open = rtc_open,
422 .release = rtc_release,
423 .fasync = rtc_fasync,
424};
425
426static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id, struct pt_regs *regs) 279static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id, struct pt_regs *regs)
427{ 280{
428 spin_lock(&rtc_lock); 281 struct platform_device *pdev = (struct platform_device *)dev_id;
429 rtc2_write(RTCINTREG, ELAPSEDTIME_INT); 282 struct rtc_device *rtc = platform_get_drvdata(pdev);
430
431 rtc_irq_data += 0x100;
432 rtc_irq_data &= ~0xff;
433 rtc_irq_data |= RTC_AF;
434 spin_unlock(&rtc_lock);
435 283
436 spin_lock(&rtc_lock); 284 rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
437 if (rtc_callback)
438 rtc_callback->func(rtc_callback->private_data);
439 spin_unlock(&rtc_lock);
440
441 wake_up_interruptible(&rtc_wait);
442 285
443 kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); 286 rtc_update_irq(&rtc->class_dev, 1, RTC_AF);
444 287
445 return IRQ_HANDLED; 288 return IRQ_HANDLED;
446} 289}
447 290
448static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *regs) 291static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
449{ 292{
293 struct platform_device *pdev = (struct platform_device *)dev_id;
294 struct rtc_device *rtc = platform_get_drvdata(pdev);
450 unsigned long count = periodic_count; 295 unsigned long count = periodic_count;
451 296
452 spin_lock(&rtc_lock);
453 rtc2_write(RTCINTREG, RTCLONG1_INT); 297 rtc2_write(RTCINTREG, RTCLONG1_INT);
454 298
455 rtc1_write(RTCL1LREG, count); 299 rtc1_write(RTCL1LREG, count);
456 rtc1_write(RTCL1HREG, count >> 16); 300 rtc1_write(RTCL1HREG, count >> 16);
457 301
458 rtc_irq_data += 0x100; 302 rtc_update_irq(&rtc->class_dev, 1, RTC_PF);
459 rtc_irq_data &= ~0xff;
460 rtc_irq_data |= RTC_PF;
461 spin_unlock(&rtc_lock);
462
463 spin_lock(&rtc_task_lock);
464 if (rtc_callback)
465 rtc_callback->func(rtc_callback->private_data);
466 spin_unlock(&rtc_task_lock);
467
468 wake_up_interruptible(&rtc_wait);
469
470 kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
471 303
472 return IRQ_HANDLED; 304 return IRQ_HANDLED;
473} 305}
474 306
475int rtc_register(rtc_task_t *task) 307static struct rtc_class_ops vr41xx_rtc_ops = {
476{ 308 .release = vr41xx_rtc_release,
477 if (task == NULL || task->func == NULL) 309 .ioctl = vr41xx_rtc_ioctl,
478 return -EINVAL; 310 .read_time = vr41xx_rtc_read_time,
479 311 .set_time = vr41xx_rtc_set_time,
480 spin_lock_irq(&rtc_lock); 312 .read_alarm = vr41xx_rtc_read_alarm,
481 if (rtc_status == RTC_OPEN) { 313 .set_alarm = vr41xx_rtc_set_alarm,
482 spin_unlock_irq(&rtc_lock);
483 return -EBUSY;
484 }
485
486 spin_lock(&rtc_task_lock);
487 if (rtc_callback != NULL) {
488 spin_unlock(&rtc_task_lock);
489 spin_unlock_irq(&rtc_task_lock);
490 return -EBUSY;
491 }
492
493 rtc_callback = task;
494 spin_unlock(&rtc_task_lock);
495
496 rtc_status = RTC_OPEN;
497
498 spin_unlock_irq(&rtc_lock);
499
500 return 0;
501}
502
503EXPORT_SYMBOL_GPL(rtc_register);
504
505int rtc_unregister(rtc_task_t *task)
506{
507 spin_lock_irq(&rtc_task_lock);
508 if (task == NULL || rtc_callback != task) {
509 spin_unlock_irq(&rtc_task_lock);
510 return -ENXIO;
511 }
512
513 spin_lock(&rtc_lock);
514
515 rtc1_write(ECMPLREG, 0);
516 rtc1_write(ECMPMREG, 0);
517 rtc1_write(ECMPHREG, 0);
518 rtc1_write(RTCL1LREG, 0);
519 rtc1_write(RTCL1HREG, 0);
520
521 rtc_status = RTC_RELEASE;
522
523 spin_unlock(&rtc_lock);
524
525 rtc_callback = NULL;
526
527 spin_unlock_irq(&rtc_task_lock);
528
529 disable_irq(ELAPSEDTIME_IRQ);
530 disable_irq(RTCLONG1_IRQ);
531
532 return 0;
533}
534
535EXPORT_SYMBOL_GPL(rtc_unregister);
536
537int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
538{
539 int retval = 0;
540
541 spin_lock_irq(&rtc_task_lock);
542
543 if (rtc_callback != task)
544 retval = -ENXIO;
545 else
546 rtc_do_ioctl(cmd, arg, FUNCTION_RTC_CONTROL);
547
548 spin_unlock_irq(&rtc_task_lock);
549
550 return retval;
551}
552
553EXPORT_SYMBOL_GPL(rtc_control);
554
555static struct miscdevice rtc_miscdevice = {
556 .minor = RTC_MINOR,
557 .name = rtc_name,
558 .fops = &rtc_fops,
559}; 314};
560 315
561static int __devinit rtc_probe(struct platform_device *pdev) 316static int __devinit rtc_probe(struct platform_device *pdev)
562{ 317{
318 struct rtc_device *rtc;
563 unsigned int irq; 319 unsigned int irq;
564 int retval; 320 int retval;
565 321
@@ -577,13 +333,13 @@ static int __devinit rtc_probe(struct platform_device *pdev)
577 return -EBUSY; 333 return -EBUSY;
578 } 334 }
579 335
580 retval = misc_register(&rtc_miscdevice); 336 rtc = rtc_device_register(rtc_name, &pdev->dev, &vr41xx_rtc_ops, THIS_MODULE);
581 if (retval < 0) { 337 if (IS_ERR(rtc)) {
582 iounmap(rtc1_base); 338 iounmap(rtc1_base);
583 iounmap(rtc2_base); 339 iounmap(rtc2_base);
584 rtc1_base = NULL; 340 rtc1_base = NULL;
585 rtc2_base = NULL; 341 rtc2_base = NULL;
586 return retval; 342 return PTR_ERR(rtc);
587 } 343 }
588 344
589 spin_lock_irq(&rtc_lock); 345 spin_lock_irq(&rtc_lock);
@@ -594,24 +350,20 @@ static int __devinit rtc_probe(struct platform_device *pdev)
594 rtc1_write(RTCL1LREG, 0); 350 rtc1_write(RTCL1LREG, 0);
595 rtc1_write(RTCL1HREG, 0); 351 rtc1_write(RTCL1HREG, 0);
596 352
597 rtc_status = RTC_RELEASE;
598 rtc_irq_data = 0;
599
600 spin_unlock_irq(&rtc_lock); 353 spin_unlock_irq(&rtc_lock);
601 354
602 init_waitqueue_head(&rtc_wait);
603
604 irq = ELAPSEDTIME_IRQ; 355 irq = ELAPSEDTIME_IRQ;
605 retval = request_irq(irq, elapsedtime_interrupt, SA_INTERRUPT, 356 retval = request_irq(irq, elapsedtime_interrupt, SA_INTERRUPT,
606 "elapsed_time", NULL); 357 "elapsed_time", pdev);
607 if (retval == 0) { 358 if (retval == 0) {
608 irq = RTCLONG1_IRQ; 359 irq = RTCLONG1_IRQ;
609 retval = request_irq(irq, rtclong1_interrupt, SA_INTERRUPT, 360 retval = request_irq(irq, rtclong1_interrupt, SA_INTERRUPT,
610 "rtclong1", NULL); 361 "rtclong1", pdev);
611 } 362 }
612 363
613 if (retval < 0) { 364 if (retval < 0) {
614 printk(KERN_ERR "rtc: IRQ%d is busy\n", irq); 365 printk(KERN_ERR "rtc: IRQ%d is busy\n", irq);
366 rtc_device_unregister(rtc);
615 if (irq == RTCLONG1_IRQ) 367 if (irq == RTCLONG1_IRQ)
616 free_irq(ELAPSEDTIME_IRQ, NULL); 368 free_irq(ELAPSEDTIME_IRQ, NULL);
617 iounmap(rtc1_base); 369 iounmap(rtc1_base);
@@ -621,23 +373,25 @@ static int __devinit rtc_probe(struct platform_device *pdev)
621 return retval; 373 return retval;
622 } 374 }
623 375
376 platform_set_drvdata(pdev, rtc);
377
624 disable_irq(ELAPSEDTIME_IRQ); 378 disable_irq(ELAPSEDTIME_IRQ);
625 disable_irq(RTCLONG1_IRQ); 379 disable_irq(RTCLONG1_IRQ);
626 380
627 spin_lock_init(&rtc_task_lock);
628
629 printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n"); 381 printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n");
630 382
631 return 0; 383 return 0;
632} 384}
633 385
634static int __devexit rtc_remove(struct platform_device *dev) 386static int __devexit rtc_remove(struct platform_device *pdev)
635{ 387{
636 int retval; 388 struct rtc_device *rtc;
637 389
638 retval = misc_deregister(&rtc_miscdevice); 390 rtc = platform_get_drvdata(pdev);
639 if (retval < 0) 391 if (rtc != NULL)
640 return retval; 392 rtc_device_unregister(rtc);
393
394 platform_set_drvdata(pdev, NULL);
641 395
642 free_irq(ELAPSEDTIME_IRQ, NULL); 396 free_irq(ELAPSEDTIME_IRQ, NULL);
643 free_irq(RTCLONG1_IRQ, NULL); 397 free_irq(RTCLONG1_IRQ, NULL);
@@ -651,7 +405,7 @@ static int __devexit rtc_remove(struct platform_device *dev)
651 405
652static struct platform_device *rtc_platform_device; 406static struct platform_device *rtc_platform_device;
653 407
654static struct platform_driver rtc_device_driver = { 408static struct platform_driver rtc_platform_driver = {
655 .probe = rtc_probe, 409 .probe = rtc_probe,
656 .remove = __devexit_p(rtc_remove), 410 .remove = __devexit_p(rtc_remove),
657 .driver = { 411 .driver = {
@@ -686,7 +440,7 @@ static int __init vr41xx_rtc_init(void)
686 } 440 }
687 441
688 rtc_platform_device = platform_device_alloc("RTC", -1); 442 rtc_platform_device = platform_device_alloc("RTC", -1);
689 if (!rtc_platform_device) 443 if (rtc_platform_device == NULL)
690 return -ENOMEM; 444 return -ENOMEM;
691 445
692 retval = platform_device_add_resources(rtc_platform_device, 446 retval = platform_device_add_resources(rtc_platform_device,
@@ -700,7 +454,7 @@ static int __init vr41xx_rtc_init(void)
700 return retval; 454 return retval;
701 } 455 }
702 456
703 retval = platform_driver_register(&rtc_device_driver); 457 retval = platform_driver_register(&rtc_platform_driver);
704 if (retval < 0) 458 if (retval < 0)
705 platform_device_unregister(rtc_platform_device); 459 platform_device_unregister(rtc_platform_device);
706 460
@@ -709,7 +463,7 @@ static int __init vr41xx_rtc_init(void)
709 463
710static void __exit vr41xx_rtc_exit(void) 464static void __exit vr41xx_rtc_exit(void)
711{ 465{
712 platform_driver_unregister(&rtc_device_driver); 466 platform_driver_unregister(&rtc_platform_driver);
713 platform_device_unregister(rtc_platform_device); 467 platform_device_unregister(rtc_platform_device);
714} 468}
715 469