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 <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20211018151933.76865-3-alexandre.belloni@bootlin.com
This commit is contained in:
Alexandre Belloni 2021-10-18 17:19:28 +02:00
parent 917425f71f
commit 6a8af1b656
2 changed files with 58 additions and 0 deletions

View File

@ -208,6 +208,7 @@ static long rtc_dev_ioctl(struct file *file,
const struct rtc_class_ops *ops = rtc->ops; const struct rtc_class_ops *ops = rtc->ops;
struct rtc_time tm; struct rtc_time tm;
struct rtc_wkalrm alarm; struct rtc_wkalrm alarm;
struct rtc_param param;
void __user *uarg = (void __user *)arg; void __user *uarg = (void __user *)arg;
err = mutex_lock_interruptible(&rtc->ops_lock); err = mutex_lock_interruptible(&rtc->ops_lock);
@ -221,6 +222,7 @@ static long rtc_dev_ioctl(struct file *file,
switch (cmd) { switch (cmd) {
case RTC_EPOCH_SET: case RTC_EPOCH_SET:
case RTC_SET_TIME: case RTC_SET_TIME:
case RTC_PARAM_SET:
if (!capable(CAP_SYS_TIME)) if (!capable(CAP_SYS_TIME))
err = -EACCES; err = -EACCES;
break; break;
@ -382,6 +384,44 @@ static long rtc_dev_ioctl(struct file *file,
err = -EFAULT; err = -EFAULT;
return err; 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: default:
/* Finally try the driver's ioctl interface */ /* Finally try the driver's ioctl interface */
if (ops->ioctl) { if (ops->ioctl) {

View File

@ -14,6 +14,7 @@
#include <linux/const.h> #include <linux/const.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/types.h>
/* /*
* The struct used to pass data via the following ioctl. Similar to the * 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 */ 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 * ioctl calls that are permitted to the /dev/rtc interface, if
* any of the RTC drivers are enabled. * 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_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_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_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_LOW _BITUL(1) /* Backup voltage is low */
#define RTC_VL_BACKUP_EMPTY _BITUL(2) /* Backup empty or not present */ #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_UPDATE_INTERRUPT 4
#define RTC_FEATURE_CNT 5 #define RTC_FEATURE_CNT 5
/* parameter list */
#define RTC_PARAM_FEATURES 0
#define RTC_MAX_FREQ 8192 #define RTC_MAX_FREQ 8192