#include <common.h>
#include <fdtdec.h>
+#include <fdt_support.h>
#include <malloc.h>
#include <dm/device.h>
#include <dm/device-internal.h>
return -EINVAL;
ret = uclass_get(drv->id, &uc);
- if (ret)
+ if (ret) {
+ debug("Missing uclass for driver %s\n", drv->name);
return ret;
+ }
dev = calloc(1, sizeof(struct udevice));
if (!dev)
dev->flags |= DM_FLAG_ACTIVATED;
- /* continue regardless of the result of pinctrl */
- pinctrl_select_state(dev, "default");
+ /*
+ * Process pinctrl for everything except the root device, and
+ * continue regardless of the result of pinctrl.
+ */
+ if (dev->parent)
+ pinctrl_select_state(dev, "default");
ret = uclass_pre_probe_device(dev);
if (ret)
return dev->uclass_priv;
}
-void *dev_get_parentdata(struct udevice *dev)
+void *dev_get_parent_priv(struct udevice *dev)
{
if (!dev) {
dm_warn("%s: null device\n", __func__);
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;
- addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
- 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 (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", &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.
+ */
+ 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);
+ }
}
+ /*
+ * 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 += dm_get_translation_offset();
+
return addr;
#else
return FDT_ADDR_T_NONE;
#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);