10、分离分层

1、bus虚拟总线

  2440中在mach_smdk2440.c中,通过smdk2440_machine_init会把很多device都注册了,这样driver层在注册的时候就可以调用probe函数了

2、在mach_xxxxx.c这个架构相关函数中,在他的init函数中会通过platform_add_devices来注册很多的device,利用平台总线的特性,当利用platform注册同名的driver时,probe函数会被调用的特性来设置各个驱动程序的底层相关函数。

对于一个新内核,通过make s3c2410_defconfig或者make mini2440_defconfig指令来生成.config文件,在.config文件中就会备注宏=y  或者=M,表示将驱动编译进内核或者模块,当执行make s3c2410_defconfig的时候CONFIG_ARCH_SMDK2410 = y,与这个宏相对应的mach_smdk2440.c就会编译进内核,并调用该驱动的init函数

static struct platform_device *smdk2440_devices[] __initdata = {
&s3c_device_ohci,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
};

static void __init smdk2440_machine_init(void)
{
s3c24xx_fb_set_platdata(&smdk2440_fb_info);
s3c_i2c0_set_platdata(NULL);

platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
smdk_machine_init();
}

从Linux2.6内核起,引入一套新的驱动管理和注册机制:platform_device 和 platform_driver 。Linux 中大部分的设备驱动,都可以使用这套机制,设备用 platform_device 表示;驱动用 platform_driver 进行注册。

    Linux platform driver 机制和传统的device driver机制(即:通过 driver_register 函数进行注册)相比,一个十分明显的优势在于platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序中用使用这些资源时,通过platform device提供的标准接口进行申请并使用。

    platform 是一个虚拟的地址总线,相比 PCI、USB,它主要用于描述SOC上的片上资源。platform 所描述的资源有一个共同点:在CPU 的总线上直接取址。平台设备会分到一个名称(用在驱动绑定中)以及一系列诸如地址和中断请求号(IRQ)之类的资源。

    platform 总线下驱动的开发步骤是:

    1、 设备

    需要实现的结构体是:platform_device 。

    1)初始化 resource 结构变量

    2)初始化 platform_device 结构变量

    3)向系统注册设备:platform_device_register。

    以上三步,必须在设备驱动加载前完成,即执行platform_driver_register()之前,原因是驱动注册时需要匹配内核中所有已注册的设备名。platform_driver_register()中添加device到内核最终还是调用的device_add函数。Platform_device_add和device_add最主要的区别是多了一步insert_resource(p, r),即将platform资源(resource)添加进内核,由内核统一管理。

    2、驱动

    驱动注册中,需要实现的结构体是:platform_driver 。

    在驱动程序的初始化函数中,调用了platform_driver_register()注册 platform_driver 。需要注意的是:platform_driver 和 platform_device 中的 name 变量的值必须是相同的 。这样在 platform_driver_register() 注册时,会将当前注册的 platform_driver 中的 name 变量的值和已注册的所有 platform_device 中的 name 变量的值进行比较,只有找到具有相同名称的 platform_device 才能注册成功。当注册成功时,会调用 platform_driver 结构元素 probe 函数指针。

    platform_driver_register()的注册过程:

      platform_driver_register(&s3c2410fb_driver)

        driver_register(&drv->driver)

          bus_add_driver(drv)

            driver_attach(drv)

              bus_for_each_dev(drv->bus, NULL, drv, __driver_attach)

                __driver_attach(struct device * dev, void * data)

                  driver_probe_device(drv, dev)

                    really_probe(dev, drv)

    在really_probe()中:为设备指派管理该设备的驱动:dev->driver = drv, 调用probe()函数初始化设备:drv->probe(dev)

原文地址:https://www.cnblogs.com/liusiluandzhangkun/p/8570338.html