summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/core/device.c11
-rw-r--r--drivers/core/lists.c16
-rw-r--r--drivers/core/root.c11
-rw-r--r--include/asm-generic/global_data.h14
-rw-r--r--include/dm/device-internal.h2
-rw-r--r--include/dm/platdata.h14
-rw-r--r--test/dm/of_platdata.c19
7 files changed, 65 insertions, 22 deletions
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 746c619cd9..2e5767ed99 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -249,7 +249,7 @@ int device_bind_ofnode(struct udevice *parent, const struct driver *drv,
}
int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
- struct driver_info *info, struct udevice **devp)
+ const struct driver_info *info, struct udevice **devp)
{
struct driver *drv;
uint platdata_size = 0;
@@ -269,9 +269,6 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
platdata_size, devp);
if (ret)
return ret;
-#if CONFIG_IS_ENABLED(OF_PLATDATA)
- info->dev = *devp;
-#endif
return ret;
}
@@ -764,9 +761,13 @@ int device_get_global_by_ofnode(ofnode ofnode, struct udevice **devp)
int device_get_by_driver_info(const struct driver_info *info,
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 = info->dev;
+ dev = drt->dev;
*devp = NULL;
return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index 5beba9181c..2e6bd5006c 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -56,14 +56,20 @@ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only)
struct driver_info *info =
ll_entry_start(struct driver_info, driver_info);
const int n_ents = ll_entry_count(struct driver_info, driver_info);
- struct driver_info *entry;
- struct udevice *dev;
int result = 0;
- int ret;
+ uint idx;
+
+ for (idx = 0; idx < n_ents; idx++) {
+ const struct driver_info *entry = info + idx;
+ struct driver_rt *drt = gd_dm_driver_rt() + idx;
+ struct udevice *dev;
+ int ret;
- for (entry = info; entry != info + n_ents; entry++) {
ret = device_bind_by_name(parent, pre_reloc_only, entry, &dev);
- if (ret && ret != -EPERM) {
+ if (!ret) {
+ if (CONFIG_IS_ENABLED(OF_PLATDATA))
+ drt->dev = dev;
+ } else if (ret != -EPERM) {
dm_warn("No match for driver '%s'\n", entry->name);
if (!result || ret != -ENOENT)
result = ret;
diff --git a/drivers/core/root.c b/drivers/core/root.c
index de23161cff..e8df5aebe8 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -185,6 +185,17 @@ int dm_scan_platdata(bool pre_reloc_only)
{
int ret;
+ if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
+ struct driver_rt *dyn;
+ int n_ents;
+
+ n_ents = ll_entry_count(struct driver_info, driver_info);
+ dyn = calloc(n_ents, sizeof(struct driver_rt));
+ if (!dyn)
+ return -ENOMEM;
+ gd_set_dm_driver_rt(dyn);
+ }
+
ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only);
if (ret == -ENOENT) {
dm_warn("Some drivers were not found\n");
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index cadfc05dd7..0aa1144184 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -24,6 +24,8 @@
#include <membuff.h>
#include <linux/list.h>
+struct driver_rt;
+
typedef struct global_data gd_t;
/**
@@ -192,6 +194,10 @@ struct global_data {
* @uclass_root: head of core tree
*/
struct list_head uclass_root;
+# if CONFIG_IS_ENABLED(OF_PLATDATA)
+ /** Dynamic info about the driver */
+ struct driver_rt *dm_driver_rt;
+# endif
#endif
#ifdef CONFIG_TIMER
/**
@@ -438,6 +444,14 @@ struct global_data {
#define gd_set_of_root(_root)
#endif
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+#define gd_set_dm_driver_rt(dyn) gd->dm_driver_rt = dyn
+#define gd_dm_driver_rt() gd->dm_driver_rt
+#else
+#define gd_set_dm_driver_rt(dyn)
+#define gd_dm_driver_rt() NULL
+#endif
+
/**
* enum gd_flags - global data flags
*
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index 1dcc22f689..c5d7ec0650 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -81,7 +81,7 @@ int device_bind_with_driver_data(struct udevice *parent,
* @return 0 if OK, -ve on error
*/
int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
- struct driver_info *info, struct udevice **devp);
+ const struct driver_info *info, struct udevice **devp);
/**
* device_reparent: reparent the device to a new parent
diff --git a/include/dm/platdata.h b/include/dm/platdata.h
index 25479b03d2..2c3cc90c29 100644
--- a/include/dm/platdata.h
+++ b/include/dm/platdata.h
@@ -22,18 +22,28 @@
* @name: Driver name
* @platdata: Driver-specific platform data
* @platdata_size: Size of platform data structure
- * @dev: Device created from this structure data
*/
struct driver_info {
const char *name;
const void *platdata;
#if CONFIG_IS_ENABLED(OF_PLATDATA)
uint platdata_size;
- struct udevice *dev;
#endif
};
/**
+ * driver_rt - runtime information set up by U-Boot
+ *
+ * There is one of these for every driver_info in the linker list, indexed by
+ * the driver_info idx value.
+ *
+ * @dev: Device created from this idx
+ */
+struct driver_rt {
+ struct udevice *dev;
+};
+
+/**
* NOTE: Avoid using these except in extreme circumstances, where device tree
* is not feasible (e.g. serial driver in SPL where <8KB of SRAM is
* available). U-Boot's driver model uses device tree for configuration.
diff --git a/test/dm/of_platdata.c b/test/dm/of_platdata.c
index 57f903611a..e827d45ffb 100644
--- a/test/dm/of_platdata.c
+++ b/test/dm/of_platdata.c
@@ -109,16 +109,16 @@ static int find_driver_info(struct unit_test_state *uts, struct udevice *parent,
/* If not the root device, find the entry that caused it to be bound */
if (parent->parent) {
- const struct driver_info *info =
- ll_entry_start(struct driver_info, driver_info);
const int n_ents =
ll_entry_count(struct driver_info, driver_info);
- const struct driver_info *entry;
int idx = -1;
+ int i;
- for (entry = info; entry != info + n_ents; entry++) {
- if (entry->dev == parent) {
- idx = entry - info;
+ for (i = 0; i < n_ents; i++) {
+ const struct driver_rt *drt = gd_dm_driver_rt() + i;
+
+ if (drt->dev == parent) {
+ idx = i;
found[idx] = true;
break;
}
@@ -153,16 +153,17 @@ static int dm_test_of_platdata_dev(struct unit_test_state *uts)
/* Make sure that the driver entries without devices have no ->dev */
for (i = 0; i < n_ents; i++) {
+ const struct driver_rt *drt = gd_dm_driver_rt() + i;
const struct driver_info *entry = info + i;
struct udevice *dev;
if (found[i]) {
/* Make sure we can find it */
- ut_assertnonnull(entry->dev);
+ ut_assertnonnull(drt->dev);
ut_assertok(device_get_by_driver_info(entry, &dev));
- ut_asserteq_ptr(dev, entry->dev);
+ ut_asserteq_ptr(dev, drt->dev);
} else {
- ut_assertnull(entry->dev);
+ ut_assertnull(drt->dev);
ut_asserteq(-ENOENT,
device_get_by_driver_info(entry, &dev));
}