linux中platform总线解析(二)(platform设备的注册)

这里分析的是linux3.10内核,mips架构。

然后说一下platform设备注册的时机:

那是系统启动到什么时候调用的呢?
就是在device_initcall阶段,也就是对应的对应6阶段。

看一下函数调用:

ls2h_device-initcall--->platform_add_devices(ls2h_platform_devices,ARRAY_SIZE(ls2h_platform_devices))

这里的platform_add_devices进行platfrom设备的注册。

那么这个函数在哪里进行定义的呢?或者说在哪里开始运行的呢?

#define device_initcall(fn)		__define_initcall(fn, 6)
#define __define_initcall(level,fn) \
	static initcall_t __initcall_##fn __used \
	__attribute__((__section__(".initcall" level ".init"))) = fn


static int __init loongson3_device_init(void)
{
	if (loongson_pch)
		loongson_pch->pch_device_initcall();

	return 0;
}
device_initcall(loongson3_device_init);

这里把loongson3_device_init设置为.initcall6.init段中。

而这里loongson3_device_init函数调用的pch_device_initcall是函数ls2h_device_initcall.
也就是在系统初始化的第六阶段开始调用运行。

下面就来看看设备注册都做了什么把。。

int platform_add_devices(struct platform_device **devs, int num)
{
	int i, ret = 0;
//调用platform_device_register函数设备注册进系统
	for (i = 0; i < num; i++) {
		ret = platform_device_register(devs[i]);
		if (ret) {
			while (--i >= 0)
				platform_device_unregister(devs[i]);
			break;
		}
	}
	return ret;
}

调用platform_device_register函数设备注册进系统,也就是函数调用platform_device_register做了下面注册工作

int platform_device_register(struct platform_device *pdev)
{
//初始化设备
	device_initialize(&pdev->dev);
//设备架构相关的数据
	arch_setup_pdev_archdata(pdev);
//调用platform_device_add把设备加入系统中
	return platform_device_add(pdev);
}
void device_initialize(struct device *dev)
{
//设置所属的目录
	dev->kobj.kset = devices_kset;
//在sysfs中设备的操作函数
	kobject_init(&dev->kobj, &device_ktype);
	INIT_LIST_HEAD(&dev->dma_pools);
	mutex_init(&dev->mutex);
	lockdep_set_novalidate_class(&dev->mutex);
//锁初始化
	spin_lock_init(&dev->devres_lock);
	INIT_LIST_HEAD(&dev->devres_head);
//电源管理相关
	device_pm_init(dev);
//设置跟cpu的距离
	set_dev_node(dev, -1);
}

在这里的arch_setup_pdev_archdata(pdev);为空函数。

int platform_device_add(struct platform_device *pdev)
{
	int i, ret;

	if (!pdev)
		return -EINVAL;
//设置父设备,这里为platfrom设备
	if (!pdev->dev.parent)
		pdev->dev.parent = &platform_bus;
//设置挂载的总线类型,这里为platform总线
	pdev->dev.bus = &platform_bus_type;

	switch (pdev->id) {
	default:
//设置设备名字,如有两个网卡设备名字为:mac0,mac1
		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
		break;
	case PLATFORM_DEVID_NONE:
		dev_set_name(&pdev->dev, "%s", pdev->name);
		break;
	case PLATFORM_DEVID_AUTO:
		ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL);
		if (ret < 0)
			goto err_out;
		pdev->id = ret;
		pdev->id_auto = true;
		dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, pdev->id);
		break;
	}
//为设备申请资源
	for (i = 0; i < pdev->num_resources; i++) {
		struct resource *p, *r = &pdev->resource[i];

		if (r->name == NULL)
			r->name = dev_name(&pdev->dev);

		p = r->parent;
		if (!p) {
			if (resource_type(r) == IORESOURCE_MEM)
				p = &iomem_resource;
			else if (resource_type(r) == IORESOURCE_IO)
				p = &ioport_resourc
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值