花了一个下午时间,把rtc代码的架构弄懂了,如下图所示:
下面附上各个包含详细注释的C文件源代码:
class.c源代码:
1 /* 2 * RTC subsystem, base class 3 * 4 * Copyright (C) 2005 Tower Technologies 5 * Author: Alessandro Zummo <a.zummo@towertech.it> 6 * 7 * class skeleton from drivers/hwmon/hwmon.c 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 本c文件工作总结: 13 1.在init函数中: 14 (1):创建sysfs文件系统的/sys/class/rtc目录,并且初始化rtc类的相关成员 15 作用:向用户空间提供设备的信息,驱动程序不需要直接处理类 16 (2):动态分配rtc字符设备的设备号 17 (3):初始化rtc的/sys/class/rtc目录中的属性文件 18 2.在exit函数中: 19 (1):注销rtc设备号 20 (2):注销sysfs文件系统的/sys/class/rtc目录。 21 3.在rtc_device_register中 22 (1):申请一个idr整数ID管理机制结构体,并且初始化相关成员 23 (2):将设备dev关联sysfs下的rtc类 24 (3):初始化rtc结构体的信号量 25 (4):初始化rtc结构体中的中断 26 (5):设置rtc的名字 27 (6):初始化rtc字符设备的设备号,然后注册rtc设备,自动创建/dev/rtc(n)设备节点文件 28 (7):注册字符设备 29 (8):在/sys/rtc/目录下创建一个闹钟属性文件 30 (9):创建/proc/driver/rtc目录 31 4.在rtc_device_unregister中 32 (1):删除sysfs中的rtc设备,即删除/sys/class/rtc目录 33 (2):删除dev下的/dev/rtc(n)设备节点文件 34 (3):删除虚拟文件系统接口,即删除/proc/driver/rtc目录 35 (4):卸载字符设备 36 (5):清空rtc的操作函数指针rtc->ops 37 (6):释放rtc的device结构体 38 5.在rtc_device_release函数中 39 (1):卸载idr数字管理机制结构体 40 (2):释放rtc结构体的内存 41 */ 42 43 #include <linux/module.h> 44 #include <linux/rtc.h> 45 #include <linux/kdev_t.h> 46 #include <linux/idr.h> 47 48 #include "rtc-core.h" 49 static DEFINE_MUTEX 50 51 static DEFINE_IDR(rtc_idr); //定义整数ID管理机制idr结构体 52 (idr_lock); 53 struct class *rtc_class; //定义sysfs的类结构体 54 55 static void rtc_device_release(struct device *dev) 56 { 57 struct rtc_device *rtc = to_rtc_device(dev); 58 mutex_lock(&idr_lock); 59 idr_remove(&rtc_idr, rtc->id); //卸载idr数字管理机制结构体 60 mutex_unlock(&idr_lock); 61 kfree(rtc); //释放rtc结构体的内存 62 } 63 64 #if defined(CONFIG_PM) && defined(CONFIG_RTC_HCTOSYS_DEVICE) 65 66 /* 67 * On suspend(), measure the delta between one RTC and the 68 * system's wall clock; restore it on resume(). 69 */ 70 71 static struct timespec delta; 72 static time_t oldtime; 73 74 static int rtc_suspend(struct device *dev, pm_message_t mesg) 75 { 76 struct rtc_device *rtc = to_rtc_device(dev); 77 struct rtc_time tm; 78 struct timespec ts = current_kernel_time(); 79 80 if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) 81 return 0; 82 83 rtc_read_time(rtc, &tm); 84 rtc_tm_to_time(&tm, &oldtime); 85 86 /* RTC precision is 1 second; adjust delta for avg 1/2 sec err */ 87 set_normalized_timespec(&delta, 88 ts.tv_sec - oldtime, 89 ts.tv_nsec - (NSEC_PER_SEC >> 1)); 90 91 return 0; 92 } 93 94 static int rtc_resume(struct device *dev) 95 { 96 struct rtc_device *rtc = to_rtc_device(dev); 97 struct rtc_time tm; 98 time_t newtime; 99 struct timespec time; 100 101 if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) 102 return 0; 103 104 rtc_read_time(rtc, &tm); 105 if (rtc_valid_tm(&tm) != 0) { 106 pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); 107 return 0; 108 } 109 rtc_tm_to_time(&tm, &newtime); 110 if (newtime <= oldtime) { 111 if (newtime < oldtime) 112 pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); 113 return 0; 114 } 115 116 /* restore wall clock using delta against this RTC; 117 * adjust again for avg 1/2 second RTC sampling error 118 */ 119 set_normalized_timespec(&time, 120 newtime + delta.tv_sec, 121 (NSEC_PER_SEC >> 1) + delta.tv_nsec); 122 do_settimeofday(&time); 123 124 return 0; 125 } 126 127 #else 128 #define rtc_suspend NULL 129 #define rtc_resume NULL 130 #endif 131 132 133 /** 134 * rtc_device_register - register w/ RTC class 135 * @dev: the device to register 136 * 137 * rtc_device_unregister() must be called when the class device is no 138 * longer needed. 139 * 140 * Returns the pointer to the new struct class device. 141 */ 142 struct rtc_device *rtc_device_register(const char *name, struct device *dev, 143 const struct rtc_class_ops *ops, 144 struct module *owner) 145 { 146 struct rtc_device *rtc; 147 int id, err; 148 //整数ID管理机制 149 if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) { //检测IDR是否能正常获取 150 err = -ENOMEM; 151 goto exit; 152 } 153 154 155 mutex_lock(&idr_lock); //原子操作,上锁,防止被打断 156 err = idr_get_new(&rtc_idr, NULL, &id); //获取一个idr结构,并与id相关联 157 mutex_unlock(&idr_lock); //解锁 158 159 if (err < 0) 160 goto exit; 161 162 id = id & MAX_ID_MASK; //将32为id的无效高位清零 163 164 rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); //分配一个rtc_device结构体 165 if (rtc == NULL) { 166 err = -ENOMEM; 167 goto exit_idr; 168 } 169 170 rtc->id = id; //整数ID管理机制 171 rtc->ops = ops; //关联定义的操作函数结构体 open,release,ioctl等函数 172 rtc->owner = owner; //所属模块的相关信息 173 rtc->max_user_freq = 64; //最大使用数量 64 174 rtc->dev.parent = dev; //父设备 175 rtc->dev.class = rtc_class; //包含的sysfs下面的类 176 rtc->dev.release = rtc_device_release; //释放函数 177 178 mutex_init(&rtc->ops_lock); //初始化信号量 179 spin_lock_init(&rtc->irq_lock); 180 spin_lock_init(&rtc->irq_task_lock); 181 init_waitqueue_head(&rtc->irq_queue); //定义rtc中断 182 183 strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); //设置rtc的名字 184 dev_set_name(&rtc->dev, "rtc%d", id); 185 186 rtc_dev_prepare(rtc); //初始化rtc字符设备的设备号 187 188 err = device_register(&rtc->dev); //注册rtc设备,这样rtc会自动创建设备文件rtc(n) 189 if (err) 190 goto exit_kfree; 191 192 rtc_dev_add_device(rtc); //注册字符设备 193 rtc_sysfs_add_device(rtc); //为设备添加一个闹钟属性,在/sys/rtc下面创建闹钟属性文件 194 rtc_proc_add_device(rtc); //穿件proc文件结构体 在/proc目录下创建 driver/rtc 195 196 dev_info(dev, "rtc core: registered %s as %s\n", 197 rtc->name, dev_name(&rtc->dev)); //打印信息 198 199 return rtc; 200 201 exit_kfree: 202 kfree(rtc); 203 204 exit_idr: 205 mutex_lock(&idr_lock); 206 idr_remove(&rtc_idr, id); 207 mutex_unlock(&idr_lock); 208 209 exit: 210 dev_err(dev, "rtc core: unable to register %s, err = %d\n", 211 name, err); 212 return ERR_PTR(err); 213 } 214 EXPORT_SYMBOL_GPL(rtc_device_register); 215 216 217 /** 218 * rtc_device_unregister - removes the previously registered RTC class device 219 * 220 * @rtc: the RTC class device to destroy 221 */ 222 void rtc_device_unregister(struct rtc_device *rtc) 223 { 224 if (get_device(&rtc->dev) != NULL) { 225 mutex_lock(&rtc->ops_lock); //上锁 226 /* remove innards of this RTC, then disable it, before 227 * letting any rtc_class_open() users access it again 228 */ 229 rtc_sysfs_del_device(rtc); //删除sysfs下面的rtc设备 230 rtc_dev_del_device(rtc); //删除dev下的rtc 231 rtc_proc_del_device(rtc); //删除虚拟文件系统接口 232 device_unregister(&rtc->dev); //卸载字符设备 233 rtc->ops = NULL; //将rtc的操作函数指针清空 234 mutex_unlock(&rtc->ops_lock); //解锁 235 put_device(&rtc->dev); //释放rtc的device结构体 236 } 237 } 238 EXPORT_SYMBOL_GPL(rtc_device_unregister); 239 240 static int __init rtc_init(void) 241 { 242 rtc_class = class_create(THIS_MODULE, "rtc");//在/sys/class下面创建类目录,类名为rtc 243 if (IS_ERR(rtc_class)) { 244 printk(KERN_ERR "%s: couldn't create class\n", __FILE__); 245 return PTR_ERR(rtc_class); 246 } 247 //类的作用就是向用户空间提供设备的信息,驱动程序不需要直接处理类 248 rtc_class->suspend = rtc_suspend; //初始化类结构体的相关成员 249 rtc_class->resume = rtc_resume; //动态分配rtc的设备号 250 rtc_dev_init(); //动态分配 251 rtc_sysfs_init(rtc_class); //初始化rtc的属性文件 252 return 0; 253 } 254 255 static void __exit rtc_exit(void) 256 { 257 rtc_dev_exit(); //注销rtc设备号 258 class_destroy(rtc_class); //注销/sys/class下的类目录 259 } 260 261 subsys_initcall(rtc_init); 262 module_exit(rtc_exit); 263 264 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); 265 MODULE_DESCRIPTION("RTC class support"); 266 MODULE_LICENSE("GPL");