微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARMLinux驱动RTC(实时时钟)驱动分析

ARMLinux驱动RTC(实时时钟)驱动分析

时间:11-09 来源:互联网 点击:

这个参数后,就需要从中提取出需要的信息。它一般会通过调用内核提供的platform_get_resource和platform_get_irq等函数来获得相关信息。如通过platform_get_resource获得设备的起始地址后,可以对其进行request_mem_region和ioremap等操作,以便应用程序对其进行操作。通过platform_get_irq得到设备的中断号以后,就可以调用request_irq函数来向系统申请中断。这些操作在设备驱动程序中一般都要完成。

static int __devinit s3c_rtc_probe(struct platform_device *pdev){struct rtc_device *rtc;//定义rtc_device结构体,定义在/include/linux/rtc.hstruct resource *res;//定义资源结构体,定义在/include/linux/ioport.hint ret;pr_debug("%s: probe=%p\n", __func__, pdev);/* find the IRQs */s3c_rtc_tickno = platform_get_irq(pdev, 1);//在系统定义的平台设备中获取中断号if (s3c_rtc_tickno < 0) {//异常处理dev_err(&pdev->dev, "no irq for rtc tick\n");return -ENOENT;}/* get the memory region */res = platform_get_resource(pdev, IORESOURCE_MEM, 0);//获取RTC平台使用的IO资源if (res == NULL) {dev_err(&pdev->dev, "failed to get memory region resource\n");return -ENOENT;}//申请内存区域,res是struct resource类型,见本函数后面s3c_rtc_mem = request_mem_region(res->start,res->end-res->start+1,pdev->name);if (s3c_rtc_mem == NULL) {//申请内存出错dev_err(&pdev->dev, "failed to reserve memory region\n");ret = -ENOENT;goto err_nores;}//将寄存器地址映射成虚拟地址,以便访问s3c_rtc_base = ioremap(res->start, res->end - res->start + 1);if (s3c_rtc_base == NULL) {dev_err(&pdev->dev, "failed ioremap()\n");ret = -EINVAL;goto err_nomap;}/* check to see if everything is setup correctly */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);//详情见下面的函数实现/* register RTC and exit */rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops,THIS_MODULE);//注册RTC为RTC设备,其中s3c_rtcops定义见下if (IS_ERR(rtc)) {dev_err(&pdev->dev, "cannot attach rtc\n");ret = PTR_ERR(rtc);goto err_nortc;}rtc->max_user_freq = 128;//设置RTC节拍时间计数寄存器TICNT的节拍时间计数值的用户最大相对值//将RTC类的设备数据传递给系统设备,在/include/linux/platform_device.h中
//#define platform_set_drvdata(_dev,data)	dev_set_drvdata(&(_dev)->dev, (data)),该函数在/include/linux/device.h中定义,见本函数下面
platform_set_drvdata(pdev, rtc);
return 0;
//异常处理err_nortc:s3c_rtc_enable(pdev, 0);iounmap(s3c_rtc_base);err_nomap:release_resource(s3c_rtc_mem);err_nores:return ret;}
下面是/include/linux/ioport.h中struct resource结构体定义
struct resource {resource_size_t start;resource_size_t end;const char *name;unsigned long flags;struct resource *parent, *sibling, *child;};
这是dev_set_drvdata()的函数定义:
static inline void dev_set_drvdata(struct device *dev, void *data){dev->driver_data = data;}
接下来是在s3c_rtc_probe()函数用到的两个函数s3c_rtc_enable()和s3c_rtc_setfreq()
static void s3c_rtc_enable(struct platform_device *pdev, int en){
void __iomem *base = s3c_rtc_base;//__iomem的作用就是为了使编译器更好的优化编译unsigned int tmp;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-enable the device, and check it is ok *///en!=0的情况,表示系统复位,重新使能RTC驱动if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){//RTCCON第0位为0,将其设置为1,重新使能dev_info(&pdev->dev, "rtc disabled, re-enabling\n");tmp = readb(base + S3C2410_RTCCON);writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON);}if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n");tmp = readb(base + S3C2410_RTCCON);writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON);//设置RTCCON第2位为0,设置BCD计数为混合BCD计数}if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){dev_info(&pdev->dev, "removing RTCCON_CLKRST\n");tmp = readb(base + S3C2410_RTCCON);writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON);//RTC时钟计数器复位}}}
static int s3c_rtc_setfreq(struct device *dev, int freq)//设定节拍时间计数值{unsigned int tmp;spin_lock_irq(&s3c_rtc_pie_lock);//获取自旋锁,对资源互斥访问tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;//节拍时间使能有效tmp |= (128 / freq)-1;writeb(tmp, s3c_rtc_base + S3C2410_TICNT);spin_unlock_irq(&s3c_rtc_pie_lock);//解锁return 0;}
接下来是RTC设备类的操作。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top