platform_device設備

    文章的分析基於linux-2.6.22,led驅動分析了s3c24xx的led設備的註冊、驅動的註冊,以及其設備和驅動的關聯過程;platform_bus_init過程分析了platform_bus設備的註冊。  platform_bus設備,platform_device設備,device設備,到底有多少名字近似的設備啊?

    今天學習下platform_device設備,儘量把幾個概念搞清楚。

1.
void __init smdk_machine_init(void)
{
        ......

	platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));

	......
}

static struct platform_device __initdata *smdk_devs[] = {
	.......

	&smdk_led4, //這個就是platform_device設備了

        ......
};

static struct platform_device smdk_led4 = {
	.name		= "s3c24xx_led",
	.id		= 0,
	.dev		= {
		.platform_data = &smdk_pdata_led4,
	},
};


2.
/**
 *	platform_add_devices - add a numbers of platform devices
 *	@devs: array of platform devices to add
 *	@num: number of platform devices in array
 */
int platform_add_devices(struct platform_device **devs, int num)
{
	int i, ret = 0;

	for (i = 0; i < num; i++) {
		ret = platform_device_register(devs[i]); //註冊platform_device設備
		if (ret) {
			while (--i >= 0)
				platform_device_unregister(devs[i]);
			break;
		}
	}

	return ret;
}


3. //以前看這裏發懵:add到哪?
/**
 *	platform_device_register - add a platform-level device
 *	@pdev:	platform device we're adding
 *
 */
int platform_device_register(struct platform_device * pdev)
{
	device_initialize(&pdev->dev); //3.1分析
	return platform_device_add(pdev); //3.2分析
}


3.1 //設置platform_device的kset指向devices_subsys
/**
 *	device_initialize - init device structure.
 *	@dev:	device.
 *
 *	This prepares the device for use by other layers,
 *	including adding it to the device hierarchy.
 *	It is the first half of device_register(), if called by
 *	that, though it can also be called separately, so one
 *	may use @dev's fields (e.g. the refcount).
 */

//devices_subsys的目錄名爲devices
void device_initialize(struct device *dev)
{
        ......	

        kobj_set_kset_s(dev, devices_subsys); //設置dev的kset指向devices_subsys
     
        .......

	INIT_LIST_HEAD(&dev->node);

	.......
}


3.2
/**
 *	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)
{
        ......

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

	pdev->dev.bus = &platform_bus_type; //以前對這個platform_bus_type沒認知

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

	ret = device_add(&pdev->dev);

        ......
}


3.2.1
/**
 *	device_add - add device to device hierarchy.
 *	@dev:	device.
 *
 *	This is part 2 of device_register(), though may be called
 *	separately _iff_ device_initialize() has been called separately.
 *
 *	This adds it to the kobject hierarchy via kobject_add(), adds it
 *	to the global and sibling lists for the device, then
 *	adds it to the other relevant subsystems of the driver model.
 */
int device_add(struct device *dev)
{
        ......

        /* first, register with generic layer. */
	kobject_set_name(&dev->kobj, "%s", dev->bus_id);
	error = kobject_add(&dev->kobj); //將dev_kobj接入platform_bus(kset)的鏈表

        ......

        bus_attach_device(dev); //將dev接入bus的鏈表

        ......
}

3.2.3
/**
 *	bus_attach_device - add device to bus
 *	@dev:	device tried to attach to a driver
 *
 *	- Add device to bus's list of devices.
 *	- Try to attach to driver.
 */
void bus_attach_device(struct device * dev)
{
	struct bus_type *bus = dev->bus;
	int ret = 0;

	if (bus) {
		dev->is_registered = 1;
		if (bus->drivers_autoprobe)
			ret = device_attach(dev);
		WARN_ON(ret < 0);
		if (ret >= 0)
			klist_add_tail(&dev->knode_bus, &bus->klist_devices); //添加到bus的list鏈表
		else
			dev->is_registered = 0;
	}
}

    添加的設備與platform_bus_type和platform_bus的關係如下圖,從圖中很容易解答我心中的的疑惑:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章