第一节已经分析了整个RTC驱动的框架,这一节我们开始分析真正的主角rtc-s3c.c.看一个驱动,一般都是从驱动文件的最底层看起,不知道是不是写linux内核的大师们学习过我们的《易经》,易经64卦,每一卦有6 爻,我们分析一个卦的时候,也是从底下一个爻开始分析。废话少说,把代码直接拉到最下面:
666-669行:该驱动文件的描述,作者,申明为开源,以及声明一个模块别称,这些和具体的功能无关,了解一下也不是坏事;
652-664行:这个大家再熟悉不过了,系统起来的时候回去执行s3c_rtc_init,模块卸载的时候回去调用s3c_rtc_exit;s3c_rtc_init很爽快,就干了一件事,把这个驱动注册到系统中,与对应的设备匹配起来;而他的兄弟s3c_rtc_exit完成了相反的动作;
638-648行:RTC驱动结构体,如果前面的驱动成功注册进系统后,并找到了何止相对应的设备名,则s3c_rtc_probe函数被调用,它才是驱动开始的第一炮;也就是说,系统起来的时候,只要此驱动找到了与之对应的设备名,probe函数就会被调用。
Suspend和resume也是一对好哥们,系统睡眠和唤醒的时候,分别被调用。这两个和电源管理有关的,我们就不去细究了。
下面我们进入到prboe函数中:
467-477行:从平台设备中获取中断资源;
490-504行:从平台设备中获取IO内存资源;
这里要提一下,前面驱动注册的时候用platform_driver_register();就是把驱动注册成了一个平台驱动,对应的平台设备为
struct platform_device s3c_device_rtc = {
.name = "s3c2410-rtc",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_rtc_resource),
.resource = s3c_rtc_resource,
};
资源结构体:
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
}
};
我们在回过头来跟进
int platform_get_irq(struct platform_device *dev, unsigned int num)
{
struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
return r ? r->start : -ENXIO;
}
是不是一目了然了。
接着分析:
507-519行,获取clock并使能时钟,enable RTC;
524行:device_init_wakeup(&pdev->dev, 1);打开唤醒中断开关,RTC能在睡眠情况下唤醒系统,这只是一个开关,真正能不能唤醒系统,需要把中断设置为唤醒中断。
528行:把RTC驱动注册进linux系统,从此,这个RTC就在linux内核中有一席之地了,不再是“没房”一族了。
531-534行:注册失败,打道回府,后面都是徒劳。
到这里probe函数的主要功能算是完成啦。后面几行留给大家分析一下。
讲了这么多,好像还是和RTC的功能没占上半毛钱关系,什么设置闹钟,设置时间的词眼还没出现一个,下面一节开始分析这一块。