标签:
①RTC设备层:static struct resource s3c_rtc_resource[] = { [0] = { .start = S3C24XX_PA_RTC, .end = S3C24XX_PA_RTC + 0xff, .flags = IORESOURCE_MEM, }, [1] = { .start = IRQ_RTC, .end = IRQ_RTC, .flags = IORESOURCE_IRQ, }, [2] = { .start = IRQ_TICK, .end = IRQ_TICK, .flags = IORESOURCE_IRQ } }; struct platform_device s3c_device_rtc = { .name = "s3c2410-rtc", .id = -1, .num_resources = ARRAY_SIZE(s3c_rtc_resource), .resource = s3c_rtc_resource, //## };arch/arm/mach-s3c2440/mach-tq2440.c
static struct platform_device *tq2440_devices[] __initdata = { ......, &s3c_device_rtc, //## ......, };tq2440_devices[]这个数组在哪里被使用?这意味着RTC设备在哪里被注册。它是个静态数组,就在该文件找就行了。
platform_add_devices(tq2440_devices, ARRAY_SIZE(tq2440_devices));//注意:是platform_add_devices是通过for循环调用platform_devices_add()函数根据宏的展开:
//通过这个函数就把这个数组里边所有的设备资源都注册到了platform设备总线下
static struct platform_driver s3c2410_rtc_driver = { .probe = s3c_rtc_probe, ...... .driver = { .name = "s3c2410-rtc", .owner = THIS_MODULE, }, };函数调用关系:
return platform_driver_register(&s3c2410_rtc_driver);//这样就把RTC驱动注册到platform总线上去了看看驱动层的探针函数的实现:
s3c_rtc_probe(struct platform_device *pdev) { ...... s3c_rtc_tickno = platform_get_irq(pdev, 1); ...... s3c_rtc_alarmno = platform_get_irq(pdev, 0); ...... res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ...... s3c_rtc_base = ioremap(res->start, res->end - res->start + 1); ...... s3c_rtc_enable(pdev, 1); ...... s3c_rtc_setfreq(&pdev->dev, 1); ...... rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops,THIS_MODULE);//【进去分析】 }当我进去分析rtc_device_register()的实现时让我纳闷的是:
rtc_device_register(const char *name, struct device *dev,const struct rtc_class_ops *ops,struct module *owner) { struct rtc_device *rtc; ...... //①申请这么一个结构体往后就初始化他的成员 rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); ...... rtc->id = id; rtc->ops = ops; rtc->owner = owner; rtc->max_user_freq = 64; rtc->dev.parent = dev; rtc->dev.class = rtc_class; rtc->dev.release = rtc_device_release; ...... rtc_dev_prepare(rtc);//这个函数在/drivers/rtc/rtc-dev.c:定义 //②把这个结构的dev结构成员往上注册 err = device_register(&rtc->dev); //这个函数最终就是调用device_add(&pdev->dev); ...... rtc_dev_add_device(rtc); rtc_sysfs_add_device(rtc); rtc_proc_add_device(rtc); ...... }且看rtc_device结构体:
struct rtc_device { struct device dev; struct module *owner; int id; char name[RTC_DEVICE_NAME_SIZE]; ....... const struct rtc_class_ops *ops; //## struct mutex ops_lock; ....... struct cdev char_dev; unsigned long flags; int max_user_freq; }在/drivers/rtc/rtc-s3c.c
static const struct rtc_class_ops s3c_rtcops = { .open = s3c_rtc_open, .release = s3c_rtc_release, .read_time = s3c_rtc_gettime, .set_time = s3c_rtc_settime, .read_alarm = s3c_rtc_getalarm, .set_alarm = s3c_rtc_setalarm, .irq_set_freq = s3c_rtc_setfreq, .irq_set_state = s3c_rtc_setpie, .proc = s3c_rtc_proc, };这个结构体的成员函数都是实实在在地要操作底层硬件的函数。
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,//**ioctl()函数里边命令的响应函数在/drivers/rtc/intreface.c中定义 .open = rtc_dev_open, .release = rtc_dev_release, .fasync = rtc_dev_fasync, };看看这个file_operation在哪里被使用:
rtc_dev_prepare(struct rtc_device *rtc) { ...... rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id); ...... cdev_init(&rtc->char_dev, &rtc_dev_fops);//在这里被用来注册字符设备 rtc->char_dev.owner = rtc->owner; }那rtc_dev_prepare()这个函数在什么时候在什么地方被调用?
rtc_device_register(const char *name, struct device *dev,const struct rtc_class_ops *ops,struct module *owner) { struct rtc_device *rtc; ...... //①申请这么一个结构体往后就初始化他的成员 rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); ...... rtc->id = id; rtc->ops = ops; ...... rtc->dev.class = rtc_class; ...... rtc_dev_prepare(rtc);//## //②把这个结构的dev结构成员往上注册 err = device_register(&rtc->dev); //这个函数最终就是调用device_add(&pdev->dev); ...... rtc_dev_add_device(rtc); ...... }分析到这里RTC驱动的主线工作路线就呈现出来了,但有一个问题自然会想到,在RTC驱动层和设备层已经把RTC驱动
rtc_device_register(const char *name, struct device *dev,const struct rtc_class_ops *ops,struct module *owner) { struct rtc_device *rtc; ...... //①申请这么一个结构体往后就初始化他的成员 rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); ...... rtc->ops = ops; ...... rtc->dev.class = rtc_class; rtc_dev_prepare(rtc);//这个函数在最终完成字符设备的注册 //②从根源的角度来说以下就是probe函数最终多做的事情 err = device_register(&rtc->dev); //这个函数最终就是调用device_add(&pdev->dev); ...... rtc_dev_add_device(rtc); rtc_sysfs_add_device(rtc); rtc_proc_add_device(rtc); ...... }在/drivers/rtc/class.c
rtc_init(void) { rtc_class = class_create(THIS_MODULE, "rtc"); /* 创建了一个类--rtc */ ...... rtc_class->suspend = rtc_suspend; rtc_class->resume = rtc_resume; rtc_dev_init(); /* 为RTC设备动态分配设备号 */ rtc_sysfs_init(rtc_class); return 0; }这个函数在linux设备模型sysfs下创建了一个rtc的类,那么肯定有一个地方会往这个类中添加设备,按照这种推理
error = device_add_class_symlinks(dev);就是这个函数了:
static int device_add_class_symlinks(struct device *dev)//从函数的名字猜测:在类下创建设备的符号链接文件 { int error; ...... error = sysfs_create_link(&dev->kobj,&dev->class->p->class_subsys.kobj,"subsystem");//创建链接文件 ...... class_name = make_class_name(dev->class->name,&dev->kobj);//设置类下的设备名 }如此,我们上面关心的问题就都解决了,多做这些事情无非是想把rtc归为一个类,所有这种设备都会统一添加到这rtc类中
标签:
原文地址:http://blog.csdn.net/clb1609158506/article/details/45165539