In the Linux kernel, the RTC device driver is also a standard character device driver. The RTC device is operated in the application through functions such as open, close, read, write, and ioctl.
In the Linux kernel, the RTC device also has its own device structure rtc_device, so the process of the RTC device driver is the application and initialization of the rtc_device structure, and then the rtc_device structure is registered in the kernel. It can be seen that most devices are in such a process, but the structure and function of the device are different.
The rtc_device structure is defined in the include/linux/rtc.h file, and the content is as follows:
104 struct rtc_device
105 {
106 struct device dev; /* 设备 */
107 struct module *owner;
108
109 int id; /* ID */
110 char name[RTC_DEVICE_NAME_SIZE]; /* 名字 */
111
112 const struct rtc_class_ops *ops; /* RTC 设备底层操作函数 */
113 struct mutex ops_lock;
114
115 struct cdev char_dev; /* 字符设备 */
116 unsigned long flags;
117
118 unsigned long irq_data;
119 spinlock_t irq_lock;
120 wait_queue_head_t irq_queue;
121 struct fasync_struct *async_queue;
122
123 struct rtc_task *irq_task;
124 spinlock_t irq_task_lock;
125 int irq_freq;
126 int max_user_freq;
127
128 struct timerqueue_head timerqueue;
129 struct rtc_timer aie_timer;
130 struct rtc_timer uie_rtctimer;
131 struct hrtimer pie_timer; /* sub second exp, so needs hrtimer */
132 int pie_enabled;
133 struct work_struct irqwork;
134 /* Some hardware can't support UIE mode */
135 int uie_unsupported;
......
147 };
Although there are many member variables in the rtc_device structure, most of them don't need us to worry about. What we need to focus on is the ops member variable, which is a pointer variable of type rtc_class_ops. The rtc_class_ops structure is a collection of operation functions at the bottom of the RTC device, including functions such as reading and writing time. Therefore, the functions implemented in the rtc_class_ops structure are different in different RTC devices. The rtc_class_ops structure is defined in the include/linux/rtc.h file, and the content is as follows:
71 struct rtc_class_ops {
72 int (*open)(struct device *);
73 void (*release)(struct device *);
74 int (*ioctl)(struct device *, unsigned int, unsigned long);
75 int (*read_time)(struct device *, struct rtc_time *);
76 int (*set_time)(struct device *, struct rtc_time *);
77 int (*read_alarm)(struct device *, struct rtc_wkalrm *);
78 int (*set_alarm)(struct device *, struct rtc_wkalrm *);
79 int (*proc)(struct device *, struct seq_file *);
80 int (*set_mmss64)(struct device *, time64_t secs);
81 int (*set_mmss)(struct device *, unsigned long secs);
82 int (*read_callback)(struct device *, int data);
83 int (*alarm_irq_enable)(struct device *, unsigned int enabled);
84 };
It can be seen from the member variables of the tc_class_ops structure that all functions are integrated. But it should be noted that these functions in rtc_class_ops are only the lowest RTC device operation functions, not the file_operations function operation set provided to the application layer. RTC is a character device, so there must be a file_operations function operation set for character devices. The Linux kernel provides a RTC universal character device driver file named drivers/rtc/rtc-dev.c. The rtc-dev.c file provides all The file_operations function operation set shared by RTC devices is as follows:
448 static const struct file_operations rtc_dev_fops = {
449 .owner = THIS_MODULE,
450 .llseek = no_llseek,
451 .read = rtc_dev_read,
452 .poll = rtc_dev_poll,
453 .unlocked_ioctl = rtc_dev_ioctl,
454 .open = rtc_dev_open,
455 .release = rtc_dev_release,
456 .fasync = rtc_dev_fasync,
457 };
With the operation set of the standard character device, the application can realize the functions it needs through the functions in this structure. For example, to read and set the time, it will be realized through the rtc_dev_ioctl function. The rtc_dev_ioctl function will call the read_time, set_time and other functions in the rtc_class_ops structure to read and write to specific RTC devices. Let's take a brief look at the rtc_dev_ioctl function. The part of the function is as follows:
218 static long rtc_dev_ioctl(struct file *file,
219 unsigned int cmd, unsigned long arg)
220 {
221 int err = 0;
222 struct rtc_device *rtc = file->private_data;
223 const struct rtc_class_ops *ops = rtc->ops;
224 struct rtc_time tm;
225 struct rtc_wkalrm alarm;
226 void __user *uarg = (void __user *) arg;
227
228 err = mutex_lock_interruptible(&rtc->ops_lock);
229 if (err)
230 return err;
......
269 switch (cmd) {
......
333 case RTC_RD_TIME: /* 读取时间 */
334 mutex_unlock(&rtc->ops_lock);
335
336 err = rtc_read_time(rtc, &tm);
337 if (err < 0)
338 return err;
339
340 if (copy_to_user(uarg, &tm, sizeof(tm)))
341 err = -EFAULT;
342 return err;
343
344 case RTC_SET_TIME: /* 设置时间 */
345 mutex_unlock(&rtc->ops_lock);
346
347 if (copy_from_user(&tm, uarg, sizeof(tm)))
348 return -EFAULT;
349
350 return rtc_set_time(rtc, &tm);
......
401 default:
402 /* Finally try the driver's ioctl interface */
403 if (ops->ioctl) {
404 err = ops->ioctl(rtc->dev.parent, cmd, arg);
405 if (err == -ENOIOCTLCMD)
406 err = -ENOTTY;
407 } else
408 err = -ENOTTY;
409 break;
410 }
411
412 done:
413 mutex_unlock(&rtc->ops_lock);
414 return err;
415 }
In line 333, RTC_RD_TIME is the time read command.
In line 336, if it is to read the time, call the rtc_read_time function to get the current RTC clock.
In the rtc_read_time function, rtc_read_time will call the __rtc_read_time function. The content of the __rtc_read_time function is as follows:
23 static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
24 {
25 int err;
26 if (!rtc->ops)
27 err = -ENODEV;
28 else if (!rtc->ops->read_time)
29 err = -EINVAL;
30 else {
31 memset(tm, 0, sizeof(struct rtc_time));
32 err = rtc->ops->read_time(rtc->dev.parent, tm);
33 if (err < 0) {
34 dev_dbg(&rtc->dev, "read_time: fail to read: %d\n",
35 err);
36 return err;
37 }
38
39 err = rtc_valid_tm(tm);
40 if (err < 0)
41 dev_dbg(&rtc->dev, "read_time: rtc_time isn't valid\n");
42 }
43 return err;
44 }
On line 32, the __rtc_read_time function calls read_time in the rtc_class_ops structure to obtain the current time from the RTC device.
The other commands in the rtc_dev_ioctl function are similar, and the corresponding functions in the rtc_class_ops structure will eventually be called. Therefore, the calling process of the RTC driver in the Linux kernel is:
application (ioctl) -> kernel layer (rtc_dev_ioctl) -> device driver layer (rtc_class_ops)
rtc_device_register function: Register the rtc_device structure to the kernel. This function will apply for an rtc_device and initialize the rtc_device, and finally return the rtc_device to the caller. The function prototype is as follows:
struct rtc_device *rtc_device_register(const char *name,
struct device *dev,
const struct rtc_class_ops *ops,
struct module *owner)
name: The name of the device.
dev: device.
ops: RTC low-level driver function set.
owner: The owner of the drive module.
Return value: If the registration is successful, it will return rtc_device, if it is wrong, it will return a negative value.
rtc_device_unregister function: used the rtc_device structure of unregistered registration. The function prototype is as follows:
void rtc_device_unregister(struct rtc_device *rtc)