[Linux驱动入门]Platform总线

第七章 Paltform总线

7.1 Paltform设备驱动概念

7.1.1 Platform总线

struct bus_type platform_bus_type = {

       .name = platform,               //

       .dev_attrs = platform_dev_attrs,     //属性

       .match = platform_match,          //设备和驱动的匹配函数

       .uevent = platform_uevent,         //卸载处理

       .pm = &platform_dev_pm_ops,     //电源管理

}

设备和驱动的匹配函数match.

static int platform_match(struct device * dev,struct device_driver * drv)

{

   struct platform_device * pdev = to_platform_device(dev);   //获得平台设备

   struct platform_device * pdrv = to_platform_device(drv);   //获得平台驱动

   if(pdrv->id_table)        //如果平台驱动有支持项,进入platform_match_id

           return platform_match_id(pdrv->id_table,pdev)  != NULL;

   return (strcmp(pdev->name,drv->name) == 0);     //没有支持项,则老实匹配名字

}

    通过上面的match函数可知,如果驱动中定义了驱动支持项,那么在总线执行match函数时,就会将驱动支持项中每一个名字和设备名字匹配,看看是否匹配成功。如果驱动没有设置支持项,就会把驱动的名字和设备的名字匹配,如果一样,则匹配成功。

 

7.1.2 Platform设备

Struct platform_device

{

   Const char *name;                //

   Int id;

   Struct device dev;                //内嵌设备

   U32 num_resources;             //资源个数

   Struct platform_device_id *id_entry;//资源结构体

   Struct pdev_archdata archdata;

}

Platform_device中资源结构体的定义

ruct resource

{

    Resource_size_t start;

    Resource_size_t end;

    Const char *name;

    Unsigned long flags;

    Struct resource *parent, *sibling, *child;

}

对于flags标号可以有IORESOURCE_IO、IORESOURC_MEM、IORESOURC_IRQ、IORESOURC_DMA四种选择,申请内存IORESOURC_MEM、申请中断号IORESOURC_IRQ用的比较多。

 

1platform设备的静态加载

所谓静态加载就是把platform设备编译进内核,对于platform_device的定义常常在BSP中实现。以mini2240举例,看看对应的BSP文件match-smdk2240.c

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                                   

      }

     };

这是基于MINI2440的LCD平台设备在BSP文件中的定义

Static struct platform_device *smdk2440_devices[] _initdata = {

     &s3c_device_usb,

     &s3c_device_lcd,

     &s3c_device_wdt,

     &s3c_devide_i2c0,

     &s3c_device_iis,

};

原来建立了platform_device数组,然后把LCD的platform_device添加到这个数组中

Static void_init smad2440_machine_init(void)

{

    S3c24xx_fb_set_platform(&smdk2440_fb_info);

    S3c_i2c0_set_platdata(NULL);

    Platform_add_devices(smdk2440_devices,ARRAY_SIZE(smdk2440_devices));

    Smdk_machine_init();

}

调用platform_add_devices函数把platform_device注册到内核,再继续跟踪platform_add_devices.

Int platform_add_devices(struct platform_device **devs, int num)

{

     Int i;

     Int ret = 0;

     For(i = 0; i < num; i++)

 {

        Ret = platform_device_register(devs[i]);

        If(ret)

        {

While(--i >= 0)

{

Platform_device_unregister(devs[i]);

     }

     Break;

    }

}

    Return ret;

}


除了BSP中定义的资源外,有的设备可能还会有一些配置信息,这些配置信息依赖于板子,不适合放到驱动中。为此,platform提供了平台数据platform_data的支持,在内核中添加平台数据有两种方式

 

2、platform设备的动态加载

由于静态添加platform_device,则需要最后编译内核,这个不利于修改,所以在开发阶段,我们可以采用platform设备的动态加载方法。具体方法是:先分配platform_device,然后向platform_device中添加资源结构体,最后把platform_device注册到内核。


7.1.3 Platform驱动

Struct platform_driver

{

Int (*probe)(struct platform_device *);

Int (*remove)(struct platform_device *);

Void (*shutdown)(struct platform_device *);

Int (*suspend)(struct platform_device *,pm_message_t state);

Int(*resume)(struct platform_device*);

Struct device_driver driver;

Struct platform_device_id *id_table;

};

1、platform驱动的静态加载

写一个驱动,在测试阶段我们一般采用动态加载的方式,当驱动已经成型,就会采用静态加载的方式,把驱动编译入内核。把驱动静态编译入内核的方式主要是根据MAKEFILE和KCONFIG两张地图,在MAKEFILE中添加驱动文件名,在kconfig中添加对应的驱动菜单选项。

 

2、platform驱动的动态加载

只需要在驱动模块加载函数中执行“platform_driver_register(&my_driver)”就可以把platform驱动加入内核。在进行insmod加载时就会调用这个模块加载函数,从而注册platform驱动。

 

7.2 平台设备的资源

7.2.1 平台数据和私有数据的区别

在讲平台设备的静态加载时,提到了平台数据的概念,内核驱动代码中还会出现私有数据这一名词。

那平台数据和私有数据的区别:

平台数据是由于引入平台设备而产生的,青苔数据主要保存的是一些依赖于板子的配置信息,平台数据是定义在平台设备所在的BSP中的,在平台驱动中可以进行读取到在BSP中定义的平台数据。

私有数据是作为一个驱动中保存设备信息的一个结构体,它定义在平台驱动中,而不是BSP中,我们在平台驱动中可以把一个设备结构设置为这个平台驱动的私有数据,也可以根据这个平台设备,读取这个平台设备的私有数据. 

在平台驱动中读取在BSP中定义的平台数据:

Struct s3c2410fb_match_info *pdata = pdev->dev.platform_data;

设置平台设备的私有数据

Struct buttons *key;

Platform_set_drvdata(pdev,key);

读取私有数据

Struct buttons *key = platform_get_drvdata(pdev);

补充:第一,根据经验发现平台数据是为私有数据服务,平台数据可能成为私有数据的一部分;第二,对于由设备获得平台设备的情况,可通过*pdev = to_platform_device(dev)获得。

 

7.2.2 Platform设备资源的读取

 

BSP中定义平台设备的资源,可以在probe函数中读取到。对资源中存储空间的资源读取,首先要都区资源,然后申请空间,最后完成由虚拟地址到物理地址的映射。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值