diff options
Diffstat (limited to 'drivers/core/device.c')
-rw-r--r-- | drivers/core/device.c | 60 |
1 files changed, 46 insertions, 14 deletions
diff --git a/drivers/core/device.c b/drivers/core/device.c index 758f39064c..8c6e6b067e 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -581,38 +581,65 @@ const char *dev_get_uclass_name(struct udevice *dev) return dev->uclass->uc_drv->name; } -fdt_addr_t dev_get_addr(struct udevice *dev) +fdt_addr_t dev_get_addr_index(struct udevice *dev, int index) { #if CONFIG_IS_ENABLED(OF_CONTROL) fdt_addr_t addr; if (CONFIG_IS_ENABLED(OF_TRANSLATE)) { const fdt32_t *reg; + int len = 0; + int na, ns; + + na = fdt_address_cells(gd->fdt_blob, dev->parent->of_offset); + if (na < 1) { + debug("bad #address-cells\n"); + return FDT_ADDR_T_NONE; + } + + ns = fdt_size_cells(gd->fdt_blob, dev->parent->of_offset); + if (ns < 0) { + debug("bad #size-cells\n"); + return FDT_ADDR_T_NONE; + } - reg = fdt_getprop(gd->fdt_blob, dev->of_offset, "reg", NULL); - if (!reg) + reg = fdt_getprop(gd->fdt_blob, dev->of_offset, "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); /* * Use the full-fledged translate function for complex * bus setups. */ - return fdt_translate_address((void *)gd->fdt_blob, + addr = fdt_translate_address((void *)gd->fdt_blob, dev->of_offset, reg); + } else { + /* + * Use the "simple" translate function for less complex + * bus setups. + */ + addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, + dev->parent->of_offset, + dev->of_offset, "reg", + index, NULL); + 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); + } } /* - * Use the "simple" translate function for less complex - * bus setups. + * Some platforms need a special address translation. Those + * platforms (e.g. mvebu in SPL) can configure a translation + * offset in the DM by calling dm_set_translation_offset() that + * will get added to all addresses returned by dev_get_addr(). */ - addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, - dev->parent->of_offset, - dev->of_offset, "reg", - 0, NULL); - 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); - } + addr += dm_get_translation_offset(); return addr; #else @@ -620,6 +647,11 @@ fdt_addr_t dev_get_addr(struct udevice *dev) #endif } +fdt_addr_t dev_get_addr(struct udevice *dev) +{ + return dev_get_addr_index(dev, 0); +} + bool device_has_children(struct udevice *dev) { return !list_empty(&dev->child_head); |