diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/Kconfig | 2 | ||||
-rw-r--r-- | drivers/rtc/Makefile | 3 | ||||
-rw-r--r-- | drivers/rtc/class.c | 8 | ||||
-rw-r--r-- | drivers/rtc/rtc-core.h | 15 | ||||
-rw-r--r-- | drivers/rtc/rtc-dev.c | 106 |
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 | ||
73 | config RTC_INTF_DEV | 73 | config 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 | |||
11 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o | 11 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o |
12 | rtc-core-y := class.o interface.o | 12 | rtc-core-y := class.o interface.o |
13 | 13 | ||
14 | rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o | ||
15 | |||
14 | obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | 16 | obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o |
15 | obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o | 17 | obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o |
16 | obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o | ||
17 | 18 | ||
18 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 19 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
19 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 20 | obj-$(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 | |||
19 | static DEFINE_IDR(rtc_idr); | 22 | static DEFINE_IDR(rtc_idr); |
20 | static DEFINE_MUTEX(idr_lock); | 23 | static DEFINE_MUTEX(idr_lock); |
21 | struct class *rtc_class; | 24 | struct 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 | ||
146 | static void __exit rtc_exit(void) | 153 | static 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 | |||
3 | extern void __init rtc_dev_init(void); | ||
4 | extern void __exit rtc_dev_exit(void); | ||
5 | extern void rtc_dev_add_device(struct rtc_device *rtc); | ||
6 | extern 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 | ||
17 | static struct class *rtc_dev_class; | ||
18 | static dev_t rtc_devt; | 18 | static 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 | ||
400 | static int rtc_dev_add_device(struct class_device *class_dev, | 400 | void 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 | |||
444 | err_cdev_del: | ||
445 | |||
446 | cdev_del(&rtc->char_dev); | ||
447 | return err; | ||
448 | } | 429 | } |
449 | 430 | ||
450 | static void rtc_dev_remove_device(struct class_device *class_dev, | 431 | void 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 */ | 437 | void __init rtc_dev_init(void) |
466 | |||
467 | static struct class_interface rtc_dev_interface = { | ||
468 | .add = &rtc_dev_add_device, | ||
469 | .remove = &rtc_dev_remove_device, | ||
470 | }; | ||
471 | |||
472 | static 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 | |||
496 | err_unregister_chrdev: | ||
497 | unregister_chrdev_region(rtc_devt, RTC_DEV_MAX); | ||
498 | |||
499 | err_destroy_class: | ||
500 | class_destroy(rtc_dev_class); | ||
501 | |||
502 | return err; | ||
503 | } | 445 | } |
504 | 446 | ||
505 | static void __exit rtc_dev_exit(void) | 447 | void __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 | |||
512 | subsys_initcall(rtc_dev_init); | ||
513 | module_exit(rtc_dev_exit); | ||
514 | |||
515 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
516 | MODULE_DESCRIPTION("RTC class dev interface"); | ||
517 | MODULE_LICENSE("GPL"); | ||