rtc_irq_set_freq() requires power-of-two and associated kerneldoc
authorDavid Brownell <david-b@pacbell.net>
Tue, 16 Oct 2007 08:28:16 +0000 (01:28 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 16 Oct 2007 16:43:13 +0000 (09:43 -0700)
RTC periodic IRQs are only defined to work for 2^N Hz values.  This patch
moves that validity check into the infrastructure, so drivers don't need to
check it; and adds kerneldoc for the two interface functions related to
periodic IRQs.  (One of which was quite mysterious until its first use was
recently checked in!)

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/rtc/interface.c
drivers/rtc/rtc-cmos.c

index a43afa54f0d74f79d4d566876f3617618fabbdc9..8adcab3c365303b49c9bbe9b91038408e2bbd789 100644 (file)
@@ -12,6 +12,7 @@
 */
 
 #include <linux/rtc.h>
+#include <linux/log2.h>
 
 int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
 {
@@ -236,6 +237,16 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
 }
 EXPORT_SYMBOL_GPL(rtc_irq_unregister);
 
+/**
+ * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs
+ * @rtc: the rtc device
+ * @task: currently registered with rtc_irq_register()
+ * @enabled: true to enable periodic IRQs
+ * Context: any
+ *
+ * Note that rtc_irq_set_freq() should previously have been used to
+ * specify the desired frequency of periodic IRQ task->func() callbacks.
+ */
 int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled)
 {
        int err = 0;
@@ -258,6 +269,16 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled
 }
 EXPORT_SYMBOL_GPL(rtc_irq_set_state);
 
+/**
+ * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ
+ * @rtc: the rtc device
+ * @task: currently registered with rtc_irq_register()
+ * @freq: positive frequency with which task->func() will be called
+ * Context: any
+ *
+ * Note that rtc_irq_set_state() is used to enable or disable the
+ * periodic IRQs.
+ */
 int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
 {
        int err = 0;
@@ -266,6 +287,9 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
        if (rtc->ops->irq_set_freq == NULL)
                return -ENXIO;
 
+       if (!is_power_of_2(freq))
+               return -EINVAL;
+
        spin_lock_irqsave(&rtc->irq_task_lock, flags);
        if (rtc->irq_task != NULL && task == NULL)
                err = -EBUSY;
index 5d760bb6c2cd2100e051dadc9d0bba00c0c8da33..6d0c35397b4932fc09d6b95b951858c9e555a8e4 100644 (file)
@@ -246,11 +246,9 @@ static int cmos_irq_set_freq(struct device *dev, int freq)
 
        /* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */
        f = ffs(freq);
-       if (f != 0) {
-               if (f-- > 16 || freq != (1 << f))
-                       return -EINVAL;
-               f = 16 - f;
-       }
+       if (f-- > 16)
+               return -EINVAL;
+       f = 16 - f;
 
        spin_lock_irqsave(&rtc_lock, flags);
        CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);