diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/interface.c | 24 | ||||
-rw-r--r-- | drivers/rtc/rtc-cmos.c | 8 |
2 files changed, 27 insertions, 5 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index a43afa54f0d7..8adcab3c3653 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
15 | #include <linux/log2.h> | ||
15 | 16 | ||
16 | int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | 17 | int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) |
17 | { | 18 | { |
@@ -236,6 +237,16 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task) | |||
236 | } | 237 | } |
237 | EXPORT_SYMBOL_GPL(rtc_irq_unregister); | 238 | EXPORT_SYMBOL_GPL(rtc_irq_unregister); |
238 | 239 | ||
240 | /** | ||
241 | * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs | ||
242 | * @rtc: the rtc device | ||
243 | * @task: currently registered with rtc_irq_register() | ||
244 | * @enabled: true to enable periodic IRQs | ||
245 | * Context: any | ||
246 | * | ||
247 | * Note that rtc_irq_set_freq() should previously have been used to | ||
248 | * specify the desired frequency of periodic IRQ task->func() callbacks. | ||
249 | */ | ||
239 | int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled) | 250 | int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled) |
240 | { | 251 | { |
241 | int err = 0; | 252 | int err = 0; |
@@ -258,6 +269,16 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled | |||
258 | } | 269 | } |
259 | EXPORT_SYMBOL_GPL(rtc_irq_set_state); | 270 | EXPORT_SYMBOL_GPL(rtc_irq_set_state); |
260 | 271 | ||
272 | /** | ||
273 | * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ | ||
274 | * @rtc: the rtc device | ||
275 | * @task: currently registered with rtc_irq_register() | ||
276 | * @freq: positive frequency with which task->func() will be called | ||
277 | * Context: any | ||
278 | * | ||
279 | * Note that rtc_irq_set_state() is used to enable or disable the | ||
280 | * periodic IRQs. | ||
281 | */ | ||
261 | int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) | 282 | int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) |
262 | { | 283 | { |
263 | int err = 0; | 284 | int err = 0; |
@@ -266,6 +287,9 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) | |||
266 | if (rtc->ops->irq_set_freq == NULL) | 287 | if (rtc->ops->irq_set_freq == NULL) |
267 | return -ENXIO; | 288 | return -ENXIO; |
268 | 289 | ||
290 | if (!is_power_of_2(freq)) | ||
291 | return -EINVAL; | ||
292 | |||
269 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 293 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
270 | if (rtc->irq_task != NULL && task == NULL) | 294 | if (rtc->irq_task != NULL && task == NULL) |
271 | err = -EBUSY; | 295 | err = -EBUSY; |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 5d760bb6c2cd..6d0c35397b49 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -246,11 +246,9 @@ static int cmos_irq_set_freq(struct device *dev, int freq) | |||
246 | 246 | ||
247 | /* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */ | 247 | /* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */ |
248 | f = ffs(freq); | 248 | f = ffs(freq); |
249 | if (f != 0) { | 249 | if (f-- > 16) |
250 | if (f-- > 16 || freq != (1 << f)) | 250 | return -EINVAL; |
251 | return -EINVAL; | 251 | f = 16 - f; |
252 | f = 16 - f; | ||
253 | } | ||
254 | 252 | ||
255 | spin_lock_irqsave(&rtc_lock, flags); | 253 | spin_lock_irqsave(&rtc_lock, flags); |
256 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | 254 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); |