Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alessandro Zummo and committed by
Linus Torvalds
099e6576 54566b2c

+101 -18
+5 -1
drivers/rtc/Kconfig
··· 102 102 depends on RTC_INTF_DEV 103 103 help 104 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 106 once-per-second update interrupts, used for synchronization. 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. 107 111 108 112 config RTC_DRV_TEST 109 113 tristate "Test driver/device"
+54
drivers/rtc/interface.c
··· 307 307 } 308 308 EXPORT_SYMBOL_GPL(rtc_set_alarm); 309 309 310 + int 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 + } 326 + EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable); 327 + 328 + int 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 + } 362 + EXPORT_SYMBOL_GPL(rtc_update_irq_enable); 363 + 310 364 /** 311 365 * rtc_update_irq - report RTC periodic, alarm, and/or update irqs 312 366 * @rtc: the rtc device
+35 -16
drivers/rtc/rtc-dev.c
··· 92 92 spin_unlock_irqrestore(&rtc->irq_lock, flags); 93 93 } 94 94 95 - static void clear_uie(struct rtc_device *rtc) 95 + static int clear_uie(struct rtc_device *rtc) 96 96 { 97 97 spin_lock_irq(&rtc->irq_lock); 98 - if (rtc->irq_active) { 98 + if (rtc->uie_irq_active) { 99 99 rtc->stop_uie_polling = 1; 100 100 if (rtc->uie_timer_active) { 101 101 spin_unlock_irq(&rtc->irq_lock); ··· 108 108 flush_scheduled_work(); 109 109 spin_lock_irq(&rtc->irq_lock); 110 110 } 111 - rtc->irq_active = 0; 111 + rtc->uie_irq_active = 0; 112 112 } 113 113 spin_unlock_irq(&rtc->irq_lock); 114 + return 0; 114 115 } 115 116 116 117 static int set_uie(struct rtc_device *rtc) ··· 123 122 if (err) 124 123 return err; 125 124 spin_lock_irq(&rtc->irq_lock); 126 - if (!rtc->irq_active) { 127 - rtc->irq_active = 1; 125 + if (!rtc->uie_irq_active) { 126 + rtc->uie_irq_active = 1; 128 127 rtc->stop_uie_polling = 0; 129 128 rtc->oldsecs = tm.tm_sec; 130 129 rtc->uie_task_active = 1; ··· 135 134 spin_unlock_irq(&rtc->irq_lock); 136 135 return 0; 137 136 } 137 + 138 + int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled) 139 + { 140 + if (enabled) 141 + return set_uie(rtc); 142 + else 143 + return clear_uie(rtc); 144 + } 145 + EXPORT_SYMBOL(rtc_dev_update_irq_enable_emul); 146 + 138 147 #endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */ 139 148 140 149 static ssize_t ··· 368 357 err = rtc_irq_set_state(rtc, NULL, 0); 369 358 break; 370 359 360 + case RTC_AIE_ON: 361 + mutex_unlock(&rtc->ops_lock); 362 + return rtc_alarm_irq_enable(rtc, 1); 363 + 364 + case RTC_AIE_OFF: 365 + mutex_unlock(&rtc->ops_lock); 366 + return rtc_alarm_irq_enable(rtc, 0); 367 + 368 + case RTC_UIE_ON: 369 + mutex_unlock(&rtc->ops_lock); 370 + return rtc_update_irq_enable(rtc, 1); 371 + 372 + case RTC_UIE_OFF: 373 + mutex_unlock(&rtc->ops_lock); 374 + return rtc_update_irq_enable(rtc, 0); 375 + 371 376 case RTC_IRQP_SET: 372 377 err = rtc_irq_set_freq(rtc, NULL, arg); 373 378 break; ··· 428 401 err = -EFAULT; 429 402 return err; 430 403 431 - #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL 432 - case RTC_UIE_OFF: 433 - mutex_unlock(&rtc->ops_lock); 434 - clear_uie(rtc); 435 - return 0; 436 - 437 - case RTC_UIE_ON: 438 - mutex_unlock(&rtc->ops_lock); 439 - err = set_uie(rtc); 440 - return err; 441 - #endif 442 404 default: 443 405 err = -ENOTTY; 444 406 break; ··· 456 440 * Leave the alarm alone; it may be set to trigger a system wakeup 457 441 * later, or be used by kernel code, and is a one-shot event anyway. 458 442 */ 443 + 444 + /* Keep ioctl until all drivers are converted */ 459 445 rtc_dev_ioctl(file, RTC_UIE_OFF, 0); 446 + rtc_update_irq_enable(rtc, 0); 460 447 rtc_irq_set_state(rtc, NULL, 0); 461 448 462 449 if (rtc->ops->release)
+7 -1
include/linux/rtc.h
··· 145 145 int (*irq_set_state)(struct device *, int enabled); 146 146 int (*irq_set_freq)(struct device *, int freq); 147 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 152 #define RTC_DEVICE_NAME_SIZE 20 ··· 183 181 struct timer_list uie_timer; 184 182 /* Those fields are protected by rtc->irq_lock */ 185 183 unsigned int oldsecs; 186 - unsigned int irq_active:1; 184 + unsigned int uie_irq_active:1; 187 185 unsigned int stop_uie_polling:1; 188 186 unsigned int uie_task_active:1; 189 187 unsigned int uie_timer_active:1; ··· 218 216 struct rtc_task *task, int enabled); 219 217 extern int rtc_irq_set_freq(struct rtc_device *rtc, 220 218 struct rtc_task *task, int freq); 219 + extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled); 220 + extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled); 221 + extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, 222 + unsigned int enabled); 221 223 222 224 typedef struct rtc_task { 223 225 void (*func)(void *private_data);