forked from mirrors/linux
		
	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:
		
							parent
							
								
									917425f71f
								
							
						
					
					
						commit
						6a8af1b656
					
				
					 2 changed files with 58 additions and 0 deletions
				
			
		|  | @ -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(¶m, 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, ¶m, sizeof(param))) | ||||||
|  | 				err = -EFAULT; | ||||||
|  | 
 | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	case RTC_PARAM_SET: | ||||||
|  | 		if (copy_from_user(¶m, 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) { | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Alexandre Belloni
						Alexandre Belloni