aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-dev.c')
-rw-r--r--drivers/rtc/rtc-dev.c106
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
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");