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"); | ||
