微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM-Linux驱动--DMA驱动分析(一)

ARM-Linux驱动--DMA驱动分析(一)

时间:11-20 来源:互联网 点击:
硬件平台:FL2440 (s3c2440

内核版本:2.6.35

主机平台:Ubuntu 11.04

内核版本:2.6.39

1、DMA的功能和工作原理这里就不多说了,可以查看s3c2440的手册

2、在正式分析DMA驱动之前,我们先来看一下DMA的注册和初始化过程

系统设备:(翻译自源码注释)

系统设备和系统模型有点不同,它不需要动态绑定驱动,不能被探测(probe),不归结为任何的系统总线,所以要区分对待。对待系统设备我们仍然要有设备驱动的观念,因为我们需要对设备进行基本的操作。

定义系统设备,在./arch/arm/mach-s3c2440/s3c244x.c中

  1. /*定义系统设备类*/
  2. structsysdev_classs3c2440_sysclass={
  3. .name="s3c2440-core",
  4. .suspend=s3c244x_suspend,
  5. .resume=s3c244x_resume
  6. };

注册系统设备类,在真正注册设备之前,确保已经注册了初始化了的系统设备类

  1. staticint__inits3c2440_core_init(void)
  2. {
  3. returnsysdev_class_register(&s3c2440_sysclass);
  4. }

下面就是系统设备类的注册函数,在./drivers/base/sys.c中

  1. intsysdev_class_register(structsysdev_class*cls)
  2. {
  3. intretval;
  4. pr_debug("Registeringsysdevclass%s\n",cls->name);
  5. INIT_LIST_HEAD(&cls->drivers);
  6. memset(&cls->kset.kobj,0x00,sizeof(structkobject));
  7. cls->kset.kobj.parent=&system_kset->kobj;
  8. cls->kset.kobj.ktype=&ktype_sysdev_class;
  9. cls->kset.kobj.kset=system_kset;
  10. retval=kobject_set_name(&cls->kset.kobj,"%s",cls->name);
  11. if(retval)
  12. returnretval;
  13. retval=kset_register(&cls->kset);
  14. if(!retval&&cls->attrs)
  15. retval=sysfs_create_files(&cls->kset.kobj,
  16. (conststructattribute**)cls->attrs);
  17. returnretval;
  18. }

  1. /*定义DMA系统设备驱动*/
  2. staticstructsysdev_drivers3c2440_dma_driver={
  3. .add=s3c2440_dma_add,/*添加add函数*/
  4. };

下面是add函数,就是调用三个函数

  1. staticint__inits3c2440_dma_add(structsys_device*sysdev)
  2. {
  3. s3c2410_dma_init();
  4. s3c24xx_dma_order_set(&s3c2440_dma_order);
  5. returns3c24xx_dma_init_map(&s3c2440_dma_sel);
  6. }

注册DMA驱动到系统设备

  1. staticint__inits3c2440_dma_init(void)
  2. {
  3. returnsysdev_driver_register(&s3c2440_sysclass,&s3c2440_dma_driver);
  4. }

下面就是系统设备驱动的注册函数

  1. /**
  2. *sysdev_driver_register-Registerauxillarydriver
  3. *@cls:Deviceclassdriverbelongsto.
  4. *@drv:Driver.
  5. *
  6. *@drvisinsertedinto@cls->driverstobe
  7. *calledoneachoperationondevicesofthatclass.Therefcount
  8. *of@clsisincremented.
  9. */
  10. intsysdev_driver_register(structsysdev_class*cls,structsysdev_driver*drv)
  11. {
  12. interr=0;
  13. if(!cls){
  14. WARN(1,KERN_WARNING"sysdev:invalidclasspassedto"
  15. "sysdev_driver_register!\n");
  16. return-EINVAL;
  17. }
  18. /*Checkwhetherthisdriverhasalreadybeenaddedtoaclass.*/
  19. if(drv->entry.next&&!list_empty(&drv->entry))
  20. WARN(1,KERN_WARNING"sysdev:class%s:driver(%p)hasalready"
  21. "beenregisteredtoaclass,somethingiswrong,but"
  22. "willforgeon!\n",cls->name,drv);
  23. mutex_lock(&sysdev_drivers_lock);
  24. if(cls&&kset_get(&cls->kset)){
  25. list_add_tail(&drv->entry,&cls->drivers);/*将设备驱动添加到系统设备类的链表中*/
  26. /*Ifdevicesofthisclassalreadyexist,tellthedriver*/
  27. if(drv->add){
  28. structsys_device*dev;
  29. list_for_each_entry(dev,&cls->kset.list,kobj.entry)
  30. drv->add(dev);
  31. }
  32. }else{
  33. err=-EINVAL;
  34. WARN(1,KERN_ERR"%s:invaliddeviceclass\n",__func__);
  35. }
  36. mutex_unlock(&sysdev_drivers_lock);
  37. returnerr;
  38. }

在./arch/arm/mach-s3c2440/s3c2440.c中定义s3c2440的系统设备和注册

  1. staticstructsys_devices3c2440_sysdev={
  2. .cls=&s3c2440_sysclass,/*定义系统设备的所属系统设备类,用于系统设备注册到指定设备类*/
  3. };
  4. /*S3C2440初始化*/
  5. int__inits3c2440_init(void)
  6. {
  7. printk("S3C2440:Initialisingarchitecture\n");
  8. s3c24xx_gpiocfg_default.set_pull=s3c_gpio_setpull_1up;
  9. s3c24xx_gpiocfg_default.get_pull=s3c_gpio_getpull_1up;
  10. /*changeirqforwatchdog*/
  11. s3c_device_wdt.resource[1].start=IRQ_S3C2440_WDT;
  12. s3c_device_wdt.resource[1].end=IRQ_S3C2440_WDT;
  13. /*registeroursystemdeviceforeverythingelse*/
  14. returnsysdev_register(&s3c2440_sysdev);/*注册s3c2440的系统设备*/
  15. }

接下来是系统设备的注册函数

  1. /**
  2. *sysdev_register-addasystemdevicetothetree
  3. *@sysdev:deviceinquestion
  4. *
  5. */
  6. /*系统设备的注册*/
  7. intsysdev_register(structsys_device

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

网站地图

Top