aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/rtc/Kconfig6
-rw-r--r--drivers/rtc/interface.c54
-rw-r--r--drivers/rtc/rtc-dev.c51
-rw-r--r--include/linux/rtc.h8
4 files changed, 101 insertions, 18 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)
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 91f597ad6acc..4046b75563c1 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -145,6 +145,8 @@ struct rtc_class_ops {
145 int (*irq_set_state)(struct device *, int enabled); 145 int (*irq_set_state)(struct device *, int enabled);
146 int (*irq_set_freq)(struct device *, int freq); 146 int (*irq_set_freq)(struct device *, int freq);
147 int (*read_callback)(struct device *, int data); 147 int (*read_callback)(struct device *, int data);
148 int (*alarm_irq_enable)(struct device *, unsigned int enabled);
149 int (*update_irq_enable)(struct device *, unsigned int enabled);
148}; 150};
149 151
150#define RTC_DEVICE_NAME_SIZE 20 152#define RTC_DEVICE_NAME_SIZE 20
@@ -181,7 +183,7 @@ struct rtc_device
181 struct timer_list uie_timer; 183 struct timer_list uie_timer;
182 /* Those fields are protected by rtc->irq_lock */ 184 /* Those fields are protected by rtc->irq_lock */
183 unsigned int oldsecs; 185 unsigned int oldsecs;
184 unsigned int irq_active:1; 186 unsigned int uie_irq_active:1;
185 unsigned int stop_uie_polling:1; 187 unsigned int stop_uie_polling:1;
186 unsigned int uie_task_active:1; 188 unsigned int uie_task_active:1;
187 unsigned int uie_timer_active:1; 189 unsigned int uie_timer_active:1;
@@ -216,6 +218,10 @@ extern int rtc_irq_set_state(struct rtc_device *rtc,
216 struct rtc_task *task, int enabled); 218 struct rtc_task *task, int enabled);
217extern int rtc_irq_set_freq(struct rtc_device *rtc, 219extern int rtc_irq_set_freq(struct rtc_device *rtc,
218 struct rtc_task *task, int freq); 220 struct rtc_task *task, int freq);
221extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled);
222extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled);
223extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc,
224 unsigned int enabled);
219 225
220typedef struct rtc_task { 226typedef struct rtc_task {
221 void (*func)(void *private_data); 227 void (*func)(void *private_data);