DM9000驱动详细分析(二)

虚拟总线,没有对应的硬件设备,主要用于管理系统的外设资源。内核假设所有的设备都挂载到platform总线上来进行统一的管理,提高了驱动和资源管理的独立性,并且拥有较好的可移植性和安全性。

Platform_device 和 Platform_driver分别用以表示设备和驱动,使用platform机制开发底层驱动大致流程:调用函数platform_add_devices注册platform_device; 调用函数platform_driver_register注册platform_driver。

Platform的初始化:start_kernel---> rest_init ---> kernel_thread(kernel_init,NULL, CLONE_FS | CLONE_SIGHAND) ---> do_basic_setup ---> driver_init---> platform_bus_init

int __init platform_bus_init(void)

{

         interror;

         early_platform_cleanup();

         error= device_register(&platform_bus);

         if(error)

                   returnerror;

         error=  bus_register(&platform_bus_type);

         if(error)

                   device_unregister(&platform_bus);

         returnerror;

}

 

Platform_device注册过程:

struct platform_device {

         constchar        * name;

         int              id;

         structdevice    dev;

         u32            num_resources;

         struct resource        *resource;

 

         structplatform_device_id       *id_entry;

};

成员resource存入了最为重要的设备资源信息,定义在include/linux/ioport.h

/*

 *Resources are tree-like, allowing

 *nesting etc..

 */

struct resource {

         resource_size_tstart;

         resource_size_tend;

         constchar *name;

         unsignedlong flags;

         structresource *parent, *sibling, *child;

};

下面以tq2440平台的dm9000驱动为例简单分析一下:

static struct platform_device*tq2440_devices[] __initdata = {

         &s3c_device_usb,

         &s3c_device_lcd,

         &s3c_device_wdt,

         &s3c_device_i2c0,

         &s3c_device_iis,

         &s3c_device_rtc,

#ifdef CONFIG_DM9000

         &s3c_device_dm9000,

#endif

         &s3c_device_usbgadget,

         &s3c_device_uda134x,

};

struct platform_device s3c_device_dm9000 ={

         .name                = "dm9000",

         .id                       = 0,

         .num_resources       = ARRAY_SIZE(s3c_dm9k_resource),

         .resource          =s3c_dm9k_resource,

         .dev                    = {

                   .platform_data= &s3c_dm9k_platdata,

         }

};

//DM9000网卡使用的资源列表,0x20000000,0x20000004

static struct resource s3c_dm9k_resource[]= {

         [0]= {

                   .start        =S3C2410_CS4,  // S3C2410_CS4:0x20000000(BANK4基地址)

                   .end = S3C2410_CS4 + 3,

                   .flags        = IORESOURCE_MEM,

         },

         [1]= {

                   .start        =S3C2410_CS4 + 4,

                   .end = S3C2410_CS4 + 4 + 3,

                   .flags        = IORESOURCE_MEM,

         },

         [2]= {

                   .start        =IRQ_EINT7,   //连接 EINT7引脚

                   .end = IRQ_EINT7,

                   .flags        = IORESOURCE_IRQ | IRQF_TRIGGER_RISING,

         }

};

定义好设备之后就可以调用platform_device_add添加platform_device 到设备模型中,具体过程如下:

MACHINE_START(S3C2440, "TQ2440")

         .phys_io   = S3C2410_PA_UART,

         .io_pg_offst     = (((u32)S3C24XX_VA_UART) >> 18)& 0xfffc,

         .boot_params = S3C2410_SDRAM_PA + 0x100,

 

         .init_irq    = s3c24xx_init_irq,

         .map_io             = tq2440_map_io,

         .init_machine  = tq2440_machine_init,

         .timer                = &s3c24xx_timer,

MACHINE_END

------>

platform_add_devices(tq2440_devices,ARRAY_SIZE(tq2440_devices));

添加tq2440_devices[]中定义的platform设备,按照数组的定义依次调用platform_device_register;最终调用platform_device_add把platform设备添加到设备模型。

int platform_device_add(structplatform_device *pdev)

{

         inti, ret = 0;

 

         if(!pdev)

                   return-EINVAL;

         if(!pdev->dev.parent)

                   pdev->dev.parent= &platform_bus;

         pdev->dev.bus= &platform_bus_type;

         if(pdev->id != -1)

                   dev_set_name(&pdev->dev,"%s.%d", pdev->name, pdev->id); // 有多个同类设备,用pdev->name,  pdev->id标识该设备。

         else

                   dev_set_name(&pdev->dev,pdev->name); //只用pdev->name标识该设备

         for(i = 0; i < pdev->num_resources; i++) {

                   structresource *p, *r = &pdev->resource[i];

                   if(r->name == NULL)

                            r->name= dev_name(&pdev->dev);

                   p= r->parent;

                   if(!p) {

                            if(resource_type(r) == IORESOURCE_MEM)

                                     p= &iomem_resource; //作为IOMEM资源分配

                            elseif (resource_type(r) == IORESOURCE_IO)

                                     p= &ioport_resource; //作为IOPORT资源分配

                   }

                   if(p && insert_resource(p, r)) {

                            printk(KERN_ERR

                                   "%s: failed to claim resource%d\n",

                                   dev_name(&pdev->dev), i);

                            ret= -EBUSY;

                            gotofailed;

                   }

         }

         pr_debug("Registeringplatform device '%s'. Parent at %s\n",

                    dev_name(&pdev->dev),dev_name(pdev->dev.parent));

         ret= device_add(&pdev->dev); //添加设备到设备树

         if(ret == 0)

                   returnret;

 failed:

         while(--i >= 0) {

                   structresource *r = &pdev->resource[i];

                   unsignedlong type = resource_type(r);

                   if(type == IORESOURCE_MEM || type == IORESOURCE_IO)

                            release_resource(r);

         }

         returnret;

}

你可能感兴趣的:(linux,kernel)