summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2015-01-25 08:27:01 -0700
committerSimon Glass <sjg@chromium.org>2015-01-29 17:09:54 -0700
commitcdc133bde9dd221319b9cf7fd99fcb4da8ba195c (patch)
treedaef0d65d0107aa4b93d3611f217947a6cf502e8 /drivers
parentf8a85449ef3e0963add728815771ccc09aa99875 (diff)
downloadu-boot-imx-cdc133bde9dd221319b9cf7fd99fcb4da8ba195c.zip
u-boot-imx-cdc133bde9dd221319b9cf7fd99fcb4da8ba195c.tar.gz
u-boot-imx-cdc133bde9dd221319b9cf7fd99fcb4da8ba195c.tar.bz2
dm: core: Allow parents to have platform data for their children
For buses it is common for parents to need to know the address of the child on the bus, the bus speed to use for that child, and other information. This can be provided in platform data attached to each child. Add driver model support for this, including auto-allocation which can be requested using a new property to specify the size of the data. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/core/device-remove.c4
-rw-r--r--drivers/core/device.c30
2 files changed, 32 insertions, 2 deletions
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 2c82577..56c358a 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -92,6 +92,10 @@ int device_unbind(struct udevice *dev)
free(dev->platdata);
dev->platdata = NULL;
}
+ if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
+ free(dev->parent_platdata);
+ dev->parent_platdata = NULL;
+ }
ret = uclass_unbind_device(dev);
if (ret)
return ret;
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 366cffe..ee97cc8 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -80,6 +80,18 @@ int device_bind(struct udevice *parent, struct driver *drv, const char *name,
goto fail_alloc1;
}
}
+ if (parent) {
+ int size = parent->driver->per_child_platdata_auto_alloc_size;
+
+ if (size) {
+ dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
+ dev->parent_platdata = calloc(1, size);
+ if (!dev->parent_platdata) {
+ ret = -ENOMEM;
+ goto fail_alloc2;
+ }
+ }
+ }
/* put dev into parent's successor list */
if (parent)
@@ -107,8 +119,12 @@ fail_bind:
dev->name);
}
fail_uclass_bind:
- if (parent)
- list_del(&dev->sibling_node);
+ list_del(&dev->sibling_node);
+ if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
+ free(dev->parent_platdata);
+ dev->parent_platdata = NULL;
+ }
+fail_alloc2:
if (dev->flags & DM_FLAG_ALLOC_PDATA) {
free(dev->platdata);
dev->platdata = NULL;
@@ -247,6 +263,16 @@ void *dev_get_platdata(struct udevice *dev)
return dev->platdata;
}
+void *dev_get_parent_platdata(struct udevice *dev)
+{
+ if (!dev) {
+ dm_warn("%s: null device", __func__);
+ return NULL;
+ }
+
+ return dev->parent_platdata;
+}
+
void *dev_get_priv(struct udevice *dev)
{
if (!dev) {