dts --> dtb 
 ------------------------------------ 
 dtc -I dts -O dtb -S 0x3000 -o obj_name.dtb source_name.dts 
 -S 指定的是生成的dtb文件的大小,需要适当地扩大,以供u-boot创建/choose节点时使用
 查看dts设备节点 
 ------------------------------------ 
 # ls -al /proc/device-tree 
 
 内核如何解析设备树 
 ------------------------------------ 
 1) 首先将从u-boot 传递过来的映像基地址和dtb 文件映像基地址保存通用      寄存器    r30,r31; 
 
 2) 通过调用machine_init() --> early_init_devtree()函数来获 
 取内核前期初始化所需的bootargs,cmd_line等系统引导参数; 
 
 3) 调用start_kernel() --> setup_arch() --> 
 unflat      te    n_device_tree()函数来解析dtb文件,构建一个由device_node结构连接而成的单项链表,并使用全局变量allnodes指针来保存这个链表的头指针; 
 
 4) 内核调用OF提供的A      PI    函数获取allnodes链表信息来初始化内核其他子系统、设备等。 
 
 dispAllnodes() -- 显示DTS设备节点 
 -------------------------------------- 
 ./arch/powerpc/kernel/p      rom    .c 
 
 void dispAllnodes() 
 { 
 struct device_node *dn; 
 dn = allnodes; 
 while (dn) 
 { 
 printk("dn->name = %s\n", dn->name); 
 printk("dn->type = %s\n", dn->type); 
 printk("dn->full_name = %s\n", dn->full_name); 
 printk("\n"); 
 dn = dn->next; 
 } 
 } 
 EXPORT_SYMBOL(dispAllnodes); 
 
 根据DTS文件的设备节点,添加设备 
      linux    -2.6.28\arch\powerpc\boot\dts\mpc8548cds.dts 
 ------------------------------------------------------- 
 soc8548@e0000000 { 
 #address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>; 
 device_type = "soc"; 
 ranges = <0 e0000000 00100000>; 
 reg = ;    // C      CSR    BAR 1M 
 bus-frequency = <0>; 
 
 mdio@24520 { 
 #address-cells = <1>; 
 #size-cells = <0>; 
 device_type = "mdio"; 
 compa      ti    ble = "gianfar"; 
 reg = <24520 20>; 
 phy0:      ethernet    -phy@0 { 
 interrupt-parent = <&mpic>; 
 interrupts = <35 0>; 
 reg = <0>; 
 device_type = "ethernet-phy"; 
 }; 
 }; 
 
 
 linux-2.6.21.7 
 gfar_mdio_of_init() --> 
 platform_device_register_simple() --> 
 platform_device_add() --> 
 device_add() 
 将mdio设备节点添加到platform总线上,这样添加方式(单独添加某个节点) 
 比较麻烦,抽象度不够,每个节点都需要自己的添加代码,不科学 
 还是of_platform_bus_probe()比较好,统一添加allnodes下的所有节点 
 -------------------------------------------------------
sta   TI  c int __init gfar_mdio_of_init(void) 
 { 
 ... 
 // 获取device_type = "mdio" && compa   TI  ble = "gianfar"的设备节点 
 np = of_find_compa   TI  ble_node(np, "mdio", "gianfar")); 
 of_address_to_resource(np, 0, &res); 
 // 添加平台设备res.start = e0024520 
 platform_device_register_simple("fsl-gianfar_mdio", res.start, &res, 1); 
 ... 
 } 
 arch_initcall(gfar_mdio_of_init); 
 
 
 
 struct platform_device *platform_device_register_simple(char *name, 
 unsigned int id, 
 struct resource *res, unsigned int num) 
 { 
 ... 
 // 生成platform_device 
 // platform_device->name = name; "fsl-gianfar_mdio" 
 // platform_device->id = id; e0024520 
 pdev = platform_device_alloc(name, id); 
 ... 
 platform_device_add(pdev); 
 ... 
 } 
 
 
 
 int platform_device_add(struct platform_device *pdev) 
 { 
 ... 
 // 设置pdev->dev.bus_id = fsl-gianfar_mdio.e0024520 
 // bus_id长度限制为BUS_ID_SIZE 
 // #define BUS_ID_SIZE    KOBJ_NAME_LEN 
 // 如果"%s.%x"      字符    串的长度超过KOBJ_NAME_LEN,将会造成设备节点名信息丢失 
 // 信息的丢失有可能导致设备添加失败,所以需要将KOBJ_NAME_LEN改大(20 --> 64) 
 snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%x", pdev->name, pdev->id); 
 ... 
 device_add(&pdev->dev); 
 ... 
 } 
 
 
 
 int device_add(struct device *dev) 
 { 
 ... 
 // 设置kobject->name = fsl-gianfar_mdio.e0024520 
 // #define KOBJ_NAME_LEN 20 
 kobject_set_name(&dev->kobj, "%s", dev->bus_id); 
 ... 
 // 在/sys/devices/platform/目录下生成设备节点 
 // 设备节点名称为fsl-gianfar_mdio.e0024520 
 device_create_file(dev, &dev->uevent_attr); 
 ... 
 } 
 
 
 
 设备与驱动的对应关系 
 ----------------------------------------------------- 
 sta   TI  c struct device_driver gianfar_mdio_driver = { 
 .name = "fsl-gianfar_mdio", 
 .bus = &platform_bus_type, //该驱动所归属的总线 
 .probe = gfar_mdio_probe, 
 .remove = gfar_mdio_remove, 
 }; 
 
 cat /sys/devices/platform/fsl-gianfar_mdio.e0024520/modalias 
 fsl-gianfar_mdio 
 
 
 static struct platform_driver gfar_driver = { 
 .probe = gfar_probe, 
 .remove = gfar_remove, 
 .driver    = { 
 .name = "fsl-gianfar", 
 }, 
 }; 
 
 cat /sys/devices/platform/fsl-gianfar.0/modalias 
 fsl-gianfar
 
 

 
 


