dm: allow setting driver_data before/during bind

This will allow a driver's bind function to use the driver data. One
example is the Tegra186 GPIO driver, which instantiates child devices
for each of its GPIO ports, yet supports two different HW instances each
with a different set of ports, and identified by the udevice_id .data
field.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Simon Glass <sjg@chromium.org>
master
Stephen Warren 8 years ago committed by Simon Glass
parent 6523dbf7cc
commit daac3bfee5
  1. 23
      doc/driver-model/README.txt
  2. 25
      drivers/core/device.c
  3. 4
      drivers/core/lists.c
  4. 24
      include/dm/device-internal.h

@ -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

@ -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)
{

@ -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;

@ -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

Loading…
Cancel
Save