diff options
Diffstat (limited to 'drivers/rtc/rtc-dev.c')
| -rw-r--r-- | drivers/rtc/rtc-dev.c | 106 |
1 files changed, 20 insertions, 86 deletions
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"); | ||
