Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2100896
  • 博文数量: 361
  • 博客积分: 10828
  • 博客等级: 上将
  • 技术积分: 4161
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-20 14:34
文章分类

全部博文(361)

文章存档

2011年(132)

2010年(229)

分类: LINUX

2011-04-07 11:08:36

  • platform bus
我们先来看看platform_bus的定义:

struct device platform_bus = {
.bus_id = "platform",
};

struct bus_type platform_bus_type = {
.name = "platform",
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
.suspend = platform_suspend,
.suspend_late = platform_suspend_late,
.resume_early = platform_resume_early,
.resume = platform_resume,
};

int __init platform_bus_init(void)
{
int error;

error = device_register(&platform_bus);
if (error)
return error;
error = bus_register(&platform_bus_type);
if (error)
device_unregister(&platform_bus);
return error;
}


platform_bus数据结构描述了platform bus设备,platform_bus_type描述了platform bus总线,它提供了platform总线设备和驱动的匹配函数。platform总线是由函数platform_bus_init(void)初始化的。
对于Linux我们一般的设备驱动程序来说,就像前面Bus一段提到的那样,我们不需要关心platform总线本身,我们只要调用我们的设备和驱动接口就可以了。
  • Platform Device
如果你想让platform总线来管理设备,那么,你需要先向platform系统注册设备,这个过程是通过下面的函数接口来实现的:

int platform_device_add(struct platform_device *pdev);
int platform_device_register(struct platform_device *pdev);


我们一般需要调用platform_device_register函数来向系统添加platform设备。这两个函数唯一的差别就是platform_device_register在添加设备前会初始化platform_device的dev数据成员,它是一个struct device类型数据。当一个platform_device添加到platform总线中后,platform总线就会为它找到匹配的设备驱动程序,很显然,在这之前,你需要向系统注册platform_driver。
  • Platform Driver
我们先来看看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 (*suspend_late)(struct platform_device *, pm_message_t state);
int (*resume_early)(struct platform_device *);
int (*resume)(struct platform_device *);
struct device_driver driver;
};

extern int platform_driver_register(struct platform_driver *);


很显然,它“继承”自struct device_driver,同样类似于struct device_driver,一般我们需要实现probe函数,及指定platform_driver能驱动的设备的名字。
  • 使用Platform总线
下面这个例子告诉你如何使用platoform总线,这是一个Android Goldfish GPIO驱动程序。它本身就是一个platform设备驱动(goldfish-gpio),同时,它又会向系统注新的设备(android-timed-gpio),这个新设备又被timed_output.c驱动程序驱动。

......
#include

struct platform_device timed_gpio_device = {
.name = "android-timed-gpio",
.id = -1,
.dev.platform_data = &timed_gpio_platform_data,
};

static int goldfish_gpio_probe(struct platform_device *pdev)
{
struct goldfish_gpio_data *gpio_data;
......
error = platform_device_register(&timed_gpio_device);
......
return 0;
}

static int goldfish_gpio_remove(struct platform_device *pdev)
{
int i;
struct goldfish_gpio_data *gpio_data;
......
platform_device_unregister(&timed_gpio_device);
......
return 0;
}

static struct platform_driver goldfish_gpio_driver = {
.probe = goldfish_gpio_probe,
.remove = goldfish_gpio_remove,
.driver = {
.name = "goldfish-gpio"
}
};

static int __init goldfish_gpio_init(void)
{
return platform_driver_register(&goldfish_gpio_driver);
}

static void __exit goldfish_gpio_exit(void)
{
platform_driver_unregister(&goldfish_gpio_driver);
}


这个新注册的设备(timed_gpio_device)由timed_output驱动管理,通过浏览这段代码,你应该对如何使用platform总线有个全面的了解。(本想把全部code放在这里,但超过最大字数限制!)

static struct class *timed_gpio_class;
struct timed_gpio_data {
struct device *dev;
struct hrtimer timer;
spinlock_t lock;
unsigned gpio;
int max_timeout;
u8 active_low;
};
......

static int android_timed_gpio_probe(struct platform_device *pdev)
{
struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
struct timed_gpio *cur_gpio;
struct timed_gpio_data *gpio_data, *gpio_dat;
int i, ret = 0;
......
}

static int android_timed_gpio_remove(struct platform_device *pdev)
{
}

static struct platform_driver android_timed_gpio_driver = {
.probe = android_timed_gpio_probe,
.remove = android_timed_gpio_remove,
.driver = {
.name = "android-timed-gpio",
.owner = THIS_MODULE,
},
};

static int __init android_timed_gpio_init(void)
{
timed_gpio_class = class_create(THIS_MODULE, "timed_output");
if (IS_ERR(timed_gpio_class))
return PTR_ERR(timed_gpio_class);
return platform_driver_register(&android_timed_gpio_driver);
}

static void __exit android_timed_gpio_exit(void)
{
class_destroy(timed_gpio_class);
platform_driver_unregister(&android_timed_gpio_driver);
}


Kobject和kset
提到Linux的设备模型,就不得不提kobject和kset这两个内核对象,他们才是Linux内核设备模型的最基础的结构,但讲解他们却是一个枯燥过程,限于篇幅,这个就不作介绍了,请参考Linux文档

后记
在这里,我们简单的介绍了Linux的设备模型,包括基本总线、设备、驱动的关系,同时也简单的介绍了Linux2.6内核的platform总线。这些内容应该足够让你了解如何使用Linux设备模型来管理设备了。
阅读(1354) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~