summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/rtc/class.c5
-rw-r--r--drivers/rtc/interface.c12
-rw-r--r--include/linux/rtc.h2
-rw-r--r--include/uapi/linux/rtc.h5
4 files changed, 18 insertions, 6 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 7e470fbd5e4d..03abd0aa229a 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -231,6 +231,8 @@ static struct rtc_device *rtc_allocate_device(void)
rtc->pie_timer.function = rtc_pie_update_irq;
rtc->pie_enabled = 0;
+ set_bit(RTC_FEATURE_ALARM, rtc->features);
+
return rtc;
}
@@ -386,6 +388,9 @@ int __devm_rtc_register_device(struct module *owner, struct rtc_device *rtc)
return -EINVAL;
}
+ if (!rtc->ops->set_alarm)
+ clear_bit(RTC_FEATURE_ALARM, rtc->features);
+
rtc->owner = owner;
rtc_device_get_offset(rtc);
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 794a4f036b99..dcb34c73319e 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -186,7 +186,7 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc,
if (!rtc->ops) {
err = -ENODEV;
- } else if (!rtc->ops->read_alarm) {
+ } else if (!test_bit(RTC_FEATURE_ALARM, rtc->features) || !rtc->ops->read_alarm) {
err = -EINVAL;
} else {
alarm->enabled = 0;
@@ -392,7 +392,7 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
return err;
if (!rtc->ops) {
err = -ENODEV;
- } else if (!rtc->ops->read_alarm) {
+ } else if (!test_bit(RTC_FEATURE_ALARM, rtc->features) || !rtc->ops->read_alarm) {
err = -EINVAL;
} else {
memset(alarm, 0, sizeof(struct rtc_wkalrm));
@@ -436,7 +436,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
if (!rtc->ops)
err = -ENODEV;
- else if (!rtc->ops->set_alarm)
+ else if (!test_bit(RTC_FEATURE_ALARM, rtc->features))
err = -EINVAL;
else
err = rtc->ops->set_alarm(rtc->dev.parent, alarm);
@@ -451,7 +451,7 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
if (!rtc->ops)
return -ENODEV;
- else if (!rtc->ops->set_alarm)
+ else if (!test_bit(RTC_FEATURE_ALARM, rtc->features))
return -EINVAL;
err = rtc_valid_tm(&alarm->time);
@@ -531,7 +531,7 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
/* nothing */;
else if (!rtc->ops)
err = -ENODEV;
- else if (!rtc->ops->alarm_irq_enable)
+ else if (!test_bit(RTC_FEATURE_ALARM, rtc->features) || !rtc->ops->alarm_irq_enable)
err = -EINVAL;
else
err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled);
@@ -843,7 +843,7 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
static void rtc_alarm_disable(struct rtc_device *rtc)
{
- if (!rtc->ops || !rtc->ops->alarm_irq_enable)
+ if (!rtc->ops || !test_bit(RTC_FEATURE_ALARM, rtc->features) || !rtc->ops->alarm_irq_enable)
return;
rtc->ops->alarm_irq_enable(rtc->dev.parent, false);
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 568909449c13..bd611e26291d 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -141,6 +141,8 @@ struct rtc_device {
*/
unsigned long set_offset_nsec;
+ unsigned long features[BITS_TO_LONGS(RTC_FEATURE_CNT)];
+
time64_t range_min;
timeu64_t range_max;
time64_t start_secs;
diff --git a/include/uapi/linux/rtc.h b/include/uapi/linux/rtc.h
index fa9aff91cbf2..f950bff75e97 100644
--- a/include/uapi/linux/rtc.h
+++ b/include/uapi/linux/rtc.h
@@ -110,6 +110,11 @@ struct rtc_pll_info {
#define RTC_AF 0x20 /* Alarm interrupt */
#define RTC_UF 0x10 /* Update interrupt for 1Hz RTC */
+/* feature list */
+#define RTC_FEATURE_ALARM 0
+#define RTC_FEATURE_ALARM_RES_MINUTE 1
+#define RTC_FEATURE_NEED_WEEK_DAY 2
+#define RTC_FEATURE_CNT 3
#define RTC_MAX_FREQ 8192