aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorAlessandro Zummo <a.zummo@towertech.it>2009-01-04 15:00:54 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-04 16:33:20 -0500
commit099e657625e801adf82054c8050dde5aceb68452 (patch)
treed6c28df68ab390fa237b8339c6081e4db380aa5f /drivers/rtc
parent54566b2c1594c2326a645a3551f9d989f7ba3c5e (diff)
rtc: add alarm/update irq interfaces
Add standard interfaces for alarm/update irqs enabling. Drivers are no more required to implement equivalent ioctl code as rtc-dev will provide it. UIE emulation should now be handled correctly and will work even for those RTC drivers who cannot be configured to do both UIE and AIE. Signed-off-by: Alessandro Zummo <a.zummo@towertech.it> Cc: David Brownell <david-b@pacbell.net> Cc: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Cc: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig6
-rw-r--r--drivers/rtc/interface.c54
-rw-r--r--drivers/rtc/rtc-dev.c51
3 files changed, 94 insertions, 17 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 123092d8a984..165a81843357 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -102,9 +102,13 @@ config RTC_INTF_DEV_UIE_EMUL
102 depends on RTC_INTF_DEV 102 depends on RTC_INTF_DEV
103 help 103 help
104 Provides an emulation for RTC_UIE if the underlying rtc chip 104 Provides an emulation for RTC_UIE if the underlying rtc chip
105 driver does not expose RTC_UIE ioctls. Those requests generate 105 driver does not expose RTC_UIE ioctls. Those requests generate
106 once-per-second update interrupts, used for synchronization. 106 once-per-second update interrupts, used for synchronization.
107 107
108 The emulation code will read the time from the hardware
109 clock several times per second, please enable this option
110 only if you know that you really need it.
111
108config RTC_DRV_TEST 112config RTC_DRV_TEST
109 tristate "Test driver/device" 113 tristate "Test driver/device"
110 help 114 help
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index a04c1b6b1575..fd2c652504ff 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -307,6 +307,60 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
307} 307}
308EXPORT_SYMBOL_GPL(rtc_set_alarm); 308EXPORT_SYMBOL_GPL(rtc_set_alarm);
309 309
310int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
311{
312 int err = mutex_lock_interruptible(&rtc->ops_lock);
313 if (err)
314 return err;
315
316 if (!rtc->ops)
317 err = -ENODEV;
318 else if (!rtc->ops->alarm_irq_enable)
319 err = -EINVAL;
320 else
321 err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled);
322
323 mutex_unlock(&rtc->ops_lock);
324 return err;
325}
326EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable);
327
328int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)
329{
330 int err = mutex_lock_interruptible(&rtc->ops_lock);
331 if (err)
332 return err;
333
334#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
335 if (enabled == 0 && rtc->uie_irq_active) {
336 mutex_unlock(&rtc->ops_lock);
337 return rtc_dev_update_irq_enable_emul(rtc, enabled);
338 }
339#endif
340
341 if (!rtc->ops)
342 err = -ENODEV;
343 else if (!rtc->ops->update_irq_enable)
344 err = -EINVAL;
345 else
346 err = rtc->ops->update_irq_enable(rtc->dev.parent, enabled);
347
348 mutex_unlock(&rtc->ops_lock);
349
350#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
351 /*
352 * Enable emulation if the driver did not provide
353 * the update_irq_enable function pointer or if returned
354 * -EINVAL to signal that it has been configured without
355 * interrupts or that are not available at the moment.
356 */
357 if (err == -EINVAL)
358 err = rtc_dev_update_irq_enable_emul(rtc, enabled);
359#endif
360 return err;
361}
362EXPORT_SYMBOL_GPL(rtc_update_irq_enable);
363
310/** 364/**
311 * rtc_update_irq - report RTC periodic, alarm, and/or update irqs 365 * rtc_update_irq - report RTC periodic, alarm, and/or update irqs
312 * @rtc: the rtc device 366 * @rtc: the rtc device
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index ecdea44ae4e5..45152f4952d6 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -92,10 +92,10 @@ static void rtc_uie_timer(unsigned long data)
92 spin_unlock_irqrestore(&rtc->irq_lock, flags); 92 spin_unlock_irqrestore(&rtc->irq_lock, flags);
93} 93}
94 94
95static void clear_uie(struct rtc_device *rtc) 95static int clear_uie(struct rtc_device *rtc)
96{ 96{
97 spin_lock_irq(&rtc->irq_lock); 97 spin_lock_irq(&rtc->irq_lock);
98 if (rtc->irq_active) { 98 if (rtc->uie_irq_active) {
99 rtc->stop_uie_polling = 1; 99 rtc->stop_uie_polling = 1;
100 if (rtc->uie_timer_active) { 100 if (rtc->uie_timer_active) {
101 spin_unlock_irq(&rtc->irq_lock); 101 spin_unlock_irq(&rtc->irq_lock);
@@ -108,9 +108,10 @@ static void clear_uie(struct rtc_device *rtc)
108 flush_scheduled_work(); 108 flush_scheduled_work();
109 spin_lock_irq(&rtc->irq_lock); 109 spin_lock_irq(&rtc->irq_lock);
110 } 110 }
111 rtc->irq_active = 0; 111 rtc->uie_irq_active = 0;
112 } 112 }
113 spin_unlock_irq(&rtc->irq_lock); 113 spin_unlock_irq(&rtc->irq_lock);
114 return 0;
114} 115}
115 116
116static int set_uie(struct rtc_device *rtc) 117static int set_uie(struct rtc_device *rtc)
@@ -122,8 +123,8 @@ static int set_uie(struct rtc_device *rtc)
122 if (err) 123 if (err)
123 return err; 124 return err;
124 spin_lock_irq(&rtc->irq_lock); 125 spin_lock_irq(&rtc->irq_lock);
125 if (!rtc->irq_active) { 126 if (!rtc->uie_irq_active) {
126 rtc->irq_active = 1; 127 rtc->uie_irq_active = 1;
127 rtc->stop_uie_polling = 0; 128 rtc->stop_uie_polling = 0;
128 rtc->oldsecs = tm.tm_sec; 129 rtc->oldsecs = tm.tm_sec;
129 rtc->uie_task_active = 1; 130 rtc->uie_task_active = 1;
@@ -134,6 +135,16 @@ static int set_uie(struct rtc_device *rtc)
134 spin_unlock_irq(&rtc->irq_lock); 135 spin_unlock_irq(&rtc->irq_lock);
135 return 0; 136 return 0;
136} 137}
138
139int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled)
140{
141 if (enabled)
142 return set_uie(rtc);
143 else
144 return clear_uie(rtc);
145}
146EXPORT_SYMBOL(rtc_dev_update_irq_enable_emul);
147
137#endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */ 148#endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */
138 149
139static ssize_t 150static ssize_t
@@ -357,6 +368,22 @@ static long rtc_dev_ioctl(struct file *file,
357 err = rtc_irq_set_state(rtc, NULL, 0); 368 err = rtc_irq_set_state(rtc, NULL, 0);
358 break; 369 break;
359 370
371 case RTC_AIE_ON:
372 mutex_unlock(&rtc->ops_lock);
373 return rtc_alarm_irq_enable(rtc, 1);
374
375 case RTC_AIE_OFF:
376 mutex_unlock(&rtc->ops_lock);
377 return rtc_alarm_irq_enable(rtc, 0);
378
379 case RTC_UIE_ON:
380 mutex_unlock(&rtc->ops_lock);
381 return rtc_update_irq_enable(rtc, 1);
382
383 case RTC_UIE_OFF:
384 mutex_unlock(&rtc->ops_lock);
385 return rtc_update_irq_enable(rtc, 0);
386
360 case RTC_IRQP_SET: 387 case RTC_IRQP_SET:
361 err = rtc_irq_set_freq(rtc, NULL, arg); 388 err = rtc_irq_set_freq(rtc, NULL, arg);
362 break; 389 break;
@@ -401,17 +428,6 @@ static long rtc_dev_ioctl(struct file *file,
401 err = -EFAULT; 428 err = -EFAULT;
402 return err; 429 return err;
403 430
404#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
405 case RTC_UIE_OFF:
406 mutex_unlock(&rtc->ops_lock);
407 clear_uie(rtc);
408 return 0;
409
410 case RTC_UIE_ON:
411 mutex_unlock(&rtc->ops_lock);
412 err = set_uie(rtc);
413 return err;
414#endif
415 default: 431 default:
416 err = -ENOTTY; 432 err = -ENOTTY;
417 break; 433 break;
@@ -440,7 +456,10 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
440 * Leave the alarm alone; it may be set to trigger a system wakeup 456 * Leave the alarm alone; it may be set to trigger a system wakeup
441 * later, or be used by kernel code, and is a one-shot event anyway. 457 * later, or be used by kernel code, and is a one-shot event anyway.
442 */ 458 */
459
460 /* Keep ioctl until all drivers are converted */
443 rtc_dev_ioctl(file, RTC_UIE_OFF, 0); 461 rtc_dev_ioctl(file, RTC_UIE_OFF, 0);
462 rtc_update_irq_enable(rtc, 0);
444 rtc_irq_set_state(rtc, NULL, 0); 463 rtc_irq_set_state(rtc, NULL, 0);
445 464
446 if (rtc->ops->release) 465 if (rtc->ops->release)