1. RTC Subsystem Framework
The RTC (Real Time Clock) subsystem is divided into the following three parts:
-
RTC Core is responsible for the registration and deregistration of RTC devices, providing character device files and sysfs interfaces to user space.
-
RTC Driver registers the RTC device into the RTC subsystem and provides a set of low-level hardware operation functions.
-
User Space Interface includes the
<span>/dev/rtcX</span>character device file, as well as debugging interfaces such as<span>/sys/class/rtc/rtcX/</span>and<span>/proc/driver/rtc</span>.

The initialization of the RTC subsystem mainly includes allocating the <span>rtc_class</span> class and assigning device numbers for the RTC devices:
rtc_init → class_create // Create rtc_class class → rtc_dev_init → alloc_chrdev_region // Allocate sub-device number range (0~15) for RTC devices, with the major device number assigned randomly, and the result stored in rtc_devt
During system startup, the RTC time is set to the system time:
rtc_hctosys → rtc_read_time → rtc_tm_to_time64 → do_settimeofday64
Interrupt Type Description:
-
AIE: Alarm Interrupt Enable
-
UIE: Update Interrupt Enable
-
PIE: Periodic Interrupt Enable
-
WIE: Watchdog Interrupt Enable
2. RTC Configuration
Kernel Configuration Options:
Device Drivers → Real Time Clock → [*] Set system time from RTC on startup and resume → (rtc0) RTC used to set the system time → [*] Set the RTC time based on NTP synchronization → (rtc0) RTC used to synchronize NTP adjustment → [*] RTC debug support → [*] RTC non-volatile storage support → [*] /sys/class/rtc/rtcN (sysfs) → [*] /proc/driver/rtc (procfs for rtcN) → [*] /dev/rtcN (character devices) → [*] RTC
Related Source Code File Structure:
drivers/rtc/├── class.c // rtc_class creation, device registration/deregistration, power management├── dev.c // RTC subsystem initialization, character device operation function set├── hctosys.c // Set system time from RTC at startup (Hardware Clock to System)├── interface.c // General timer interface and rtc_class_ops calls├── lib.c // General functions for time and date├── nvmem.c // NVRAM access for RTC information├── proc.c // Implementation of /proc/driver/rtc├── rtc.c // RTC driver├── sysfs.c // Implementation of sysfs attribute interface└── systohc.c // Write NTP time to RTC (System to Hardware Clock)
3. RTC Data Structures and APIs
1. Core Data Structure
struct rtc_device:
struct rtc_device { struct device dev; struct module *owner; int id; // RTC device number const struct rtc_class_ops *ops;// Low-level hardware operation function set struct mutex ops_lock; struct cdev char_dev; // Character device unsigned long flags; unsigned long irq_data; spinlock_t irq_lock; wait_queue_head_t irq_queue; // For poll wait queue struct fasync_struct *async_queue; // For fasync asynchronous notification // ...};
struct rtc_class_ops:
struct rtc_class_ops { int (*ioctl)(struct device *, unsigned int, unsigned long); int (*read_time)(struct device *, struct rtc_time *); int (*set_time)(struct device *, struct rtc_time *); int (*read_alarm)(struct device *, struct rtc_wkalrm *); int (*set_alarm)(struct device *, struct rtc_wkalrm *); int (*proc)(struct device *, struct seq_file *); int (*alarm_irq_enable)(struct device *, unsigned int enabled); int (*read_offset)(struct device *, long *offset); int (*set_offset)(struct device *, long offset);};
2. RTC Device Registration Functions
struct rtc_device *devm_rtc_device_register( struct device *dev, const char *name, const struct rtc_class_ops *ops, struct module *owner);struct rtc_device *devm_rtc_allocate_device(struct device *dev);int __rtc_register_device(struct module *owner, struct rtc_device *rtc);
Overview of the Registration Process:
devm_rtc_device_register → devm_rtc_allocate_device → rtc_device_get_id // Get device number → devres_alloc // Allocate resource management structure → rtc_allocate_device → kzalloc // Allocate rtc_device → device_initialize // Initialize device structure → rtc_timer_init // Initialize timers (aie_timer, uie_rtctimer, pie_timer) → __rtc_register_device → rtc_dev_prepare // Initialize cdev → cdev_device_add // Register character device → rtc_proc_add_device // Create /proc/driver/rtc interface
Each RTC device has the following attributes under <span>/sys/class/rtc/rtcX/</span>:
static struct attribute *rtc_attrs[] = { &dev_attr_name.attr, &dev_attr_date.attr, &dev_attr_time.attr, &dev_attr_since_epoch.attr, &dev_attr_max_user_freq.attr, &dev_attr_hctosys.attr, &dev_attr_wakealarm.attr, &dev_attr_offset.attr, &dev_attr_range.attr, NULL,};
3. Device File Operation Function Set
static const struct file_operations rtc_dev_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .read = rtc_dev_read, .poll = rtc_dev_poll, .unlocked_ioctl = rtc_dev_ioctl, .open = rtc_dev_open, .release = rtc_dev_release, .fasync = rtc_dev_fasync,};
Example of ioctl Operation:
static long rtc_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { case RTC_ALM_READ: err = rtc_read_alarm(rtc, &alarm); // ... case RTC_ALM_SET: err = rtc_set_alarm(rtc, &alarm); // ... case RTC_RD_TIME: err = rtc_read_time(rtc, &tm); // ... case RTC_SET_TIME: err = rtc_set_time(rtc, &tm); // ... default: if (ops->ioctl) err = ops->ioctl(rtc->dev.parent, cmd, arg); // ... }}
Poll and Fasync Mechanism:
// Poll waiting for interruptstatic __poll_t rtc_dev_poll(struct file *file, poll_table *wait) { poll_wait(file, &rtc->irq_queue, wait); return (rtc->irq_data != 0) ? (EPOLLIN | EPOLLRDNORM) : 0;}// Fasync asynchronous notificationstatic int rtc_dev_fasync(int fd, struct file *file, int on) { return fasync_helper(fd, file, on, &rtc->async_queue);}
4. Common RTC Operation APIs
extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm);extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);extern int rtc_set_ntp_time(struct timespec64 now, unsigned long *target_nsec);int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm);extern int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alrm);extern int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alrm);extern int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alrm);extern void rtc_update_irq(struct rtc_device *rtc, unsigned long num, unsigned long events);extern int rtc_irq_set_state(struct rtc_device *rtc, int enabled);extern int rtc_irq_set_freq(struct rtc_device *rtc, int freq);extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled);extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled);