Commit 97144c67 authored by David Brownell's avatar David Brownell Committed by Linus Torvalds

rtc_irq_set_freq() requires power-of-two and associated kerneldoc

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: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d691eb90
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
*/ */
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/log2.h>
int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) 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) ...@@ -236,6 +237,16 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
} }
EXPORT_SYMBOL_GPL(rtc_irq_unregister); 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 rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled)
{ {
int err = 0; int err = 0;
...@@ -258,6 +269,16 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled ...@@ -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); 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 rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
{ {
int err = 0; int err = 0;
...@@ -266,6 +287,9 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) ...@@ -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) if (rtc->ops->irq_set_freq == NULL)
return -ENXIO; return -ENXIO;
if (!is_power_of_2(freq))
return -EINVAL;
spin_lock_irqsave(&rtc->irq_task_lock, flags); spin_lock_irqsave(&rtc->irq_task_lock, flags);
if (rtc->irq_task != NULL && task == NULL) if (rtc->irq_task != NULL && task == NULL)
err = -EBUSY; err = -EBUSY;
......
...@@ -246,11 +246,9 @@ static int cmos_irq_set_freq(struct device *dev, int freq) ...@@ -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 */ /* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */
f = ffs(freq); f = ffs(freq);
if (f != 0) { if (f-- > 16)
if (f-- > 16 || freq != (1 << f)) return -EINVAL;
return -EINVAL; f = 16 - f;
f = 16 - f;
}
spin_lock_irqsave(&rtc_lock, flags); spin_lock_irqsave(&rtc_lock, flags);
CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment