diff options
Diffstat (limited to 'drivers/rtc/class.c')
-rw-r--r-- | drivers/rtc/class.c | 82 |
1 files changed, 76 insertions, 6 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 9b742d3ffb94..02426812bebc 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -38,7 +38,7 @@ static void rtc_device_release(struct device *dev) int rtc_hctosys_ret = -ENODEV; #endif -#if defined(CONFIG_PM) && defined(CONFIG_RTC_HCTOSYS_DEVICE) +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_RTC_HCTOSYS_DEVICE) /* * On suspend(), measure the delta between one RTC and the * system's wall clock; restore it on resume(). @@ -47,7 +47,7 @@ int rtc_hctosys_ret = -ENODEV; static struct timespec old_rtc, old_system, old_delta; -static int rtc_suspend(struct device *dev, pm_message_t mesg) +static int rtc_suspend(struct device *dev) { struct rtc_device *rtc = to_rtc_device(dev); struct rtc_time tm; @@ -135,9 +135,10 @@ static int rtc_resume(struct device *dev) return 0; } +static SIMPLE_DEV_PM_OPS(rtc_class_dev_pm_ops, rtc_suspend, rtc_resume); +#define RTC_CLASS_DEV_PM_OPS (&rtc_class_dev_pm_ops) #else -#define rtc_suspend NULL -#define rtc_resume NULL +#define RTC_CLASS_DEV_PM_OPS NULL #endif @@ -259,6 +260,76 @@ void rtc_device_unregister(struct rtc_device *rtc) } EXPORT_SYMBOL_GPL(rtc_device_unregister); +static void devm_rtc_device_release(struct device *dev, void *res) +{ + struct rtc_device *rtc = *(struct rtc_device **)res; + + rtc_device_unregister(rtc); +} + +static int devm_rtc_device_match(struct device *dev, void *res, void *data) +{ + struct rtc **r = res; + + return *r == data; +} + +/** + * devm_rtc_device_register - resource managed rtc_device_register() + * @dev: the device to register + * @name: the name of the device + * @ops: the rtc operations structure + * @owner: the module owner + * + * @return a struct rtc on success, or an ERR_PTR on error + * + * Managed rtc_device_register(). The rtc_device returned from this function + * are automatically freed on driver detach. See rtc_device_register() + * for more information. + */ + +struct rtc_device *devm_rtc_device_register(struct device *dev, + const char *name, + const struct rtc_class_ops *ops, + struct module *owner) +{ + struct rtc_device **ptr, *rtc; + + ptr = devres_alloc(devm_rtc_device_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + rtc = rtc_device_register(name, dev, ops, owner); + if (!IS_ERR(rtc)) { + *ptr = rtc; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return rtc; +} +EXPORT_SYMBOL_GPL(devm_rtc_device_register); + +/** + * devm_rtc_device_unregister - resource managed devm_rtc_device_unregister() + * @dev: the device to unregister + * @rtc: the RTC class device to unregister + * + * Deallocated a rtc allocated with devm_rtc_device_register(). Normally this + * function will not need to be called and the resource management code will + * ensure that the resource is freed. + */ +void devm_rtc_device_unregister(struct device *dev, struct rtc_device *rtc) +{ + int rc; + + rc = devres_release(dev, devm_rtc_device_release, + devm_rtc_device_match, rtc); + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_rtc_device_unregister); + static int __init rtc_init(void) { rtc_class = class_create(THIS_MODULE, "rtc"); @@ -266,8 +337,7 @@ static int __init rtc_init(void) pr_err("couldn't create class\n"); return PTR_ERR(rtc_class); } - rtc_class->suspend = rtc_suspend; - rtc_class->resume = rtc_resume; + rtc_class->pm = RTC_CLASS_DEV_PM_OPS; rtc_dev_init(); rtc_sysfs_init(rtc_class); return 0; |