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

rtc: introduce features bitfield

Introduce a bitfield to allow the drivers to announce the available
features for an RTC.

The main use case would be to better handle alarms, that could be present
or not or have a minute resolution or may need a correct week day to be set.

Use the newly introduced RTC_FEATURE_ALARM bit to then test whether alarms
are available instead of relying on the presence of ops->set_alarm.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20210110231752.1418816-2-alexandre.belloni@bootlin.com

+18 -6
+5
drivers/rtc/class.c
··· 231 231 rtc->pie_timer.function = rtc_pie_update_irq; 232 232 rtc->pie_enabled = 0; 233 233 234 + set_bit(RTC_FEATURE_ALARM, rtc->features); 235 + 234 236 return rtc; 235 237 } 236 238 ··· 387 385 dev_dbg(&rtc->dev, "no ops set\n"); 388 386 return -EINVAL; 389 387 } 388 + 389 + if (!rtc->ops->set_alarm) 390 + clear_bit(RTC_FEATURE_ALARM, rtc->features); 390 391 391 392 rtc->owner = owner; 392 393 rtc_device_get_offset(rtc);
+6 -6
drivers/rtc/interface.c
··· 186 186 187 187 if (!rtc->ops) { 188 188 err = -ENODEV; 189 - } else if (!rtc->ops->read_alarm) { 189 + } else if (!test_bit(RTC_FEATURE_ALARM, rtc->features) || !rtc->ops->read_alarm) { 190 190 err = -EINVAL; 191 191 } else { 192 192 alarm->enabled = 0; ··· 392 392 return err; 393 393 if (!rtc->ops) { 394 394 err = -ENODEV; 395 - } else if (!rtc->ops->read_alarm) { 395 + } else if (!test_bit(RTC_FEATURE_ALARM, rtc->features) || !rtc->ops->read_alarm) { 396 396 err = -EINVAL; 397 397 } else { 398 398 memset(alarm, 0, sizeof(struct rtc_wkalrm)); ··· 436 436 437 437 if (!rtc->ops) 438 438 err = -ENODEV; 439 - else if (!rtc->ops->set_alarm) 439 + else if (!test_bit(RTC_FEATURE_ALARM, rtc->features)) 440 440 err = -EINVAL; 441 441 else 442 442 err = rtc->ops->set_alarm(rtc->dev.parent, alarm); ··· 451 451 452 452 if (!rtc->ops) 453 453 return -ENODEV; 454 - else if (!rtc->ops->set_alarm) 454 + else if (!test_bit(RTC_FEATURE_ALARM, rtc->features)) 455 455 return -EINVAL; 456 456 457 457 err = rtc_valid_tm(&alarm->time); ··· 531 531 /* nothing */; 532 532 else if (!rtc->ops) 533 533 err = -ENODEV; 534 - else if (!rtc->ops->alarm_irq_enable) 534 + else if (!test_bit(RTC_FEATURE_ALARM, rtc->features) || !rtc->ops->alarm_irq_enable) 535 535 err = -EINVAL; 536 536 else 537 537 err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled); ··· 843 843 844 844 static void rtc_alarm_disable(struct rtc_device *rtc) 845 845 { 846 - if (!rtc->ops || !rtc->ops->alarm_irq_enable) 846 + if (!rtc->ops || !test_bit(RTC_FEATURE_ALARM, rtc->features) || !rtc->ops->alarm_irq_enable) 847 847 return; 848 848 849 849 rtc->ops->alarm_irq_enable(rtc->dev.parent, false);
+2
include/linux/rtc.h
··· 141 141 */ 142 142 unsigned long set_offset_nsec; 143 143 144 + unsigned long features[BITS_TO_LONGS(RTC_FEATURE_CNT)]; 145 + 144 146 time64_t range_min; 145 147 timeu64_t range_max; 146 148 time64_t start_secs;
+5
include/uapi/linux/rtc.h
··· 110 110 #define RTC_AF 0x20 /* Alarm interrupt */ 111 111 #define RTC_UF 0x10 /* Update interrupt for 1Hz RTC */ 112 112 113 + /* feature list */ 114 + #define RTC_FEATURE_ALARM 0 115 + #define RTC_FEATURE_ALARM_RES_MINUTE 1 116 + #define RTC_FEATURE_NEED_WEEK_DAY 2 117 + #define RTC_FEATURE_CNT 3 113 118 114 119 #define RTC_MAX_FREQ 8192 115 120