zircon内核驱动初始化

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/tiantao2012/article/details/96481421
zircon中内核驱动的初始化的的入口为platform_early_init->pdev_init
pdev_init的代码如下:
void pdev_init(const zbi_header_t* zbi) {
    ASSERT(zbi);
#保存driver的入口
    driver_zbi = zbi;
#开始初始化内核驱动
    pdev_run_hooks(LK_INIT_LEVEL_PLATFORM_EARLY);
}
static void pdev_run_hooks(uint level) {
    if (!driver_zbi) {
        return;
    }

    const uint8_t* start = (uint8_t*)item + sizeof(zbi_header_t);
    const uint8_t* end = start + item->length;

    while (static_cast<size_t>(end - start) > sizeof(zbi_header_t)) {
        item = reinterpret_cast<const zbi_header_t*>(start);
        if (item->type == ZBI_TYPE_KERNEL_DRIVER) {
            // kernel driver type is in boot item extra
            // driver data follows boot item
#开始运行__start_lk_pdev_init和__stop_lk_pdev_init 之间的hook函数
            pdev_init_driver(item->extra, &item[1], item->length, level);
        }
        start += ZBI_ALIGN((uint32_t)sizeof(zbi_header_t) + item->length);
    }
}

static void pdev_init_driver(uint32_t type, const void* driver_data, uint32_t length, uint level) {
    const struct lk_pdev_init_struct* ptr;
    for (ptr = __start_lk_pdev_init; ptr != __stop_lk_pdev_init; ptr++) {
#这里的type应该是ZBI_CONTAINER_MAGIC。level应该是LK_INIT_LEVEL_PLATFORM_EARLY
        if (ptr->type == type && ptr->level == level) {
            ptr->hook(driver_data, length);
            return;
        }
    }
}
那具体哪些驱动会被定义在__start_lk_pdev_init和__stop_lk_pdev_init之间呢
zircon-master/kernel/dev/pdev/include/pdev/driver.h
#define LK_PDEV_INIT(_name, _type, _hook, _level)                                                                      \
    __ALIGNED(sizeof(void*))                                                                                           \
    __USED __SECTION(".data.rel.ro.lk_pdev_init") static const struct lk_pdev_init_struct _dev_init_struct_##_name = { \
        .type = _type,                                                                                                 \
        .hook = _hook,                                                                                                 \
        .level = _level,                                                                                               \
        .name = #_name,                                                                                                \
    };



"zircon-master/kernel/kernel.ld"
PROVIDE_HIDDEN(__start_lk_pdev_init = .);
KEEP(*(.data.rel.ro.lk_pdev_init))
PROVIDE_HIDDEN(__stop_lk_pdev_init = .);

从这里可以知道凡是用调用LK_PDEV_INIT 初始化的驱动在这这个范围中
以power 驱动为例
static void xxxx_power_init(const void* driver_data, uint32_t length) {
  
    auto driver = static_cast<const dcfg_xxxx_power_driver_t*>(driver_data);
   


    // get virtual addresses of our peripheral bases
    sctrl_base = periph_paddr_to_vaddr(driver->sctrl_phys);
    pmu_base = periph_paddr_to_vaddr(driver->pmu_phys);
    ASSERT(sctrl_base && pmu_base);

    pdev_register_power(&xxxx_power_ops);
}

LK_PDEV_INIT(xxxx_power_init, KDRV_xxxxLICON_POWER, xxxx_power_init, LK_INIT_LEVEL_PLATFORM)
最终的注册也只是将驱动实现的power的ops保存到全局变量power_ops中
void pdev_register_power(const struct pdev_power_ops* ops) {
    power_ops = ops;
    smp_mb();
}

猜你喜欢

转载自blog.csdn.net/tiantao2012/article/details/96481421