日期:2014-05-16  浏览次数:20976 次

深入解析linux下rtc架构

一.描述rtc相关结构体

1.rtc设备

struct rtc_device	//rtc设备
{
	struct device dev;					//设备文件
	struct module *owner;				//所有者
	int id;								//次设备号
	char name[RTC_DEVICE_NAME_SIZE];	//rtc设备名
	const struct rtc_class_ops *ops;	//rtc类操作函数集
	struct mutex ops_lock;
	struct cdev char_dev;				//字符设备
	unsigned long flags;				//忙标志 (RTC_DEV_BUSY)
	unsigned long irq_data;				//中断数据
	spinlock_t irq_lock;
	wait_queue_head_t irq_queue;
	struct fasync_struct *async_queue;
	struct rtc_task *irq_task;			//中断任务
	spinlock_t irq_task_lock;
	int irq_freq;						//中断频率
	int max_user_freq;					//默认64
};

1.1 同时也定义了一个宏,通过设备文件查找rtc设备

#define to_rtc_device(d) container_of(d, struct rtc_device, dev)

2.rtc类操作函数集

struct rtc_class_ops {
	int (*open)(struct device *);										//打开
	void (*release)(struct device *);									//释放
	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 *);					//proc接口
	int (*set_mmss)(struct device *, unsigned long secs);				//设置时间mmss
	int (*irq_set_state)(struct device *, int enabled);					//设置中断状态
	int (*irq_set_freq)(struct device *, int freq);						//设置中断频率
	int (*read_callback)(struct device *, int data);					//读回调函数
	int (*alarm_irq_enable)(struct device *, unsigned int enabled);		//闹钟中断使能
	int (*update_irq_enable)(struct device *, unsigned int enabled);	//更新中断使能
};

这里有两种设置时间的方法set_time和set_mmss,看它们参数可以区别出set_time使用rtc时间来设置,
set_mmss是根据秒数来设置(“Gregorian”时间)

二.rtc架构

1.rtc设备初始化函数

void __init rtc_dev_init(void)	//入口函数
{
	int err;
	err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc");	//动态分配rtc设备号 RTC_DEV_MAX=16个
	if (err < 0)
		printk(KERN_ERR "%s: failed to allocate char dev region\n",__FILE__);
}

2.rtc设备的注册

rtc注册由具体设备驱动调用,同时设备驱动必须提供rtc_class_ops操作函数集

struct rtc_device *rtc_device_register(const char *name, struct device *dev,const struct rtc_class_ops *ops,struct module *owner)
{
	struct rtc_device *rtc;	//rtc设备
	int id, err;
	if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) {	//idr机制预分配
		err = -ENOMEM;
		goto exit;
	}
	mutex_lock(&idr_lock);
	err = idr_get_new(&rtc_idr, NULL, &id);	//通过idr机制获取id号
	mutex_unlock(&idr_lock);
	if (err < 0)
		goto exit;
	id = id & MAX_ID_MASK;	//id掩码过滤
	rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL);	//分配rtc设备
	if (rtc == NULL) {
		err = -ENOMEM;
		goto exit_idr;
	}
	rtc->id = id;				//次设备号
	rtc->ops = ops;				//rtc类操作函数集
	rtc->owner = owner;			//所有者
	rtc->max_user_freq = 64;	//最大用户频率
	rtc->dev.parent = dev;		//设备父设备
	rtc->dev.class = rtc_class;	//2.1 设备类
	rtc->dev.release = rtc_device_release;	//设备释放方法
	mutex_init(&rtc->ops_lock);
	spin_lock_init(&rtc->irq_lock);
	spin_lock_init(&rtc->irq_task_lock);
	init_waitqueue_head(&rtc->irq_queue);
	strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);	//设置rtc设备名
	dev_set_name(&rtc->dev, "rtc%d", id);			//设置设备名
	rtc_dev_prepare(rtc);							//2.2 rtc设备准备
	err = device_register(&rtc->dev);				//注册设备文件
	if (err) {
		put_device(&rtc->dev);
		goto exit_kfree;
	}
	rtc_dev_add_device(rtc);	//2.3 rtc添加设备
	rtc_sysfs_add_device(rtc);	//sysfs添加设备文件
	rtc_proc_add_device(rtc);	//procfs添加设备文件
	dev_info(dev, "rtc core: registered %s as %s\n",rtc->name, dev_name(&rtc->dev));
	return rtc;
exit_kfree:
	kfree(rtc);
exit_idr:
	mutex_lock(&idr_lock);
	idr_remove(&rtc_idr, id);
	mutex_unlock(&idr_lock);
exit:
	dev_err(dev, "rtc core: unable to regi