From c1d6f91952d0761f61b0f0f96e4c7aa32eee2788 Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:17 +0200
Subject: dm: core: add internal functions for getting the device without probe
This commit extends the uclass-internal functions by:
- uclass_find_first_device()
- uclass_find_next_device()
For both functions, the returned device is not probed.
After some cleanup, the above functions are called by:
- uclass_first_device()
- uclass_next_device()
for which, the returned device is probed.
Signed-off-by: Przemyslaw Marczak
Cc: Simon Glass
Acked-by: Simon Glass
---
drivers/core/uclass.c | 59 +++++++++++++++++++++++++++++----------------------
1 file changed, 34 insertions(+), 25 deletions(-)
(limited to 'drivers')
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 98c15e585df..21ab0d52452 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -156,6 +156,36 @@ int uclass_find_device(enum uclass_id id, int index, struct udevice **devp)
return -ENODEV;
}
+int uclass_find_first_device(enum uclass_id id, struct udevice **devp)
+{
+ struct uclass *uc;
+ int ret;
+
+ *devp = NULL;
+ ret = uclass_get(id, &uc);
+ if (ret)
+ return ret;
+ if (list_empty(&uc->dev_head))
+ return 0;
+
+ *devp = list_first_entry(&uc->dev_head, struct udevice, uclass_node);
+
+ return 0;
+}
+
+int uclass_find_next_device(struct udevice **devp)
+{
+ struct udevice *dev = *devp;
+
+ *devp = NULL;
+ if (list_is_last(&dev->uclass_node, &dev->uclass->dev_head))
+ return 0;
+
+ *devp = list_entry(dev->uclass_node.next, struct udevice, uclass_node);
+
+ return 0;
+}
+
int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq,
bool find_req_seq, struct udevice **devp)
{
@@ -274,24 +304,12 @@ int uclass_get_device_by_of_offset(enum uclass_id id, int node,
int uclass_first_device(enum uclass_id id, struct udevice **devp)
{
- struct uclass *uc;
struct udevice *dev;
int ret;
*devp = NULL;
- ret = uclass_get(id, &uc);
- if (ret)
- return ret;
- if (list_empty(&uc->dev_head))
- return 0;
-
- dev = list_first_entry(&uc->dev_head, struct udevice, uclass_node);
- ret = device_probe(dev);
- if (ret)
- return ret;
- *devp = dev;
-
- return 0;
+ ret = uclass_find_first_device(id, &dev);
+ return uclass_get_device_tail(dev, ret, devp);
}
int uclass_next_device(struct udevice **devp)
@@ -300,17 +318,8 @@ int uclass_next_device(struct udevice **devp)
int ret;
*devp = NULL;
- if (list_is_last(&dev->uclass_node, &dev->uclass->dev_head))
- return 0;
-
- dev = list_entry(dev->uclass_node.next, struct udevice,
- uclass_node);
- ret = device_probe(dev);
- if (ret)
- return ret;
- *devp = dev;
-
- return 0;
+ ret = uclass_find_next_device(&dev);
+ return uclass_get_device_tail(dev, ret, devp);
}
int uclass_bind_device(struct udevice *dev)
--
cgit v1.3.1
From 5eaed880282480a5a0a2b555c5f98a11252ed94e Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:18 +0200
Subject: dm: core: Extend struct udevice by '.uclass_platdata' field.
This commit adds 'uclass_platdata' field to 'struct udevice', which
can be automatically allocated at bind. The allocation size is defined
in 'struct uclass_driver' as 'per_device_platdata_auto_alloc_size'.
New device's flag is added: DM_FLAG_ALLOC_UCLASS_PDATA, which is used
for memory freeing at device unbind method.
As for other udevice's fields, a complementary function is added:
- dev_get_uclass_platdata()
Signed-off-by: Przemyslaw Marczak
Cc: Simon Glass
Acked-by: Simon Glass
---
drivers/core/device-remove.c | 4 ++++
drivers/core/device.c | 33 +++++++++++++++++++++++++++++----
include/dm/device.h | 17 ++++++++++++++++-
include/dm/uclass.h | 4 ++++
4 files changed, 53 insertions(+), 5 deletions(-)
(limited to 'drivers')
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 7fee1c001e4..6a16b4f690f 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_UCLASS_PDATA) {
+ free(dev->uclass_platdata);
+ dev->uclass_platdata = NULL;
+ }
if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
free(dev->parent_platdata);
dev->parent_platdata = NULL;
diff --git a/drivers/core/device.c b/drivers/core/device.c
index ccaa99ca63f..80eb55bb3b8 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -30,7 +30,7 @@ int device_bind(struct udevice *parent, const struct driver *drv,
{
struct udevice *dev;
struct uclass *uc;
- int ret = 0;
+ int size, ret = 0;
*devp = NULL;
if (!name)
@@ -79,9 +79,19 @@ int device_bind(struct udevice *parent, const struct driver *drv,
goto fail_alloc1;
}
}
- if (parent) {
- int size = parent->driver->per_child_platdata_auto_alloc_size;
+ size = uc->uc_drv->per_device_platdata_auto_alloc_size;
+ if (size) {
+ dev->flags |= DM_FLAG_ALLOC_UCLASS_PDATA;
+ dev->uclass_platdata = calloc(1, size);
+ if (!dev->uclass_platdata) {
+ ret = -ENOMEM;
+ goto fail_alloc2;
+ }
+ }
+
+ if (parent) {
+ size = parent->driver->per_child_platdata_auto_alloc_size;
if (!size) {
size = parent->uclass->uc_drv->
per_child_platdata_auto_alloc_size;
@@ -91,7 +101,7 @@ int device_bind(struct udevice *parent, const struct driver *drv,
dev->parent_platdata = calloc(1, size);
if (!dev->parent_platdata) {
ret = -ENOMEM;
- goto fail_alloc2;
+ goto fail_alloc3;
}
}
}
@@ -139,6 +149,11 @@ fail_uclass_bind:
free(dev->parent_platdata);
dev->parent_platdata = NULL;
}
+fail_alloc3:
+ if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
+ free(dev->uclass_platdata);
+ dev->uclass_platdata = NULL;
+ }
fail_alloc2:
if (dev->flags & DM_FLAG_ALLOC_PDATA) {
free(dev->platdata);
@@ -314,6 +329,16 @@ void *dev_get_parent_platdata(struct udevice *dev)
return dev->parent_platdata;
}
+void *dev_get_uclass_platdata(struct udevice *dev)
+{
+ if (!dev) {
+ dm_warn("%s: null device", __func__);
+ return NULL;
+ }
+
+ return dev->uclass_platdata;
+}
+
void *dev_get_priv(struct udevice *dev)
{
if (!dev) {
diff --git a/include/dm/device.h b/include/dm/device.h
index c11342c33b2..ad002feca2f 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -30,8 +30,11 @@ struct driver_info;
/* DM is responsible for allocating and freeing parent_platdata */
#define DM_FLAG_ALLOC_PARENT_PDATA (1 << 3)
+/* DM is responsible for allocating and freeing uclass_platdata */
+#define DM_FLAG_ALLOC_UCLASS_PDATA (1 << 4)
+
/* Allocate driver private data on a DMA boundary */
-#define DM_FLAG_ALLOC_PRIV_DMA (1 << 4)
+#define DM_FLAG_ALLOC_PRIV_DMA (1 << 5)
/**
* struct udevice - An instance of a driver
@@ -54,6 +57,7 @@ struct driver_info;
* @name: Name of device, typically the FDT node name
* @platdata: Configuration data for this device
* @parent_platdata: The parent bus's configuration data for this device
+ * @uclass_platdata: The uclass's configuration data for this device
* @of_offset: Device tree node offset for this device (- for none)
* @driver_data: Driver data word for the entry that matched this device with
* its driver
@@ -75,6 +79,7 @@ struct udevice {
const char *name;
void *platdata;
void *parent_platdata;
+ void *uclass_platdata;
int of_offset;
ulong driver_data;
struct udevice *parent;
@@ -209,6 +214,16 @@ void *dev_get_platdata(struct udevice *dev);
*/
void *dev_get_parent_platdata(struct udevice *dev);
+/**
+ * dev_get_uclass_platdata() - Get the uclass platform data for a device
+ *
+ * This checks that dev is not NULL, but no other checks for now
+ *
+ * @dev Device to check
+ * @return uclass's platform data, or NULL if none
+ */
+void *dev_get_uclass_platdata(struct udevice *dev);
+
/**
* dev_get_parentdata() - Get the parent data for a device
*
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index d57d8042598..b2714726183 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -65,6 +65,9 @@ struct udevice;
* @per_device_auto_alloc_size: Each device can hold private data owned
* by the uclass. If required this will be automatically allocated if this
* value is non-zero.
+ * @per_device_platdata_auto_alloc_size: Each device can hold platform data
+ * owned by the uclass as 'dev->uclass_platdata'. If the value is non-zero,
+ * then this will be automatically allocated.
* @per_child_auto_alloc_size: Each child device (of a parent in this
* uclass) can hold parent data for the device/uclass. This value is only
* used as a falback if this member is 0 in the driver.
@@ -90,6 +93,7 @@ struct uclass_driver {
int (*destroy)(struct uclass *class);
int priv_auto_alloc_size;
int per_device_auto_alloc_size;
+ int per_device_platdata_auto_alloc_size;
int per_child_auto_alloc_size;
int per_child_platdata_auto_alloc_size;
const void *ops;
--
cgit v1.3.1
From e0735a4c60577fafdaed71c5ef046f04b0f53f09 Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:22 +0200
Subject: dm: core: uclass: add function: uclass_find_device_by_name()
This commit extends the driver model uclass's API by function:
- uclass_find_device_by_name()
And this function returns the device if:
- uclass with given ID, exists,
- device with exactly given name(dev->name), exists.
The returned device is not activated - need to be probed before use.
Note:
This function returns the first device, which name is equal
to the given one. This means, that using this function you must
assume, that the device name is unique in the given uclass's ID
device list.
uclass-internal.h: cleanup - move the uclass_find_device_by_seq()
declaration and description, near the other uclass_find*() functions.
Signed-off-by: Przemyslaw Marczak
Cc: Simon Glass
Acked-by: Simon Glass
---
drivers/core/uclass.c | 24 +++++++++++++++++
include/dm/uclass-internal.h | 61 +++++++++++++++++++++++++++-----------------
2 files changed, 62 insertions(+), 23 deletions(-)
(limited to 'drivers')
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 21ab0d52452..61e96e9a427 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -186,6 +186,30 @@ int uclass_find_next_device(struct udevice **devp)
return 0;
}
+int uclass_find_device_by_name(enum uclass_id id, const char *name,
+ struct udevice **devp)
+{
+ struct uclass *uc;
+ struct udevice *dev;
+ int ret;
+
+ *devp = NULL;
+ if (!name)
+ return -EINVAL;
+ ret = uclass_get(id, &uc);
+ if (ret)
+ return ret;
+
+ list_for_each_entry(dev, &uc->dev_head, uclass_node) {
+ if (!strncmp(dev->name, name, strlen(name))) {
+ *devp = dev;
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq,
bool find_req_seq, struct udevice **devp)
{
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index befbae5a01b..d0f1e22e58c 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -45,6 +45,44 @@ int uclass_find_first_device(enum uclass_id id, struct udevice **devp);
*/
int uclass_find_next_device(struct udevice **devp);
+/**
+ * uclass_find_device_by_name() - Find uclass device based on ID and name
+ *
+ * This searches for a device with the given name.
+ *
+ * The device is NOT probed, it is merely returned.
+ *
+ * @id: ID to look up
+ * @name: name of a device to find
+ * @devp: Returns pointer to device (the first one with the name)
+ * @return 0 if OK, -ve on error
+ */
+int uclass_find_device_by_name(enum uclass_id id, const char *name,
+ struct udevice **devp);
+
+/**
+ * uclass_find_device_by_seq() - Find uclass device based on ID and sequence
+ *
+ * This searches for a device with the given seq or req_seq.
+ *
+ * For seq, if an active device has this sequence it will be returned.
+ * If there is no such device then this will return -ENODEV.
+ *
+ * For req_seq, if a device (whether activated or not) has this req_seq
+ * value, that device will be returned. This is a strong indication that
+ * the device will receive that sequence when activated.
+ *
+ * The device is NOT probed, it is merely returned.
+ *
+ * @id: ID to look up
+ * @seq_or_req_seq: Sequence number to find (0=first)
+ * @find_req_seq: true to find req_seq, false to find seq
+ * @devp: Returns pointer to device (there is only one per for each seq)
+ * @return 0 if OK, -ve on error
+ */
+int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq,
+ bool find_req_seq, struct udevice **devp);
+
/**
* uclass_bind_device() - Associate device with a uclass
*
@@ -116,27 +154,4 @@ struct uclass *uclass_find(enum uclass_id key);
*/
int uclass_destroy(struct uclass *uc);
-/**
- * uclass_find_device_by_seq() - Find uclass device based on ID and sequence
- *
- * This searches for a device with the given seq or req_seq.
- *
- * For seq, if an active device has this sequence it will be returned.
- * If there is no such device then this will return -ENODEV.
- *
- * For req_seq, if a device (whether activated or not) has this req_seq
- * value, that device will be returned. This is a strong indication that
- * the device will receive that sequence when activated.
- *
- * The device is NOT probed, it is merely returned.
- *
- * @id: ID to look up
- * @seq_or_req_seq: Sequence number to find (0=first)
- * @find_req_seq: true to find req_seq, false to find seq
- * @devp: Returns pointer to device (there is only one per for each seq)
- * @return 0 if OK, -ve on error
- */
-int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq,
- bool find_req_seq, struct udevice **devp);
-
#endif
--
cgit v1.3.1
From b7af1a2da767c0dd283ffce3d50efd36af32df14 Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:23 +0200
Subject: dm: core: uclass: add function: uclass_get_device_by_name()
This commit extends the driver model uclass's API by function:
- uclass_get_device_by_name()
And this function returns the device if:
- uclass with given ID, exists,
- device with exactly given name(dev->name), exists,
- device probe, doesn't return an error.
The returned device is activated and ready to use.
Note:
This function returns the first device, which name is equal
to the given one. This means, that using this function you must
assume, that the device name is unique in the given uclass's ID
device list.
Signed-off-by: Przemyslaw Marczak
Cc: Simon Glass
Acked-by: Simon Glass
---
drivers/core/uclass.c | 11 +++++++++++
include/dm/uclass.h | 15 +++++++++++++++
2 files changed, 26 insertions(+)
(limited to 'drivers')
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 61e96e9a427..c1ebee77f01 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -298,6 +298,17 @@ int uclass_get_device(enum uclass_id id, int index, struct udevice **devp)
return uclass_get_device_tail(dev, ret, devp);
}
+int uclass_get_device_by_name(enum uclass_id id, const char *name,
+ struct udevice **devp)
+{
+ struct udevice *dev;
+ int ret;
+
+ *devp = NULL;
+ ret = uclass_find_device_by_name(id, name, &dev);
+ return uclass_get_device_tail(dev, ret, devp);
+}
+
int uclass_get_device_by_seq(enum uclass_id id, int seq, struct udevice **devp)
{
struct udevice *dev;
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index b2714726183..66e0ea509c9 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -129,6 +129,21 @@ int uclass_get(enum uclass_id key, struct uclass **ucp);
*/
int uclass_get_device(enum uclass_id id, int index, struct udevice **devp);
+/**
+ * uclass_get_device_by_name() - Get a uclass device by it's name
+ *
+ * This searches the devices in the uclass for one with the given name.
+ *
+ * The device is probed to activate it ready for use.
+ *
+ * @id: ID to look up
+ * @name: name of a device to get
+ * @devp: Returns pointer to device (the first one with the name)
+ * @return 0 if OK, -ve on error
+ */
+int uclass_get_device_by_name(enum uclass_id id, const char *name,
+ struct udevice **devp);
+
/**
* uclass_get_device_by_seq() - Get a uclass device based on an ID and sequence
*
--
cgit v1.3.1
From cc73d37b7f1edbbf03e2abcf5815bdd122e8baed Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:24 +0200
Subject: dm: core: device: add function: dev_get_driver_ops()
This commit extends the driver model device's API by function:
- dev_get_driver_ops()
And this function returns the device's driver's operations if given:
- dev pointer, is non-NULL
- dev->driver->ops pointer, is non-NULL
in other case the, the NULL pointer is returned.
Signed-off-by: Przemyslaw Marczak
Cc: Simon Glass
Acked-by: Simon Glass
---
drivers/core/device.c | 8 ++++++++
include/dm/device.h | 11 +++++++++++
2 files changed, 19 insertions(+)
(limited to 'drivers')
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 80eb55bb3b8..d024abbd417 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -499,6 +499,14 @@ ulong dev_get_driver_data(struct udevice *dev)
return dev->driver_data;
}
+const void *dev_get_driver_ops(struct udevice *dev)
+{
+ if (!dev || !dev->driver->ops)
+ return NULL;
+
+ return dev->driver->ops;
+}
+
enum uclass_id device_get_uclass_id(struct udevice *dev)
{
return dev->uclass->uc_drv->id;
diff --git a/include/dm/device.h b/include/dm/device.h
index ad002feca2f..049cb2f5e2d 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -280,6 +280,17 @@ void *dev_get_uclass_priv(struct udevice *dev);
*/
ulong dev_get_driver_data(struct udevice *dev);
+/**
+ * dev_get_driver_ops() - get the device's driver's operations
+ *
+ * This checks that dev is not NULL, and returns the pointer to device's
+ * driver's operations.
+ *
+ * @dev: Device to check
+ * @return void pointer to driver's operations or NULL for NULL-dev or NULL-ops
+ */
+const void *dev_get_driver_ops(struct udevice *dev);
+
/*
* device_get_uclass_id() - return the uclass ID of a device
*
--
cgit v1.3.1
From f9c370dcdf056f035f18bf77db8a706cea21f9ce Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:25 +0200
Subject: dm: core: device: add function: dev_get_uclass_name()
This commit extends the driver model device's API by function:
- dev_get_uclass_name()
And this function returns the device's uclass driver name if:
- given dev pointer, is non_NULL
otherwise, the NULL pointer is returned.
Signed-off-by: Przemyslaw Marczak
Cc: Simon Glass
Acked-by: Simon Glass
---
drivers/core/device.c | 8 ++++++++
include/dm/device.h | 10 ++++++++++
2 files changed, 18 insertions(+)
(limited to 'drivers')
diff --git a/drivers/core/device.c b/drivers/core/device.c
index d024abbd417..df81b8e63d2 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -512,6 +512,14 @@ enum uclass_id device_get_uclass_id(struct udevice *dev)
return dev->uclass->uc_drv->id;
}
+const char *dev_get_uclass_name(struct udevice *dev)
+{
+ if (!dev)
+ return NULL;
+
+ return dev->uclass->uc_drv->name;
+}
+
#ifdef CONFIG_OF_CONTROL
fdt_addr_t dev_get_addr(struct udevice *dev)
{
diff --git a/include/dm/device.h b/include/dm/device.h
index 049cb2f5e2d..18296bb6861 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -299,6 +299,16 @@ const void *dev_get_driver_ops(struct udevice *dev);
*/
enum uclass_id device_get_uclass_id(struct udevice *dev);
+/*
+ * dev_get_uclass_name() - return the uclass name of a device
+ *
+ * This checks that dev is not NULL.
+ *
+ * @dev: Device to check
+ * @return pointer to the uclass name for the device
+ */
+const char *dev_get_uclass_name(struct udevice *dev);
+
/**
* device_get_child() - Get the child of a device by index
*
--
cgit v1.3.1
From 794d521917eab07651248174a81ba51cd265d9dc Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Mon, 20 Apr 2015 13:32:32 +0200
Subject: dm: core: remove type 'static' of function uclass_get_device_tail()
Uclass API provides a few functions for get/find the device.
To provide a complete function set of uclass-internal functions,
for use by the drivers, the function uclass_get_device_tail()
should be non-static.
Signed-off-by: Przemyslaw Marczak
Cc: Simon Glass
Acked-by: Simon Glass
---
drivers/core/uclass.c | 12 +-----------
include/dm/uclass-internal.h | 21 ++++++++++++++++++---
2 files changed, 19 insertions(+), 14 deletions(-)
(limited to 'drivers')
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index c1ebee77f01..7627ad141b5 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -263,17 +263,7 @@ static int uclass_find_device_by_of_offset(enum uclass_id id, int node,
return -ENODEV;
}
-/**
- * uclass_get_device_tail() - handle the end of a get_device call
- *
- * This handles returning an error or probing a device as needed.
- *
- * @dev: Device that needs to be probed
- * @ret: Error to return. If non-zero then the device is not probed
- * @devp: Returns the value of 'dev' if there is no error
- * @return ret, if non-zero, else the result of the device_probe() call
- */
-static int uclass_get_device_tail(struct udevice *dev, int ret,
+int uclass_get_device_tail(struct udevice *dev, int ret,
struct udevice **devp)
{
if (ret)
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index d0f1e22e58c..153f2a7626f 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -10,13 +10,26 @@
#ifndef _DM_UCLASS_INTERNAL_H
#define _DM_UCLASS_INTERNAL_H
+/**
+ * uclass_get_device_tail() - handle the end of a get_device call
+ *
+ * This handles returning an error or probing a device as needed.
+ *
+ * @dev: Device that needs to be probed
+ * @ret: Error to return. If non-zero then the device is not probed
+ * @devp: Returns the value of 'dev' if there is no error
+ * @return ret, if non-zero, else the result of the device_probe() call
+ */
+int uclass_get_device_tail(struct udevice *dev, int ret, struct udevice **devp);
+
/**
* uclass_find_device() - Return n-th child of uclass
* @id: Id number of the uclass
* @index: Position of the child in uclass's list
* #devp: Returns pointer to device, or NULL on error
*
- * The device is not prepared for use - this is an internal function
+ * The device is not prepared for use - this is an internal function.
+ * The function uclass_get_device_tail() can be used to probe the device.
*
* @return the uclass pointer of a child at the given index or
* return NULL on error.
@@ -28,7 +41,8 @@ int uclass_find_device(enum uclass_id id, int index, struct udevice **devp);
* @id: Id number of the uclass
* #devp: Returns pointer to device, or NULL on error
*
- * The device is not prepared for use - this is an internal function
+ * The device is not prepared for use - this is an internal function.
+ * The function uclass_get_device_tail() can be used to probe the device.
*
* @return 0 if OK (found or not found), -1 on error
*/
@@ -39,7 +53,8 @@ int uclass_find_first_device(enum uclass_id id, struct udevice **devp);
* @devp: On entry, pointer to device to lookup. On exit, returns pointer
* to the next device in the same uclass, or NULL if none
*
- * The device is not prepared for use - this is an internal function
+ * The device is not prepared for use - this is an internal function.
+ * The function uclass_get_device_tail() can be used to probe the device.
*
* @return 0 if OK (found or not found), -1 on error
*/
--
cgit v1.3.1
From 07d260e047680971d926bc9a573f9291f39fc988 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Sun, 19 Apr 2015 07:20:58 -0600
Subject: dm: core: Handle recursive unbinding of uclass devices
Since a device can have children in the same uclass as itself, we need
to handle unbinding carefully: we must allow that unbinding a device in a
uclass may cause another device in the same uclass to be unbound.
Adjust the code to cope.
Signed-off-by: Simon Glass
Reviewed-by: Joe Hershberger
Tested-by: Joe Hershberger
---
drivers/core/uclass.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
(limited to 'drivers')
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 7627ad141b5..9fec8c9c7ad 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -99,10 +99,18 @@ fail_mem:
int uclass_destroy(struct uclass *uc)
{
struct uclass_driver *uc_drv;
- struct udevice *dev, *tmp;
+ struct udevice *dev;
int ret;
- list_for_each_entry_safe(dev, tmp, &uc->dev_head, uclass_node) {
+ /*
+ * We cannot use list_for_each_entry_safe() here. If a device in this
+ * uclass has a child device also in this uclass, it will be also be
+ * unbound (by the recursion in the call to device_unbind() below).
+ * We can loop until the list is empty.
+ */
+ while (!list_empty(&uc->dev_head)) {
+ dev = list_first_entry(&uc->dev_head, struct udevice,
+ uclass_node);
ret = device_remove(dev);
if (ret)
return ret;
--
cgit v1.3.1
From 093f2dce443296ab05b1b9a356a9153d5621791b Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Sun, 19 Apr 2015 07:20:59 -0600
Subject: dm: usb: Add a terminator to the string destructor list
The terminator is missing. Add it for completeness.
Signed-off-by: Simon Glass
Reviewed-by: Joe Hershberger
Tested-by: Joe Hershberger
---
drivers/usb/emul/sandbox_hub.c | 1 +
1 file changed, 1 insertion(+)
(limited to 'drivers')
diff --git a/drivers/usb/emul/sandbox_hub.c b/drivers/usb/emul/sandbox_hub.c
index 280c7080f2a..baf8bdc857b 100644
--- a/drivers/usb/emul/sandbox_hub.c
+++ b/drivers/usb/emul/sandbox_hub.c
@@ -32,6 +32,7 @@ static struct usb_string hub_strings[] = {
{STRING_MANUFACTURER, "sandbox"},
{STRING_PRODUCT, "hub"},
{STRING_SERIAL, "2345"},
+ {},
};
static struct usb_device_descriptor hub_device_desc = {
--
cgit v1.3.1
From dd0b0122bacc286a6c9321178fcdd947a8bbf0a8 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:25 -0700
Subject: serial: ns16550: Add an option to specify the debug UART register
shift
This UART permits different register spacing. To support the debug UART on
devices which have a spacing other than 1 byte, allow the shift value to
be specified.
Signed-off-by: Simon Glass
---
drivers/serial/Kconfig | 10 ++++++++++
drivers/serial/ns16550.c | 25 +++++++++++++++----------
2 files changed, 25 insertions(+), 10 deletions(-)
(limited to 'drivers')
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 1686a1f951e..54e6f26d38d 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -66,6 +66,16 @@ config DEBUG_UART_CLOCK
A default should be provided by your board, but if not you will need
to use the correct value here.
+config DEBUG_UART_SHIFT
+ int "UART register shift"
+ depends on DEBUG_UART
+ default 0 if DEBUG_UART
+ help
+ Some UARTs (notably ns16550) support different register layouts
+ where the registers are spaced either as bytes, words or some other
+ value. Use this value to specify the shift to use, where 0=byte
+ registers, 2=32-bit word registers, etc.
+
config UNIPHIER_SERIAL
bool "UniPhier on-chip UART support"
depends on ARCH_UNIPHIER && DM_SERIAL
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 67b1d60171a..362f2ee8796 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -254,15 +254,20 @@ void debug_uart_init(void)
*/
baud_divisor = calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
CONFIG_BAUDRATE);
-
- serial_out_shift(&com_port->ier, 0, CONFIG_SYS_NS16550_IER);
- serial_out_shift(&com_port->mcr, 0, UART_MCRVAL);
- serial_out_shift(&com_port->fcr, 0, UART_FCRVAL);
-
- serial_out_shift(&com_port->lcr, 0, UART_LCR_BKSE | UART_LCRVAL);
- serial_out_shift(&com_port->dll, 0, baud_divisor & 0xff);
- serial_out_shift(&com_port->dlm, 0, (baud_divisor >> 8) & 0xff);
- serial_out_shift(&com_port->lcr, 0, UART_LCRVAL);
+ baud_divisor = 13;
+ serial_out_shift(&com_port->ier, CONFIG_DEBUG_UART_SHIFT,
+ CONFIG_SYS_NS16550_IER);
+ serial_out_shift(&com_port->mcr, CONFIG_DEBUG_UART_SHIFT, UART_MCRVAL);
+ serial_out_shift(&com_port->fcr, CONFIG_DEBUG_UART_SHIFT, UART_FCRVAL);
+
+ serial_out_shift(&com_port->lcr, CONFIG_DEBUG_UART_SHIFT,
+ UART_LCR_BKSE | UART_LCRVAL);
+ serial_out_shift(&com_port->dll, CONFIG_DEBUG_UART_SHIFT,
+ baud_divisor & 0xff);
+ serial_out_shift(&com_port->dlm, CONFIG_DEBUG_UART_SHIFT,
+ (baud_divisor >> 8) & 0xff);
+ serial_out_shift(&com_port->lcr, CONFIG_DEBUG_UART_SHIFT,
+ UART_LCRVAL);
}
static inline void _debug_uart_putc(int ch)
@@ -271,7 +276,7 @@ static inline void _debug_uart_putc(int ch)
while (!(serial_in_shift(&com_port->lsr, 0) & UART_LSR_THRE))
;
- serial_out_shift(&com_port->thr, 0, ch);
+ serial_out_shift(&com_port->thr, CONFIG_DEBUG_UART_SHIFT, ch);
}
DEBUG_UART_FUNCS
--
cgit v1.3.1
From 363e6da10313edb9ab7bffd8ee9000f72af11290 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:26 -0700
Subject: dm: ns16550: Support non-byte register spacing with driver model
Allow this driver to support boards where the register shift is not 0.
This fixes some compiler warnings which appear in that case.
Signed-off-by: Simon Glass
---
drivers/serial/ns16550.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
(limited to 'drivers')
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 362f2ee8796..61312995fb8 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -57,7 +57,7 @@ DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_DM_SERIAL
-static inline void serial_out_shift(unsigned char *addr, int shift, int value)
+static inline void serial_out_shift(void *addr, int shift, int value)
{
#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
outb(value, (ulong)addr);
@@ -72,7 +72,7 @@ static inline void serial_out_shift(unsigned char *addr, int shift, int value)
#endif
}
-static inline int serial_in_shift(unsigned char *addr, int shift)
+static inline int serial_in_shift(void *addr, int shift)
{
#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
return inb((ulong)addr);
@@ -114,9 +114,11 @@ static int ns16550_readb(NS16550_t port, int offset)
/* We can clean these up once everything is moved to driver model */
#define serial_out(value, addr) \
- ns16550_writeb(com_port, addr - (unsigned char *)com_port, value)
+ ns16550_writeb(com_port, \
+ (unsigned char *)addr - (unsigned char *)com_port, value)
#define serial_in(addr) \
- ns16550_readb(com_port, addr - (unsigned char *)com_port)
+ ns16550_readb(com_port, \
+ (unsigned char *)addr - (unsigned char *)com_port)
#endif
static inline int calc_divisor(NS16550_t port, int clock, int baudrate)
--
cgit v1.3.1
From ab9fd2e83a0f781534fbb8a2b88c724a29b7f20a Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:28 -0700
Subject: serial: ns16550: Remove unnecessary init on UART setup
It is not necessary to write a zero baud rate to the device, and for some
chips this will cause problems. Drop this code.
Signed-off-by: Simon Glass
---
drivers/serial/ns16550.c | 1 -
1 file changed, 1 deletion(-)
(limited to 'drivers')
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 61312995fb8..fd110b3ddcd 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -175,7 +175,6 @@ void NS16550_init(NS16550_t com_port, int baud_divisor)
defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX)
serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/
#endif
- NS16550_setbrg(com_port, 0);
serial_out(UART_MCRVAL, &com_port->mcr);
serial_out(UART_FCRVAL, &com_port->fcr);
if (baud_divisor != -1)
--
cgit v1.3.1
From 36fa61dc612e363fb60840a06333fc37ec3fb68e Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:30 -0700
Subject: dm: core: Allow sequence alias support to be removed for SPL
In many cases SPL only uses a single serial port and there is no need for
alias sequence support. We will just use the serial port pointed to by
stdout-path in the /chosen node.
Signed-off-by: Simon Glass
---
drivers/core/Kconfig | 9 +++++++++
drivers/core/device.c | 28 +++++++++++++++-------------
include/config_uncmd_spl.h | 1 +
3 files changed, 25 insertions(+), 13 deletions(-)
(limited to 'drivers')
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 75d182d27f7..2861b430795 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -46,3 +46,12 @@ config DM_STDIO
Normally serial drivers register with stdio so that they can be used
as normal output devices. In SPL we don't normally use stdio, so
we can omit this feature.
+
+config DM_SEQ_ALIAS
+ bool "Support numbered aliases in device tree"
+ depends on DM
+ default y
+ help
+ Most boards will have a '/aliases' node containing the path to
+ numbered devices (e.g. serial0 = &serial0). This feature can be
+ disabled if it is not required, to save code space in SPL.
diff --git a/drivers/core/device.c b/drivers/core/device.c
index df81b8e63d2..7f24243fd7f 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -56,21 +56,23 @@ int device_bind(struct udevice *parent, const struct driver *drv,
dev->seq = -1;
dev->req_seq = -1;
-#ifdef CONFIG_OF_CONTROL
- /*
- * Some devices, such as a SPI bus, I2C bus and serial ports are
- * numbered using aliases.
- *
- * This is just a 'requested' sequence, and will be
- * resolved (and ->seq updated) when the device is probed.
- */
- if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
- if (uc->uc_drv->name && of_offset != -1) {
- fdtdec_get_alias_seq(gd->fdt_blob, uc->uc_drv->name,
- of_offset, &dev->req_seq);
+ if (IS_ENABLED(CONFIG_OF_CONTROL) && IS_ENABLED(CONFIG_DM_SEQ_ALIAS)) {
+ /*
+ * Some devices, such as a SPI bus, I2C bus and serial ports
+ * are numbered using aliases.
+ *
+ * This is just a 'requested' sequence, and will be
+ * resolved (and ->seq updated) when the device is probed.
+ */
+ if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
+ if (uc->uc_drv->name && of_offset != -1) {
+ fdtdec_get_alias_seq(gd->fdt_blob,
+ uc->uc_drv->name, of_offset,
+ &dev->req_seq);
+ }
}
}
-#endif
+
if (!dev->platdata && drv->platdata_auto_alloc_size) {
dev->flags |= DM_FLAG_ALLOC_PDATA;
dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
diff --git a/include/config_uncmd_spl.h b/include/config_uncmd_spl.h
index a9106f4f3b7..38cb0e8abac 100644
--- a/include/config_uncmd_spl.h
+++ b/include/config_uncmd_spl.h
@@ -31,6 +31,7 @@
#undef CONFIG_DM_WARN
#undef CONFIG_DM_DEVICE_REMOVE
+#undef CONFIG_DM_SEQ_ALIAS
#undef CONFIG_DM_STDIO
#endif /* CONFIG_SPL_BUILD */
--
cgit v1.3.1
From 7f9875e733b79556ade508b88f88ac1f8a2c7e3c Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:31 -0700
Subject: dm: core: Remove unbind operations when not required
The CONFIG_DM_DEVICE_REMOVE option takes out code related to removing
devices. It should also remove the 'unbind' code since if we cannot
remove we probably don't need to unbind.
Signed-off-by: Simon Glass
---
drivers/core/uclass.c | 4 ++++
include/dm/uclass-internal.h | 8 ++++++++
2 files changed, 12 insertions(+)
(limited to 'drivers')
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 9fec8c9c7ad..04e939d6c13 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -386,6 +386,7 @@ err:
return ret;
}
+#ifdef CONFIG_DM_DEVICE_REMOVE
int uclass_unbind_device(struct udevice *dev)
{
struct uclass *uc;
@@ -401,6 +402,7 @@ int uclass_unbind_device(struct udevice *dev)
list_del(&dev->uclass_node);
return 0;
}
+#endif
int uclass_resolve_seq(struct udevice *dev)
{
@@ -464,6 +466,7 @@ int uclass_post_probe_device(struct udevice *dev)
return 0;
}
+#ifdef CONFIG_DM_DEVICE_REMOVE
int uclass_pre_remove_device(struct udevice *dev)
{
struct uclass_driver *uc_drv;
@@ -485,3 +488,4 @@ int uclass_pre_remove_device(struct udevice *dev)
return 0;
}
+#endif
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index a9b2fbe2c65..9b685086671 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -116,7 +116,11 @@ int uclass_bind_device(struct udevice *dev);
* @dev: Pointer to the device
* #return 0 on success, -ve on error
*/
+#ifdef CONFIG_DM_DEVICE_REMOVE
int uclass_unbind_device(struct udevice *dev);
+#else
+static inline int uclass_unbind_device(struct udevice *dev) { return 0; }
+#endif
/**
* uclass_pre_probe_device() - Deal with a device that is about to be probed
@@ -149,7 +153,11 @@ int uclass_post_probe_device(struct udevice *dev);
* @dev: Pointer to the device
* #return 0 on success, -ve on error
*/
+#ifdef CONFIG_DM_DEVICE_REMOVE
int uclass_pre_remove_device(struct udevice *dev);
+#else
+static inline int uclass_pre_remove_device(struct udevice *dev) { return 0; }
+#endif
/**
* uclass_find() - Find uclass by its id
--
cgit v1.3.1
From 66312374dca86e77fc9b08f774546e62b6cd1aa7 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:32 -0700
Subject: dm: Add a panic_str() function to reduce code size
The printf() in panic() adds about 1.5KB of code size to SPL when compiled
with Thumb-2. Provide a smaller version that does not support printf()-style
arguments and use it in two commonly compiled places.
Signed-off-by: Simon Glass
---
drivers/serial/serial-uclass.c | 2 +-
include/vsprintf.h | 23 +++++++++++++++++++++++
lib/fdtdec.c | 8 +++++---
lib/vsprintf.c | 23 ++++++++++++++++++-----
4 files changed, 47 insertions(+), 9 deletions(-)
(limited to 'drivers')
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index b239691efe9..b8c2f482288 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -70,7 +70,7 @@ static void serial_find_console_or_panic(void)
if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) &&
uclass_get_device(UCLASS_SERIAL, INDEX, &dev) &&
(uclass_first_device(UCLASS_SERIAL, &dev) || !dev))
- panic("No serial driver found");
+ panic_str("No serial driver found");
#undef INDEX
gd->cur_serial_dev = dev;
}
diff --git a/include/vsprintf.h b/include/vsprintf.h
index 5624482d573..09c8abd951d 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -39,9 +39,32 @@ int strict_strtoul(const char *cp, unsigned int base, unsigned long *res);
unsigned long long simple_strtoull(const char *cp, char **endp,
unsigned int base);
long simple_strtol(const char *cp, char **endp, unsigned int base);
+
+/**
+ * panic() - Print a message and reset/hang
+ *
+ * Prints a message on the console(s) and then resets. If CONFIG_PANIC_HANG is
+ * defined, then it will hang instead of reseting.
+ *
+ * @param fmt: printf() format string for message, which should not include
+ * \n, followed by arguments
+ */
void panic(const char *fmt, ...)
__attribute__ ((format (__printf__, 1, 2), noreturn));
+/**
+ * panic_str() - Print a message and reset/hang
+ *
+ * Prints a message on the console(s) and then resets. If CONFIG_PANIC_HANG is
+ * defined, then it will hang instead of reseting.
+ *
+ * This function can be used instead of panic() when your board does not
+ * already use printf(), * to keep code size small.
+ *
+ * @param fmt: string to display, which should not include \n
+ */
+void panic_str(const char *str) __attribute__ ((noreturn));
+
/**
* Format a string and place it in a buffer
*
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 331eae2ce1e..577c60ed0d9 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -565,9 +565,11 @@ int fdtdec_prepare_fdt(void)
{
if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) ||
fdt_check_header(gd->fdt_blob)) {
- printf("No valid FDT found - please append one to U-Boot "
- "binary, use u-boot-dtb.bin or define "
- "CONFIG_OF_EMBED. For sandbox, use -d \n");
+#ifdef CONFIG_SPL_BUILD
+ puts("Missing DTB\n");
+#else
+ puts("No valid device tree binary found - please append one to U-Boot binary, use u-boot-dtb.bin or define CONFIG_OF_EMBED. For sandbox, use -d \n");
+#endif
return -1;
}
return 0;
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index e0f264850f7..bedc865240d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -842,13 +842,11 @@ int sprintf(char *buf, const char *fmt, ...)
return i;
}
-void panic(const char *fmt, ...)
+static void panic_finish(void) __attribute__ ((noreturn));
+
+static void panic_finish(void)
{
- va_list args;
- va_start(args, fmt);
- vprintf(fmt, args);
putc('\n');
- va_end(args);
#if defined(CONFIG_PANIC_HANG)
hang();
#else
@@ -859,6 +857,21 @@ void panic(const char *fmt, ...)
;
}
+void panic_str(const char *str)
+{
+ puts(str);
+ panic_finish();
+}
+
+void panic(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ panic_finish();
+}
+
void __assert_fail(const char *assertion, const char *file, unsigned line,
const char *function)
{
--
cgit v1.3.1
From 5a87c4174d18fe40dcc847ba36853a9f15cb3e1e Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:33 -0700
Subject: dm: core: Drop device removal error path when not supported
When CONFIG_DM_DEVICE_REMOVE is not enabled, such as in SPL, we cannot
remove or unbind devices and do not expect to get errors when binding
and probing devices. So drop the error path to reduce code size.
Signed-off-by: Simon Glass
---
drivers/core/device.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
(limited to 'drivers')
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 7f24243fd7f..3b77d231d34 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -135,21 +135,27 @@ int device_bind(struct udevice *parent, const struct driver *drv,
return 0;
fail_child_post_bind:
- if (drv->unbind && drv->unbind(dev)) {
- dm_warn("unbind() method failed on dev '%s' on error path\n",
- dev->name);
+ if (IS_ENABLED(DM_DEVICE_REMOVE)) {
+ if (drv->unbind && drv->unbind(dev)) {
+ dm_warn("unbind() method failed on dev '%s' on error path\n",
+ dev->name);
+ }
}
fail_bind:
- if (uclass_unbind_device(dev)) {
- dm_warn("Failed to unbind dev '%s' on error path\n",
- dev->name);
+ if (IS_ENABLED(DM_DEVICE_REMOVE)) {
+ if (uclass_unbind_device(dev)) {
+ dm_warn("Failed to unbind dev '%s' on error path\n",
+ dev->name);
+ }
}
fail_uclass_bind:
- list_del(&dev->sibling_node);
- if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
- free(dev->parent_platdata);
- dev->parent_platdata = NULL;
+ if (IS_ENABLED(DM_DEVICE_REMOVE)) {
+ list_del(&dev->sibling_node);
+ if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
+ free(dev->parent_platdata);
+ dev->parent_platdata = NULL;
+ }
}
fail_alloc3:
if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
--
cgit v1.3.1
From b2b0d3e7129d4e59be1a016ad4fb05db87b8c5b4 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:41 -0700
Subject: dm: core: Select device tree control correctly for SPL
Some boards will not use device tree for SPL even with driver model. Add
the logic to support this.
Signed-off-by: Simon Glass
---
drivers/core/root.c | 14 ++++++++------
include/fdtdec.h | 10 ++++++++++
2 files changed, 18 insertions(+), 6 deletions(-)
(limited to 'drivers')
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 9b5c6bb10cb..12d046051fd 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -197,13 +197,15 @@ int dm_init_and_scan(bool pre_reloc_only)
debug("dm_scan_platdata() failed: %d\n", ret);
return ret;
}
-#ifdef CONFIG_OF_CONTROL
- ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
- if (ret) {
- debug("dm_scan_fdt() failed: %d\n", ret);
- return ret;
+
+ if (OF_CONTROL) {
+ ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
+ if (ret) {
+ debug("dm_scan_fdt() failed: %d\n", ret);
+ return ret;
+ }
}
-#endif
+
ret = dm_scan_other(pre_reloc_only);
if (ret)
return ret;
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 0d3e6d9711d..659047097a1 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -41,6 +41,16 @@ struct fdt_memory {
fdt_addr_t end;
};
+#ifdef CONFIG_OF_CONTROL
+# if defined(CONFIG_SPL_BUILD) && defined(SPL_DISABLE_OF_CONTROL)
+# define OF_CONTROL 0
+# else
+# define OF_CONTROL 1
+# endif
+#else
+# define OF_CONTROL 0
+#endif
+
/*
* Information about a resource. start is the first address of the resource
* and end is the last address (inclusive). The length of the resource will
--
cgit v1.3.1