2021-10-17 21:53:19

by Alexandre Belloni

[permalink] [raw]
Subject: [PATCH 0/7] rtc: add new ioctl interface and BSM support

This adds a new ioctl interface allowing to get and set extended
parameters on RTCs. While its main goal is to support backup switch
mode, it also intends to fix a long time issue. Until now, it was not
possible to know what features were supported by an RTC before actually
trying to make use of it and see that succeed or fail. In order to make
tests more reliable and allow userspace to take the correct decision,
the features are now exposed.

Alexandre Belloni (7):
rtc: add alarm related features
rtc: add parameter ioctl
rtc: expose correction feature
rtc: add correction parameter
rtc: add BSM parameter
rtc: rv3028: add BSM support
rtc: rv3032: allow setting BSM

drivers/rtc/class.c | 3 ++
drivers/rtc/dev.c | 65 +++++++++++++++++++++++++++++++++
drivers/rtc/rtc-rv3028.c | 73 +++++++++++++++++++++++++++++++++++++
drivers/rtc/rtc-rv3032.c | 78 ++++++++++++++++++++++++++++++++++++++++
include/linux/rtc.h | 2 ++
include/uapi/linux/rtc.h | 33 +++++++++++++++--
6 files changed, 252 insertions(+), 2 deletions(-)

--
2.31.1


2021-10-17 21:53:19

by Alexandre Belloni

[permalink] [raw]
Subject: [PATCH 2/7] rtc: add parameter ioctl

Add an ioctl allowing to get and set extra parameters for an RTC. For now,
only handle getting available features.

Signed-off-by: Alexandre Belloni <[email protected]>
---
drivers/rtc/dev.c | 40 ++++++++++++++++++++++++++++++++++++++++
include/uapi/linux/rtc.h | 18 ++++++++++++++++++
2 files changed, 58 insertions(+)

