#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
+#include <linux/log2.h>
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <asm-generic/rtc.h>
if (!is_valid_irq(cmos->irq))
return -ENXIO;
+ if (!is_power_of_2(freq))
+ return -EINVAL;
/* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */
f = ffs(freq);
if (f-- > 16)
goto cleanup2;
}
- pr_info("%s: alarms up to one %s%s, %zd bytes nvram%s\n",
- dev_name(&cmos_rtc.rtc->dev),
- is_valid_irq(rtc_irq)
- ? (cmos_rtc.mon_alrm
- ? "year"
- : (cmos_rtc.day_alrm
- ? "month" : "day"))
- : "no",
- cmos_rtc.century ? ", y3k" : "",
- nvram.size,
- is_hpet_enabled() ? ", hpet irqs" : "");
+ pr_info("%s: %s%s, %zd bytes nvram%s\n",
+ dev_name(&cmos_rtc.rtc->dev),
+ !is_valid_irq(rtc_irq) ? "no alarms" :
+ cmos_rtc.mon_alrm ? "alarms up to one year" :
+ cmos_rtc.day_alrm ? "alarms up to one month" :
+ "alarms up to one day",
+ cmos_rtc.century ? ", y3k" : "",
+ nvram.size,
+ is_hpet_enabled() ? ", hpet irqs" : "");
return 0;
}
};
+#ifdef CONFIG_PNP
+static bool pnp_driver_registered;
+#endif
+static bool platform_driver_registered;
+
static int __init cmos_init(void)
{
int retval = 0;
#ifdef CONFIG_PNP
- pnp_register_driver(&cmos_pnp_driver);
+ retval = pnp_register_driver(&cmos_pnp_driver);
+ if (retval == 0)
+ pnp_driver_registered = true;
#endif
- if (!cmos_rtc.dev)
+ if (!cmos_rtc.dev) {
retval = platform_driver_probe(&cmos_platform_driver,
cmos_platform_probe);
+ if (retval == 0)
+ platform_driver_registered = true;
+ }
if (retval == 0)
return 0;
#ifdef CONFIG_PNP
- pnp_unregister_driver(&cmos_pnp_driver);
+ if (pnp_driver_registered)
+ pnp_unregister_driver(&cmos_pnp_driver);
#endif
return retval;
}
static void __exit cmos_exit(void)
{
#ifdef CONFIG_PNP
- pnp_unregister_driver(&cmos_pnp_driver);
+ if (pnp_driver_registered)
+ pnp_unregister_driver(&cmos_pnp_driver);
#endif
- platform_driver_unregister(&cmos_platform_driver);
+ if (platform_driver_registered)
+ platform_driver_unregister(&cmos_platform_driver);
}
module_exit(cmos_exit);