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
}
posted @ 2022-02-23 13:06  liujunhuasd  阅读(264)  评论(0编辑  收藏  举报