1.rk3288 dts 路径
路径:kernel\arch\arm\boot\dts\rk3288.dtsi
路径:kernel\arch\arm\boot\dts\rk3288-miniarm.dts
根目录下的compatible 属性表示该设备树可以兼容的平台,优先匹配"rockchip,rk3288-miniarm", 匹配不到的话,再进行匹配"rockchip,rk3288"。
/ {
compatible = "rockchip,rk3288-miniarm", "rockchip,rk3288";
memory {
device_type = "memory";
reg = <0x0 0x0 0x0 0x80000000>;
};
/
2.该设备树如何与设备平台进行匹配?
asmlinkage __visible void __init start_kernel(void)
->setup_arch(&command_line);//(路径:kernel\init\main.c)
->mdesc = setup_machine_fdt(__atags_pointer);//(路径:kernel\arch\arm\kernel\devtree.c) 检查传入的dtb 是否有效
->mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);//(路径:kernel\drivers\of\fdt.c) 找到machine_desc的最佳匹配
1)machine_desc 的结构体
路径:arch/arm/include/asm/mach/arch.h
struct machine_desc {
unsigned int nr; /* architecture number */
const char *name; /* architecture name */
unsigned long atag_offset; /* tagged list (relative) */
const char *const *dt_compat; /* array of device tree
* 'compatible' strings */
unsigned int nr_irqs; /* number of IRQs */
#ifdef CONFIG_ZONE_DMA
phys_addr_t dma_zone_size; /* size of DMA-able area */
#endif
unsigned int video_start; /* start of video RAM */
unsigned int video_end; /* end of video RAM */
unsigned char reserve_lp0 :1; /* never has lp0 */
unsigned char reserve_lp1 :1; /* never has lp1 */
unsigned char reserve_lp2 :1; /* never has lp2 */
enum reboot_mode reboot_mode; /* default restart mode */
unsigned l2c_aux_val; /* L2 cache aux value */
unsigned l2c_aux_mask; /* L2 cache aux mask */
void (*l2c_write_sec)(unsigned long, unsigned);
const struct smp_operations *smp; /* SMP operations */
bool (*smp_init)(void);
void (*fixup)(struct tag *, char **);
void (*dt_fixup)(void);
long long (*pv_fixup)(void);
void (*reserve)(void);/* reserve mem blocks */
void (*map_io)(void);/* IO mapping function */
void (*init_early)(void);
void (*init_irq)(void);
void (*init_time)(void);
void (*init_machine)(void);
void (*init_late)(void);
#ifdef CONFIG_MULTI_IRQ_HANDLER
void (*handle_irq)(struct pt_regs *);
#endif
void (*restart)(enum reboot_mode, const char *);
};
2)of_flat_dt_match_machine 根目录下的compatible 属性与设备平台匹配过程
每次调用函数 of_flat_dt_match_machine(mdesc_best, arch_get_next_mach); 从地址 __arch_info_begin 到 __arch_info_end 遍历,都会返回一个结构体machine_desc 的成员dt_compat与设备树中的compatible 属性对比。
static const void * __init arch_get_next_mach(const char *const **match)
{
static const struct machine_desc *mdesc = __arch_info_begin;
const struct machine_desc *m = mdesc;
if (m >= __arch_info_end)
return NULL;
mdesc++;
*match = m->dt_compat;
return m;
}
主要看__arch_info_begin 到 __arch_info_end 地址由来。
路径:kernel\arch\arm\kernel\vmlinux.lds.S
.init.arch.info : {
__arch_info_begin = .;
*(.arch.info.init)
__arch_info_end = .;
}
.init.arch.info 的定义
/*
* Set of macros to define architecture features. This is built into
* a table by the linker.
*/
#define MACHINE_START(_type,_name) \
static const struct machine_desc __mach_desc_##_type \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_##_type, \
.name = _name,
#define MACHINE_END \
};
#define DT_MACHINE_START(_name, _namestr) \
static const struct machine_desc __mach_desc_##_name \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
.nr = ~0, \
.name = _namestr,
#endif
3)最终找到设备数可以匹配平台的设备字符串
路径:kernel\arch\arm\mach-rockchip\rockchip.c
static const char * const rockchip_board_dt_compat[] = {
"rockchip,rk2928",
"rockchip,rk3066a",
"rockchip,rk3066b",
"rockchip,rk3188",
"rockchip,rk3288",
NULL,
};
DT_MACHINE_START(ROCKCHIP_DT, "Rockchip (Device Tree)")
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
.init_time = rockchip_timer_init,
.dt_compat = rockchip_board_dt_compat,
.init_machine = rockchip_dt_init,
MACHINE_END