amba总线注册:
static int __init amba_init(void)
{
return bus_register(&amba_bustype);
}
postcore_initcall(amba_init);
I2C总线注册是在i2c-core.c注册的:
static int __init i2c_init(void)
{
int retval;
retval = bus_register(&i2c_bus_type);
.......
}
postcore_initcall(i2c_init);
设备添加到总线:
###################hisilicon.c文件中定义:
#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101)
DT_MACHINE_START(HI3519_DT, "Hisilicon Hi3519 (Flattened Device Tree)")
.map_io = hi3519_map_io,
.dt_compat = hi3519_compat,
.reserve = hi3519_reserve,
MACHINE_END
#endif
###################arch/arm/kernel/setup.c
static int __init customize_machine(void)
{
/*
* customizes platform devices, or adds new ones
* On DT based machines, we fall back to populating the
* machine from the device tree, if no callback is provided,
* otherwise we would always need an init_machine callback.
*/
if (machine_desc->init_machine)
machine_desc->init_machine();
#ifdef CONFIG_OF
else//因为没有定义machine_desc->init_machine,所以运行of_platform_populate
of_platform_populate(NULL, of_default_bus_match_table,
NULL, NULL);
#endif
return 0;
}
arch_initcall(customize_machine);
#############################drivers/of/platform.c
static int of_platform_bus_create(struct device_node *bus,
const struct of_device_id *matches,
const struct of_dev_auxdata *lookup,
struct device *parent, bool strict)
{
const struct of_dev_auxdata *auxdata;
struct device_node *child;
struct platform_device *dev;
const char *bus_id = NULL;
void *platform_data = NULL;
int rc = 0;
/* Make sure it has a compatible property */
if (strict && (!of_get_property(bus, "compatible", NULL))) {
pr_debug("%s() - skipping %s, no compatible prop\n",
__func__, bus->full_name);
return 0;
}
auxdata = of_dev_lookup(lookup, bus);
if (auxdata) {
bus_id = auxdata->name;
platform_data = auxdata->platform_data;
}
if (of_device_is_compatible(bus, "arm,primecell")) {//添加设备并挂在amba总线上.......串口,spi,gpio都是用的这个总线.
/*
* Don't return an error here to keep compatibility with older
* device tree files.
*/
of_amba_device_create(bus, bus_id, platform_data, parent);
return 0;
}
dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);//挂在其他总线,并匹配驱动,如果有驱动,运行驱动.
if (!dev || !of_match_node(matches, bus))
return 0;
for_each_child_of_node(bus, child) {
pr_debug(" create child: %s\n", child->full_name);
rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);
if (rc) {
of_node_put(child);
break;
}
}
of_node_set_flag(bus, OF_POPULATED_BUS);
return rc;
}
of_platform_device_create_pdata-----of_device_add-----device_add------bus_probe_device-----device_attach新注册还没有绑定驱动-----bus_for_each_drv-----__device_attach----------driver_match_device(匹配调用drv->bus->match,)如果匹配成功-------dev->bus->probe或者drv->probe
驱动注册的时候如果匹配成功也会调用probe接口,注册驱动都会调用到driver_register------bus_add_driver------driver_attach-------__driver_attach--------driver_match_device(匹配调用drv->bus->match)如果成功------driver_probe_device------really_probe-----dev->bus->probe或者drv->probe
###################i2c-hisi-v110.c中注册i2c的适配器驱动
module_platform_driver(hi_i2c_driver); 对应platform_driver_register----------__platform_driver_register-----driver_register
看代码注册方式:module_init
###################在i2c-dev.c添加/dev设备
module_init(i2c_dev_init);
#######################drivers/tty/serial/amba-pl011.c注册串口驱动
arch_initcall(pl011_init);
启动优先级,注:module_init对应device_initcall,总线早,设备驱动不定时间
#define pure_initcall(fn) __define_initcall(fn, 0)
#define core_initcall(fn) __define_initcall(fn, 1)
#define core_initcall_sync(fn) __define_initcall(fn, 1s)
#define postcore_initcall(fn) __define_initcall(fn, 2)
#define postcore_initcall_sync(fn) __define_initcall(fn, 2s)
#define arch_initcall(fn) __define_initcall(fn, 3)
#define arch_initcall_sync(fn) __define_initcall(fn, 3s)
#define subsys_initcall(fn) __define_initcall(fn, 4)
#define subsys_initcall_sync(fn) __define_initcall(fn, 4s)
#define fs_initcall(fn) __define_initcall(fn, 5)
#define fs_initcall_sync(fn) __define_initcall(fn, 5s)
#define rootfs_initcall(fn) __define_initcall(fn, rootfs)
#define device_initcall(fn) __define_initcall(fn, 6)
#define device_initcall_sync(fn) __define_initcall(fn, 6s)
#define late_initcall(fn) __define_initcall(fn, 7)
#define late_initcall_sync(fn) __define_initcall(fn, 7s)
linux下对/sys/class/gpio中的gpio的编号确定 ===》 for i in gpiochip* ; do echo `cat $i/label`: `cat $i/base` ; done
根据/proc/partitions获取插入的U盘设备名称,参考https://blog.csdn.net/zhouzhenhe2008/article/details/72943314