platform总线

platform总线是linux2.6内核加入的一种虚拟总线。platform机制的本身使用并不复杂,由两部分组成:platform_device和platform_driver。

platform驱动与传统的设备驱动模型相比,优势在于platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序使用这些资源时使用统一的接口,这样提高了程序的可移植性。

通过platform机制开发底层设备驱动的流程:

定义platform_device ---> 注册platform_device ---> 定义platform_driver ---> 注册platform_driver


1. 平台设备

struct platform_device {
    const char *name;         // 设备名
    int id;                                // 设备编号,配合设备名使用
    struct device dev;
    u32 num_resources;
    struct resource *resource;     // 设备资源
};


struct resource {
    resource_size_t start;      // 资源的起始物理地址
    resource_size_t end;       // 资源的结束物理地址
    const char *name;         // 资源的名称
    unsigned long flags;       // 资源的类型,如MEM,IO,IRQ类型
    struct resource *parent, *sibling, *child;            // 资源链表指针
};


/**
 *	platform_device_alloc
 *	@name:	base name of the device we're adding
 *	@id:    instance id
 *
 *	Create a platform device object which can have other objects attached
 *	to it, and which will have attached objects freed when it is released.
 */
struct platform_device *platform_device_alloc(const char *name, int id)                 // name:设备名;id:设备id,一般为-1
{
	struct platform_object *pa;

	pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);
	if (pa) {
		strcpy(pa->name, name);
		pa->pdev.name = pa->name;
		pa->pdev.id = id;
		device_initialize(&pa->pdev.dev);
		pa->pdev.dev.release = platform_device_release;
	}

	return pa ? &pa->pdev : NULL;
}

/**
 *	platform_device_add - add a platform device to device hierarchy
 *	@pdev:	platform device we're adding
 *
 *	This is part 2 of platform_device_register(), though may be called
 *	separately _iff_ pdev was allocated by platform_device_alloc().
 */
int platform_device_add(struct platform_device *pdev)
{
	int i, ret = 0;

	if (!pdev)
		return -EINVAL;

	if (!pdev->dev.parent)
		pdev->dev.parent = &platform_bus;

	pdev->dev.bus = &platform_bus_type;

	if (pdev->id != -1)
		snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name,
			 pdev->id);
	else
		strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);

	for (i = 0; i < pdev->num_resources; i++) {
		struct resource *p, *r = &pdev->resource[i];

		if (r->name == NULL)
			r->name = pdev->dev.bus_id;

		p = r->parent;
		if (!p) {
			if (r->flags & IORESOURCE_MEM)
				p = &iomem_resource;
			else if (r->flags & IORESOURCE_IO)
				p = &ioport_resource;
		}

		if (p && insert_resource(p, r)) {
			printk(KERN_ERR
			       "%s: failed to claim resource %d\n",
			       pdev->dev.bus_id, i);
			ret = -EBUSY;
			goto failed;
		}
	}

	pr_debug("Registering platform device '%s'. Parent at %s\n",
		 pdev->dev.bus_id, pdev->dev.parent->bus_id);

	ret = device_add(&pdev->dev);
	if (ret == 0)
		return ret;

 failed:
	while (--i >= 0)
		if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO))
			release_resource(&pdev->resource[i]);
	return ret;
}

static struct resource s3c_wdt_resource1 = {
	.start = 0x44100000,
	.end = 0x44200000,
	.flags = IORESOURCE_MEM,
};
static resource s3c_wdt_resource2 = {
	.start = 20,
	.end = 20,
	.flags = IORESOURCE_IRQ,
};

/**
 *	platform_get_resource - get a resource for a device
 *	@dev: platform device
 *	@type: resource type
 *	@num: resource index
 */
struct resource *
platform_get_resource(struct platform_device *dev, unsigned int type,
		      unsigned int num)
{
	int i;

	for (i = 0; i < dev->num_resources; i++) {
		struct resource *r = &dev->resource[i];

		if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
				 IORESOURCE_IRQ|IORESOURCE_DMA))
		    == type)
			if (num-- == 0)
				return r;
	}
	return NULL;
}

参数:
dev:资源所属的设备
type:获取的资源类型
num:所要获取资源类型的序号

如:platform_get_resource(pdev, IORESOURCE_IRQ, 0);    // 获取中断号,获取第0个中断号资源(即第1个)



2. 平台驱动

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;
};

/**
 *	platform_driver_register
 *	@drv: platform driver structure
 */
int platform_driver_register(struct platform_driver *drv)
{
	drv->driver.bus = &platform_bus_type;
	if (drv->probe)
		drv->driver.probe = platform_drv_probe;
	if (drv->remove)
		drv->driver.remove = platform_drv_remove;
	if (drv->shutdown)
		drv->driver.shutdown = platform_drv_shutdown;
	if (drv->suspend)
		drv->driver.suspend = platform_drv_suspend;
	if (drv->resume)
		drv->driver.resume = platform_drv_resume;
	return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(platform_driver_register);

/**
 *	platform_driver_unregister
 *	@drv: platform driver structure
 */
void platform_driver_unregister(struct platform_driver *drv)
{
	driver_unregister(&drv->driver);
}
EXPORT_SYMBOL_GPL(platform_driver_unregister);


实例:

plat_dev.c

#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/platform_device.h>

MODULE_AUTHOR("gzliu");
MODULE_LICENSE("Dual BSD/GPL");

static struct platform_device *my_device;

static int __init my_device_init(void)
{
	int ret = 0;
        
        /* 分配结构 */
	my_device = platform_device_alloc("my_dev", -1);
        
        /*注册设备*/
	ret = platform_device_add(my_device);
	
	/*注册失败,释放相关内存*/
	if (ret)
	    platform_device_put(my_device);
	
	return ret;	
}

static void my_device_exit(void)
{
	platform_device_unregister(my_device);
}

module_init(my_device_init);
module_exit(my_device_exit);

plat_drv.c

#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/platform_device.h>

MODULE_AUTHOR("David Xie");
MODULE_LICENSE("Dual BSD/GPL");

static int my_probe(struct device *dev)
{
    printk("Driver found device which my driver can handle!\n");
    return 0;
}

static int my_remove(struct device *dev)
{
    printk("Driver found device unpluged!\n");
    return 0;
}

static struct platform_driver my_driver = {
	.probe		= my_probe,
	.remove		= my_remove,
	.driver		= {
		.owner	= THIS_MODULE,
		.name	= "my_dev",
	},
};

static int __init my_driver_init(void)
{       
        /*注册平台驱动*/
	return platform_driver_register(&my_driver);
}

static void my_driver_exit(void)
{
	platform_driver_unregister(&my_driver);
}

module_init(my_driver_init);
module_exit(my_driver_exit);



你可能感兴趣的:(object,struct,Module,hierarchy,resources,structure)