aboutsummaryrefslogtreecommitdiff
path: root/drivers/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/core')
-rw-r--r--drivers/core/device.c111
-rw-r--r--drivers/core/of_addr.c4
-rw-r--r--drivers/core/root.c85
-rw-r--r--drivers/core/uclass.c7
4 files changed, 149 insertions, 58 deletions
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 81f6880..cb960f8 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -45,6 +45,9 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv,
bool auto_seq = true;
void *ptr;
+ if (CONFIG_IS_ENABLED(OF_PLATDATA_NO_BIND))
+ return -ENOSYS;
+
if (devp)
*devp = NULL;
if (!name)
@@ -395,26 +398,31 @@ int device_of_to_plat(struct udevice *dev)
if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
return 0;
- /* Ensure all parents have ofdata */
- if (dev->parent) {
- ret = device_of_to_plat(dev->parent);
+ /*
+ * This is not needed if binding is disabled, since data is allocated
+ * at build time.
+ */
+ if (!CONFIG_IS_ENABLED(OF_PLATDATA_NO_BIND)) {
+ /* Ensure all parents have ofdata */
+ if (dev->parent) {
+ ret = device_of_to_plat(dev->parent);
+ if (ret)
+ goto fail;
+
+ /*
+ * The device might have already been probed during
+ * the call to device_probe() on its parent device
+ * (e.g. PCI bridge devices). Test the flags again
+ * so that we don't mess up the device.
+ */
+ if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
+ return 0;
+ }
+
+ ret = device_alloc_priv(dev);
if (ret)
goto fail;
-
- /*
- * The device might have already been probed during
- * the call to device_probe() on its parent device
- * (e.g. PCI bridge devices). Test the flags again
- * so that we don't mess up the device.
- */
- if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
- return 0;
}
-
- ret = device_alloc_priv(dev);
- if (ret)
- goto fail;
-
drv = dev->driver;
assert(drv);
@@ -592,7 +600,7 @@ void *dev_get_plat(const struct udevice *dev)
return NULL;
}
- return dev->plat_;
+ return dm_priv_to_rw(dev->plat_);
}
void *dev_get_parent_plat(const struct udevice *dev)
@@ -602,7 +610,7 @@ void *dev_get_parent_plat(const struct udevice *dev)
return NULL;
}
- return dev->parent_plat_;
+ return dm_priv_to_rw(dev->parent_plat_);
}
void *dev_get_uclass_plat(const struct udevice *dev)
@@ -612,7 +620,7 @@ void *dev_get_uclass_plat(const struct udevice *dev)
return NULL;
}
- return dev->uclass_plat_;
+ return dm_priv_to_rw(dev->uclass_plat_);
}
void *dev_get_priv(const struct udevice *dev)
@@ -622,7 +630,7 @@ void *dev_get_priv(const struct udevice *dev)
return NULL;
}
- return dev->priv_;
+ return dm_priv_to_rw(dev->priv_);
}
void *dev_get_uclass_priv(const struct udevice *dev)
@@ -632,7 +640,7 @@ void *dev_get_uclass_priv(const struct udevice *dev)
return NULL;
}
- return dev->uclass_priv_;
+ return dm_priv_to_rw(dev->uclass_priv_);
}
void *dev_get_parent_priv(const struct udevice *dev)
@@ -642,7 +650,7 @@ void *dev_get_parent_priv(const struct udevice *dev)
return NULL;
}
- return dev->parent_priv_;
+ return dm_priv_to_rw(dev->parent_priv_);
}
static int device_get_device_tail(struct udevice *dev, int ret,
@@ -803,27 +811,19 @@ int device_get_global_by_ofnode(ofnode ofnode, struct udevice **devp)
}
#if CONFIG_IS_ENABLED(OF_PLATDATA)
-int device_get_by_driver_info(const struct driver_info *info,
- struct udevice **devp)
+int device_get_by_ofplat_idx(uint idx, struct udevice **devp)
{
- struct driver_info *info_base =
- ll_entry_start(struct driver_info, driver_info);
- int idx = info - info_base;
- struct driver_rt *drt = gd_dm_driver_rt() + idx;
struct udevice *dev;
- dev = drt->dev;
- *devp = NULL;
-
- return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
-}
+ if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+ struct udevice *base = ll_entry_start(struct udevice, udevice);
-int device_get_by_driver_info_idx(uint idx, struct udevice **devp)
-{
- struct driver_rt *drt = gd_dm_driver_rt() + idx;
- struct udevice *dev;
+ dev = base + idx;
+ } else {
+ struct driver_rt *drt = gd_dm_driver_rt() + idx;
- dev = drt->dev;
+ dev = drt->dev;
+ }
*devp = NULL;
return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
@@ -1136,3 +1136,36 @@ int dev_enable_by_path(const char *path)
return lists_bind_fdt(parent, node, NULL, false);
}
#endif
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA_RT)
+static struct udevice_rt *dev_get_rt(const struct udevice *dev)
+{
+ struct udevice *base = ll_entry_start(struct udevice, udevice);
+ int idx = dev - base;
+
+ struct udevice_rt *urt = gd_dm_udevice_rt() + idx;
+
+ return urt;
+}
+
+u32 dev_get_flags(const struct udevice *dev)
+{
+ const struct udevice_rt *urt = dev_get_rt(dev);
+
+ return urt->flags_;
+}
+
+void dev_or_flags(const struct udevice *dev, u32 or)
+{
+ struct udevice_rt *urt = dev_get_rt(dev);
+
+ urt->flags_ |= or;
+}
+
+void dev_bic_flags(const struct udevice *dev, u32 bic)
+{
+ struct udevice_rt *urt = dev_get_rt(dev);
+
+ urt->flags_ &= ~bic;
+}
+#endif /* OF_PLATDATA_RT */
diff --git a/drivers/core/of_addr.c b/drivers/core/of_addr.c
index 5bc6ca1..b3e384d 100644
--- a/drivers/core/of_addr.c
+++ b/drivers/core/of_addr.c
@@ -372,7 +372,7 @@ int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu,
bus_node->count_cells(dev, &na, &ns);
if (!OF_CHECK_COUNTS(na, ns)) {
printf("Bad cell count for %s\n", of_node_full_name(dev));
- return -EINVAL;
+ ret = -EINVAL;
goto out_parent;
}
@@ -380,7 +380,7 @@ int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu,
bus_node->count_cells(parent, &pna, &pns);
if (!OF_CHECK_COUNTS(pna, pns)) {
printf("Bad cell count for %s\n", of_node_full_name(parent));
- return -EINVAL;
+ ret = -EINVAL;
goto out_parent;
}
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 9bc682c..d9a19c5 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -11,6 +11,7 @@
#include <fdtdec.h>
#include <log.h>
#include <malloc.h>
+#include <asm-generic/sections.h>
#include <asm/global_data.h>
#include <linux/libfdt.h>
#include <dm/acpi.h>
@@ -129,6 +130,36 @@ void fix_devices(void)
}
}
+static int dm_setup_inst(void)
+{
+ DM_ROOT_NON_CONST = DM_DEVICE_GET(root);
+
+ if (CONFIG_IS_ENABLED(OF_PLATDATA_RT)) {
+ struct udevice_rt *urt;
+ void *base;
+ int n_ents;
+ uint size;
+
+ /* Allocate the udevice_rt table */
+ n_ents = ll_entry_count(struct udevice, udevice);
+ urt = calloc(n_ents, sizeof(struct udevice_rt));
+ if (!urt)
+ return log_msg_ret("urt", -ENOMEM);
+ gd_set_dm_udevice_rt(urt);
+
+ /* Now allocate space for the priv/plat data, and copy it in */
+ size = __priv_data_end - __priv_data_start;
+
+ base = calloc(1, size);
+ if (!base)
+ return log_msg_ret("priv", -ENOMEM);
+ memcpy(base, __priv_data_start, size);
+ gd_set_dm_priv_base(base);
+ }
+
+ return 0;
+}
+
int dm_init(bool of_live)
{
int ret;
@@ -140,8 +171,12 @@ int dm_init(bool of_live)
dm_warn("Virtual root driver already exists!\n");
return -EINVAL;
}
- gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST;
- INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST);
+ if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+ gd->uclass_root = &uclass_head;
+ } else {
+ gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST;
+ INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST);
+ }
if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) {
fix_drivers();
@@ -149,14 +184,23 @@ int dm_init(bool of_live)
fix_devices();
}
- ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
- if (ret)
- return ret;
- if (CONFIG_IS_ENABLED(OF_CONTROL))
- dev_set_ofnode(DM_ROOT_NON_CONST, ofnode_root());
- ret = device_probe(DM_ROOT_NON_CONST);
- if (ret)
- return ret;
+ if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+ ret = dm_setup_inst();
+ if (ret) {
+ log_debug("dm_setup_inst() failed: %d\n", ret);
+ return ret;
+ }
+ } else {
+ ret = device_bind_by_name(NULL, false, &root_info,
+ &DM_ROOT_NON_CONST);
+ if (ret)
+ return ret;
+ if (CONFIG_IS_ENABLED(OF_CONTROL))
+ dev_set_ofnode(DM_ROOT_NON_CONST, ofnode_root());
+ ret = device_probe(DM_ROOT_NON_CONST);
+ if (ret)
+ return ret;
+ }
return 0;
}
@@ -185,7 +229,7 @@ int dm_scan_plat(bool pre_reloc_only)
{
int ret;
- if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
+ if (CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT)) {
struct driver_rt *dyn;
int n_ents;
@@ -303,6 +347,15 @@ __weak int dm_scan_other(bool pre_reloc_only)
return 0;
}
+#if CONFIG_IS_ENABLED(OF_PLATDATA_INST) && CONFIG_IS_ENABLED(READ_ONLY)
+void *dm_priv_to_rw(void *priv)
+{
+ long offset = priv - (void *)__priv_data_start;
+
+ return gd_dm_priv_base() + offset;
+}
+#endif
+
/**
* dm_scan() - Scan tables to bind devices
*
@@ -347,10 +400,12 @@ int dm_init_and_scan(bool pre_reloc_only)
debug("dm_init() failed: %d\n", ret);
return ret;
}
- ret = dm_scan(pre_reloc_only);
- if (ret) {
- log_debug("dm_scan() failed: %d\n", ret);
- return ret;
+ if (!CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+ ret = dm_scan(pre_reloc_only);
+ if (ret) {
+ log_debug("dm_scan() failed: %d\n", ret);
+ return ret;
+ }
}
return 0;
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 1a4ea7a..117d35a 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -148,8 +148,11 @@ int uclass_get(enum uclass_id id, struct uclass **ucp)
*ucp = NULL;
uc = uclass_find(id);
- if (!uc)
+ if (!uc) {
+ if (CONFIG_IS_ENABLED(OF_PLATDATA_INST))
+ return -ENOENT;
return uclass_add(id, ucp);
+ }
*ucp = uc;
return 0;
@@ -391,7 +394,7 @@ done:
return ret;
}
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent,
const char *name, struct udevice **devp)
{