• 驱动开发学习笔记. 0.04 linux 2.6 platform device register 平台设备注册 1/2 共2篇


                    驱动开发读书笔记. 0.04  linux 2.6 platform device register 平台设备注册  1/2 共2篇
    下面这段摘自 linux源码里面的文档 :
    Documentation/driver-model/platform.txt
    Device Enumeration
      82 ~~~~~~~~~~~~~~~~~~
      83 As a rule, platform specific (and often board-specific) setup code will
      84 register platform devices:
      85
      86        int platform_device_register(struct platform_device *pdev);
      87
      88        int platform_add_devices(struct platform_device **pdevs, int ndev);
      89
      90 The general rule is to register only those devices that actually exist,
      91 but in some cases extra devices might be registered.  For example, a kernel
      92 might be configured to work with an external network adapter that might not
      93 be populated on all boards, or likewise to work with an integrated controller
      94 that some boards might not hook up to any peripherals.
      95
      96 In some cases, boot firmware will export tables describing the devices
      97 that are populated on a given board.   Without such tables, often the
      98 only way for system setup code to set up the correct devices is to build
      99 a kernel for a specific target board.  Such board-specific kernels are
     100 common with embedded and custom systems development.
     101
     102 In many cases, the memory and IRQ resources associated with the platform
     103 device are not enough to let the device's driver work.  Board setup code
     104 will often provide additional information using the device's platform_data
     105 field to hold additional information.
     106
     107 Embedded systems frequently need one or more clocks for platform devices,
     108 which are normally kept off until they're actively needed (to save power).
     109 System setup also associates those clocks with the device, so that that
     110 calls to clk_get(&pdev->dev, clock_name) return them as needed.
     111
     112
     113 Legacy Drivers:  Device Probing
     114 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     115 Some drivers are not fully converted to the driver model, because they take
     116 on a non-driver role:  the driver registers its platform device, rather than
     117 leaving that for system infrastructure.  Such drivers can't be hotplugged
     118 or coldplugged, since those mechanisms require device creation to be in a
     119 different system component than the driver.
     120
     121 The only "good" reason for this is to handle older system designs which, like
     122 original IBM PCs, rely on error-prone "probe-the-hardware" models for hardware
     123 configuration.  Newer systems have largely abandoned that model, in favor of
     124 bus-level support for dynamic configuration (PCI, USB), or device tables
     125 provided by the boot firmware (e.g. PNPACPI on x86).  There are too many
     126 conflicting options about what might be where, and even educated guesses by
     127 an operating system will be wrong often enough to make trouble.
     128
     129 This style of driver is discouraged.  If you're updating such a driver,
     130 please try to move the device enumeration to a more appropriate location,
     131 outside the driver.  This will usually be cleanup, since such drivers
     132 tend to already have "normal" modes, such as ones using device nodes that
     133 were created by PNP or by platform device setup.
     134
     135 None the less, there are some APIs to support such legacy drivers.  Avoid
     136 using these calls except with such hotplug-deficient drivers.
     137
     138        struct platform_device *platform_device_alloc(
     139                        const char *name, int id);
     140
     141 You can use platform_device_alloc() to dynamically allocate a device, which
     142 you will then initialize with resources and platform_device_register().
     143 A better solution is usually:
     144
     145        struct platform_device *platform_device_register_simple(
     146                        const char *name, int id,
     147                        struct resource *res, unsigned int nres);
     148
     149 You can use platform_device_register_simple() as a one-step call to allocate
     150 and register a device.

    上文讲了两种platform设备注册方式,一种是

    platform specific (and often board-specific) setup code

    平台特定的,在/arch/arm/plat-s3c24xx/devs.c中找到相关数据结构和代码

    第一步:定义资源结构体
    static struct resource s3c_lcd_resource[] = {
            [0] = {
                    .start = S3C24XX_PA_LCD,
                    .end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
                    .flags = IORESOURCE_MEM,
            },
            [1] = {
                    .start = IRQ_LCD,
                    .end   = IRQ_LCD,
                    .flags = IORESOURCE_IRQ,
            }
    
    };


    第二步:定义platform_device (主要的有 设备名称 设备id(区分相同设备名) 资源个数 资源定义 内嵌设备)
    struct platform_device s3c_device_lcd = {
           .name             = "s3c2410-lcd",
           .id               = -1,
           .num_resources    = ARRAY_SIZE(s3c_lcd_resource),
           .resource         = s3c_lcd_resource,
           .dev              = {
                    .dma_mask               = &s3c_device_lcd_dmamask,
                    .coherent_dma_mask      = 0xffffffffUL
            }
    };
      第三步:添加到platform_device指针数组 smdk2440_devices (arch/arm/mach-s3c2440/mach-smdk2440.c)
    static struct platform_device *smdk2440_devices[] __initdata = {
            &s3c_device_usb,
            &s3c_device_lcd,
            &s3c_device_wdt,
            &s3c_device_i2c,
            &s3c_device_iis,
    };
    第四步:添加到platform_device指针数组 (arch/arm/mach-s3c2440/mach-smdk2440.c)
    static void __init smdk2440_machine_init(void)
    {
            s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
    
            platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
            smdk_machine_init();
    }
    platform_add_devices会将platform_device 注册到内核
    第五步:有没有发现上面有个 s3c24xx_fb_set_platdata  函数?他是干什么的呢?
    platform.txt 写道:
    In many cases, the memory and IRQ resources associated with the platform
    device are not enough to let the device's driver work. Board setup code will often provide additional information using the device's platform_data field to hold additional information.

    因为 resource 结构是定义好的,所以不方便添加更多的信息 platform提供了平台数据platform_data的支持.

    下面为函数原型:(感觉就是个不美观的补丁。。。)
    void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
    {
            struct s3c2410fb_mach_info *npd;
    
            npd = kmalloc(sizeof(*npd), GFP_KERNEL);
            if (npd) {
                    memcpy(npd, pd, sizeof(*npd));
                    s3c_device_lcd.dev.platform_data = npd;
            } else {
                    printk(KERN_ERR "no memory for LCD platform data
    ");
            }
    }
    第六步:第四步的代码还有个smdk_machine_init();
    是进行gpio的设置,还有注册led设备

    小结:第一种方法 定义资源 定义平台data 设置platdata(与platform_device 关联) 然后使用 platform_add_devices函数进行注册
    注意 platform_add_devices 和platform_device_add区别很大,platform_add_devices(struct platform_device ** devs,int num) 里面根据传入的指针,
    计算出需要注册的platform_device的数量(注意,这个number不是platform_device.id)然后使用迭代来调用platform_device_register(struct platform_device *)
    进行注册.
      所以核心的函数调用就是 platform_device_register这个函数,多个设备时调用platform_add_devices

    有兴趣的朋友可以看一下platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));里面ARRAY_SIZE 计算数组元素个数 的实现方法
    这个宏在<linux/kernel.h>里面

    注意的是:上面代码都是编译进内核,而不是内核模块


    小小的感想:
      写了字符设备驱动之后,学习这个platform 设备驱动,十分好奇说是设备驱动,但是没有提供应用接口 open write的方法,百思不得其解;后来来回翻了几本书籍,发现platform似乎
    就没有也不是为了提供这些接口而设计的,你可以在driver初始化或者proe探测函数里面 注册字符/混合/类设备 ,达到为应用提供write open的目的,而字符设备与platform 设备驱动的
    联系似乎只是 提供注册和销毁的关系,设备驱动真是复杂,希望早日攻克。


                                            下次介绍 第二种注册方式

    参考资料:
         linux源码 2.6.22
        《linux驱动入门》----主编 魏清 副主编 梁庚 徐志国 

    23:56:02
    2016-10-05
     
  • 相关阅读:
    如何培养编程所需要的逻辑思维?
    CSS教程
    Android中Service(服务)详解
    Tomcat热部署的实现原理
    Java多线程和线程池(转)
    导出Excel表格
    各种时间格式化的转化
    上传多媒体文件到微信公众平台
    发起https请求并获取结果
    Java 将字节转换为十六进制字符串
  • 原文地址:https://www.cnblogs.com/simonlin/p/5933010.html
Copyright © 2020-2023  润新知