https://www.cnblogs.com/lifexy/p/7839625.html
RTC驱动分析总结:
drivers\rtc\rtc-s3c.c
s3c_rtc_init
platform_driver_register
s3c_rtc_probe
rtc_device_register("s3c", &pdev->dev, &s3c_rtcops, THIS_MODULE)
rtc_dev_prepare
cdev_init(&rtc->char_dev, &rtc_dev_fops);
rtc_dev_add_device
cdev_add
linux中的rtc驱动位于drivers/rtc下,里面包含了许多开发平台的RTC驱动,我们这里是以S3C24XX为主,所以它的RTC驱动为rc-s3c.c
1、进入./drivers/rtc/rtc-s3c.c
还是首先进入入口函数,如下图所示:
这里注册了一个"s3c2410-rtc"名称的平台设备驱动
而"s3c2410-rtc"的平台设备,在./arch/arm/plat-s3c24xx/devs.c里定义了,只不过没有注册,如下图所示:
当内核匹配到有与它名称同名的平台设备,就会调用.probe函数,接下来我们便进入s3c2410_rtcdrv->probe函数中看看,做了什么:
static int s3c_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtc; //rtc设备结构体
struct resource *res;
int ret;
s3c_rtc_tickno = platform_get_irq(pdev, 1); //获取IRQ_TICK节拍中断资源
s3c_rtc_alarmno = platform_get_irq(pdev, 0); //获取IRQ_RTC闹钟中断资源
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取内存资源
s3c_rtc_mem = request_mem_region(res->start,res->end-res->start+1,pdev->name);//申请内存资源
s3c_rtc_base = ioremap(res->start, res->end - res->start + 1); //对内存进行重映射
s3c_rtc_enable(pdev, 1); //设置硬件相关设置,使能RTC寄存器
s3c_rtc_setfreq(s3c_rtc_freq); //设置TICONT寄存器,使能节拍中断,设置节拍计数值
/*1.注册RTC设备*/
rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops,THIS_MODULE);
rtc->max_user_freq = 128;
platform_set_drvdata(pdev, rtc);
return 0;
}
显然最终会调用rtc_device_register()函数来向内核注册rtc_device设备,注册成功会返回一个已注册好的rtc_device。
而s3c_rtcops是一个rtc_class_ops结构体,里面就是保存如何操作这个rtc设备的函数,比如读写RTC时间,读写闹钟时间等,注册后,会保存在rtc_device->ops里
该函数在drivers/rtc/class.c文件内被定义。class.c文件主要定义了RTC子系统,
而内核初始化,便会进入class.c,进入rtc_init()-&g