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