这里分析的是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