免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1074 | 回复: 0
打印 上一主题 下一主题

第三讲:2410下rtc驱动分析 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-27 10:22 |只看该作者 |倒序浏览

首先RTC设备是一种片上设备, 用platform_device来表示 该设备(即platform_device的RTC对象)在设备的初始化过程中就已经注册进了系统(可以参考2410下soc上的设备的驱动流程(RTC, watchdog等)), 因此我们在RTC驱动的初始化里把RTC驱动注册到系统后,系统会probe到这个RTC设备,最后调用我们RTC驱动的probe函数.
下面就重点分析2410的RTC驱动.
首先是初始化函数和退出函数:
static void __init s3c2410_rtc_init(void)
{
    printk(banner);

     /*
* 这就把这个RTC驱动注册进了系统,同时系统会查找匹配的RTC设备,并调用
* s3c2410_rtcdrv的probe函数.
*/
    return platform_driver_register(&s3c2410_rtcdrv);
}
Static void __exit s3c2410_rtc_exit(void)
{
    /*卸载这个RTC驱动, 之后RTC设备就无法使用了*/
    platform_driver_unregister(&s3c2410_rtcdrv);  
}
static struct platform_driver s3c2410_rtcdrv = {
      .probe    = s3c2410_rtc_probe,
      .remove   = s3c2410_rtc_remove,
      .suspend  = s3c2410_rtc_suspend,
      .resume   = s3c2410_rtc_resume,
      .driver    = {
           .name = “s3c2410-rtc”,  //这个字符串必须和RTC设备的定义一样,系统才会匹配正确.
           .owner = THIS_MODULE,
       },
};
当系统把RTC设备注册到系统后,它就开始查找相应总线上的所有设备, 并与这个驱动比较, 如果系统找到匹配的RTC设备就会调用RTC驱动的s3c2410_rtc_probe函数, 注意RTC设备实在系统初始化时就注册进了系统.
static int s3c2410_rtc_probe(struct platform_device *pdev /*rtc设备*/)
{
    struct resource *res;
       int ret;

       pr_debug("%s: probe=%p\n", __FUNCTION__, pdev);

       /*
* 获取设备的tick中断资源, 通过查看platform_get_irq可知,实际上通过查找pdev的资源获得的, * 而pdev的资源是在构建platform_device对象的时候就指定好的, 可到Devs.c中查看
*/
       s3c2410_rtc_tickno = platform_get_irq(pdev, 1);
       if (s3c2410_rtc_tickno
              dev_err(&pdev->dev, "no irq for rtc tick\n");
              return -ENOENT;
       }

       /*
* 获取设备的rtc中断资源, 通过查看platform_get_irq可知,实际上通过查找pdev的资源获得的, * 而pdev的资源是在构建platform_device对象的时候就指定好的, 可到Devs.c中查看
*/
       s3c2410_rtc_alarmno = platform_get_irq(pdev, 0);
       if (s3c2410_rtc_alarmno
              dev_err(&pdev->dev, "no irq for alarm\n");
              return -ENOENT;
       }

       pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n",
               s3c2410_rtc_tickno, s3c2410_rtc_alarmno);

       /*
* 获取设备的memory资源, 通过查看platform_get_irq可知,实际上通过查找pdev的资源获得的, * 而pdev的资源是在构建platform_device对象的时候就指定好的, 可到Devs.c中查看
*/
       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
       if (res == NULL) {
              dev_err(&pdev->dev, "failed to get memory region resource\n");
              return -ENOENT;
       }
   
    /*
     * 查看指定的memory是否可以使用.
     */
       s3c2410_rtc_mem = request_mem_region(res->start, res->end-res->start+1,
                                 pdev->name);

       if (s3c2410_rtc_mem == NULL) {
              dev_err(&pdev->dev, "failed to reserve memory region\n");
              ret = -ENOENT;
              goto exit_err;
       }
   
    /*
* 重映射指定的内存区域,即把原来的物理地址映射到相应的虚拟地址, 这样以后就可以用这个* 虚拟地址直接访问原来的物理地址了, 这里是映射RTC的寄存器地址区间.
*/
       s3c2410_rtc_base = ioremap(res->start, res->end - res->start + 1);
       if (s3c2410_rtc_base == NULL) {
              dev_err(&pdev->dev, "failed ioremap()\n");
              ret = -EINVAL;
              goto exit_err;
       }

       s3c2410_rtc_mem = res;
       pr_debug("s3c2410_rtc_base=%p\n", s3c2410_rtc_base);

      pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON));

       /*正确初始化RTC设备 */
       s3c2410_rtc_enable(pdev, 1);

      pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON));
   
    /*设置好设备的频率*/
       s3c2410_rtc_setfreq(s3c2410_rtc_freq);

       /* 注册RTC设备的操作函数, 以后对该设备的访问将调用这些操作函数*/
       register_rtc(&s3c2410_rtcops);
       return 0;

exit_err:
       dev_err(&pdev->dev, "error %d during initialisation\n", ret);

       return ret;
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/110728/showart_2161837.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP