diff options
| -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); |
