驱动架构 & platform平台总线驱动模型

1、驱动架构

1.1 bus 总线

struct bus_type platform_bus_type = {
	.name		= "platform",
	.dev_groups	= platform_dev_groups,
	.match		= platform_match,
	...
};

int __init platform_bus_init(void)
{
	...
	//注册platform_bus,其类型我bus_type
	error =  bus_register(&platform_bus_type);
	...
}

1.2 device 设备

struct device {
	struct kobject kobj;
	struct device		*parent;

	struct device_private	*p;

	const char		*init_name; /* initial name of the device */
	const struct device_type *type;

	struct bus_type	*bus;		/* type of bus device is on */
	struct device_driver *driver;	/* which driver has allocated this
					   device */
	void		*platform_data;	/* Platform specific data, device
					   core doesn't touch it */
	void		*driver_data;	/* Driver data, set and get with
					   dev_set_drvdata/dev_get_drvdata */
}

int of_device_add(struct platform_device *ofdev)
{
	//注册platform_device 其实就是将platform_device 的device 注册
	return device_add(&ofdev->dev);
}

static struct platform_device *of_platform_device_create_pdata(
					struct device_node *np,
					const char *bus_id,
					void *platform_data,
					struct device *parent)
{
	struct platform_device *dev;

	//定义platform_device 的总线类型,表示其挂在platform_bus下面
	dev->dev.bus = &platform_bus_type;

	//注册platform_device
	if (of_device_add(dev) != 0) {
		platform_device_put(dev);
		goto err_clear_flag;
	}
	...
}

1.3 driver 驱动

static struct platform_driver onboard_hub_driver = {
	.probe = onboard_hub_probe,
	.remove = onboard_hub_remove,

	.driver = {
		.name = "onboard-usb-hub",
		.of_match_table = onboard_hub_match,
		.pm = pm_ptr(&onboard_hub_pm_ops),
		.dev_groups = onboard_hub_groups,
	},
};

int __platform_driver_register(struct platform_driver *drv,
				struct module *owner)
{
	drv->driver.owner = owner;
	//定义platform_driver的总线类型,表示其挂在platform_bus下面
	drv->driver.bus = &platform_bus_type;
	drv->driver.probe = platform_drv_probe;
	drv->driver.remove = platform_drv_remove;
	drv->driver.shutdown = platform_drv_shutdown;

	//注册 platform_driver 其实就是注册 platform_driver的 device_driver
	return driver_register(&drv->driver);
}

static int __init onboard_hub_init(void)
{
	...
	//注册platform_driver
	ret = platform_driver_register(&onboard_hub_driver);
	...
}

2、platform驱动模型

      platform总线是kernel 2.6中引入的一种虚拟总线,主要用来管理CPU的片上资源,具有良好的移植性。相对于USB、PCI、I2C等物理总线来说,平台总线是Linux设备驱动模型为了保持设备驱动的统一性而虚拟出来的总线。
      usb、i2c、pci等设备都是直接挂在相应的总线下与cpu进行数据交互的,但在嵌入式系统中,并非所有的设备都能够归属于这些常见的总线类型。如SoC系统中集成的独立的外设控制器、挂接在SoC内存空间的外设等,都不依附于此类总线。
      通常情况下只要和内核本身运行依赖性不大的外围设备,相对独立的,拥有各自独立的资源(地址总线和IRQs),都可以用platform driver来管理,而timer,irq等小系统之内的设备则最好不用platfrom driver机制。

2.1 platform_device

struct platform_device {
          const char      	*name; 	//定义平台设备的名称,和相应驱动命名一致
          struct device   	dev;
          struct resource 	*resource;  //定义平台设备的资源
 	};

      在这个结构里封装了struct device及struct resource。可知:platform_device由device派生而来,是一种特殊的device。
       注册设备:

int platform_device_register(struct platform_device *pdev)

2.2 platform_driver

struct platform_driver {
          int (*probe)(struct platform_device *);
		  const char *name;
		  const struct platform_device_id *id_table;
          int (*remove)(struct platform_device *);
          int (*suspend)(struct platform_device *, pm_message_t state);
          int (*resume)(struct platform_device *);
          struct device_driver driver;
};

      可见,platform_driver包含了设备操作的几个功能函数,同时包含了一个device_driver结构,说明device_driver是platform_driver的基类。 注册驱动:

 int platform_driver_register(struct platform_driver *drv)

2.3 platform_bus

struct bus_type platform_bus_type = {
	.name		= "platform",
	.dev_groups	= platform_dev_groups,
	.match		= platform_match,
	.uevent		= platform_uevent,
	.dma_configure	= platform_dma_configure,
	.pm		= &platform_dev_pm_ops,
};

Platform driver通过platform bus获取platform_device。

2.4 匹配方法

(1) 优先匹配driver中的id_table,里面包含了支持不同平台的名字;
(2) 直接匹配driver中的名字和device中的名字。

2.5 platform_driver成员函数

      platform_driver与platform_device匹配后进入driver的probe函数,当进入probe函数后,需要实现一系列函数接口,包括:
(1)注册驱动:

int platform_driver_register(struct platform_driver *drv)

将驱动添加到platform总线链表(即注册),等待设备的出现,并由总线来完成设备与驱动之间的匹配关联过程。
(2)获取设备的资源信息:

platform_get_resource(struct platform_device * dev, unsigned int type, unsigned int num)

(3)获取资源中的中断号:

struct int platform_get_irq(struct platform_device *dev, unsigned int num); 

(4)driver通过file_operations成员函数实现与用户空间的交流。

static const struct file_operations i2cdev_fops = {
         .owner          = THIS_MODULE,
         .llseek         = no_llseek,
         .read           = i2cdev_read,
         .write          = i2cdev_write,
         .ioctl          = i2cdev_ioctl,
         .open           = i2cdev_open,
         .release        = i2cdev_release,
 };
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值