aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig2
-rw-r--r--drivers/rtc/Makefile3
-rw-r--r--drivers/rtc/class.c8
-rw-r--r--drivers/rtc/rtc-core.h15
-rw-r--r--drivers/rtc/rtc-dev.c106
5 files changed, 46 insertions, 88 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 1b853c4ff86d..48eca80bbfc4 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -71,7 +71,7 @@ config RTC_INTF_PROC
71 will be called rtc-proc. 71 will be called rtc-proc.
72 72
73config RTC_INTF_DEV 73config RTC_INTF_DEV
74 tristate "dev" 74 boolean "dev"
75 depends on RTC_CLASS 75 depends on RTC_CLASS
76 default RTC_CLASS 76 default RTC_CLASS
77 help 77 help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index f9a3e0130f4e..4820dcc6a8fa 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -11,9 +11,10 @@ obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o
11obj-$(CONFIG_RTC_CLASS) += rtc-core.o 11obj-$(CONFIG_RTC_CLASS) += rtc-core.o
12rtc-core-y := class.o interface.o 12rtc-core-y := class.o interface.o
13 13
14rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o
15
14obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o 16obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
15obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o 17obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
16obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o
17 18
18obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o 19obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
19obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o 20obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 04aaa6347234..786406c2cf78 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -16,6 +16,9 @@
16#include <linux/kdev_t.h> 16#include <linux/kdev_t.h>
17#include <linux/idr.h> 17#include <linux/idr.h>
18 18
19#include "rtc-core.h"
20
21
19static DEFINE_IDR(rtc_idr); 22static DEFINE_IDR(rtc_idr);
20static DEFINE_MUTEX(idr_lock); 23static DEFINE_MUTEX(idr_lock);
21struct class *rtc_class; 24struct class *rtc_class;
@@ -85,6 +88,8 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
85 if (err) 88 if (err)
86 goto exit_kfree; 89 goto exit_kfree;
87 90
91 rtc_dev_add_device(rtc);
92
88 dev_info(dev, "rtc core: registered %s as %s\n", 93 dev_info(dev, "rtc core: registered %s as %s\n",
89 rtc->name, rtc->class_dev.class_id); 94 rtc->name, rtc->class_dev.class_id);
90 95
@@ -118,6 +123,7 @@ void rtc_device_unregister(struct rtc_device *rtc)
118 /* remove innards of this RTC, then disable it, before 123 /* remove innards of this RTC, then disable it, before
119 * letting any rtc_class_open() users access it again 124 * letting any rtc_class_open() users access it again
120 */ 125 */
126 rtc_dev_del_device(rtc);
121 class_device_unregister(&rtc->class_dev); 127 class_device_unregister(&rtc->class_dev);
122 rtc->ops = NULL; 128 rtc->ops = NULL;
123 mutex_unlock(&rtc->ops_lock); 129 mutex_unlock(&rtc->ops_lock);
@@ -140,11 +146,13 @@ static int __init rtc_init(void)
140 printk(KERN_ERR "%s: couldn't create class\n", __FILE__); 146 printk(KERN_ERR "%s: couldn't create class\n", __FILE__);
141 return PTR_ERR(rtc_class); 147 return PTR_ERR(rtc_class);
142 } 148 }
149 rtc_dev_init();
143 return 0; 150 return 0;
144} 151}
145 152
146static void __exit rtc_exit(void) 153static void __exit rtc_exit(void)
147{ 154{
155 rtc_dev_exit();
148 class_destroy(rtc_class); 156 class_destroy(rtc_class);
149} 157}
150 158
diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h
new file mode 100644
index 000000000000..c3c495ed1869
--- /dev/null
+++ b/drivers/rtc/rtc-core.h
@@ -0,0 +1,15 @@
1#ifdef CONFIG_RTC_INTF_DEV
2
3extern void __init rtc_dev_init(void);
4extern void __exit rtc_dev_exit(void);
5extern void rtc_dev_add_device(struct rtc_device *rtc);
6extern void rtc_dev_del_device(struct rtc_device *rtc);
7
8#else
9
10#define rtc_dev_init() do{}while(0)
11#define rtc_dev_exit() do{}while(0)
12#define rtc_dev_add_device(r) do{}while(0)
13#define rtc_dev_del_device(r) do{}while(0)
14
15#endif
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 137330b8636b..3fa6138523b5 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -13,8 +13,8 @@
13 13
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/rtc.h> 15#include <linux/rtc.h>
16#include "rtc-core.h"
16 17
17static struct class *rtc_dev_class;
18static dev_t rtc_devt; 18static dev_t rtc_devt;
19 19
20#define RTC_DEV_MAX 16 /* 16 RTCs should be enough for everyone... */ 20#define RTC_DEV_MAX 16 /* 16 RTCs should be enough for everyone... */
@@ -397,17 +397,18 @@ static const struct file_operations rtc_dev_fops = {
397 397
398/* insertion/removal hooks */ 398/* insertion/removal hooks */
399 399
400static int rtc_dev_add_device(struct class_device *class_dev, 400void rtc_dev_add_device(struct rtc_device *rtc)
401 struct class_interface *class_intf)
402{ 401{
403 int err = 0; 402 if (!rtc_devt)
404 struct rtc_device *rtc = to_rtc_device(class_dev); 403 return;
405 404
406 if (rtc->id >= RTC_DEV_MAX) { 405 if (rtc->id >= RTC_DEV_MAX) {
407 dev_err(class_dev->dev, "too many RTCs\n"); 406 pr_debug("%s: too many RTC devices\n", rtc->name);
408 return -EINVAL; 407 return;
409 } 408 }
410 409
410 rtc->class_dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id);
411
411 mutex_init(&rtc->char_lock); 412 mutex_init(&rtc->char_lock);
412 spin_lock_init(&rtc->irq_lock); 413 spin_lock_init(&rtc->irq_lock);
413 init_waitqueue_head(&rtc->irq_queue); 414 init_waitqueue_head(&rtc->irq_queue);
@@ -419,99 +420,32 @@ static int rtc_dev_add_device(struct class_device *class_dev,
419 cdev_init(&rtc->char_dev, &rtc_dev_fops); 420 cdev_init(&rtc->char_dev, &rtc_dev_fops);
420 rtc->char_dev.owner = rtc->owner; 421 rtc->char_dev.owner = rtc->owner;
421 422
422 if (cdev_add(&rtc->char_dev, MKDEV(MAJOR(rtc_devt), rtc->id), 1)) { 423 if (cdev_add(&rtc->char_dev, rtc->class_dev.devt, 1))
423 dev_err(class_dev->dev, 424 printk(KERN_WARNING "%s: failed to add char device %d:%d\n",
424 "failed to add char device %d:%d\n", 425 rtc->name, MAJOR(rtc_devt), rtc->id);
426 else
427 pr_debug("%s: dev (%d:%d)\n", rtc->name,
425 MAJOR(rtc_devt), rtc->id); 428 MAJOR(rtc_devt), rtc->id);
426 return -ENODEV;
427 }
428
429 rtc->rtc_dev = class_device_create(rtc_dev_class, NULL,
430 MKDEV(MAJOR(rtc_devt), rtc->id),
431 class_dev->dev, "rtc%d", rtc->id);
432 if (IS_ERR(rtc->rtc_dev)) {
433 dev_err(class_dev->dev, "cannot create rtc_dev device\n");
434 err = PTR_ERR(rtc->rtc_dev);
435 goto err_cdev_del;
436 }
437
438 dev_dbg(class_dev->dev, "rtc intf: dev (%d:%d)\n",
439 MAJOR(rtc->rtc_dev->devt),
440 MINOR(rtc->rtc_dev->devt));
441
442 return 0;
443
444err_cdev_del:
445
446 cdev_del(&rtc->char_dev);
447 return err;
448} 429}
449 430
450static void rtc_dev_remove_device(struct class_device *class_dev, 431void rtc_dev_del_device(struct rtc_device *rtc)
451 struct class_interface *class_intf)
452{ 432{
453 struct rtc_device *rtc = to_rtc_device(class_dev); 433 if (rtc->class_dev.devt)
454
455 if (rtc->rtc_dev) {
456 dev_dbg(class_dev->dev, "removing char %d:%d\n",
457 MAJOR(rtc->rtc_dev->devt),
458 MINOR(rtc->rtc_dev->devt));
459
460 class_device_unregister(rtc->rtc_dev);
461 cdev_del(&rtc->char_dev); 434 cdev_del(&rtc->char_dev);
462 }
463} 435}
464 436
465/* interface registration */ 437void __init rtc_dev_init(void)
466
467static struct class_interface rtc_dev_interface = {
468 .add = &rtc_dev_add_device,
469 .remove = &rtc_dev_remove_device,
470};
471
472static int __init rtc_dev_init(void)
473{ 438{
474 int err; 439 int err;
475 440
476 rtc_dev_class = class_create(THIS_MODULE, "rtc-dev");
477 if (IS_ERR(rtc_dev_class))
478 return PTR_ERR(rtc_dev_class);
479
480 err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc"); 441 err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc");
481 if (err < 0) { 442 if (err < 0)
482 printk(KERN_ERR "%s: failed to allocate char dev region\n", 443 printk(KERN_ERR "%s: failed to allocate char dev region\n",
483 __FILE__); 444 __FILE__);
484 goto err_destroy_class;
485 }
486
487 err = rtc_interface_register(&rtc_dev_interface);
488 if (err < 0) {
489 printk(KERN_ERR "%s: failed to register the interface\n",
490 __FILE__);
491 goto err_unregister_chrdev;
492 }
493
494 return 0;
495
496err_unregister_chrdev:
497 unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
498
499err_destroy_class:
500 class_destroy(rtc_dev_class);
501
502 return err;
503} 445}
504 446
505static void __exit rtc_dev_exit(void) 447void __exit rtc_dev_exit(void)
506{ 448{
507 class_interface_unregister(&rtc_dev_interface); 449 if (rtc_devt)
508 class_destroy(rtc_dev_class); 450 unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
509 unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
510} 451}
511
512subsys_initcall(rtc_dev_init);
513module_exit(rtc_dev_exit);
514
515MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
516MODULE_DESCRIPTION("RTC class dev interface");
517MODULE_LICENSE("GPL");