Commit 6a8af1b6 authored by Alexandre Belloni's avatar Alexandre Belloni
Browse files

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: default avatarAlexandre Belloni <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20211018151933.76865-3-alexandre.belloni@bootlin.com
parent 917425f7
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -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) {
+18 −0
Original line number Diff line number Diff line
@@ -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