rtc: add parameter ioctl
authorAlexandre Belloni <alexandre.belloni@bootlin.com>
Mon, 18 Oct 2021 15:19:28 +0000 (17:19 +0200)
committerAlexandre Belloni <alexandre.belloni@bootlin.com>
Mon, 18 Oct 2021 15:20:50 +0000 (17:20 +0200)
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 <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20211018151933.76865-3-alexandre.belloni@bootlin.com
drivers/rtc/dev.c
include/uapi/linux/rtc.h

index 5b8ebe8..143c097 100644 (file)
@@ -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) {
index f4037c5..3241f9e 100644 (file)
@@ -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_UPDATE_INTERRUPT   4
 #define RTC_FEATURE_CNT                        5
 
+/* parameter list */
+#define RTC_PARAM_FEATURES             0
+
 #define RTC_MAX_FREQ   8192