u-boot devfdt_get_addr_index函数


fdt_addr_t devfdt_get_addr_index(const struct udevice *dev, int index) { #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)     fdt_addr_t addr;
    if (CONFIG_IS_ENABLED(OF_TRANSLATE)) {         const fdt32_t *reg;         int len = 0;         int na, ns; //在fdt_blob是parent设备的偏移 //获取address_cells数量
        na = fdt_address_cells(gd->fdt_blob,                        dev_of_offset(dev->parent));         if (na < 1) {             debug("bad #address-cells\n");             return FDT_ADDR_T_NONE;         } //获取size_cells数量
        ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent));         if (ns < 0) {             debug("bad #size-cells\n");             return FDT_ADDR_T_NONE;         }
        reg = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "reg",                   &len);         if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) {             debug("Req index out of range\n");             return FDT_ADDR_T_NONE;         }
        reg += index * (na + ns);
        if (ns) {             /*              * Use the full-fledged translate function for complex              * bus setups.              */             addr = fdt_translate_address((void *)gd->fdt_blob,                              dev_of_offset(dev), reg);         } else {             /* Non translatable if #size-cells == 0 */             addr = fdt_read_number(reg, na);         }     } else {         /*          * Use the "simple" translate function for less complex          * bus setups.          */         addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,                 dev_of_offset(dev->parent), dev_of_offset(dev),                 "reg", index, NULL, false);         if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) {             if (device_get_uclass_id(dev->parent) ==                 UCLASS_SIMPLE_BUS)                 addr = simple_bus_translate(dev->parent, addr);         }     }
#if defined(CONFIG_TRANSLATION_OFFSET)     /*      * Some platforms need a special address translation. Those      * platforms (e.g. mvebu in SPL) can configure a translation      * offset by setting this value in the GD and enaling this      * feature via CONFIG_TRANSLATION_OFFSET. This value will      * get added to all addresses returned by devfdt_get_addr().      */     addr += gd->translation_offset; #endif
    return addr; #else     return FDT_ADDR_T_NONE; #endif }

相关