aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/interface.c24
-rw-r--r--drivers/rtc/rtc-cmos.c8
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
16int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) 17int 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}
237EXPORT_SYMBOL_GPL(rtc_irq_unregister); 238EXPORT_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 */
239int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled) 250int 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}
259EXPORT_SYMBOL_GPL(rtc_irq_set_state); 270EXPORT_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 */
261int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) 282int 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);