linux内核RTC驱动框架源码分析.doc_第1页
linux内核RTC驱动框架源码分析.doc_第2页
linux内核RTC驱动框架源码分析.doc_第3页
linux内核RTC驱动框架源码分析.doc_第4页
linux内核RTC驱动框架源码分析.doc_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

s3c2410 RTC驱动框架linux内核源码分析/*Description:s3c2410的rtc驱动的实现,rtc(realtimeclock)实时时钟的驱动是个很好的*理解如果编写驱动的硬件,它包括了最基本的硬中断,软中断的底层机制;*s3c2410的RTC驱动的实现个人认为更是对linux设备驱动一个很好的例子,他是通过二层结构来*实现的一个驱动,上层是一个armcommon的公共层,对上提供标准的通用的RTC操作接口,下层由*我们来实现针对自己的chip和自己要提供的功能来实现的一层驱动;*FileTree:*linux-|-arch|-arm|-mach-s3c2410|-devs.c/包含了对各个部件的resource的分配和定义,在这看rtc的资源;|-common|-rtctime.c/一个arm平台的通用rtc函数层,它对上隐藏了各种soc的rtcdriver的区别;|-kernel|-time.c/内核的初始化例程time_init()会调用的xxx_cmos_xxx函数的实现;定义了全局自旋锁rtc_lock用来串行化所有CPU对RTC的操作|-drivers|-char|-s3c2410-rtc.c/具体的s3c2410上的rtcchip的驱动实现,如果需要在arm平台的|板子上实现一个驱动,改写它就ok了。|-include|-asm-arm|-arch-s3c2410|-regs-rtc.h/S3C2410InternalRTCregisterdefinitionrefertodatasheet;|-rtc.h/arm平台rtc操作抽象层rtctime.c对应的.h|-linux|-time.h/mktime的实现;|-rtc.h/公用RTC.h*小结*1)提供给user的接口,在arch/arm/common/rtctime.c,include/asm-arm/rtc.h中实现,调用操作硬件驱动在drivers/char/s3c2410-rtc.c,include/asm-arm/arch-s3c2410/regs-rtc.h实现;*2)提供给kernel的接口,在arch/arm/kernel/time.c,include/linux/time.h中实现,调用操作硬件驱动在drivers/char/s3c2410-rtc.c,include/asm-arm/arch-s3c2410/regs-rtc.h实现;*Author:*FunctionList:*Changelog:*2007-06-24LiYangFirstversion*FQA:*50%Q1.在驱动中要将设备注册到总线,必须将设备封装成structdevice_driver;调查这个结构体中的每个成员.*0%Q2.在板子(什么类型)上什么样的设备要用总线(什么类型)注册?*90%Q3.*structdevice-总线设备*structdevice_driver-总线设备驱动*structplatform_device-平台设备*structresource-平台资源*!0%Q4.初始化rtcregister的函数的后面的flag具体控制什么?(在s2s65a里是否可以用它控制是softResetorhardwareReset)*0%Q5.什么时候调用suspend,resume?*/*Structures&Unions&Enums(#typedef)*/*include/linux/device.h*总线设备驱动结构体,将它注册到板子的总线上*/staticstructdevice_drivers3c2410_rtcdrv=.name=s3c2410-rtc,.owner=THIS_MODULE,.bus=&platform_bus_type,/总线类型,貌似不用管.probe=s3c2410_rtc_probe,/自检-初始化REG-注册到上一层.remove=s3c2410_rtc_remove,/注销.suspend=s3c2410_rtc_suspend,/挂起?.resume=s3c2410_rtc_resume,/重起?;/*/include/asm-arm/rtc.h*底层特别操作集,将他注册到上层的armcommon操作层*/staticstructrtc_opss3c2410_rtcops=.owner=THIS_MODULE,.open=s3c2410_rtc_open,.release=s3c2410_rtc_release,.ioctl=s3c2410_rtc_ioctl,.read_time=s3c2410_rtc_gettime,.set_time=s3c2410_rtc_settime,.read_alarm=s3c2410_rtc_getalarm,.set_alarm=s3c2410_rtc_setalarm,.proc=s3c2410_rtc_proc,;/*GlobalVariables*/s3c2410-rtc.c|/*IRQHandlers*/|-s3c2410_rtc_alarmirq(intirq,void*id,structpt_regs*r)|-rtc_update(1,RTC_AF|RTC_IRQF);/获得中断标志,和唤醒read阻塞,异步通知;|-s3c2410_rtc_tickirq(intirq,void*id,structpt_regs*r)|/*Updatecontrolregisters,与硬件实现有关,refertodatasheet*/|-s3c2410_rtc_setaie(intto)|-s3c2410_rtc_setpie(intto)|-s3c2410_rtc_setfreq(intfreq)|/*实现了要插到上层armcommon层的具体的硬件操作,来填充structrtc_ops,这个具体与硬件相关的操作集会用|register_rtc注册到上层的*/|-s3c2410_rtc_gettime(structrtc_time*rtc_tm)|-s3c2410_rtc_settime(structrtc_time*tm)|-s3c2410_rtc_getalarm(structrtc_wkalrm*alrm)|-s3c2410_rtc_setalarm(structrtc_wkalrm*alrm)|/*|*插入到上层ioctl中的ioctl,上层中已经通过这个driver中的gettime,settime在其ioctl中实现了取得和设置时间|*,和一些共同的ioctl操作了|*所以我们在这只要实现与硬件不同部分的ioctl操作*/|-s3c2410_rtc_ioctl(unsignedintcmd,unsignedlongarg)|-s3c2410_rtc_proc(char*buf)|-s3c2410_rtc_open(void)|1.注册申请闹钟中断ISQ-s3c2410_rtc_alarmirq|2.周期中断ISQ-s3c2410_rtc_tickirq|-s3c2410_rtc_release(void)|/*InitializeRTCRegs*/|-s3c2410_rtc_enable(structdevice*dev,inten)|-if(!en)|/*beforepoweroff,theRTCENbitshouldbeclearedto|0topreventinadvertentwritingintoRTCregisters.*/|1.将控制R的RTCEN位清0;|2.disableinterrupt.|-else/*re-enablethedevice,andcheckitisok*/|1.将控制R的RTCEN位致1。|2.BCDcountselect.-0=MergeBCDcounters|3.RTCclockcountreset.-0=noreset|-s3c2410_rtc_probe(structdevice*dev)|?structplatform_device*pdev=to_platform_device(dev);/通过这个设备找到它宿主平台的大设备;|structresource*res;|/*findtheIRQs,RTC有2中中断,周期中断和闹钟中断*/|-s3c2410_rtc_tickno=platform_get_irq(pdev,1);/从平台上取得一个IRQ号给这个设备;|/*getthememoryregion*/|-res=platform_get_resource(pdev,IORESOURCE_MEM,0);|/*向内核申请资源空间*/|-s3c2410_rtc_mem=request_mem_region(res-start,res-end-res-start+1,pdev-name);/res-start这些资源的分配和在哪个段下,可以看./mach-s3c2410/devs.c|/*然后将物理地址映射到虚拟地址,这样驱动和内核就可以看到设备的I/Oregs了*/|-s3c2410_rtc_base=ioremap(res-start,res-end-res-start+1);|/*初始化设备regs*/|-s3c2410_rtc_enable(dev,1);/可以用后面这个1(这个flag在s2s65a中可以用ram0-7来保存,掉电不清的)来控制是softreset还是hardwarereset.|-s3c2410_rtc_setfreq(s3c2410_rtc_freq);/设定RTC周期频率;|/*最关键的一步,将与具体不同的底层硬件相关的设备驱动注册给arm通用操作层common/rtctime.c*/|-register_rtc(&s3c2410_rtcops);|-s3c2410_rtc_remove(structdevice*dev)|-unregister_rtc(&s3c2410_rtcops);/从上一层将s3c2410的rtc的devicedirveroperationset拔下来。|-s3c2410_rtc_setpie(0);/disable周期中断|-s3c2410_rtc_setaie(0);/disablealarminterrupt|-iounmap(s3c2410_rtc_base);|-release_resource(s3c2410_rtc_mem);|-kfree(s3c2410_rtc_mem);/MQA哪块kmalloc了呢,为什么这要free?|#ifdefCONFIG_PM/如果电源控制开关打开|-s3c2410_rtc_suspend(structdevice*dev,pm_message_tstate,u32level)|if(level=SUSPEND_POWER_DOWN)/SUSPEND_POWER_DOWN在include/linux/device.h(generic,centralizeddrivermodel)中定义,这个里面是否是对设备的一些公用的行为的操作宏的定义呢?|1.保存周期中断寄存器的值;|2.从RTC中读出时间|-s3c2410_rtc_gettime(&tm);/localvariablestructrtc_timetm;|3.将从RTC取出的时间ConvertGregoriandatetosecondssince01-01-197000:00:00.|-rtc_tm_to_time(&tm,&time.tv_sec);/arch/arm/common/rtctime.c|4.将系统时间和RTC时间的差值保存到s3c2410_rtc_delta里;|-save_time_delta(&s3c2410_rtc_delta,&time);|5.启动RTC,注意这次启动后面的falg为0了;|-s3c2410_rtc_enable(dev,0);|-s3c2410_rtc_resume(structdevice*dev,u32level)|1.启动RTC,注意这次启动后面的falg为1了;|-s3c2410_rtc_enable(dev,1);|2.从RTC中读出时间|-s3c2410_rtc_gettime(&tm);|3.转换|-rtc_tm_to_time(&tm,&time.tv_sec);|4.利用在suspend中保存的delta来恢复系统时间|-restore_time_delta(&s3c2410_rtc_delta,&time);|5.恢复周期中断寄存器的值;|LiY|suspend(暂停,挂起)和resume(恢复,再开始)有点象关机前保存现场和开机后再恢复现场一样;|#else|#defines3c2410_rtc_suspendNULL|#defines3c2410_rtc_resumeNULL|#endif|module_init(s3c2410_rtc_init)|-s3c2410_rtc_init|-driver_register(&s3c2410_rtcdrv);|purposeregisterdriverwithbus;|module_exit(s3c2410_rtc_exit)|-s3c2410_rtc_exit(void)|-driver_unregister(&s3c2410_rtcdrv)/*ExternFunctionDetails*/*drivers/base/driver.c*driver_register-registerdriverwithbus*drv:drivertoregister*Wepassoffmostoftheworktothebus_add_driver()call,*sincemostofthethingswehavetododealwiththebus*structures.*Theoneinterestingaspectisthatwesetupdrv-unloaded*asacompletionthatgetscompletewhenthedriverreference*countreaches0.*/intdriver_register(structdevice_driver*drv)klist_init(&drv-klist_devices,klist_devices_get,klist_devices_put);init_completion(&drv-unloaded);returnbus_add_driver(drv);/*drivers/base/platform.c*platform_get_irq-getanIRQforadevice*dev:platformdevice*num:IRQnumberindex*/intplatform_get_irq(structplatform_device*dev,unsignedintnum)structresource*r=platform_get_resource(dev,IORESOURCE_IRQ,num);returnr?r-start:0;/*drivers/base/platform.c*platform_get_resource-getaresourceforadevice*dev:platformdevice*type:resourcetype*num:resourceindex*/structresource*platform_get_resource(structplatform_device*dev,unsignedinttype,unsignedintnum)inti;for(i=0;inum_resources;i+)structresource*r=&dev-resourcei;if(r-flags&(IORESOURCE_IO|IORESOURCE_MEM|IORESOURCE_IRQ|IORESOURCE_DMA)=type)if(num-=0)returnr;returnNULL;/*./include/linux/ioport.h*Resourcesaretree-like,allowing*nestingetc.*/structresourceconstchar*name;unsignedlongstart,end;unsignedlongflags;structresource*parent,*sibling,*child;/*arch/arm/kernel/time.c*save_time_delta-SavetheoffsetbetweensystemtimeandRTCtime*delta:pointertotimespectostoredelta*rtc:pointertotimespecforcurrentRTCtime*ReturnadeltabetweenthesystemtimeandtheRTCtime,such*thatsystemtimecanberestoredlaterwithrestore_time

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论