From c1d6f91952d0761f61b0f0f96e4c7aa32eee2788 Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:17 +0200
Subject: [PATCH 01/31] 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 +++++++++++++++++++++++++-------------------
include/dm/uclass-internal.h | 22 +++++++++++++++++
2 files changed, 56 insertions(+), 25 deletions(-)
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 98c15e5..21ab0d5 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)
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index ae2a93d..befbae5 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -24,6 +24,28 @@
int uclass_find_device(enum uclass_id id, int index, struct udevice **devp);
/**
+ * uclass_find_first_device() - Return the first device in a uclass
+ * @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
+ *
+ * @return 0 if OK (found or not found), -1 on error
+ */
+int uclass_find_first_device(enum uclass_id id, struct udevice **devp);
+
+/**
+ * uclass_find_next_device() - Return the next device in a uclass
+ * @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
+ *
+ * @return 0 if OK (found or not found), -1 on error
+ */
+int uclass_find_next_device(struct udevice **devp);
+
+/**
* uclass_bind_device() - Associate device with a uclass
*
* Connect the device into uclass's list of devices.
From 5eaed880282480a5a0a2b555c5f98a11252ed94e Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:18 +0200
Subject: [PATCH 02/31] 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(-)
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 7fee1c0..6a16b4f 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 ccaa99c..80eb55b 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 c11342c..ad002fe 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;
@@ -210,6 +215,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
*
* The parent data is data stored in the device but owned by the parent.
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index d57d804..b271472 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;
From 754e71e850cb09d53543846fbed74cc5a1491c76 Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:19 +0200
Subject: [PATCH 03/31] dm: test: Add tests for device's uclass platform data
This test introduces new test structure type:dm_test_perdev_uc_pdata.
The structure consists of three int values only. For the test purposes,
three pattern values are defined by enum, starting with TEST_UC_PDATA_INTVAL1.
This commit adds two test cases for uclass platform data:
- Test: dm_test_autobind_uclass_pdata_alloc - this tests if:
* uclass driver sets: .per_device_platdata_auto_alloc_size field
* the devices's: dev->uclass_platdata is non-NULL
- Test: dm_test_autobind_uclass_pdata_valid - this tests:
* if the devices's: dev->uclass_platdata is non-NULL
* the structure of type 'dm_test_perdev_uc_pdata' allocated at address
pointed by dev->uclass_platdata. Each structure field, should be equal
to proper pattern data, starting from .intval1 == TEST_UC_PDATA_INTVAL1.
Signed-off-by: Przemyslaw Marczak
Cc: Simon Glass
Acked-by: Simon Glass
---
include/dm/test.h | 20 +++++++++++++++++++
test/dm/core.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++
test/dm/test-uclass.c | 11 +++++++++++
3 files changed, 86 insertions(+)
diff --git a/include/dm/test.h b/include/dm/test.h
index 9c4b8d3..f03fbcb 100644
--- a/include/dm/test.h
+++ b/include/dm/test.h
@@ -98,6 +98,26 @@ struct dm_test_parent_data {
int flag;
};
+/* Test values for test device's uclass platform data */
+enum {
+ TEST_UC_PDATA_INTVAL1 = 2,
+ TEST_UC_PDATA_INTVAL2 = 334,
+ TEST_UC_PDATA_INTVAL3 = 789452,
+};
+
+/**
+ * struct dm_test_uclass_platda - uclass's information on each device
+ *
+ * @intval1: set to TEST_UC_PDATA_INTVAL1 in .post_bind method of test uclass
+ * @intval2: set to TEST_UC_PDATA_INTVAL2 in .post_bind method of test uclass
+ * @intval3: set to TEST_UC_PDATA_INTVAL3 in .post_bind method of test uclass
+ */
+struct dm_test_perdev_uc_pdata {
+ int intval1;
+ int intval2;
+ int intval3;
+};
+
/*
* Operation counts for the test driver, used to check that each method is
* called correctly
diff --git a/test/dm/core.c b/test/dm/core.c
index 990d390..009ad36 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -129,6 +129,61 @@ static int dm_test_autobind(struct dm_test_state *dms)
}
DM_TEST(dm_test_autobind, 0);
+/* Test that binding with uclass platdata allocation occurs correctly */
+static int dm_test_autobind_uclass_pdata_alloc(struct dm_test_state *dms)
+{
+ struct dm_test_perdev_uc_pdata *uc_pdata;
+ struct udevice *dev;
+ struct uclass *uc;
+
+ ut_assertok(uclass_get(UCLASS_TEST, &uc));
+ ut_assert(uc);
+
+ /**
+ * Test if test uclass driver requires allocation for the uclass
+ * platform data and then check the dev->uclass_platdata pointer.
+ */
+ ut_assert(uc->uc_drv->per_device_platdata_auto_alloc_size);
+
+ for (uclass_find_first_device(UCLASS_TEST, &dev);
+ dev;
+ uclass_find_next_device(&dev)) {
+ ut_assert(dev);
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+ ut_assert(uc_pdata);
+ }
+
+ return 0;
+}
+DM_TEST(dm_test_autobind_uclass_pdata_alloc, DM_TESTF_SCAN_PDATA);
+
+/* Test that binding with uclass platdata setting occurs correctly */
+static int dm_test_autobind_uclass_pdata_valid(struct dm_test_state *dms)
+{
+ struct dm_test_perdev_uc_pdata *uc_pdata;
+ struct udevice *dev;
+
+ /**
+ * In the test_postbind() method of test uclass driver, the uclass
+ * platform data should be set to three test int values - test it.
+ */
+ for (uclass_find_first_device(UCLASS_TEST, &dev);
+ dev;
+ uclass_find_next_device(&dev)) {
+ ut_assert(dev);
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+ ut_assert(uc_pdata);
+ ut_assert(uc_pdata->intval1 == TEST_UC_PDATA_INTVAL1);
+ ut_assert(uc_pdata->intval2 == TEST_UC_PDATA_INTVAL2);
+ ut_assert(uc_pdata->intval3 == TEST_UC_PDATA_INTVAL3);
+ }
+
+ return 0;
+}
+DM_TEST(dm_test_autobind_uclass_pdata_valid, DM_TESTF_SCAN_PDATA);
+
/* Test that autoprobe finds all the expected devices */
static int dm_test_autoprobe(struct dm_test_state *dms)
{
diff --git a/test/dm/test-uclass.c b/test/dm/test-uclass.c
index 7cb37f7..4ae75ef 100644
--- a/test/dm/test-uclass.c
+++ b/test/dm/test-uclass.c
@@ -30,9 +30,18 @@ int test_ping(struct udevice *dev, int pingval, int *pingret)
static int test_post_bind(struct udevice *dev)
{
+ struct dm_test_perdev_uc_pdata *uc_pdata;
+
dm_testdrv_op_count[DM_TEST_OP_POST_BIND]++;
ut_assert(!device_active(dev));
+ uc_pdata = dev_get_uclass_platdata(dev);
+ ut_assert(uc_pdata);
+
+ uc_pdata->intval1 = TEST_UC_PDATA_INTVAL1;
+ uc_pdata->intval2 = TEST_UC_PDATA_INTVAL2;
+ uc_pdata->intval3 = TEST_UC_PDATA_INTVAL3;
+
return 0;
}
@@ -115,4 +124,6 @@ UCLASS_DRIVER(test) = {
.destroy = test_destroy,
.priv_auto_alloc_size = sizeof(struct dm_test_uclass_priv),
.per_device_auto_alloc_size = sizeof(struct dm_test_uclass_perdev_priv),
+ .per_device_platdata_auto_alloc_size =
+ sizeof(struct dm_test_perdev_uc_pdata),
};
From 9e85f13ddc47d253d90411a0645f9fbd8fa6e4b8 Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:20 +0200
Subject: [PATCH 04/31] dm: test: Add tests for get/find uclass devices
This commit introduces simple tests for functions:
- uclass_find_first_device()
- uclass_find_next_device()
- uclass_first_device()
- uclass_next_device()
Tests added by this commit:
- Test: dm_test_uclass_devices_find:
* call uclass_find_first_device(), then check if: (dev != NULL), (ret == 0)
* for the rest devices, call uclass_find_next_device() and do the same check
- Test: dm_test_uclass_devices_get:
* call uclass_first_device(), then check if:
-- (dev != NULL), (ret == 0), device_active()
* for the rest devices, call uclass_next_device() and do the same check
Signed-off-by: Przemyslaw Marczak
Cc: Simon Glass
Acked-by: Simon Glass
---
test/dm/core.c | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/test/dm/core.c b/test/dm/core.c
index 009ad36..3a8dd1d 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -656,9 +656,41 @@ static int dm_test_uclass_before_ready(struct dm_test_state *dms)
return 0;
}
-
DM_TEST(dm_test_uclass_before_ready, 0);
+static int dm_test_uclass_devices_find(struct dm_test_state *dms)
+{
+ struct udevice *dev;
+ int ret;
+
+ for (ret = uclass_find_first_device(UCLASS_TEST, &dev);
+ dev;
+ ret = uclass_find_next_device(&dev)) {
+ ut_assert(!ret);
+ ut_assert(dev);
+ }
+
+ return 0;
+}
+DM_TEST(dm_test_uclass_devices_find, DM_TESTF_SCAN_PDATA);
+
+static int dm_test_uclass_devices_get(struct dm_test_state *dms)
+{
+ struct udevice *dev;
+ int ret;
+
+ for (ret = uclass_first_device(UCLASS_TEST, &dev);
+ dev;
+ ret = uclass_next_device(&dev)) {
+ ut_assert(!ret);
+ ut_assert(dev);
+ ut_assert(device_active(dev));
+ }
+
+ return 0;
+}
+DM_TEST(dm_test_uclass_devices_get, DM_TESTF_SCAN_PDATA);
+
static int dm_test_device_get_uclass_id(struct dm_test_state *dms)
{
struct udevice *dev;
From e0735a4c60577fafdaed71c5ef046f04b0f53f09 Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:22 +0200
Subject: [PATCH 05/31] 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(-)
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 21ab0d5..61e96e9 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 befbae5..d0f1e22 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -46,6 +46,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
*
* Connect the device into uclass's list of devices.
@@ -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
From b7af1a2da767c0dd283ffce3d50efd36af32df14 Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:23 +0200
Subject: [PATCH 06/31] 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(+)
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 61e96e9..c1ebee7 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 b271472..66e0ea5 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -130,6 +130,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
*
* If an active device has this sequence it will be returned. If there is no
From cc73d37b7f1edbbf03e2abcf5815bdd122e8baed Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:24 +0200
Subject: [PATCH 07/31] 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(+)
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 80eb55b..d024abb 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 ad002fe..049cb2f 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
*
From f9c370dcdf056f035f18bf77db8a706cea21f9ce Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 15 Apr 2015 13:07:25 +0200
Subject: [PATCH 08/31] 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(+)
diff --git a/drivers/core/device.c b/drivers/core/device.c
index d024abb..df81b8e 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 049cb2f..18296bb 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
*
From 794d521917eab07651248174a81ba51cd265d9dc Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Mon, 20 Apr 2015 13:32:32 +0200
Subject: [PATCH 09/31] 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(-)
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index c1ebee7..7627ad1 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 d0f1e22..153f2a7 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -11,12 +11,25 @@
#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
*/
From 6e0c4880c877fae9ecfc4135b923e167d981e5e3 Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Mon, 20 Apr 2015 13:32:33 +0200
Subject: [PATCH 10/31] dm: test: Add tests for get/find uclass's device by
name
This commit introduces simple tests for functions:
- uclass_find_device_by_name()
- uclass_get_device_by_name()
Tests added by this commit:
- Test: dm_test_uclass_devices_find_by_name: for uclass id: UCLASS_TEST_FDT
* get uclass's devices by uclass_find_first/next_device() each as 'testdev',
* for each returned device, call: uclass_find_device_by_name(),
with previously returned device's name as an argument ('testdev->name').
* for the found device ('founddev') check if:
* founddev != NULL
* testdev == founddev
* testdev->name == founddev->name (by strcmp)
- Test: dm_test_uclass_devices_get_by_name: for uclass id: UCLASS_TEST_FDT
* get uclass's devices by uclass_get_first/next_device() each as 'testdev',
* for each returned device, call: uclass_get_device_by_name(),
with previously returned device's name as an argument ('testdev->name').
* for the found device ('founddev') check if:
* founddev != NULL
* founddev is active
* testdev == founddev
* testdev->name == founddev->name (by strcmp)
Signed-off-by: Przemyslaw Marczak
Cc: Simon Glass
Acked-by: Simon Glass
---
test/dm/core.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/test/dm/core.c b/test/dm/core.c
index 3a8dd1d..7f7b977 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -674,6 +674,43 @@ static int dm_test_uclass_devices_find(struct dm_test_state *dms)
}
DM_TEST(dm_test_uclass_devices_find, DM_TESTF_SCAN_PDATA);
+static int dm_test_uclass_devices_find_by_name(struct dm_test_state *dms)
+{
+ struct udevice *finddev;
+ struct udevice *testdev;
+ int findret, ret;
+
+ /*
+ * For each test device found in fdt like: "a-test", "b-test", etc.,
+ * use its name and try to find it by uclass_find_device_by_name().
+ * Then, on success check if:
+ * - current 'testdev' name is equal to the returned 'finddev' name
+ * - current 'testdev' pointer is equal to the returned 'finddev'
+ *
+ * We assume that, each uclass's device name is unique, so if not, then
+ * this will fail on checking condition: testdev == finddev, since the
+ * uclass_find_device_by_name(), returns the first device by given name.
+ */
+ for (ret = uclass_find_first_device(UCLASS_TEST_FDT, &testdev);
+ testdev;
+ ret = uclass_find_next_device(&testdev)) {
+ ut_assertok(ret);
+ ut_assert(testdev);
+
+ findret = uclass_find_device_by_name(UCLASS_TEST_FDT,
+ testdev->name,
+ &finddev);
+
+ ut_assertok(findret);
+ ut_assert(testdev);
+ ut_asserteq_str(testdev->name, finddev->name);
+ ut_asserteq_ptr(testdev, finddev);
+ }
+
+ return 0;
+}
+DM_TEST(dm_test_uclass_devices_find_by_name, DM_TESTF_SCAN_FDT);
+
static int dm_test_uclass_devices_get(struct dm_test_state *dms)
{
struct udevice *dev;
@@ -691,6 +728,50 @@ static int dm_test_uclass_devices_get(struct dm_test_state *dms)
}
DM_TEST(dm_test_uclass_devices_get, DM_TESTF_SCAN_PDATA);
+static int dm_test_uclass_devices_get_by_name(struct dm_test_state *dms)
+{
+ struct udevice *finddev;
+ struct udevice *testdev;
+ int ret, findret;
+
+ /*
+ * For each test device found in fdt like: "a-test", "b-test", etc.,
+ * use its name and try to get it by uclass_get_device_by_name().
+ * On success check if:
+ * - returned finddev' is active
+ * - current 'testdev' name is equal to the returned 'finddev' name
+ * - current 'testdev' pointer is equal to the returned 'finddev'
+ *
+ * We asserts that the 'testdev' is active on each loop entry, so we
+ * could be sure that the 'finddev' is activated too, but for sure
+ * we check it again.
+ *
+ * We assume that, each uclass's device name is unique, so if not, then
+ * this will fail on checking condition: testdev == finddev, since the
+ * uclass_get_device_by_name(), returns the first device by given name.
+ */
+ for (ret = uclass_first_device(UCLASS_TEST_FDT, &testdev);
+ testdev;
+ ret = uclass_next_device(&testdev)) {
+ ut_assertok(ret);
+ ut_assert(testdev);
+ ut_assert(device_active(testdev));
+
+ findret = uclass_get_device_by_name(UCLASS_TEST_FDT,
+ testdev->name,
+ &finddev);
+
+ ut_assertok(findret);
+ ut_assert(finddev);
+ ut_assert(device_active(finddev));
+ ut_asserteq_str(testdev->name, finddev->name);
+ ut_asserteq_ptr(testdev, finddev);
+ }
+
+ return 0;
+}
+DM_TEST(dm_test_uclass_devices_get_by_name, DM_TESTF_SCAN_FDT);
+
static int dm_test_device_get_uclass_id(struct dm_test_state *dms)
{
struct udevice *dev;
From a7b8250210cd1b449a06f7d20769944ebeca1a41 Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Mon, 20 Apr 2015 13:32:34 +0200
Subject: [PATCH 11/31] dm: core: precise comments for get/find device by name
The functions:
- uclass_find_device_by_name()
- uclass_get_device_by_name()
searches the required device for the exactly given name.
This patch, presice this fact for both function's comments.
Signed-off-by: Przemyslaw Marczak
Cc: Simon Glass
Acked-by: Simon Glass
---
include/dm/uclass-internal.h | 2 +-
include/dm/uclass.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index 153f2a7..a9b2fbe 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -63,7 +63,7 @@ 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.
+ * This searches for a device with the exactly given name.
*
* The device is NOT probed, it is merely returned.
*
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 66e0ea5..4cfc0df 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -132,7 +132,7 @@ 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.
+ * This searches the devices in the uclass for one with the exactly given name.
*
* The device is probed to activate it ready for use.
*
From 07d260e047680971d926bc9a573f9291f39fc988 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Sun, 19 Apr 2015 07:20:58 -0600
Subject: [PATCH 12/31] 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(-)
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 7627ad1..9fec8c9 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;
From 093f2dce443296ab05b1b9a356a9153d5621791b Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Sun, 19 Apr 2015 07:20:59 -0600
Subject: [PATCH 13/31] 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(+)
diff --git a/drivers/usb/emul/sandbox_hub.c b/drivers/usb/emul/sandbox_hub.c
index 280c708..baf8bdc 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 = {
From 98a1605309d82dd85f9046b7f81afabeba390b46 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Sun, 19 Apr 2015 07:21:01 -0600
Subject: [PATCH 14/31] dm: Update the README to reflect the current test
output
There are a lot more tests now. To avoid confusion add the updated test
output to the driver model README.
Signed-off-by: Simon Glass
Reviewed-by: Joe Hershberger
---
doc/driver-model/README.txt | 58 ++++++++++++++++++++++++++++++++++++++-------
1 file changed, 50 insertions(+), 8 deletions(-)
diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt
index f83264d..f0276b1 100644
--- a/doc/driver-model/README.txt
+++ b/doc/driver-model/README.txt
@@ -95,43 +95,82 @@ are provided in test/dm. To run them, try:
You should see something like this:
<...U-Boot banner...>
- Running 29 driver model tests
+ Running 53 driver model tests
Test: dm_test_autobind
Test: dm_test_autoprobe
+ Test: dm_test_bus_child_post_bind
+ Test: dm_test_bus_child_post_bind_uclass
+ Test: dm_test_bus_child_pre_probe_uclass
Test: dm_test_bus_children
- Device 'd-test': seq 3 is in use by 'b-test'
- Device 'c-test@0': seq 0 is in use by 'a-test'
- Device 'c-test@1': seq 1 is in use by 'd-test'
+ Device 'c-test@0': seq 0 is in use by 'd-test'
+ Device 'c-test@1': seq 1 is in use by 'f-test'
Test: dm_test_bus_children_funcs
Test: dm_test_bus_children_iterators
Test: dm_test_bus_parent_data
+ Test: dm_test_bus_parent_data_uclass
Test: dm_test_bus_parent_ops
+ Test: dm_test_bus_parent_platdata
+ Test: dm_test_bus_parent_platdata_uclass
Test: dm_test_children
+ Test: dm_test_device_get_uclass_id
+ Test: dm_test_eth
+ Using eth@10002000 device
+ Using eth@10003000 device
+ Using eth@10004000 device
+ Test: dm_test_eth_alias
+ Using eth@10002000 device
+ Using eth@10004000 device
+ Using eth@10002000 device
+ Using eth@10003000 device
+ Test: dm_test_eth_prime
+ Using eth@10003000 device
+ Using eth@10002000 device
+ Test: dm_test_eth_rotate
+
+ Error: eth@10004000 address not set.
+
+ Error: eth@10004000 address not set.
+ Using eth@10002000 device
+
+ Error: eth@10004000 address not set.
+
+ Error: eth@10004000 address not set.
+ Using eth@10004000 device
Test: dm_test_fdt
- Device 'd-test': seq 3 is in use by 'b-test'
Test: dm_test_fdt_offset
Test: dm_test_fdt_pre_reloc
Test: dm_test_fdt_uclass_seq
- Device 'd-test': seq 3 is in use by 'b-test'
- Device 'a-test': seq 0 is in use by 'd-test'
Test: dm_test_gpio
extra-gpios: get_value: error: gpio b5 not reserved
Test: dm_test_gpio_anon
Test: dm_test_gpio_copy
Test: dm_test_gpio_leak
extra-gpios: get_value: error: gpio b5 not reserved
+ Test: dm_test_gpio_phandles
Test: dm_test_gpio_requestf
+ Test: dm_test_i2c_bytewise
+ Test: dm_test_i2c_find
+ Test: dm_test_i2c_offset
+ Test: dm_test_i2c_offset_len
+ Test: dm_test_i2c_probe_empty
+ Test: dm_test_i2c_read_write
+ Test: dm_test_i2c_speed
Test: dm_test_leak
Test: dm_test_lifecycle
+ Test: dm_test_net_retry
+ Using eth@10004000 device
+ Using eth@10002000 device
+ Using eth@10004000 device
Test: dm_test_operations
Test: dm_test_ordering
+ Test: dm_test_pci_base
+ Test: dm_test_pci_swapcase
Test: dm_test_platdata
Test: dm_test_pre_reloc
Test: dm_test_remove
Test: dm_test_spi_find
Invalid chip select 0:0 (err=-19)
SF: Failed to get idcodes
- Device 'name-emul': seq 0 is in use by 'name-emul'
SF: Detected M25P16 with page size 256 Bytes, erase size 64 KiB, total 2 MiB
Test: dm_test_spi_flash
2097152 bytes written in 0 ms
@@ -150,6 +189,9 @@ You should see something like this:
SF: Detected M25P16 with page size 256 Bytes, erase size 64 KiB, total 2 MiB
Test: dm_test_uclass
Test: dm_test_uclass_before_ready
+ Test: dm_test_usb_base
+ Test: dm_test_usb_flash
+ USB-1: scanning bus 1 for devices... 2 USB Device(s) found
Failures: 0
From f9fd4558ea977f0ad574c829026f26157176cea6 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Sun, 19 Apr 2015 07:21:02 -0600
Subject: [PATCH 15/31] dm: test: Don't clear global_data in
dm_test_uclass_before_ready()
We must not clear global_data even in tests, since the ram_buffer (which
is used by malloc()) will also be lost, and subsequent tests will fail.
Zero only the global_data fields that are required for the test to function.
Signed-off-by: Simon Glass
Reviewed-by: Joe Hershberger
Tested-by: Joe Hershberger
---
test/dm/core.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/test/dm/core.c b/test/dm/core.c
index 7f7b977..91be1e5 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -651,7 +651,10 @@ static int dm_test_uclass_before_ready(struct dm_test_state *dms)
ut_assertok(uclass_get(UCLASS_TEST, &uc));
- memset(gd, '\0', sizeof(*gd));
+ gd->dm_root = NULL;
+ gd->dm_root_f = NULL;
+ memset(&gd->uclass_root, '\0', sizeof(gd->uclass_root));
+
ut_asserteq_ptr(NULL, uclass_find(UCLASS_TEST));
return 0;
From 5b5e9ba3f7f40f12b3a69bb1cf3828cf3dd5e315 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Mon, 13 Apr 2015 11:19:07 -0600
Subject: [PATCH 16/31] exynos: sandbox: ti: Add SPDX license identifiers and
notes
For some files I neglected to add a license. Rectify this:
arch/arm/dts/exynos4210-pinctrl-uboot.dtsi
arch/arm/dts/exynos4x12-pinctrl-uboot.dtsi
arch/arm/dts/exynos5250-pinctrl-uboot.dtsi
arch/arm/dts/exynos54xx-pinctrl-uboot.dtsi
arch/arm/dts/s5pc100-pinctrl.dtsi
arch/arm/dts/s5pc110-pinctrl.dtsi
This file came from Linux and has no license information there, so add a
comment to that effect:
arch/sandbox/include/asm/bitops.h
This file also came from Linux - presumably someone from TI could add the
license:
include/dt-bindings/pinctrl/omap.h
Signed-off-by: Simon Glass
Reported-by: Ingrid Viitanen
---
arch/arm/dts/exynos4210-pinctrl-uboot.dtsi | 2 ++
arch/arm/dts/exynos4x12-pinctrl-uboot.dtsi | 2 ++
arch/arm/dts/exynos5250-pinctrl-uboot.dtsi | 2 ++
arch/arm/dts/exynos54xx-pinctrl-uboot.dtsi | 2 ++
arch/arm/dts/s5pc100-pinctrl.dtsi | 2 ++
arch/arm/dts/s5pc110-pinctrl.dtsi | 2 ++
arch/sandbox/include/asm/bitops.h | 2 ++
7 files changed, 14 insertions(+)
diff --git a/arch/arm/dts/exynos4210-pinctrl-uboot.dtsi b/arch/arm/dts/exynos4210-pinctrl-uboot.dtsi
index f9b61ba..0ff41d0 100644
--- a/arch/arm/dts/exynos4210-pinctrl-uboot.dtsi
+++ b/arch/arm/dts/exynos4210-pinctrl-uboot.dtsi
@@ -2,6 +2,8 @@
* U-Boot additions to enable a generic Exynos GPIO driver
*
* Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
*/
/{
diff --git a/arch/arm/dts/exynos4x12-pinctrl-uboot.dtsi b/arch/arm/dts/exynos4x12-pinctrl-uboot.dtsi
index c41d07b..8e5a6c6 100644
--- a/arch/arm/dts/exynos4x12-pinctrl-uboot.dtsi
+++ b/arch/arm/dts/exynos4x12-pinctrl-uboot.dtsi
@@ -2,6 +2,8 @@
* U-Boot additions to enable a generic Exynos GPIO driver
*
* Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
*/
/{
diff --git a/arch/arm/dts/exynos5250-pinctrl-uboot.dtsi b/arch/arm/dts/exynos5250-pinctrl-uboot.dtsi
index 7edb0ca..068c5f6 100644
--- a/arch/arm/dts/exynos5250-pinctrl-uboot.dtsi
+++ b/arch/arm/dts/exynos5250-pinctrl-uboot.dtsi
@@ -2,6 +2,8 @@
* U-Boot additions to enable a generic Exynos GPIO driver
*
* Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
*/
/{
diff --git a/arch/arm/dts/exynos54xx-pinctrl-uboot.dtsi b/arch/arm/dts/exynos54xx-pinctrl-uboot.dtsi
index 5a86211..635a1b0 100644
--- a/arch/arm/dts/exynos54xx-pinctrl-uboot.dtsi
+++ b/arch/arm/dts/exynos54xx-pinctrl-uboot.dtsi
@@ -2,6 +2,8 @@
* U-Boot additions to enable a generic Exynos GPIO driver
*
* Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
*/
/{
diff --git a/arch/arm/dts/s5pc100-pinctrl.dtsi b/arch/arm/dts/s5pc100-pinctrl.dtsi
index bd9f97c..9753869 100644
--- a/arch/arm/dts/s5pc100-pinctrl.dtsi
+++ b/arch/arm/dts/s5pc100-pinctrl.dtsi
@@ -2,6 +2,8 @@
* U-Boot additions to enable a generic Exynos GPIO driver
*
* Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
*/
/ {
diff --git a/arch/arm/dts/s5pc110-pinctrl.dtsi b/arch/arm/dts/s5pc110-pinctrl.dtsi
index d21b6ab..2e9d552 100644
--- a/arch/arm/dts/s5pc110-pinctrl.dtsi
+++ b/arch/arm/dts/s5pc110-pinctrl.dtsi
@@ -2,6 +2,8 @@
* U-Boot additions to enable a generic Exynos GPIO driver
*
* Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
*/
/ {
diff --git a/arch/sandbox/include/asm/bitops.h b/arch/sandbox/include/asm/bitops.h
index e807c4e..f1a7aee 100644
--- a/arch/sandbox/include/asm/bitops.h
+++ b/arch/sandbox/include/asm/bitops.h
@@ -1,6 +1,8 @@
/*
* Copyright (c) 2011 The Chromium OS Authors.
*
+ * Modified from Linux arch/arm/include/asm/bitops.h
+ *
* Copyright 1995, Russell King.
* Various bits and pieces copyrights include:
* Linus Torvalds (test_bit).
From dd0b0122bacc286a6c9321178fcdd947a8bbf0a8 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:25 -0700
Subject: [PATCH 17/31] 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(-)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 1686a1f..54e6f26 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 67b1d60..362f2ee 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
From 363e6da10313edb9ab7bffd8ee9000f72af11290 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:26 -0700
Subject: [PATCH 18/31] 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(-)
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 362f2ee..6131299 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)
From ab9fd2e83a0f781534fbb8a2b88c724a29b7f20a Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:28 -0700
Subject: [PATCH 19/31] 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(-)
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 6131299..fd110b3 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)
From 36fa61dc612e363fb60840a06333fc37ec3fb68e Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:30 -0700
Subject: [PATCH 20/31] 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(-)
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 75d182d..2861b43 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 df81b8e..7f24243 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 a9106f4..38cb0e8 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 */
From 7f9875e733b79556ade508b88f88ac1f8a2c7e3c Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:31 -0700
Subject: [PATCH 21/31] 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(+)
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 9fec8c9..04e939d 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 a9b2fbe..9b68508 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
From 66312374dca86e77fc9b08f774546e62b6cd1aa7 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:32 -0700
Subject: [PATCH 22/31] 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(-)
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index b239691..b8c2f48 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 5624482..09c8abd 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -39,10 +39,33 @@ 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
*
* @param buf The buffer to place the result into
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 331eae2..577c60e 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 e0f2648..bedc865 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)
{
From 5a87c4174d18fe40dcc847ba36853a9f15cb3e1e Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:33 -0700
Subject: [PATCH 23/31] 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(-)
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 7f24243..3b77d23 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) {
From b45122fdf5d314ef1f492b051fb104a7b48b8079 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:34 -0700
Subject: [PATCH 24/31] fdt: sandbox: Move setup code from board_f to fdtdec
We want to be able to set up the device tree in SPL, so move this code
to a common place.
Signed-off-by: Simon Glass
---
arch/sandbox/cpu/cpu.c | 41 +++++++++++++++++++
arch/sandbox/include/asm/u-boot-sandbox.h | 8 ++++
common/board_f.c | 67 +------------------------------
include/fdtdec.h | 6 +++
lib/fdtdec.c | 31 ++++++++++++++
5 files changed, 88 insertions(+), 65 deletions(-)
diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index f0dafed..168f2ef 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -6,6 +6,7 @@
#include
#include
#include
+#include
#include
DECLARE_GLOBAL_DATA_PTR;
@@ -97,3 +98,43 @@ phys_addr_t map_to_sysmem(const void *ptr)
void flush_dcache_range(unsigned long start, unsigned long stop)
{
}
+
+int sandbox_read_fdt_from_file(void)
+{
+ struct sandbox_state *state = state_get_current();
+ const char *fname = state->fdt_fname;
+ void *blob;
+ loff_t size;
+ int err;
+ int fd;
+
+ blob = map_sysmem(CONFIG_SYS_FDT_LOAD_ADDR, 0);
+ if (!state->fdt_fname) {
+ err = fdt_create_empty_tree(blob, 256);
+ if (!err)
+ goto done;
+ printf("Unable to create empty FDT: %s\n", fdt_strerror(err));
+ return -EINVAL;
+ }
+
+ err = os_get_filesize(fname, &size);
+ if (err < 0) {
+ printf("Failed to file FDT file '%s'\n", fname);
+ return err;
+ }
+ fd = os_open(fname, OS_O_RDONLY);
+ if (fd < 0) {
+ printf("Failed to open FDT file '%s'\n", fname);
+ return -EACCES;
+ }
+ if (os_read(fd, blob, size) != size) {
+ os_close(fd);
+ return -EIO;
+ }
+ os_close(fd);
+
+done:
+ gd->fdt_blob = blob;
+
+ return 0;
+}
diff --git a/arch/sandbox/include/asm/u-boot-sandbox.h b/arch/sandbox/include/asm/u-boot-sandbox.h
index d5b9361..da87cc3 100644
--- a/arch/sandbox/include/asm/u-boot-sandbox.h
+++ b/arch/sandbox/include/asm/u-boot-sandbox.h
@@ -75,4 +75,12 @@ int pci_unmap_physmem(const void *addr, unsigned long len,
*/
void sandbox_set_enable_pci_map(int enable);
+/**
+ * sandbox_read_fdt_from_file() - Read a device tree from a file
+ *
+ * Read a device tree file from a host file and set it up for use as the
+ * control FDT.
+ */
+int sandbox_read_fdt_from_file(void);
+
#endif /* _U_BOOT_SANDBOX_H_ */
diff --git a/common/board_f.c b/common/board_f.c
index 775df14..656c249 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -282,49 +282,6 @@ __weak int arch_cpu_init(void)
return 0;
}
-#ifdef CONFIG_OF_HOSTFILE
-
-static int read_fdt_from_file(void)
-{
- struct sandbox_state *state = state_get_current();
- const char *fname = state->fdt_fname;
- void *blob;
- loff_t size;
- int err;
- int fd;
-
- blob = map_sysmem(CONFIG_SYS_FDT_LOAD_ADDR, 0);
- if (!state->fdt_fname) {
- err = fdt_create_empty_tree(blob, 256);
- if (!err)
- goto done;
- printf("Unable to create empty FDT: %s\n", fdt_strerror(err));
- return -EINVAL;
- }
-
- err = os_get_filesize(fname, &size);
- if (err < 0) {
- printf("Failed to file FDT file '%s'\n", fname);
- return err;
- }
- fd = os_open(fname, OS_O_RDONLY);
- if (fd < 0) {
- printf("Failed to open FDT file '%s'\n", fname);
- return -EACCES;
- }
- if (os_read(fd, blob, size) != size) {
- os_close(fd);
- return -EIO;
- }
- os_close(fd);
-
-done:
- gd->fdt_blob = blob;
-
- return 0;
-}
-#endif
-
#ifdef CONFIG_SANDBOX
static int setup_ram_buf(void)
{
@@ -337,28 +294,6 @@ static int setup_ram_buf(void)
}
#endif
-static int setup_fdt(void)
-{
-#ifdef CONFIG_OF_CONTROL
-# ifdef CONFIG_OF_EMBED
- /* Get a pointer to the FDT */
- gd->fdt_blob = __dtb_dt_begin;
-# elif defined CONFIG_OF_SEPARATE
- /* FDT is at end of image */
- gd->fdt_blob = (ulong *)&_end;
-# elif defined(CONFIG_OF_HOSTFILE)
- if (read_fdt_from_file()) {
- puts("Failed to read control FDT\n");
- return -1;
- }
-# endif
- /* Allow the early environment to override the fdt address */
- gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
- (uintptr_t)gd->fdt_blob);
-#endif
- return 0;
-}
-
/* Get the top of usable RAM */
__weak ulong board_get_usable_ram_top(ulong total_size)
{
@@ -826,7 +761,9 @@ static init_fnc_t init_sequence_f[] = {
setup_ram_buf,
#endif
setup_mon_len,
+#ifdef CONFIG_OF_CONTROL
setup_fdt,
+#endif
#ifdef CONFIG_TRACE
trace_early_init,
#endif
diff --git a/include/fdtdec.h b/include/fdtdec.h
index d14e06a..ea8a526 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -793,4 +793,10 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property,
int fdtdec_decode_memory_region(const void *blob, int node,
const char *mem_type, const char *suffix,
fdt_addr_t *basep, fdt_size_t *sizep);
+
+/**
+ * Set up the device tree ready for use
+ */
+int setup_fdt(void);
+
#endif
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 577c60e..d9dbc86 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
DECLARE_GLOBAL_DATA_PTR;
@@ -1037,4 +1038,34 @@ int fdtdec_decode_memory_region(const void *blob, int config_node,
return 0;
}
+
+int setup_fdt(void)
+{
+#ifdef CONFIG_OF_CONTROL
+# ifdef CONFIG_OF_EMBED
+ /* Get a pointer to the FDT */
+ gd->fdt_blob = __dtb_dt_begin;
+# elif defined CONFIG_OF_SEPARATE
+# ifdef CONFIG_SPL_BUILD
+ /* FDT is at end of BSS */
+ gd->fdt_blob = (ulong *)&__bss_end;
+# else
+ /* FDT is at end of image */
+ gd->fdt_blob = (ulong *)&_end;
+#endif
+# elif defined(CONFIG_OF_HOSTFILE)
+ if (sandbox_read_fdt_from_file()) {
+ puts("Failed to read control FDT\n");
+ return -1;
+ }
+# endif
+# ifndef CONFIG_SPL_BUILD
+ /* Allow the early environment to override the fdt address */
+ gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
+ (uintptr_t)gd->fdt_blob);
+# endif
#endif
+ return 0;
+}
+
+#endif /* !USE_HOSTCC */
From 0879361fd3bc33eb52bcfb2574a78f1e52a36429 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:35 -0700
Subject: [PATCH 25/31] fdt: Rename setup_fdt() and make it prepare also
There is little reason to split these two functions. Bring them together
which simplifies the init sequence.
Signed-off-by: Simon Glass
---
common/board_f.c | 5 +----
include/fdtdec.h | 2 +-
lib/fdtdec.c | 4 ++--
3 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/common/board_f.c b/common/board_f.c
index 656c249..90f3b88 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -762,7 +762,7 @@ static init_fnc_t init_sequence_f[] = {
#endif
setup_mon_len,
#ifdef CONFIG_OF_CONTROL
- setup_fdt,
+ fdtdec_setup,
#endif
#ifdef CONFIG_TRACE
trace_early_init,
@@ -774,9 +774,6 @@ static init_fnc_t init_sequence_f[] = {
#endif
arch_cpu_init, /* basic arch cpu dependent setup */
mark_bootstage,
-#ifdef CONFIG_OF_CONTROL
- fdtdec_check_fdt,
-#endif
initf_dm,
arch_cpu_init_dm,
#if defined(CONFIG_BOARD_EARLY_INIT_F)
diff --git a/include/fdtdec.h b/include/fdtdec.h
index ea8a526..0d3e6d9 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -797,6 +797,6 @@ int fdtdec_decode_memory_region(const void *blob, int node,
/**
* Set up the device tree ready for use
*/
-int setup_fdt(void);
+int fdtdec_setup(void);
#endif
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index d9dbc86..80b897a 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1039,7 +1039,7 @@ int fdtdec_decode_memory_region(const void *blob, int config_node,
return 0;
}
-int setup_fdt(void)
+int fdtdec_setup(void)
{
#ifdef CONFIG_OF_CONTROL
# ifdef CONFIG_OF_EMBED
@@ -1065,7 +1065,7 @@ int setup_fdt(void)
(uintptr_t)gd->fdt_blob);
# endif
#endif
- return 0;
+ return fdtdec_prepare_fdt();
}
#endif /* !USE_HOSTCC */
From fb5cf7f16be725aec7ab0016268b3b4e26460bee Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:36 -0700
Subject: [PATCH 26/31] Move initf_malloc() to a common place
To allow this function to be used from SPL, move it to the malloc()
code.
Signed-off-by: Simon Glass
---
common/board_f.c | 12 +-----------
common/dlmalloc.c | 11 +++++++++++
include/malloc.h | 3 +++
3 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/common/board_f.c b/common/board_f.c
index 90f3b88..322e070 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include
/* TODO: Can we move these into arch/ headers? */
@@ -721,17 +722,6 @@ static int mark_bootstage(void)
return 0;
}
-static int initf_malloc(void)
-{
-#ifdef CONFIG_SYS_MALLOC_F_LEN
- assert(gd->malloc_base); /* Set up by crt0.S */
- gd->malloc_limit = gd->malloc_base + CONFIG_SYS_MALLOC_F_LEN;
- gd->malloc_ptr = 0;
-#endif
-
- return 0;
-}
-
static int initf_dm(void)
{
#if defined(CONFIG_DM) && defined(CONFIG_SYS_MALLOC_F_LEN)
diff --git a/common/dlmalloc.c b/common/dlmalloc.c
index b2ce063..b5bb051 100644
--- a/common/dlmalloc.c
+++ b/common/dlmalloc.c
@@ -3261,6 +3261,17 @@ int mALLOPt(param_number, value) int param_number; int value;
}
}
+int initf_malloc(void)
+{
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+ assert(gd->malloc_base); /* Set up by crt0.S */
+ gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN;
+ gd->malloc_ptr = 0;
+#endif
+
+ return 0;
+}
+
/*
History:
diff --git a/include/malloc.h b/include/malloc.h
index 5df6348..f4da9e6 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -906,6 +906,9 @@ void *realloc_simple(void *ptr, size_t size);
#endif
+/* Set up pre-relocation malloc() ready for use */
+int initf_malloc(void);
+
/* Public routines */
/* Simple versions which can be used when space is tight */
From 293f16b1e7f6006f192950a94830e3a14c979c4d Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:37 -0700
Subject: [PATCH 27/31] Correct malloc_limit value for pre-relocation malloc()
The limit is measured from the start of the malloc() area and is not an
absolute address. Correct this.
Signed-off-by: Simon Glass
---
common/spl/spl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 8e1fb40..af1336c 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -158,7 +158,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
CONFIG_SYS_SPL_MALLOC_SIZE);
gd->flags |= GD_FLG_FULL_MALLOC_INIT;
#elif defined(CONFIG_SYS_MALLOC_F_LEN)
- gd->malloc_limit = gd->malloc_base + CONFIG_SYS_MALLOC_F_LEN;
+ gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN;
gd->malloc_ptr = 0;
#endif
#ifdef CONFIG_SPL_DM
From 2860f03b917cf88450fdb6ed888dead10398754f Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:38 -0700
Subject: [PATCH 28/31] fdt: Add an option to disable device tree in SPL
Some boards cannot support device tree due to lack of memory. Add an option
to allow these boards to continue to work (and even use driver model).
This is a 'negative' option since most boards are expected to support device
tree in SPL.
Signed-off-by: Simon Glass
---
dts/Kconfig | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/dts/Kconfig b/dts/Kconfig
index ca5bd6f..957f5c7 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -1,9 +1,6 @@
#
# Device Tree Control
#
-# TODO:
-# This feature is not currently supported for SPL,
-# but this restriction should be removed in the future.
config SUPPORT_OF_CONTROL
bool
@@ -17,6 +14,14 @@ config OF_CONTROL
This feature provides for run-time configuration of U-Boot
via a flattened device tree.
+config SPL_DISABLE_OF_CONTROL
+ bool "Disable run-time configuration via Device Tree in SPL"
+ depends on OF_CONTROL
+ help
+ Some boards use device tree in U-Boot but only have 4KB of SRAM
+ which is not enough to support device tree. Enable this option to
+ allow such boards to be supported by U-Boot SPL.
+
choice
prompt "Provider of DTB for DT control"
depends on OF_CONTROL
From 1d76bf226ac1660ec00c4a2cb276bd000ad37a5a Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:40 -0700
Subject: [PATCH 29/31] fdt: Allow FDT functions to be built for SPL
Remove the implicit assumption that SPL does not support device tree.
Signed-off-by: Simon Glass
---
lib/Makefile | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/lib/Makefile b/lib/Makefile
index 07d175f..97ed398 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -44,6 +44,12 @@ obj-$(CONFIG_BITREVERSE) += bitrev.o
obj-y += list_sort.o
endif
+ifndef CONFIG_SPL_DISABLE_OF_CONTROL
+obj-$(CONFIG_OF_LIBFDT) += libfdt/
+obj-$(CONFIG_OF_CONTROL) += fdtdec_common.o
+obj-$(CONFIG_OF_CONTROL) += fdtdec.o
+endif
+
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o
obj-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o
From b2b0d3e7129d4e59be1a016ad4fb05db87b8c5b4 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:41 -0700
Subject: [PATCH 30/31] 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(-)
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 9b5c6bb..12d0460 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 0d3e6d9..6590470 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
From f3d46bd658ef4df575ec26c29e472ac858723159 Mon Sep 17 00:00:00 2001
From: Simon Glass
Date: Fri, 27 Feb 2015 22:06:42 -0700
Subject: [PATCH 31/31] dm: Init device tree as well as driver model in SPL
If enabled, make sure that the device tree is available in SPL before
setting up driver model.
Signed-off-by: Simon Glass
---
common/spl/spl.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/common/spl/spl.c b/common/spl/spl.c
index af1336c..6a02c9e 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -151,6 +151,8 @@ static void spl_ram_load_image(void)
void board_init_r(gd_t *dummy1, ulong dummy2)
{
u32 boot_device;
+ int ret;
+
debug(">>spl:board_init_r()\n");
#if defined(CONFIG_SYS_SPL_MALLOC_START)
@@ -161,9 +163,21 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN;
gd->malloc_ptr = 0;
#endif
-#ifdef CONFIG_SPL_DM
- dm_init_and_scan(true);
-#endif
+ if (IS_ENABLED(CONFIG_OF_CONTROL) &&
+ !IS_ENABLED(CONFIG_SPL_DISABLE_OF_CONTROL)) {
+ ret = fdtdec_setup();
+ if (ret) {
+ debug("fdtdec_setup() returned error %d\n", ret);
+ hang();
+ }
+ }
+ if (IS_ENABLED(CONFIG_SPL_DM)) {
+ ret = dm_init_and_scan(true);
+ if (ret) {
+ debug("dm_init_and_scan() returned error %d\n", ret);
+ hang();
+ }
+ }
#ifndef CONFIG_PPC
/*