ARM-Linux驱动--RTC(实时时钟)驱动分析
时间:11-20
来源:互联网
点击:
rform_device这个参数后,就需要从中提取出需要的信息。它一般会通过调用内核提供的platform_get_resource和platform_get_irq等函数来获得相关信息。如通过platform_get_resource获得设备的起始地址后,可以对其进行request_mem_region和ioremap等操作,以便应用程序对其进行操作。通过platform_get_irq得到设备的中断号以后,就可以调用request_irq函数来向系统申请中断。这些操作在设备驱动程序中一般都要完成。
[cpp]view plaincopy
- staticint__devinits3c_rtc_probe(structplatform_device*pdev)
- {
- structrtc_device*rtc;//定义rtc_device结构体,定义在/include/linux/rtc.h
- structresource*res;//定义资源结构体,定义在/include/linux/ioport.h
- intret;
- pr_debug("%s:probe=%p\n",__func__,pdev);
- /*findtheIRQs*/
- s3c_rtc_tickno=platform_get_irq(pdev,1);//在系统定义的平台设备中获取中断号
- if(s3c_rtc_tickno<0){//异常处理
- dev_err(&pdev->dev,"noirqforrtctick\n");
- return-ENOENT;
- }
- /*getthememoryregion*/
- res=platform_get_resource(pdev,IORESOURCE_MEM,0);//获取RTC平台使用的IO资源
- if(res==NULL){
- dev_err(&pdev->dev,"failedtogetmemoryregionresource\n");
- return-ENOENT;
- }
- //申请内存区域,res是structresource类型,见本函数后面
- s3c_rtc_mem=request_mem_region(res->start,
- res->end-res->start+1,
- pdev->name);
- if(s3c_rtc_mem==NULL){//申请内存出错
- dev_err(&pdev->dev,"failedtoreservememoryregion\n");
- ret=-ENOENT;
- gotoerr_nores;
- }
- //将寄存器地址映射成虚拟地址,以便访问
- s3c_rtc_base=ioremap(res->start,res->end-res->start+1);
- if(s3c_rtc_base==NULL){
- dev_err(&pdev->dev,"failedioremap()\n");
- ret=-EINVAL;
- gotoerr_nomap;
- }
- /*checktoseeifeverythingissetupcorrectly*/
- s3c_rtc_enable(pdev,1);//对RTCCON寄存器设置,详情见下面的函数实现
- pr_debug("s3c2410_rtc:RTCCON=%02x\n",
- readb(s3c_rtc_base+S3C2410_RTCCON));
- s3c_rtc_setfreq(&pdev->dev,1);//详情见下面的函数实现
- /*registerRTCandexit*/
- rtc=rtc_device_register("s3c",&pdev->dev,&s3c_rtcops,
- THIS_MODULE);//注册RTC为RTC设备,其中s3c_rtcops定义见下
- if(IS_ERR(rtc)){
- dev_err(&pdev->dev,"cannotattachrtc\n");
- ret=PTR_ERR(rtc);
- gotoerr_nortc;
- }
- rtc->max_user_freq=128;//设置RTC节拍时间计数寄存器TICNT的节拍时间计数值的用户最大相对值
- //将RTC类的设备数据传递给系统设备,在/include/linux/platform_device.h中
[cpp]view plaincopy
- //#defineplatform_set_drvdata(_dev,data)dev_set_drvdata(&(_dev)->dev,(data)),该函数在/include/linux/device.h中定义,见本函数下面
[cpp]view plaincopy
- platform_set_drvdata(pdev,rtc);
[cpp]view plaincopy
- return0;
[cpp]view plaincopy
- //异常处理
- err_nortc:
- s3c_rtc_enable(pdev,0);
- iounmap(s3c_rtc_base);
- err_nomap:
- release_resource(s3c_rtc_mem);
- err_nores:
- returnret;
- }
[cpp]view plaincopy
- structresource{
- resource_size_tstart;
- resource_size_tend;
- constchar*name;
- unsignedlongflags;
- structresource*parent,*sibling,*child;
- };
[cpp]view plaincopy
- staticinlinevoiddev_set_drvdata(structdevice*dev,void*data)
- {
- dev->driver_data=data;
- }
- staticvoids3c_rtc_enable(structplatform_device*pdev,inten)
- {
- void__iomem*base=s3c_rtc_base;//__iomem的作用就是为了使编译器更好的优化编译
- unsignedinttmp;
- if(s3c_rtc_base==NULL)
- return;
- //en作为参数传递过来如果en==0,关闭电源前的情况
- if(!en){
- tmp=readb(base+S3C2410_RTCCON);
- writeb(tmp&~S3C2410_RTCCON_RTCEN,base+S3C2410_RTCCON);//设置RTCCON寄存器,屏蔽RTC使能,可以参考数据手册中寄存器的相关定义
- tmp=readb(base+S3C2410_TICNT);
- writeb(tmp&~S3C2410_TICNT_ENABLE,base+S3C2410_TICNT);//设置TICNT寄存器,屏蔽节拍时间中断使能
- }else{
- /*re-enablethedevice,andcheckitisok*/
- //en!=0的情况,表示系统复位,重新使能RTC驱动
- if((readb(base+S3C2410_RTCCON)&S3C2410_RTCCON_RTCEN)==0){//RTCCON第0位为0,将其设置为1,重新使能
- dev_info(&pdev->dev,"rtcdisabled,re-enabling\n");
- tmp=readb(base+S3C2410_RTCCON);
- writeb(tmp|S3C2410
ARMLinux驱动RTC实时时钟驱动分 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)