Linux驱动之Platform Driver

来源:互联网 发布:软件展览会 编辑:程序博客网 时间:2024/06/18 05:08
# Platform Driver 平台驱动

    Linux中的所有设备驱动都需要注册到系统平台下,这此操作由platform_device.h中定义的一组函数完成.我们先来看看struct platform_driver这个结构体:
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; 
       const struct platform_device_id *id_table;
};
    该结构中包含了一组操作函数和一个struct device_driver的对像. 在我们自己的驱动中首先要做的就是定义platform_driver中的函数,并创建这个结构的一个对象实例, 然后在init()函数中调用platform_driver_register()向系统注册我们的驱动.
    如kernel-3.0的leds-s3c24xx.c 中的platform_driver的定义为:

static struct platform_driver s3c24xx_led_driver = {
    .probe        = s3c24xx_led_probe,
    .remove        = s3c24xx_led_remove,
    .driver        = {
        .name        = "s3c24xx_led",
        .owner        = THIS_MODULE,
    },
};

    其它中指定了.driver的名字和所有者. 在调用platform_driver_register()注册驱动时,platform首先指定该设备是在系统中platform_bus主总线下,这只是一个虚拟总线驱动.然后platform驱动在调用driver_register(), driver_register在调用bus_add_driver()向系统总线管理器中注册驱动.如果成功会进行设备扫描,在dd.c中的driver_attach()中进行.实际会调用__driver_attach(),该函数又调用driver_probe_device(), driver_probe_device()分别会调用驱动注册时指定的总线probe和驱动自己的probe函数, 即我们上面注册的s3c24xx_led_probe()函数, 总线probe函数由platform_driver_register()中设置, 还设置了默认的Driver的操作函数.

platform_driver_register(&s3c24xx_led_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)


    在我们的probe函数中主要是进行设备的探测和初始化,这里2410的led是连接到gpio上的,所以总是存在,但是如果是一些像usb那样的外设,我们就需要先探测对外的外设是否存在.在sc324xx_led_probe中主要做了以下3件事.
    1.创建一个私有数据对象, 并调用platform_set_drvdata()来附着到设备对象上.传给probe函数的参数是一个struct platform_device的平台设备对像(在那创建的呢?),
       struct platform_device在定义如下:

struct platform_device {
 const char * name;
 int  id;
 struct device dev;
 u32  num_resources;
 struct resource * resource;

 const struct platform_device_id *id_entry;

 /* MFD cell pointer */
 struct mfd_cell *mfd_cell;

 /* arch specific additions */
 struct pdev_archdata archdata;
};

   
     其中有一个struct device对象,这个对象保存了系统中一个具体的设备的相关信息. 其中driver_data一般用于保存和设备具体相关的私有信息,如这里用于保存struct s3c24xx_gpio_led实例,但是我们不要直接操作它,而应该使用platform_set_drvdata()函数.
    2. 初始化具体的gpio
    3. 调用led_classdev_register向内核注册一个led类驱动
  小节: 这这个过程我们可以看到,在一个驱动程序中需要做那些事情,及基本的流程.
       1.需要定义一个platform_driver的对象来描述驱动相关信息.
       2.实现platform_driver中定义的必要的函数
       3.向平台驱动管理器注册驱动.
       4.驱动管理器会调用.probe函数来探测设备,需要在这里做设备初始化.
       5.内核根据操作请求调用驱动的相应函数,如open, close等.
      
# Platform Device 平台设备
    在platform driver中内核回调用我们注册的.probe函数,参数为一个platform_device的对象指针,但是这个从那来的呢, 以s3c2410 smdk板为例,对应的mach为mach-s3c2410,具体用的那个要看我们在配置内核的时候选择的什么平台和mach了,具体怎么配置或增加mach,不在本文的范围. 现在打开arch/arm/mach-s3c2410/mach-smdk2410.c 在文件的最后有个MACHINE_START的结构体:
  
MACHINE_START(SMDK2410, "SMDK2410")
    .phys_io    = S3C2410_PA_UART,
    .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
    .boot_params    = S3C2410_SDRAM_PA + 0x100,
    .map_io        = smdk2410_map_io,
    .init_irq    = s3c24xx_init_irq,
    .init_machine    = smdk_machine_init,
    .timer        = &s3c24xx_timer,
MACHINE_END

   该结构体描述了该mach相关的系统资源,内核在初始化时,根据该结构体的内容,进行初始化操作.找到其中指定的smdk_machine_init函数, 该函数的内容不多,现在我们只关心:
   platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
这个调用, 进入platform_add_devices可以看到在该函数中有一个for循环来遍历devs参数中的platform_device,然后调用platform_device_register注册设备.从而生成前面我们的s3c24xx_led_probe收到的platform_device.
   那主个devs又是那来的呢,回到上一层,可以看到传入的是一个静态定义的platform_device的数组,这里面就是根据我们的mach定义那的一些设置的配置信息,有点好pc的bios.所以要修改硬件配置就需要从这里开始.

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 红米4a进水后开机就黑屏了怎么办 红米1s进水后开机了黑屏了怎么办 魅族手机已锁定魅族账号忘了怎么办 魅族5糸统升级后开不了机了怎么办 如果别人用电脑登了你的微信怎么办 消逝的光芒买错了买的普通版怎么办 在人人车卖了个车买家不过户怎么办 应用锁密码和密保问题都忘了怎么办 不小心在微信公众号发了消息怎么办 微信漂流瓶不能用了被投诉了怎么办 货物少了拉货的不承认少了怎么办 寄的快递号码留错了已经寄走怎么办 网购快递放在单位门卫室丢了怎么办 顺丰生鲜速配时效内食物坏了怎么办 竟尤理财跑路怎么办钱追的回来吗 博贝游戏用支付宝提不了现该怎么办 陌陌钱包没绑支付宝就体现了怎么办 鞋子让太阳晒的一只大一只小怎么办 美团不让上饿了么平台们商家怎么办 在汇通信诚租贷款买车被骗后怎么办 我的网银账户里的钱被盗了怎么办 老赖跑到国外去了还换了国籍怎么办 内裤把屁股两边磨得又肿又疼怎么办 京东在面临供货商不供货时怎么办的 打错的消息想撤回但按了删除怎么办 顺丰快递寄的黄皮和荔枝坏了怎么办 我发快递写错地址备签收不还怎么办 新买的床上四件套用着全身痒怎么办 华为畅玩6x锁屏密码忘了怎么办 我在淘宝上买了货不发货咋怎么办 在快递公司寄的东西丢了我该怎么办 不小心给了快递员子一个差评怎么办 不小心用发霉了的杯子喝了水怎么办 唐三复活了小舞失去的魂环怎么办了 我该怎么办?身陷动漫城输了很多钱 庄家开2球大小球踢成2球怎么办 去哪儿网订机票时邮箱写错了怎么办 在南航航班上把手机丢飞机上怎么办 买了品牌鞋穿了一周就破了怎么办 狗让狠狠的打了一顿不理人了怎么办 调好米粉宝宝吃的时候就凉了怎么办