diff --git a/drivers/rtc/dev.c b/drivers/rtc/dev.c
index 5b8ebe86124a..143c097eff0f 100644
--- a/drivers/rtc/dev.c
+++ b/drivers/rtc/dev.c
@@ -208,6 +208,7 @@ static long rtc_dev_ioctl(struct file *file,
const struct rtc_class_ops *ops = rtc->ops;
struct rtc_time tm;
struct rtc_wkalrm alarm;
+ struct rtc_param param;
void __user *uarg = (void __user *)arg;

err = mutex_lock_interruptible(&rtc->ops_lock);
@@ -221,6 +222,7 @@ static long rtc_dev_ioctl(struct file *file,
switch (cmd) {
case RTC_EPOCH_SET:
case RTC_SET_TIME:
+ case RTC_PARAM_SET:
if (!capable(CAP_SYS_TIME))
err = -EACCES;
break;
@@ -382,6 +384,44 @@ static long rtc_dev_ioctl(struct file *file,
err = -EFAULT;
return err;

+ case RTC_PARAM_GET:
+ if (copy_from_user(&param, uarg, sizeof(param))) {
+ mutex_unlock(&rtc->ops_lock);
+ return -EFAULT;
+ }
+
+ switch(param.param) {
+ long offset;
+ case RTC_PARAM_FEATURES:
+ if (param.index != 0)
+ err = -EINVAL;
+ param.uvalue = rtc->features[0];
+ break;
+
+ default:
+ err = -EINVAL;
+ }
+
+ if (!err)
+ if (copy_to_user(uarg, &param, sizeof(param)))
+ err = -EFAULT;
+
+ break;
+
+ case RTC_PARAM_SET:
+ if (copy_from_user(&param, uarg, sizeof(param))) {
+ mutex_unlock(&rtc->ops_lock);
+ return -EFAULT;
+ }
+
+ switch(param.param) {
+ case RTC_PARAM_FEATURES:
+ default:
+ err = -EINVAL;
+ }
+
+ break;
+
default:
/* Finally try the driver's ioctl interface */
if (ops->ioctl) {
diff --git a/include/uapi/linux/rtc.h b/include/uapi/linux/rtc.h
index 60ea711b1843..e4128be7963b 100644
--- a/include/uapi/linux/rtc.h
+++ b/include/uapi/linux/rtc.h
@@ -14,6 +14,7 @@

#include <linux/const.h>
#include <linux/ioctl.h>
+#include <linux/types.h>

/*
* The struct used to pass data via the following ioctl. Similar to the
@@ -66,6 +67,17 @@ struct rtc_pll_info {
long pll_clock; /* base PLL frequency */
};

+struct rtc_param {
+ __u64 param;
+ union {
+ __u64 uvalue;
+ __s64 svalue;
+ __u64 ptr;
+ };
+ __u32 index;
+ __u32 __pad;
+};
+
/*
* ioctl calls that are permitted to the /dev/rtc interface, if
* any of the RTC drivers are enabled.
@@ -95,6 +107,9 @@ struct rtc_pll_info {
#define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */
#define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */

+#define RTC_PARAM_GET _IOW('p', 0x13, struct rtc_param) /* Get parameter */
+#define RTC_PARAM_SET _IOW('p', 0x14, struct rtc_param) /* Set parameter */
+
#define RTC_VL_DATA_INVALID _BITUL(0) /* Voltage too low, RTC data is invalid */
#define RTC_VL_BACKUP_LOW _BITUL(1) /* Backup voltage is low */
#define RTC_VL_BACKUP_EMPTY _BITUL(2) /* Backup empty or not present */
@@ -118,6 +133,9 @@ struct rtc_pll_info {
#define RTC_FEATURE_NEED_WEEK_DAY 4
#define RTC_FEATURE_CNT 5

+/* parameter list */
+#define RTC_PARAM_FEATURES 0
+
#define RTC_MAX_FREQ 8192


--
2.31.1

2021-10-17 21:53:34

by Alexandre Belloni

[permalink] [raw]
Subject: [PATCH 1/7] rtc: add alarm related features

Correct and add alarm related features to be declared by drivers.

Signed-off-by: Alexandre Belloni <[email protected]>
---
include/uapi/linux/rtc.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/rtc.h b/include/uapi/linux/rtc.h
index f950bff75e97..60ea711b1843 100644
--- a/include/uapi/linux/rtc.h
+++ b/include/uapi/linux/rtc.h
@@ -113,8 +113,10 @@ struct rtc_pll_info {
/* 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_FEATURE_ALARM_RES_2S 2
+#define RTC_FEATURE_UPDATE_INTERRUPT 3
+#define RTC_FEATURE_NEED_WEEK_DAY 4
+#define RTC_FEATURE_CNT 5

#define RTC_MAX_FREQ 8192

--
2.31.1

2021-10-17 22:04:18

by Alexandre Belloni

[permalink] [raw]
Subject: [PATCH 3/7] rtc: expose correction feature

Add a new feature for RTCs able to correct the oscillator imprecision. This
is also called offset or trimming. Such drivers have a .set_offset callback,
use that to set the feature bit from the core.

Signed-off-by: Alexandre Belloni <[email protected]>
---
drivers/rtc/class.c | 3 +++
include/uapi/linux/rtc.h | 3 ++-
2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index dbccd71589b9..2e0cbc190a8a 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -389,6 +389,9 @@ int __devm_rtc_register_device(struct module *owner, struct rtc_device *rtc)
if (!rtc->ops->set_alarm)
clear_bit(RTC_FEATURE_ALARM, rtc->features);

+ if (rtc->ops->set_offset)
+ set_bit(RTC_FEATURE_CORRECTION, rtc->features);
+
rtc->owner = owner;
rtc_device_get_offset(rtc);

diff --git a/include/uapi/linux/rtc.h b/include/uapi/linux/rtc.h
index e4128be7963b..ded2aaab7ec7 100644
--- a/include/uapi/linux/rtc.h
+++ b/include/uapi/linux/rtc.h
@@ -131,7 +131,8 @@ struct rtc_param {
#define RTC_FEATURE_ALARM_RES_2S 2
#define RTC_FEATURE_UPDATE_INTERRUPT 3
#define RTC_FEATURE_NEED_WEEK_DAY 4
-#define RTC_FEATURE_CNT 5
+#define RTC_FEATURE_CORRECTION 5
+#define RTC_FEATURE_CNT 6

/* parameter list */
#define RTC_PARAM_FEATURES 0
--
2.31.1