summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/driver-model/README.txt23
-rw-r--r--drivers/core/device.c25
-rw-r--r--drivers/core/lists.c4
-rw-r--r--include/dm/device-internal.h24
4 files changed, 62 insertions, 14 deletions
diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt
index 7a24552560..1b5ccec4b2 100644
--- a/doc/driver-model/README.txt
+++ b/doc/driver-model/README.txt
@@ -606,19 +606,24 @@ methods actually defined.
1. Bind stage
-A device and its driver are bound using one of these two methods:
+U-Boot discovers devices using one of these two methods:
- - Scan the U_BOOT_DEVICE() definitions. U-Boot It looks up the
-name specified by each, to find the appropriate driver. It then calls
-device_bind() to create a new device and bind' it to its driver. This will
-call the device's bind() method.
+ - Scan the U_BOOT_DEVICE() definitions. U-Boot looks up the name specified
+by each, to find the appropriate U_BOOT_DRIVER() definition. In this case,
+there is no path by which driver_data may be provided, but the U_BOOT_DEVICE()
+may provide platdata.
- Scan through the device tree definitions. U-Boot looks at top-level
nodes in the the device tree. It looks at the compatible string in each node
-and uses the of_match part of the U_BOOT_DRIVER() structure to find the
-right driver for each node. It then calls device_bind() to bind the
-newly-created device to its driver (thereby creating a device structure).
-This will also call the device's bind() method.
+and uses the of_match table of the U_BOOT_DRIVER() structure to find the
+right driver for each node. In this case, the of_match table may provide a
+driver_data value, but platdata cannot be provided until later.
+
+For each device that is discovered, U-Boot then calls device_bind() to create a
+new device, initializes various core fields of the device object such as name,
+uclass & driver, initializes any optional fields of the device object that are
+applicable such as of_offset, driver_data & platdata, and finally calls the
+driver's bind() method if one is defined.
At this point all the devices are known, and bound to their drivers. There
is a 'struct udevice' allocated for all devices. However, nothing has been
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 45d5e3e12c..eb75b1734f 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -26,9 +26,10 @@
DECLARE_GLOBAL_DATA_PTR;
-int device_bind(struct udevice *parent, const struct driver *drv,
- const char *name, void *platdata, int of_offset,
- struct udevice **devp)
+static int device_bind_common(struct udevice *parent, const struct driver *drv,
+ const char *name, void *platdata,
+ ulong driver_data, int of_offset,
+ struct udevice **devp)
{
struct udevice *dev;
struct uclass *uc;
@@ -56,6 +57,7 @@ int device_bind(struct udevice *parent, const struct driver *drv,
INIT_LIST_HEAD(&dev->devres_head);
#endif
dev->platdata = platdata;
+ dev->driver_data = driver_data;
dev->name = name;
dev->of_offset = of_offset;
dev->parent = parent;
@@ -193,6 +195,23 @@ fail_alloc1:
return ret;
}
+int device_bind_with_driver_data(struct udevice *parent,
+ const struct driver *drv, const char *name,
+ ulong driver_data, int of_offset,
+ struct udevice **devp)
+{
+ return device_bind_common(parent, drv, name, NULL, driver_data,
+ of_offset, devp);
+}
+
+int device_bind(struct udevice *parent, const struct driver *drv,
+ const char *name, void *platdata, int of_offset,
+ struct udevice **devp)
+{
+ return device_bind_common(parent, drv, name, platdata, 0, of_offset,
+ devp);
+}
+
int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
const struct driver_info *info, struct udevice **devp)
{
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index a72db13a11..0c27717790 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -170,7 +170,8 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
}
dm_dbg(" - found match at '%s'\n", entry->name);
- ret = device_bind(parent, entry, name, NULL, offset, &dev);
+ ret = device_bind_with_driver_data(parent, entry, name,
+ id->data, offset, &dev);
if (ret == -ENODEV) {
dm_dbg("Driver '%s' refuses to bind\n", entry->name);
continue;
@@ -180,7 +181,6 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
ret);
return ret;
} else {
- dev->driver_data = id->data;
found = true;
if (devp)
*devp = dev;
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index b348ad5231..0bf8707493 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -39,6 +39,30 @@ int device_bind(struct udevice *parent, const struct driver *drv,
struct udevice **devp);
/**
+ * device_bind_with_driver_data() - Create a device and bind it to a driver
+ *
+ * Called to set up a new device attached to a driver, in the case where the
+ * driver was matched to the device by means of a match table that provides
+ * driver_data.
+ *
+ * Once bound a device exists but is not yet active until device_probe() is
+ * called.
+ *
+ * @parent: Pointer to device's parent, under which this driver will exist
+ * @drv: Device's driver
+ * @name: Name of device (e.g. device tree node name)
+ * @driver_data: The driver_data field from the driver's match table.
+ * @of_offset: Offset of device tree node for this device. This is -1 for
+ * devices which don't use device tree.
+ * @devp: if non-NULL, returns a pointer to the bound device
+ * @return 0 if OK, -ve on error
+ */
+int device_bind_with_driver_data(struct udevice *parent,
+ const struct driver *drv, const char *name,
+ ulong driver_data, int of_offset,
+ struct udevice **devp);
+
+/**
* device_bind_by_name: Create a device and bind it to a driver
*
* This is a helper function used to bind devices which do not use device
OpenPOWER on IntegriCloud