All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [RFC PATCH 01/21] dm: Don't run tests if U-Boot cannot be built
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 02/21] dm: core: Improve comments for uclass_first/next_device() Simon Glass
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

There is no point in running the tests if U-Boot cannot be built. Abort in
this case.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 test/dm/test-dm.sh | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/test/dm/test-dm.sh b/test/dm/test-dm.sh
index bb99677..8ebc392 100755
--- a/test/dm/test-dm.sh
+++ b/test/dm/test-dm.sh
@@ -1,9 +1,14 @@
 #!/bin/sh
 
+die() {
+	echo $1
+	exit 1
+}
+
 NUM_CPUS=$(cat /proc/cpuinfo |grep -c processor)
 dtc -I dts -O dtb test/dm/test.dts -o test/dm/test.dtb
-make O=sandbox sandbox_config
-make O=sandbox -s -j${NUM_CPUS}
+make O=sandbox sandbox_config || die "Cannot configure U-Boot"
+make O=sandbox -s -j${NUM_CPUS} || die "Cannot build U-Boot"
 dd if=/dev/zero of=spi.bin bs=1M count=2
 ./sandbox/u-boot -d test/dm/test.dtb -c "dm test"
 rm spi.bin
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 02/21] dm: core: Improve comments for uclass_first/next_device()
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 01/21] dm: Don't run tests if U-Boot cannot be built Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 03/21] dm: core: Set device tree node for root device Simon Glass
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

Mention that the devices are probed ready for use.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 include/dm/uclass.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index f6ec6d7..2577ae6 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -141,6 +141,8 @@ int uclass_get_device_by_of_offset(enum uclass_id id, int node,
 /**
  * uclass_first_device() - Get the first device in a uclass
  *
+ * The device returned is probed if necessary, and ready for use
+ *
  * @id: Uclass ID to look up
  * @devp: Returns pointer to the first device in that uclass, or NULL if none
  * @return 0 if OK (found or not found), -1 on error
@@ -150,6 +152,8 @@ int uclass_first_device(enum uclass_id id, struct udevice **devp);
 /**
  * uclass_next_device() - Get the next device in a uclass
  *
+ * The device returned is probed if necessary, and ready for use
+ *
  * @devp: On entry, pointer to device to lookup. On exit, returns pointer
  * to the next device in the same uclass, or NULL if none
  * @return 0 if OK (found or not found), -1 on error
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 03/21] dm: core: Set device tree node for root device
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 01/21] dm: Don't run tests if U-Boot cannot be built Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 02/21] dm: core: Improve comments for uclass_first/next_device() Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 04/21] dm: core: Tidy up error handling in device_bind() Simon Glass
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

The root device corresponds to the root device tree node, so set this up.
Also add a few notes to the documentation.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 doc/driver-model/README.txt | 4 ++++
 drivers/core/root.c         | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt
index eafa825..4041569 100644
--- a/doc/driver-model/README.txt
+++ b/doc/driver-model/README.txt
@@ -363,6 +363,10 @@ can leave out platdata_auto_alloc_size. In this case you can use malloc
 in your ofdata_to_platdata (or probe) method to allocate the required memory,
 and you should free it in the remove method.
 
+The driver model tree is intended to mirror that of the device tree. The
+root driver is at device tree offset 0 (the root node, '/'), and its
+children are the children of the root node.
+
 
 Declaring Uclasses
 ------------------
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 47b3acf..a5b0a61 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -49,6 +49,9 @@ int dm_init(void)
 	ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
 	if (ret)
 		return ret;
+#ifdef CONFIG_OF_CONTROL
+	DM_ROOT_NON_CONST->of_offset = 0;
+#endif
 	ret = device_probe(DM_ROOT_NON_CONST);
 	if (ret)
 		return ret;
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 04/21] dm: core: Tidy up error handling in device_bind()
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (2 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 03/21] dm: core: Set device tree node for root device Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 05/21] dm: core: Allocate platform data when binding a device Simon Glass
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

Make the error handling more standard to make it easier to build on top of
it. Also correct a bug in the error path where there is no parent.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/device.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index 963b16f..eca8eda 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -81,18 +81,13 @@ int device_bind(struct udevice *parent, struct driver *drv, const char *name,
 
 	ret = uclass_bind_device(dev);
 	if (ret)
-		goto fail_bind;
+		goto fail_uclass_bind;
 
 	/* if we fail to bind we remove device from successors and free it */
 	if (drv->bind) {
 		ret = drv->bind(dev);
-		if (ret) {
-			if (uclass_unbind_device(dev)) {
-				dm_warn("Failed to unbind dev '%s' on error path\n",
-					dev->name);
-			}
+		if (ret)
 			goto fail_bind;
-		}
 	}
 	if (parent)
 		dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
@@ -101,8 +96,15 @@ int device_bind(struct udevice *parent, struct driver *drv, const char *name,
 	return 0;
 
 fail_bind:
-	list_del(&dev->sibling_node);
+	if (uclass_unbind_device(dev)) {
+		dm_warn("Failed to unbind dev '%s' on error path\n",
+			dev->name);
+	}
+fail_uclass_bind:
+	if (parent)
+		list_del(&dev->sibling_node);
 	free(dev);
+
 	return ret;
 }
 
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 05/21] dm: core: Allocate platform data when binding a device
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (3 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 04/21] dm: core: Tidy up error handling in device_bind() Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 06/21] dm: core: Allow parents to have platform data for their children Simon Glass
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

When using allocated platform data, allocate it when we bind the device.
This makes it possible to fill in this information before the device is
probed.

This fits with the platform data model (when not using device tree),
since platform data exists at bind-time.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/device-remove.c |  8 ++++----
 drivers/core/device.c        | 20 ++++++++++++--------
 test/dm/test-fdt.c           |  4 ++--
 3 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 8fc6b71..2c82577 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -88,6 +88,10 @@ int device_unbind(struct udevice *dev)
 	if (ret)
 		return ret;
 
+	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
+		free(dev->platdata);
+		dev->platdata = NULL;
+	}
 	ret = uclass_unbind_device(dev);
 	if (ret)
 		return ret;
@@ -111,10 +115,6 @@ void device_free(struct udevice *dev)
 		free(dev->priv);
 		dev->priv = NULL;
 	}
-	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
-		free(dev->platdata);
-		dev->platdata = NULL;
-	}
 	size = dev->uclass->uc_drv->per_device_auto_alloc_size;
 	if (size) {
 		free(dev->uclass_priv);
diff --git a/drivers/core/device.c b/drivers/core/device.c
index eca8eda..23ee771 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -72,8 +72,14 @@ int device_bind(struct udevice *parent, struct driver *drv, const char *name,
 #else
 	dev->req_seq = -1;
 #endif
-	if (!dev->platdata && drv->platdata_auto_alloc_size)
+	if (!dev->platdata && drv->platdata_auto_alloc_size) {
 		dev->flags |= DM_FLAG_ALLOC_PDATA;
+		dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
+		if (!dev->platdata) {
+			ret = -ENOMEM;
+			goto fail_alloc1;
+		}
+	}
 
 	/* put dev into parent's successor list */
 	if (parent)
@@ -103,6 +109,11 @@ fail_bind:
 fail_uclass_bind:
 	if (parent)
 		list_del(&dev->sibling_node);
+	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
+		free(dev->platdata);
+		dev->platdata = NULL;
+	}
+fail_alloc1:
 	free(dev);
 
 	return ret;
@@ -148,13 +159,6 @@ int device_probe_child(struct udevice *dev, void *parent_priv)
 		}
 	}
 	/* Allocate private data if requested */
-	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
-		dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
-		if (!dev->platdata) {
-			ret = -ENOMEM;
-			goto fail;
-		}
-	}
 	size = dev->uclass->uc_drv->per_device_auto_alloc_size;
 	if (size) {
 		dev->uclass_priv = calloc(1, size);
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index cd2c389..dc4ebf9 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -143,12 +143,12 @@ static int dm_test_fdt(struct dm_test_state *dms)
 	/* These are num_devices compatible root-level device tree nodes */
 	ut_asserteq(num_devices, list_count_items(&uc->dev_head));
 
-	/* Each should have no platdata / priv */
+	/* Each should have platform data but no private data */
 	for (i = 0; i < num_devices; i++) {
 		ret = uclass_find_device(UCLASS_TEST_FDT, i, &dev);
 		ut_assert(!ret);
 		ut_assert(!dev_get_priv(dev));
-		ut_assert(!dev->platdata);
+		ut_assert(dev->platdata);
 	}
 
 	ut_assertok(dm_check_devices(dms, num_devices));
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 06/21] dm: core: Allow parents to have platform data for their children
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (4 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 05/21] dm: core: Allocate platform data when binding a device Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 07/21] dm: core: Allow uclasses to specific the platdata for a device's children Simon Glass
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

For buses it is common for parents to need to know the address of the child
on the bus, the bus speed to use for that child, and other information. This
can be provided in platform data attached to each child.

Add driver model support for this, including auto-allocation which can be
requested using a new property to specify the size of the data.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/device-remove.c |  4 +++
 drivers/core/device.c        | 30 ++++++++++++++--
 include/dm/device.h          | 19 +++++++++++
 test/dm/bus.c                | 81 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 132 insertions(+), 2 deletions(-)

diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 2c82577..56c358a 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -92,6 +92,10 @@ int device_unbind(struct udevice *dev)
 		free(dev->platdata);
 		dev->platdata = NULL;
 	}
+	if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
+		free(dev->parent_platdata);
+		dev->parent_platdata = NULL;
+	}
 	ret = uclass_unbind_device(dev);
 	if (ret)
 		return ret;
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 23ee771..0682e2e 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -80,6 +80,18 @@ int device_bind(struct udevice *parent, struct driver *drv, const char *name,
 			goto fail_alloc1;
 		}
 	}
+	if (parent && !dev->parent_platdata) {
+		int size = parent->driver->per_child_platdata_auto_alloc_size;
+
+		if (size) {
+			dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
+			dev->parent_platdata = calloc(1, size);
+			if (!dev->parent_platdata) {
+				ret = -ENOMEM;
+				goto fail_alloc2;
+			}
+		}
+	}
 
 	/* put dev into parent's successor list */
 	if (parent)
@@ -107,8 +119,12 @@ fail_bind:
 			dev->name);
 	}
 fail_uclass_bind:
-	if (parent)
-		list_del(&dev->sibling_node);
+	list_del(&dev->sibling_node);
+	if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
+		free(dev->parent_platdata);
+		dev->parent_platdata = NULL;
+	}
+fail_alloc2:
 	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
 		free(dev->platdata);
 		dev->platdata = NULL;
@@ -247,6 +263,16 @@ void *dev_get_platdata(struct udevice *dev)
 	return dev->platdata;
 }
 
+void *dev_get_parent_platdata(struct udevice *dev)
+{
+	if (!dev) {
+		dm_warn("%s: null device", __func__);
+		return NULL;
+	}
+
+	return dev->parent_platdata;
+}
+
 void *dev_get_priv(struct udevice *dev)
 {
 	if (!dev) {
diff --git a/include/dm/device.h b/include/dm/device.h
index 13598a1..096d84b 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -26,6 +26,9 @@ struct driver_info;
 /* DM should init this device prior to relocation */
 #define DM_FLAG_PRE_RELOC	(1 << 2)
 
+/* DM is responsible for allocating and freeing parent_platdata */
+#define DM_FLAG_ALLOC_PARENT_PDATA	(1 << 3)
+
 /**
  * struct udevice - An instance of a driver
  *
@@ -46,6 +49,7 @@ struct driver_info;
  * @driver: The driver used by this device
  * @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
  * @of_offset: Device tree node offset for this device (- for none)
  * @of_id: Pointer to the udevice_id structure which created the device
  * @parent: Parent of this device, or NULL for the top level device
@@ -65,6 +69,7 @@ struct udevice {
 	struct driver *driver;
 	const char *name;
 	void *platdata;
+	void *parent_platdata;
 	int of_offset;
 	const struct udevice_id *of_id;
 	struct udevice *parent;
@@ -146,6 +151,9 @@ struct udevice_id {
  * device_probe_child() pass it in. So far the use case for allocating it
  * is SPI, but I found that unsatisfactory. Since it is here I will leave it
  * until things are clearer.
+ * @per_child_platdata_auto_alloc_size: A bus likes to store information about
+ * its children. If non-zero this is the size of this data, to be allocated
+ * in the child's parent_platdata pointer.
  * @ops: Driver-specific operations. This is typically a list of function
  * pointers defined by the driver, to implement driver functions required by
  * the uclass.
@@ -165,6 +173,7 @@ struct driver {
 	int priv_auto_alloc_size;
 	int platdata_auto_alloc_size;
 	int per_child_auto_alloc_size;
+	int per_child_platdata_auto_alloc_size;
 	const void *ops;	/* driver-specific operations */
 	uint32_t flags;
 };
@@ -184,6 +193,16 @@ struct driver {
 void *dev_get_platdata(struct udevice *dev);
 
 /**
+ * dev_get_parent_platdata() - Get the parent platform data for a device
+ *
+ * This checks that dev is not NULL, but no other checks for now
+ *
+ * @dev		Device to check
+ * @return parent's platform data, or NULL if none
+ */
+void *dev_get_parent_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/test/dm/bus.c b/test/dm/bus.c
index abbaccf..63c8a9f 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -9,11 +9,16 @@
 #include <dm/device-internal.h>
 #include <dm/root.h>
 #include <dm/test.h>
+#include <dm/uclass-internal.h>
 #include <dm/ut.h>
 #include <dm/util.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+struct dm_test_parent_platdata {
+	int count;
+};
+
 enum {
 	FLAG_CHILD_PROBED	= 10,
 	FLAG_CHILD_REMOVED	= -7,
@@ -62,6 +67,8 @@ U_BOOT_DRIVER(testbus_drv) = {
 	.priv_auto_alloc_size = sizeof(struct dm_test_priv),
 	.platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
 	.per_child_auto_alloc_size = sizeof(struct dm_test_parent_data),
+	.per_child_platdata_auto_alloc_size =
+			sizeof(struct dm_test_parent_platdata),
 	.child_pre_probe = testbus_child_pre_probe,
 	.child_post_remove = testbus_child_post_remove,
 };
@@ -271,3 +278,77 @@ static int dm_test_bus_parent_ops(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_bus_parent_ops, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that the bus can store platform data about each child */
+static int dm_test_bus_parent_platdata(struct dm_test_state *dms)
+{
+	struct dm_test_parent_platdata *plat;
+	struct udevice *bus, *dev;
+	int child_count;
+
+	/* Check that the bus has no children */
+	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
+	device_find_first_child(bus, &dev);
+	ut_asserteq_ptr(NULL, dev);
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
+
+	for (device_find_first_child(bus, &dev), child_count = 0;
+	     dev;
+	     device_find_next_child(&dev)) {
+		/* Check that platform data is allocated */
+		plat = dev_get_parent_platdata(dev);
+		ut_assert(plat != NULL);
+
+		/*
+		 * Check that it is not affected by the device being
+		 * probed/removed
+		 */
+		plat->count++;
+		ut_asserteq(1, plat->count);
+		device_probe(dev);
+		device_remove(dev);
+
+		ut_asserteq_ptr(plat, dev_get_parent_platdata(dev));
+		ut_asserteq(1, plat->count);
+		ut_assertok(device_probe(dev));
+		child_count++;
+	}
+	ut_asserteq(3, child_count);
+
+	/* Removing the bus should also have no effect (it is still bound) */
+	device_remove(bus);
+	for (device_find_first_child(bus, &dev), child_count = 0;
+	     dev;
+	     device_find_next_child(&dev)) {
+		/* Check that platform data is allocated */
+		plat = dev_get_parent_platdata(dev);
+		ut_assert(plat != NULL);
+		ut_asserteq(1, plat->count);
+		child_count++;
+	}
+	ut_asserteq(3, child_count);
+
+	/* Unbind all the children */
+	do {
+		device_find_first_child(bus, &dev);
+		if (dev)
+			device_unbind(dev);
+	} while (dev);
+
+	/* Now the child platdata should be removed and re-added */
+	device_probe(bus);
+	for (device_find_first_child(bus, &dev), child_count = 0;
+	     dev;
+	     device_find_next_child(&dev)) {
+		/* Check that platform data is allocated */
+		plat = dev_get_parent_platdata(dev);
+		ut_assert(plat != NULL);
+		ut_asserteq(0, plat->count);
+		child_count++;
+	}
+	ut_asserteq(3, child_count);
+
+	return 0;
+}
+DM_TEST(dm_test_bus_parent_platdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 07/21] dm: core: Allow uclasses to specific the platdata for a device's children
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (5 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 06/21] dm: core: Allow parents to have platform data for their children Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 08/21] dm: core: Add a post_bind method for parents Simon Glass
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

In many cases the child platform data for a device's children is defined by
the uclass rather than the individual devices. For example, a SPI bus needs
to know the chip select and speed for each of its children. It makes sense
to allow this information to be defined the SPI uclass rather than each
individual driver.

If the device provides a size value for its child platdata, then use it.
Failng that, fall back to that provided by the uclass.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/device.c |  4 ++++
 include/dm/uclass.h   |  5 +++++
 test/dm/bus.c         | 32 ++++++++++++++++++++++++++++++--
 3 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index 0682e2e..8791688 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -83,6 +83,10 @@ int device_bind(struct udevice *parent, struct driver *drv, const char *name,
 	if (parent && !dev->parent_platdata) {
 		int size = parent->driver->per_child_platdata_auto_alloc_size;
 
+		if (!size) {
+			size = parent->uclass->uc_drv->
+					per_child_platdata_auto_alloc_size;
+		}
 		if (size) {
 			dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
 			dev->parent_platdata = calloc(1, size);
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 2577ae6..7d92d34 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -60,6 +60,10 @@ 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_child_platdata_auto_alloc_size: A bus likes to store information about
+ * its children. If non-zero this is the size of this data, to be allocated
+ * in the child device's parent_platdata pointer. This value is only used as
+ * a falback if this member is 0 in the driver.
  * @ops: Uclass operations, providing the consistent interface to devices
  * within the uclass.
  */
@@ -74,6 +78,7 @@ struct uclass_driver {
 	int (*destroy)(struct uclass *class);
 	int priv_auto_alloc_size;
 	int per_device_auto_alloc_size;
+	int per_child_platdata_auto_alloc_size;
 	const void *ops;
 };
 
diff --git a/test/dm/bus.c b/test/dm/bus.c
index 63c8a9f..26b8293 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -279,8 +279,7 @@ static int dm_test_bus_parent_ops(struct dm_test_state *dms)
 }
 DM_TEST(dm_test_bus_parent_ops, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
-/* Test that the bus can store platform data about each child */
-static int dm_test_bus_parent_platdata(struct dm_test_state *dms)
+static int test_bus_parent_platdata(struct dm_test_state *dms)
 {
 	struct dm_test_parent_platdata *plat;
 	struct udevice *bus, *dev;
@@ -351,4 +350,33 @@ static int dm_test_bus_parent_platdata(struct dm_test_state *dms)
 
 	return 0;
 }
+
+/* Test that the bus can store platform data about each child */
+static int dm_test_bus_parent_platdata(struct dm_test_state *dms)
+{
+	return test_bus_parent_platdata(dms);
+}
 DM_TEST(dm_test_bus_parent_platdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* As above but the size is controlled by the uclass */
+static int dm_test_bus_parent_platdata_uclass(struct dm_test_state *dms)
+{
+	struct udevice *bus;
+	int size;
+	int ret;
+
+	/* Set the driver size to 0 so that the uclass size is used */
+	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
+	size = bus->driver->per_child_platdata_auto_alloc_size;
+	bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = size;
+	bus->driver->per_child_platdata_auto_alloc_size = 0;
+	ret = test_bus_parent_platdata(dms);
+	if (ret)
+		return ret;
+	bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = 0;
+	bus->driver->per_child_platdata_auto_alloc_size = size;
+
+	return 0;
+}
+DM_TEST(dm_test_bus_parent_platdata_uclass,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 08/21] dm: core: Add a post_bind method for parents
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (6 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 07/21] dm: core: Allow uclasses to specific the platdata for a device's children Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 09/21] dm: core: Add a function to get a device's uclass ID Simon Glass
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

Allow parent drivers to be called when a new child is bound to them. This
allows a bus to set up information it needs for that child.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/device.c | 12 ++++++++++++
 include/dm/device.h   |  2 ++
 test/dm/bus.c         | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index 8791688..aa54575 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -111,12 +111,24 @@ int device_bind(struct udevice *parent, struct driver *drv, const char *name,
 		if (ret)
 			goto fail_bind;
 	}
+	if (parent && parent->driver->child_post_bind) {
+		ret = parent->driver->child_post_bind(dev);
+		if (ret)
+			goto fail_child_post_bind;
+	}
+
 	if (parent)
 		dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
 	*devp = dev;
 
 	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);
+	}
+
 fail_bind:
 	if (uclass_unbind_device(dev)) {
 		dm_warn("Failed to unbind dev '%s' on error path\n",
diff --git a/include/dm/device.h b/include/dm/device.h
index 096d84b..50f1b4f 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -132,6 +132,7 @@ struct udevice_id {
  * @remove: Called to remove a device, i.e. de-activate it
  * @unbind: Called to unbind a device from its driver
  * @ofdata_to_platdata: Called before probe to decode device tree data
+ * @child_post_bind: Called after a new child has been bound
  * @child_pre_probe: Called before a child device is probed. The device has
  * memory allocated but it has not yet been probed.
  * @child_post_remove: Called after a child device is removed. The device
@@ -168,6 +169,7 @@ struct driver {
 	int (*remove)(struct udevice *dev);
 	int (*unbind)(struct udevice *dev);
 	int (*ofdata_to_platdata)(struct udevice *dev);
+	int (*child_post_bind)(struct udevice *dev);
 	int (*child_pre_probe)(struct udevice *dev);
 	int (*child_post_remove)(struct udevice *dev);
 	int priv_auto_alloc_size;
diff --git a/test/dm/bus.c b/test/dm/bus.c
index 26b8293..e18a6f7 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -17,6 +17,7 @@ DECLARE_GLOBAL_DATA_PTR;
 
 struct dm_test_parent_platdata {
 	int count;
+	int bind_flag;
 };
 
 enum {
@@ -31,6 +32,16 @@ static int testbus_drv_probe(struct udevice *dev)
 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
 }
 
+static int testbus_child_post_bind(struct udevice *dev)
+{
+	struct dm_test_parent_platdata *plat;
+
+	plat = dev_get_parent_platdata(dev);
+	plat->bind_flag = 1;
+
+	return 0;
+}
+
 static int testbus_child_pre_probe(struct udevice *dev)
 {
 	struct dm_test_parent_data *parent_data = dev_get_parentdata(dev);
@@ -64,6 +75,7 @@ U_BOOT_DRIVER(testbus_drv) = {
 	.of_match	= testbus_ids,
 	.id	= UCLASS_TEST_BUS,
 	.probe	= testbus_drv_probe,
+	.child_post_bind = testbus_child_post_bind,
 	.priv_auto_alloc_size = sizeof(struct dm_test_priv),
 	.platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
 	.per_child_auto_alloc_size = sizeof(struct dm_test_parent_data),
@@ -380,3 +392,26 @@ static int dm_test_bus_parent_platdata_uclass(struct dm_test_state *dms)
 }
 DM_TEST(dm_test_bus_parent_platdata_uclass,
 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that the child post_bind method is called */
+static int dm_test_bus_child_post_bind(struct dm_test_state *dms)
+{
+	struct dm_test_parent_platdata *plat;
+	struct udevice *bus, *dev;
+	int child_count;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
+	for (device_find_first_child(bus, &dev), child_count = 0;
+	     dev;
+	     device_find_next_child(&dev)) {
+		/* Check that platform data is allocated */
+		plat = dev_get_parent_platdata(dev);
+		ut_assert(plat != NULL);
+		ut_asserteq(1, plat->bind_flag);
+		child_count++;
+	}
+	ut_asserteq(3, child_count);
+
+	return 0;
+}
+DM_TEST(dm_test_bus_child_post_bind, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 09/21] dm: core: Add a function to get a device's uclass ID
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (7 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 08/21] dm: core: Add a post_bind method for parents Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 10/21] dm: core: Add a flag to control sequence numbering Simon Glass
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

This is useful to check which uclass a device is in.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/device.c |  5 +++++
 include/dm/device.h   |  8 ++++++++
 test/dm/core.c        | 11 +++++++++++
 3 files changed, 24 insertions(+)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index aa54575..c284730 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -438,3 +438,8 @@ ulong dev_get_of_data(struct udevice *dev)
 {
 	return dev->of_id->data;
 }
+
+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 50f1b4f..81afa8c 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -245,6 +245,14 @@ struct udevice *dev_get_parent(struct udevice *child);
  */
 ulong dev_get_of_data(struct udevice *dev);
 
+/*
+ * device_get_uclass_id() - return the uclass ID of a device
+ *
+ * @dev:	Device to check
+ * @return uclass ID for the device
+ */
+enum uclass_id device_get_uclass_id(struct udevice *dev);
+
 /**
  * device_get_child() - Get the child of a device by index
  *
diff --git a/test/dm/core.c b/test/dm/core.c
index ff5c2a7..eccda09 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -598,3 +598,14 @@ static int dm_test_uclass_before_ready(struct dm_test_state *dms)
 }
 
 DM_TEST(dm_test_uclass_before_ready, 0);
+
+static int dm_test_device_get_uclass_id(struct dm_test_state *dms)
+{
+	struct udevice *dev;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST, 0, &dev));
+	ut_asserteq(UCLASS_TEST, device_get_uclass_id(dev));
+
+	return 0;
+}
+DM_TEST(dm_test_device_get_uclass_id, DM_TESTF_SCAN_PDATA);
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 10/21] dm: core: Add a flag to control sequence numbering
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (8 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 09/21] dm: core: Add a function to get a device's uclass ID Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 11/21] dm: core: Allow uclasses to specific the private data for a device's children Simon Glass
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

At present we try to use the 'reg' property and device tree aliases to give
devices a sequence number. The 'reg' property is often actually a memory
address, so the sequence numbers thus-obtained are not useful. It would be
better if the devices were just sequentially numbered in that case. In fact
neither I2C nor SPI use this feature, so drop it.

Some devices need us to look up an alias to number them within the uclass.
Add a flag to control this, so it is not done unless it is needed.

Adjust the tests to test this new behaviour.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 doc/driver-model/README.txt    | 51 +++++++++++-------------------------------
 drivers/core/device.c          | 28 +++++++++++------------
 drivers/i2c/i2c-uclass.c       |  1 +
 drivers/serial/serial-uclass.c |  1 +
 drivers/spi/spi-uclass.c       |  1 +
 include/dm/uclass.h            |  5 +++++
 test/dm/bus.c                  |  3 ++-
 test/dm/test-fdt.c             |  9 ++++----
 test/dm/test.dts               | 16 +++++++++++++
 9 files changed, 57 insertions(+), 58 deletions(-)

diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt
index 4041569..2fc900b 100644
--- a/doc/driver-model/README.txt
+++ b/doc/driver-model/README.txt
@@ -388,12 +388,12 @@ Device Sequence Numbers
 U-Boot numbers devices from 0 in many situations, such as in the command
 line for I2C and SPI buses, and the device names for serial ports (serial0,
 serial1, ...). Driver model supports this numbering and permits devices
-to be locating by their 'sequence'. This numbering unique identifies a
+to be locating by their 'sequence'. This numbering uniquely identifies a
 device in its uclass, so no two devices within a particular uclass can have
 the same sequence number.
 
 Sequence numbers start from 0 but gaps are permitted. For example, a board
-may have I2C buses 0, 1, 4, 5 but no 2 or 3. The choice of how devices are
+may have I2C buses 1, 4, 5 but no 0, 2 or 3. The choice of how devices are
 numbered is up to a particular board, and may be set by the SoC in some
 cases. While it might be tempting to automatically renumber the devices
 where there are gaps in the sequence, this can lead to confusion and is
@@ -403,7 +403,7 @@ Each device can request a sequence number. If none is required then the
 device will be automatically allocated the next available sequence number.
 
 To specify the sequence number in the device tree an alias is typically
-used.
+used. Make sure that the uclass has the DM_UC_FLAG_SEQ_ALIAS flag set.
 
 aliases {
 	serial2 = "/serial at 22230000";
@@ -413,43 +413,18 @@ This indicates that in the uclass called "serial", the named node
 ("/serial at 22230000") will be given sequence number 2. Any command or driver
 which requests serial device 2 will obtain this device.
 
-Some devices represent buses where the devices on the bus are numbered or
-addressed. For example, SPI typically numbers its slaves from 0, and I2C
-uses a 7-bit address. In these cases the 'reg' property of the subnode is
-used, for example:
+More commonly you can use phandles:
 
-{
-	aliases {
-		spi2 = "/spi at 22300000";
-	};
-
-	spi at 22300000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		spi-flash at 0 {
-			reg = <0>;
-			...
-		}
-		eeprom at 1 {
-			reg = <1>;
-		};
-	};
-
-In this case we have a SPI bus with two slaves at 0 and 1. The SPI bus
-itself is numbered 2. So we might access the SPI flash with:
-
-	sf probe 2:0
-
-and the eeprom with
-
-	sspi 2:1 32 ef
-
-These commands simply need to look up the 2nd device in the SPI uclass to
-find the right SPI bus. Then, they look at the children of that bus for the
-right sequence number (0 or 1 in this case).
+aliases {
+	serial2 = &serial_2;
+};
+...
+serial_2: serial at 22230000 {
+...
+};
 
-Typically the alias method is used for top-level nodes and the 'reg' method
-is used only for buses.
+The alias resolves to the same string in this case, but this version is
+easier to read.
 
 Device sequence numbers are resolved when a device is probed. Before then
 the sequence number is only a request which may or may not be honoured,
diff --git a/drivers/core/device.c b/drivers/core/device.c
index c284730..a149a7a 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -53,24 +53,22 @@ int device_bind(struct udevice *parent, struct driver *drv, const char *name,
 	dev->driver = drv;
 	dev->uclass = uc;
 
-	/*
-	 * For some devices, such as a SPI or I2C bus, the 'reg' property
-	 * is a reasonable indicator of the sequence number. But if there is
-	 * an alias, we use that in preference. In any case, this is just
-	 * a 'requested' sequence, and will be resolved (and ->seq updated)
-	 * when the device is probed.
-	 */
 	dev->seq = -1;
+	dev->req_seq = -1;
 #ifdef CONFIG_OF_CONTROL
-	dev->req_seq = fdtdec_get_int(gd->fdt_blob, of_offset, "reg", -1);
-	if (!IS_ERR_VALUE(dev->req_seq))
-		dev->req_seq &= INT_MAX;
-	if (uc->uc_drv->name && of_offset != -1) {
-		fdtdec_get_alias_seq(gd->fdt_blob, uc->uc_drv->name, of_offset,
-				     &dev->req_seq);
+	/*
+	 * 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);
+		}
 	}
-#else
-	dev->req_seq = -1;
 #endif
 	if (!dev->platdata && drv->platdata_auto_alloc_size) {
 		dev->flags |= DM_FLAG_ALLOC_PDATA;
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
index 25f2c18..0048f11 100644
--- a/drivers/i2c/i2c-uclass.c
+++ b/drivers/i2c/i2c-uclass.c
@@ -451,6 +451,7 @@ int i2c_post_bind(struct udevice *dev)
 UCLASS_DRIVER(i2c) = {
 	.id		= UCLASS_I2C,
 	.name		= "i2c",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 	.per_device_auto_alloc_size = sizeof(struct dm_i2c_bus),
 	.post_bind	= i2c_post_bind,
 	.post_probe	= i2c_post_probe,
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index d1b5777..9131a8f 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -297,6 +297,7 @@ static int serial_pre_remove(struct udevice *dev)
 UCLASS_DRIVER(serial) = {
 	.id		= UCLASS_SERIAL,
 	.name		= "serial",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 	.post_probe	= serial_post_probe,
 	.pre_remove	= serial_pre_remove,
 	.per_device_auto_alloc_size = sizeof(struct serial_dev_priv),
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 7a57bce..35756ad 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -344,6 +344,7 @@ int spi_ofdata_to_platdata(const void *blob, int node,
 UCLASS_DRIVER(spi) = {
 	.id		= UCLASS_SPI,
 	.name		= "spi",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 	.post_bind	= spi_post_bind,
 	.post_probe	= spi_post_probe,
 	.per_device_auto_alloc_size = sizeof(struct dm_spi_bus),
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 7d92d34..9000b22 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -40,6 +40,9 @@ struct uclass {
 
 struct udevice;
 
+/* Members of this uclass sequence themselves with aliases */
+#define DM_UC_FLAG_SEQ_ALIAS			(1 << 0)
+
 /**
  * struct uclass_driver - Driver for the uclass
  *
@@ -66,6 +69,7 @@ struct udevice;
  * a falback if this member is 0 in the driver.
  * @ops: Uclass operations, providing the consistent interface to devices
  * within the uclass.
+ * @flags: Flags for this uclass (DM_UC_...)
  */
 struct uclass_driver {
 	const char *name;
@@ -80,6 +84,7 @@ struct uclass_driver {
 	int per_device_auto_alloc_size;
 	int per_child_platdata_auto_alloc_size;
 	const void *ops;
+	uint32_t flags;
 };
 
 /* Declare a new uclass_driver */
diff --git a/test/dm/bus.c b/test/dm/bus.c
index e18a6f7..972c449 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -88,12 +88,13 @@ U_BOOT_DRIVER(testbus_drv) = {
 UCLASS_DRIVER(testbus) = {
 	.name		= "testbus",
 	.id		= UCLASS_TEST_BUS,
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 };
 
 /* Test that we can probe for children */
 static int dm_test_bus_children(struct dm_test_state *dms)
 {
-	int num_devices = 4;
+	int num_devices = 6;
 	struct udevice *bus;
 	struct uclass *uc;
 
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index dc4ebf9..dfcb3af 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -89,6 +89,7 @@ int testfdt_ping(struct udevice *dev, int pingval, int *pingret)
 UCLASS_DRIVER(testfdt) = {
 	.name		= "testfdt",
 	.id		= UCLASS_TEST_FDT,
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 };
 
 int dm_check_devices(struct dm_test_state *dms, int num_devices)
@@ -128,7 +129,7 @@ int dm_check_devices(struct dm_test_state *dms, int num_devices)
 /* Test that FDT-based binding works correctly */
 static int dm_test_fdt(struct dm_test_state *dms)
 {
-	const int num_devices = 4;
+	const int num_devices = 6;
 	struct udevice *dev;
 	struct uclass *uc;
 	int ret;
@@ -184,7 +185,7 @@ static int dm_test_fdt_uclass_seq(struct dm_test_state *dms)
 	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 3, true, &dev));
 	ut_asserteq_str("b-test", dev->name);
 
-	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 0, true, &dev));
+	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 8, true, &dev));
 	ut_asserteq_str("a-test", dev->name);
 
 	ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 5,
@@ -220,11 +221,11 @@ static int dm_test_fdt_uclass_seq(struct dm_test_state *dms)
 	ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_TEST_FDT, 1,
 						      &dev));
 	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
-	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 1, &dev));
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 4, &dev));
 
 	/* But now that it is probed, we can find it */
 	ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, &dev));
-	ut_asserteq_str("a-test", dev->name);
+	ut_asserteq_str("f-test", dev->name);
 
 	return 0;
 }
diff --git a/test/dm/test.dts b/test/dm/test.dts
index 33f2c00..84024a4 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -8,7 +8,15 @@
 
 	aliases {
 		console = &uart0;
+		i2c0 = "/i2c at 0";
+		spi0 = "/spi at 0";
 		testfdt6 = "/e-test";
+		testbus3 = "/some-bus";
+		testfdt0 = "/some-bus/c-test at 0";
+		testfdt1 = "/some-bus/c-test at 1";
+		testfdt3 = "/b-test";
+		testfdt5 = "/some-bus/c-test at 5";
+		testfdt8 = "/a-test";
 	};
 
 	uart0: serial {
@@ -86,6 +94,14 @@
 		compatible = "google,another-fdt-test";
 	};
 
+	f-test {
+		compatible = "denx,u-boot-fdt-test";
+	};
+
+	g-test {
+		compatible = "denx,u-boot-fdt-test";
+	};
+
 	gpio_a: base-gpios {
 		compatible = "sandbox,gpio";
 		gpio-controller;
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 11/21] dm: core: Allow uclasses to specific the private data for a device's children
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (9 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 10/21] dm: core: Add a flag to control sequence numbering Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 12/21] dm: spi: Move the per-child data size to the uclass Simon Glass
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

In many cases the per-child private data for a device's children is defined
by the uclass rather than the individual driver. For example, a SPI bus
needs to store information about each of its children, but all SPI drivers
store the same information. It makes sense to allow the uclass to define
this data.

If the driver provides a size value for its per-child private data, then use
it. Failng that, fall back to that provided by the uclass.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/device-remove.c |  4 ++++
 drivers/core/device.c        |  4 ++++
 include/dm/uclass.h          |  4 ++++
 test/dm/bus.c                | 31 +++++++++++++++++++++++++++++--
 4 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 56c358a..3a5f48d 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -126,6 +126,10 @@ void device_free(struct udevice *dev)
 	}
 	if (dev->parent) {
 		size = dev->parent->driver->per_child_auto_alloc_size;
+		if (!size) {
+			size = dev->parent->uclass->uc_drv->
+					per_child_auto_alloc_size;
+		}
 		if (size) {
 			free(dev->parent_priv);
 			dev->parent_priv = NULL;
diff --git a/drivers/core/device.c b/drivers/core/device.c
index a149a7a..2639fcb 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -201,6 +201,10 @@ int device_probe_child(struct udevice *dev, void *parent_priv)
 	/* Ensure all parents are probed */
 	if (dev->parent) {
 		size = dev->parent->driver->per_child_auto_alloc_size;
+		if (!size) {
+			size = dev->parent->uclass->uc_drv->
+					per_child_auto_alloc_size;
+		}
 		if (size) {
 			dev->parent_priv = calloc(1, size);
 			if (!dev->parent_priv) {
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 9000b22..ac6c850 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -63,6 +63,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_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.
  * @per_child_platdata_auto_alloc_size: A bus likes to store information about
  * its children. If non-zero this is the size of this data, to be allocated
  * in the child device's parent_platdata pointer. This value is only used as
@@ -82,6 +85,7 @@ struct uclass_driver {
 	int (*destroy)(struct uclass *class);
 	int priv_auto_alloc_size;
 	int per_device_auto_alloc_size;
+	int per_child_auto_alloc_size;
 	int per_child_platdata_auto_alloc_size;
 	const void *ops;
 	uint32_t flags;
diff --git a/test/dm/bus.c b/test/dm/bus.c
index 972c449..e909697 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -192,7 +192,7 @@ DM_TEST(dm_test_bus_children_iterators,
 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
 /* Test that the bus can store data about each child */
-static int dm_test_bus_parent_data(struct dm_test_state *dms)
+static int test_bus_parent_data(struct dm_test_state *dms)
 {
 	struct dm_test_parent_data *parent_data;
 	struct udevice *bus, *dev;
@@ -251,9 +251,36 @@ static int dm_test_bus_parent_data(struct dm_test_state *dms)
 
 	return 0;
 }
-
+/* Test that the bus can store data about each child */
+static int dm_test_bus_parent_data(struct dm_test_state *dms)
+{
+	return test_bus_parent_data(dms);
+}
 DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
+/* As above but the size is controlled by the uclass */
+static int dm_test_bus_parent_data_uclass(struct dm_test_state *dms)
+{
+	struct udevice *bus;
+	int size;
+	int ret;
+
+	/* Set the driver size to 0 so that the uclass size is used */
+	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
+	size = bus->driver->per_child_auto_alloc_size;
+	bus->uclass->uc_drv->per_child_auto_alloc_size = size;
+	bus->driver->per_child_auto_alloc_size = 0;
+	ret = test_bus_parent_data(dms);
+	if (ret)
+		return ret;
+	bus->uclass->uc_drv->per_child_auto_alloc_size = 0;
+	bus->driver->per_child_auto_alloc_size = size;
+
+	return 0;
+}
+DM_TEST(dm_test_bus_parent_data_uclass,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
 /* Test that the bus ops are called when a child is probed/removed */
 static int dm_test_bus_parent_ops(struct dm_test_state *dms)
 {
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 12/21] dm: spi: Move the per-child data size to the uclass
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (10 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 11/21] dm: core: Allow uclasses to specific the private data for a device's children Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 13/21] dm: core: Allow the uclass to set up a device's child after binding Simon Glass
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

This is common to all SPI drivers and specifies a structure used by the
uclass. It makes more sense to define it in the uclass.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/spi/cadence_qspi.c   | 1 -
 drivers/spi/designware_spi.c | 1 -
 drivers/spi/exynos_spi.c     | 1 -
 drivers/spi/sandbox_spi.c    | 1 -
 drivers/spi/soft_spi.c       | 1 -
 drivers/spi/spi-uclass.c     | 1 +
 drivers/spi/tegra114_spi.c   | 1 -
 drivers/spi/tegra20_sflash.c | 1 -
 drivers/spi/tegra20_slink.c  | 1 -
 9 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index 98ae3b8..a75fc46 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -340,6 +340,5 @@ U_BOOT_DRIVER(cadence_spi) = {
 	.ofdata_to_platdata = cadence_spi_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct cadence_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct cadence_spi_priv),
-	.per_child_auto_alloc_size = sizeof(struct spi_slave),
 	.probe = cadence_spi_probe,
 };
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 700f616..2624844 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -421,6 +421,5 @@ U_BOOT_DRIVER(dw_spi) = {
 	.ofdata_to_platdata = dw_spi_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct dw_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct dw_spi_priv),
-	.per_child_auto_alloc_size = sizeof(struct spi_slave),
 	.probe = dw_spi_probe,
 };
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index f078973..a46d8c1 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -425,6 +425,5 @@ U_BOOT_DRIVER(exynos_spi) = {
 	.ofdata_to_platdata = exynos_spi_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct exynos_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct exynos_spi_priv),
-	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
 	.probe	= exynos_spi_probe,
 };
diff --git a/drivers/spi/sandbox_spi.c b/drivers/spi/sandbox_spi.c
index e717424..bad5660 100644
--- a/drivers/spi/sandbox_spi.c
+++ b/drivers/spi/sandbox_spi.c
@@ -160,6 +160,5 @@ U_BOOT_DRIVER(spi_sandbox) = {
 	.name	= "spi_sandbox",
 	.id	= UCLASS_SPI,
 	.of_match = sandbox_spi_ids,
-	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
 	.ops	= &sandbox_spi_ops,
 };
diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c
index 423c98d..9f7d80e 100644
--- a/drivers/spi/soft_spi.c
+++ b/drivers/spi/soft_spi.c
@@ -240,7 +240,6 @@ U_BOOT_DRIVER(soft_spi) = {
 	.ofdata_to_platdata = soft_spi_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct soft_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct soft_spi_priv),
-	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
 	.probe	= soft_spi_probe,
 	.child_pre_probe	= soft_spi_child_pre_probe,
 };
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 35756ad..e5dfb30 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -348,6 +348,7 @@ UCLASS_DRIVER(spi) = {
 	.post_bind	= spi_post_bind,
 	.post_probe	= spi_post_probe,
 	.per_device_auto_alloc_size = sizeof(struct dm_spi_bus),
+	.per_child_auto_alloc_size = sizeof(struct spi_slave),
 };
 
 UCLASS_DRIVER(spi_generic) = {
diff --git a/drivers/spi/tegra114_spi.c b/drivers/spi/tegra114_spi.c
index 2d97625..53ff9ea 100644
--- a/drivers/spi/tegra114_spi.c
+++ b/drivers/spi/tegra114_spi.c
@@ -407,6 +407,5 @@ U_BOOT_DRIVER(tegra114_spi) = {
 	.ofdata_to_platdata = tegra114_spi_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct tegra_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct tegra114_spi_priv),
-	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
 	.probe	= tegra114_spi_probe,
 };
diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c
index 7d0d0f3..78c74cd 100644
--- a/drivers/spi/tegra20_sflash.c
+++ b/drivers/spi/tegra20_sflash.c
@@ -348,6 +348,5 @@ U_BOOT_DRIVER(tegra20_sflash) = {
 	.ofdata_to_platdata = tegra20_sflash_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct tegra_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct tegra20_sflash_priv),
-	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
 	.probe	= tegra20_sflash_probe,
 };
diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c
index 213fa5f..597d6ad 100644
--- a/drivers/spi/tegra20_slink.c
+++ b/drivers/spi/tegra20_slink.c
@@ -361,6 +361,5 @@ U_BOOT_DRIVER(tegra30_spi) = {
 	.ofdata_to_platdata = tegra30_spi_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct tegra_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct tegra30_spi_priv),
-	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
 	.probe	= tegra30_spi_probe,
 };
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 13/21] dm: core: Allow the uclass to set up a device's child after binding
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (11 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 12/21] dm: spi: Move the per-child data size to the uclass Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 14/21] dm: sandbox: sf: Tidy up the error handling in sandbox_sf_probe() Simon Glass
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

For buses, after a child is bound, allow the uclass to perform some
processing. This can be used to figure out the address of the child (e.g.
the chip select for SPI slaves) so that it is ready to be probed.

This avoids bus drivers having to repeat the same process, which really
should be done by the uclass, since it is common.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/uclass.c | 21 ++++++++++++++++-----
 include/dm/uclass.h   |  2 ++
 test/dm/bus.c         | 26 ++++++++++++++++++++++++++
 3 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 901b06e..29811be 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -319,18 +319,29 @@ int uclass_bind_device(struct udevice *dev)
 	int ret;
 
 	uc = dev->uclass;
-
 	list_add_tail(&dev->uclass_node, &uc->dev_head);
 
+	if (dev->parent) {
+		struct uclass_driver *parent_drv = dev->parent->uclass->uc_drv;
+
+		if (parent_drv->child_post_bind) {
+			ret = parent_drv->child_post_bind(dev);
+			if (ret)
+				goto err;
+		}
+	}
 	if (uc->uc_drv->post_bind) {
 		ret = uc->uc_drv->post_bind(dev);
-		if (ret) {
-			list_del(&dev->uclass_node);
-			return ret;
-		}
+		if (ret)
+			goto err;
 	}
 
 	return 0;
+err:
+	/* There is no need to undo the parent's post_bind call */
+	list_del(&dev->uclass_node);
+
+	return ret;
 }
 
 int uclass_unbind_device(struct udevice *dev)
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index ac6c850..5c5b8f4 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -55,6 +55,7 @@ struct udevice;
  * @pre_unbind: Called before a device is unbound from this uclass
  * @post_probe: Called after a new device is probed
  * @pre_remove: Called before a device is removed
+ * @child_post_bind: Called after a child is bound to a device in this uclass
  * @init: Called to set up the uclass
  * @destroy: Called to destroy the uclass
  * @priv_auto_alloc_size: If non-zero this is the size of the private data
@@ -81,6 +82,7 @@ struct uclass_driver {
 	int (*pre_unbind)(struct udevice *dev);
 	int (*post_probe)(struct udevice *dev);
 	int (*pre_remove)(struct udevice *dev);
+	int (*child_post_bind)(struct udevice *dev);
 	int (*init)(struct uclass *class);
 	int (*destroy)(struct uclass *class);
 	int priv_auto_alloc_size;
diff --git a/test/dm/bus.c b/test/dm/bus.c
index e909697..c123ed7 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -18,6 +18,7 @@ DECLARE_GLOBAL_DATA_PTR;
 struct dm_test_parent_platdata {
 	int count;
 	int bind_flag;
+	int uclass_bind_flag;
 };
 
 enum {
@@ -38,6 +39,7 @@ static int testbus_child_post_bind(struct udevice *dev)
 
 	plat = dev_get_parent_platdata(dev);
 	plat->bind_flag = 1;
+	plat->uclass_bind_flag = 2;
 
 	return 0;
 }
@@ -443,3 +445,27 @@ static int dm_test_bus_child_post_bind(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_bus_child_post_bind, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that the child post_bind method is called */
+static int dm_test_bus_child_post_bind_uclass(struct dm_test_state *dms)
+{
+	struct dm_test_parent_platdata *plat;
+	struct udevice *bus, *dev;
+	int child_count;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
+	for (device_find_first_child(bus, &dev), child_count = 0;
+	     dev;
+	     device_find_next_child(&dev)) {
+		/* Check that platform data is allocated */
+		plat = dev_get_parent_platdata(dev);
+		ut_assert(plat != NULL);
+		ut_asserteq(2, plat->uclass_bind_flag);
+		child_count++;
+	}
+	ut_asserteq(3, child_count);
+
+	return 0;
+}
+DM_TEST(dm_test_bus_child_post_bind_uclass,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 14/21] dm: sandbox: sf: Tidy up the error handling in sandbox_sf_probe()
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (12 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 13/21] dm: core: Allow the uclass to set up a device's child after binding Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 15/21] dm: core: Allow uclass to set up a device's child before it is probed Simon Glass
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

Use a single exit point when we have an error and add debugging there.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/mtd/spi/sandbox.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c
index 3024b98..106dda9 100644
--- a/drivers/mtd/spi/sandbox.c
+++ b/drivers/mtd/spi/sandbox.c
@@ -141,8 +141,10 @@ static int sandbox_sf_probe(struct udevice *dev)
 		assert(bus->seq != -1);
 		if (bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS)
 			spec = state->spi[bus->seq][cs].spec;
-		if (!spec)
-			return -ENOENT;
+		if (!spec) {
+			ret = -ENOENT;
+			goto error;
+		}
 
 		file = strchr(spec, ':');
 		if (!file) {
@@ -196,6 +198,7 @@ static int sandbox_sf_probe(struct udevice *dev)
 	return 0;
 
  error:
+	debug("%s: Got error %d\n", __func__, ret);
 	return ret;
 }
 
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 15/21] dm: core: Allow uclass to set up a device's child before it is probed
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (13 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 14/21] dm: sandbox: sf: Tidy up the error handling in sandbox_sf_probe() Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 16/21] dm: spi: Set up the spi_slave device pointer in child_pre_probe() Simon Glass
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

Some buses need to set up their devices before they can be used. This setup
may well be common to all buses in a particular uclass. Support a common
pre-probe method for the uclass, called before any bus devices are probed.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/device.c        |  4 ++++
 drivers/core/uclass.c        | 13 +++++++++++++
 include/dm/test.h            |  3 +++
 include/dm/uclass-internal.h | 11 +++++++++++
 include/dm/uclass.h          |  1 +
 test/dm/bus.c                | 46 ++++++++++++++++++++++++++++++++++++++++++++
 test/dm/test-fdt.c           |  7 +++++++
 7 files changed, 85 insertions(+)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index 2639fcb..b050272 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -227,6 +227,10 @@ int device_probe_child(struct udevice *dev, void *parent_priv)
 	}
 	dev->seq = seq;
 
+	ret = uclass_pre_probe_child(dev);
+	if (ret)
+		goto fail;
+
 	if (dev->parent && dev->parent->driver->child_pre_probe) {
 		ret = dev->parent->driver->child_pre_probe(dev);
 		if (ret)
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 29811be..8c91370 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -391,6 +391,19 @@ int uclass_resolve_seq(struct udevice *dev)
 	return seq;
 }
 
+int uclass_pre_probe_child(struct udevice *dev)
+{
+	struct uclass_driver *uc_drv;
+
+	if (!dev->parent)
+		return 0;
+	uc_drv = dev->parent->uclass->uc_drv;
+	if (uc_drv->child_pre_probe)
+		return uc_drv->child_pre_probe(dev);
+
+	return 0;
+}
+
 int uclass_post_probe_device(struct udevice *dev)
 {
 	struct uclass_driver *uc_drv = dev->uclass->uc_drv;
diff --git a/include/dm/test.h b/include/dm/test.h
index f08c05d..707c69e 100644
--- a/include/dm/test.h
+++ b/include/dm/test.h
@@ -67,6 +67,8 @@ enum {
 struct dm_test_priv {
 	int ping_total;
 	int op_count[DM_TEST_OP_COUNT];
+	int uclass_flag;
+	int uclass_total;
 };
 
 /**
@@ -88,6 +90,7 @@ struct dm_test_uclass_priv {
  *
  * @sum: Test value used to check parent data works correctly
  * @flag: Used to track calling of parent operations
+ * @uclass_flag: Used to track calling of parent operations by uclass
  */
 struct dm_test_parent_data {
 	int sum;
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index f718f37..f2f254a 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -44,6 +44,17 @@ int uclass_bind_device(struct udevice *dev);
 int uclass_unbind_device(struct udevice *dev);
 
 /**
+ * uclass_pre_probe_child() - Deal with a child that is about to be probed
+ *
+ * Perform any pre-processing that is needed by the uclass before it can be
+ * probed.
+ *
+ * @dev:	Pointer to the device
+ * #return 0 on success, -ve on error
+ */
+int uclass_pre_probe_child(struct udevice *dev);
+
+/**
  * uclass_post_probe_device() - Deal with a device that has just been probed
  *
  * Perform any post-processing of a probed device that is needed by the
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 5c5b8f4..d6c40c6 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -83,6 +83,7 @@ struct uclass_driver {
 	int (*post_probe)(struct udevice *dev);
 	int (*pre_remove)(struct udevice *dev);
 	int (*child_post_bind)(struct udevice *dev);
+	int (*child_pre_probe)(struct udevice *dev);
 	int (*init)(struct uclass *class);
 	int (*destroy)(struct uclass *class);
 	int priv_auto_alloc_size;
diff --git a/test/dm/bus.c b/test/dm/bus.c
index c123ed7..faffe6a 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -53,6 +53,15 @@ static int testbus_child_pre_probe(struct udevice *dev)
 	return 0;
 }
 
+static int testbus_child_pre_probe_uclass(struct udevice *dev)
+{
+	struct dm_test_priv *priv = dev_get_priv(dev);
+
+	priv->uclass_flag++;
+
+	return 0;
+}
+
 static int testbus_child_post_remove(struct udevice *dev)
 {
 	struct dm_test_parent_data *parent_data = dev_get_parentdata(dev);
@@ -91,6 +100,7 @@ UCLASS_DRIVER(testbus) = {
 	.name		= "testbus",
 	.id		= UCLASS_TEST_BUS,
 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
+	.child_pre_probe = testbus_child_pre_probe_uclass,
 };
 
 /* Test that we can probe for children */
@@ -469,3 +479,39 @@ static int dm_test_bus_child_post_bind_uclass(struct dm_test_state *dms)
 }
 DM_TEST(dm_test_bus_child_post_bind_uclass,
 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/*
+ * Test that the bus' uclass' child_pre_probe() is called before the
+ * device's probe() method
+ */
+static int dm_test_bus_child_pre_probe_uclass(struct dm_test_state *dms)
+{
+	struct udevice *bus, *dev;
+	int child_count;
+
+	/*
+	 * See testfdt_drv_probe() which effectively checks that the uclass
+	 * flag is set before that method is called
+	 */
+	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
+	for (device_find_first_child(bus, &dev), child_count = 0;
+	     dev;
+	     device_find_next_child(&dev)) {
+		struct dm_test_priv *priv = dev_get_priv(dev);
+
+		/* Check that things happened in the right order */
+		ut_asserteq_ptr(NULL, priv);
+		ut_assertok(device_probe(dev));
+
+		priv = dev_get_priv(dev);
+		ut_assert(priv != NULL);
+		ut_asserteq(1, priv->uclass_flag);
+		ut_asserteq(1, priv->uclass_total);
+		child_count++;
+	}
+	ut_asserteq(3, child_count);
+
+	return 0;
+}
+DM_TEST(dm_test_bus_child_pre_probe_uclass,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index dfcb3af..b8ee959 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -51,6 +51,13 @@ static int testfdt_drv_probe(struct udevice *dev)
 
 	priv->ping_total += DM_TEST_START_TOTAL;
 
+	/*
+	 * If this device is on a bus, the uclass_flag will be set before
+	 * calling this function. This is used by
+	 * dm_test_bus_child_pre_probe_uclass().
+	 */
+	priv->uclass_total += priv->uclass_flag;
+
 	return 0;
 }
 
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 16/21] dm: spi: Set up the spi_slave device pointer in child_pre_probe()
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (14 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 15/21] dm: core: Allow uclass to set up a device's child before it is probed Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 17/21] dm: spi: Move slave details to child platdata Simon Glass
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

At present we use struct spi_slave as our device pointer in a lot of places
to avoid changing the old SPI API. At some point this will go away.

But for now, it is better if the SPI uclass sets up this pointer, rather
than relying on passing it into the device when it is probed. We can use the
new uclass child_pre_probe() method to do this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/spi/spi-uclass.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index e5dfb30..2c134eb 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -108,6 +108,15 @@ int spi_post_probe(struct udevice *dev)
 	return 0;
 }
 
+int spi_child_pre_probe(struct udevice *dev)
+{
+	struct spi_slave *slave = dev_get_parentdata(dev);
+
+	slave->dev = dev;
+
+	return 0;
+}
+
 int spi_chip_select(struct udevice *dev)
 {
 	struct spi_slave *slave = dev_get_parentdata(dev);
@@ -347,6 +356,7 @@ UCLASS_DRIVER(spi) = {
 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 	.post_bind	= spi_post_bind,
 	.post_probe	= spi_post_probe,
+	.child_pre_probe = spi_child_pre_probe,
 	.per_device_auto_alloc_size = sizeof(struct dm_spi_bus),
 	.per_child_auto_alloc_size = sizeof(struct spi_slave),
 };
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 17/21] dm: spi: Move slave details to child platdata
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (15 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 16/21] dm: spi: Set up the spi_slave device pointer in child_pre_probe() Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 18/21] dm: i2c: " Simon Glass
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

At present we go through various contortions to store the SPI slave's chip
select in its private data. This only exists when the slave is active so
must be set up when it is probed. Until the device is probed we don't
actually know what chip select it will appear on.

However, now that we can support per-child platform data, we can use that
instead. This allows us to set up the chip select when the child is bound,
and avoid the messy contortions.

Unfortunately this is a fairly large change and it seems to be difficult to
break it down further.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/misc/cros_ec_i2c.c | 19 -----------
 drivers/misc/cros_ec_spi.c | 19 -----------
 drivers/mtd/spi/sandbox.c  |  5 +++
 drivers/mtd/spi/sf_probe.c |  3 +-
 drivers/spi/soft_spi.c     |  9 ------
 drivers/spi/spi-uclass.c   | 79 ++++++++++++++++++++++++++--------------------
 include/spi.h              | 29 +++++++++++++----
 test/dm/spi.c              |  6 ++--
 8 files changed, 78 insertions(+), 91 deletions(-)

diff --git a/drivers/misc/cros_ec_i2c.c b/drivers/misc/cros_ec_i2c.c
index 13017e1..3da8556 100644
--- a/drivers/misc/cros_ec_i2c.c
+++ b/drivers/misc/cros_ec_i2c.c
@@ -180,25 +180,6 @@ int cros_ec_i2c_init(struct cros_ec_dev *dev, const void *blob)
 #ifdef CONFIG_DM_CROS_EC
 static int cros_ec_probe(struct udevice *dev)
 {
-	struct spi_slave *slave = dev_get_parentdata(dev);
-	int ret;
-
-	/*
-	 * TODO(sjg at chromium.org)
-	 *
-	 * This is really horrible at present. It is an artifact of removing
-	 * the child_pre_probe() method for SPI. Everything here could go in
-	 * an automatic function, except that spi_get_bus_and_cs() wants to
-	 * set it up manually and call device_probe_child().
-	 *
-	 * The solution may be to re-enable the child_pre_probe() method for
-	 * SPI and have it do nothing if the child is already passed in via
-	 * device_probe_child().
-	 */
-	slave->dev = dev;
-	ret = spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, slave);
-	if (ret)
-		return ret;
 	return cros_ec_register(dev);
 }
 
diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c
index 92eace2..7f696d9 100644
--- a/drivers/misc/cros_ec_spi.c
+++ b/drivers/misc/cros_ec_spi.c
@@ -202,25 +202,6 @@ int cros_ec_spi_init(struct cros_ec_dev *dev, const void *blob)
 #ifdef CONFIG_DM_CROS_EC
 static int cros_ec_probe(struct udevice *dev)
 {
-	struct spi_slave *slave = dev_get_parentdata(dev);
-	int ret;
-
-	/*
-	 * TODO(sjg at chromium.org)
-	 *
-	 * This is really horrible at present. It is an artifact of removing
-	 * the child_pre_probe() method for SPI. Everything here could go in
-	 * an automatic function, except that spi_get_bus_and_cs() wants to
-	 * set it up manually and call device_probe_child().
-	 *
-	 * The solution may be to re-enable the child_pre_probe() method for
-	 * SPI and have it do nothing if the child is already passed in via
-	 * device_probe_child().
-	 */
-	slave->dev = dev;
-	ret = spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, slave);
-	if (ret)
-		return ret;
 	return cros_ec_register(dev);
 }
 
diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c
index 106dda9..d576d31 100644
--- a/drivers/mtd/spi/sandbox.c
+++ b/drivers/mtd/spi/sandbox.c
@@ -590,6 +590,11 @@ int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs,
 
 void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs)
 {
+	struct udevice *dev;
+
+	dev = state->spi[busnum][cs].emul;
+	device_remove(dev);
+	device_unbind(dev);
 	state->spi[busnum][cs].emul = NULL;
 }
 
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index ce9987f..4103723 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -481,11 +481,12 @@ int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
 int spi_flash_std_probe(struct udevice *dev)
 {
 	struct spi_slave *slave = dev_get_parentdata(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
 	struct spi_flash *flash;
 
 	flash = dev->uclass_priv;
 	flash->dev = dev;
-	debug("%s: slave=%p, cs=%d\n", __func__, slave, slave->cs);
+	debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs);
 	return spi_flash_probe_slave(slave, flash);
 }
 
diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c
index 9f7d80e..6ae45f5 100644
--- a/drivers/spi/soft_spi.c
+++ b/drivers/spi/soft_spi.c
@@ -179,14 +179,6 @@ static int soft_spi_set_mode(struct udevice *dev, unsigned int mode)
 	return 0;
 }
 
-static int soft_spi_child_pre_probe(struct udevice *dev)
-{
-	struct spi_slave *slave = dev_get_parentdata(dev);
-
-	slave->dev = dev;
-	return spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, slave);
-}
-
 static const struct dm_spi_ops soft_spi_ops = {
 	.claim_bus	= soft_spi_claim_bus,
 	.release_bus	= soft_spi_release_bus,
@@ -241,5 +233,4 @@ U_BOOT_DRIVER(soft_spi) = {
 	.platdata_auto_alloc_size = sizeof(struct soft_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct soft_spi_priv),
 	.probe	= soft_spi_probe,
-	.child_pre_probe	= soft_spi_child_pre_probe,
 };
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 2c134eb..14e9337 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -98,11 +98,21 @@ int spi_post_bind(struct udevice *dev)
 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
 }
 
-int spi_post_probe(struct udevice *dev)
+int spi_child_post_bind(struct udevice *dev)
 {
-	struct dm_spi_bus *spi = dev->uclass_priv;
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
 
-	spi->max_hz = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+	if (dev->of_offset == -1)
+		return 0;
+
+	return spi_slave_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, plat);
+}
+
+int spi_post_probe(struct udevice *bus)
+{
+	struct dm_spi_bus *spi = bus->uclass_priv;
+
+	spi->max_hz = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
 				     "spi-max-frequency", 0);
 
 	return 0;
@@ -112,6 +122,13 @@ int spi_child_pre_probe(struct udevice *dev)
 {
 	struct spi_slave *slave = dev_get_parentdata(dev);
 
+	/*
+	 * This is needed because we pass struct spi_slave around the place
+	 * instead slave->dev (a struct udevice). So we have to have some
+	 * way to access the slave udevice given struct spi_slave. Once we
+	 * change the SPI API to use udevice instead of spi_slave, we can
+	 * drop this.
+	 */
 	slave->dev = dev;
 
 	return 0;
@@ -119,9 +136,9 @@ int spi_child_pre_probe(struct udevice *dev)
 
 int spi_chip_select(struct udevice *dev)
 {
-	struct spi_slave *slave = dev_get_parentdata(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
 
-	return slave ? slave->cs : -ENOENT;
+	return plat ? plat->cs : -ENOENT;
 }
 
 int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp)
@@ -130,17 +147,11 @@ int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp)
 
 	for (device_find_first_child(bus, &dev); dev;
 	     device_find_next_child(&dev)) {
-		struct spi_slave store;
-		struct spi_slave *slave = dev_get_parentdata(dev);
+		struct dm_spi_slave_platdata *plat;
 
-		if (!slave)  {
-			slave = &store;
-			spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					       slave);
-		}
-		debug("%s: slave=%p, cs=%d\n", __func__, slave,
-		      slave ? slave->cs : -1);
-		if (slave && slave->cs == cs) {
+		plat = dev_get_parent_platdata(dev);
+		debug("%s: plat=%p, cs=%d\n", __func__, plat, plat->cs);
+		if (plat->cs == cs) {
 			*devp = dev;
 			return 0;
 		}
@@ -224,7 +235,6 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
 		       struct udevice **busp, struct spi_slave **devp)
 {
 	struct udevice *bus, *dev;
-	struct spi_slave *slave;
 	bool created = false;
 	int ret;
 
@@ -241,11 +251,17 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
 	 * SPI flash chip - we will bind to the correct driver.
 	 */
 	if (ret == -ENODEV && drv_name) {
+		struct dm_spi_slave_platdata *plat;
+
 		debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n",
 		      __func__, dev_name, busnum, cs, drv_name);
 		ret = device_bind_driver(bus, drv_name, dev_name, &dev);
 		if (ret)
 			return ret;
+		plat = dev_get_parent_platdata(dev);
+		plat->cs = cs;
+		plat->max_hz = speed;
+		plat->mode = mode;
 		created = true;
 	} else if (ret) {
 		printf("Invalid chip select %d:%d (err=%d)\n", busnum, cs,
@@ -254,23 +270,13 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
 	}
 
 	if (!device_active(dev)) {
-		slave = (struct spi_slave *)calloc(1,
-						   sizeof(struct spi_slave));
-		if (!slave) {
-			ret = -ENOMEM;
-			goto err;
-		}
+		struct spi_slave *slave;
 
-		ret = spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					     slave);
+		ret = device_probe(dev);
 		if (ret)
 			goto err;
-		slave->cs = cs;
+		slave = dev_get_parentdata(dev);
 		slave->dev = dev;
-		ret = device_probe_child(dev, slave);
-		free(slave);
-		if (ret)
-			goto err;
 	}
 
 	ret = spi_set_speed_mode(bus, speed, mode);
@@ -284,6 +290,8 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
 	return 0;
 
 err:
+	debug("%s: Error path, credted=%d, device '%s'\n", __func__,
+	      created, dev->name);
 	if (created) {
 		device_remove(dev);
 		device_unbind(dev);
@@ -330,13 +338,13 @@ void spi_free_slave(struct spi_slave *slave)
 	slave->dev = NULL;
 }
 
-int spi_ofdata_to_platdata(const void *blob, int node,
-			   struct spi_slave *spi)
+int spi_slave_ofdata_to_platdata(const void *blob, int node,
+				 struct dm_spi_slave_platdata *plat)
 {
 	int mode = 0;
 
-	spi->cs = fdtdec_get_int(blob, node, "reg", -1);
-	spi->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 0);
+	plat->cs = fdtdec_get_int(blob, node, "reg", -1);
+	plat->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 0);
 	if (fdtdec_get_bool(blob, node, "spi-cpol"))
 		mode |= SPI_CPOL;
 	if (fdtdec_get_bool(blob, node, "spi-cpha"))
@@ -345,7 +353,7 @@ int spi_ofdata_to_platdata(const void *blob, int node,
 		mode |= SPI_CS_HIGH;
 	if (fdtdec_get_bool(blob, node, "spi-half-duplex"))
 		mode |= SPI_PREAMBLE;
-	spi->mode = mode;
+	plat->mode = mode;
 
 	return 0;
 }
@@ -359,6 +367,9 @@ UCLASS_DRIVER(spi) = {
 	.child_pre_probe = spi_child_pre_probe,
 	.per_device_auto_alloc_size = sizeof(struct dm_spi_bus),
 	.per_child_auto_alloc_size = sizeof(struct spi_slave),
+	.per_child_platdata_auto_alloc_size =
+			sizeof(struct dm_spi_slave_platdata),
+	.child_post_bind = spi_child_post_bind,
 };
 
 UCLASS_DRIVER(spi_generic) = {
diff --git a/include/spi.h b/include/spi.h
index ec17bd0..5537a13 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -60,6 +60,23 @@ struct dm_spi_bus {
 	uint max_hz;
 };
 
+/**
+ * struct dm_spi_platdata - platform data for all SPI slaves
+ *
+ * This describes a SPI slave, a child device of the SPI bus. To obtain this
+ * struct from a spi_slave, use dev_get_parent_platdata(dev) or
+ * dev_get_parent_platdata(slave->dev).
+ *
+ * @cs:		Chip select number (0..n-1)
+ * @max_hz:	Maximum bus speed that this slave can tolerate
+ * @mode:	SPI mode to use for this device (see SPI mode flags)
+ */
+struct dm_spi_slave_platdata {
+	unsigned int cs;
+	uint max_hz;
+	uint mode;
+};
+
 #endif /* CONFIG_DM_SPI */
 
 /**
@@ -97,8 +114,8 @@ struct spi_slave {
 	uint mode;
 #else
 	unsigned int bus;
-#endif
 	unsigned int cs;
+#endif
 	u8 op_mode_rx;
 	u8 op_mode_tx;
 	unsigned int wordlen;
@@ -545,16 +562,16 @@ int spi_chip_select(struct udevice *slave);
 int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp);
 
 /**
- * spi_ofdata_to_platdata() - decode standard SPI platform data
+ * spi_slave_ofdata_to_platdata() - decode standard SPI platform data
  *
- * This decodes the speed and mode from a device tree node and puts it into
- * the spi_slave structure.
+ * This decodes the speed and mode for a slave from a device tree node
  *
  * @blob:	Device tree blob
  * @node:	Node offset to read from
- * @spi:	Place to put the decoded information
+ * @plat:	Place to put the decoded information
  */
-int spi_ofdata_to_platdata(const void *blob, int node, struct spi_slave *spi);
+int spi_slave_ofdata_to_platdata(const void *blob, int node,
+				 struct dm_spi_slave_platdata *plat);
 
 /**
  * spi_cs_info() - Check information on a chip select
diff --git a/test/dm/spi.c b/test/dm/spi.c
index 61b5b25..c7ee652 100644
--- a/test/dm/spi.c
+++ b/test/dm/spi.c
@@ -36,7 +36,6 @@ static int dm_test_spi_find(struct dm_test_state *dms)
 	ut_asserteq(0, uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus));
 	ut_assertok(spi_cs_info(bus, cs, &info));
 	of_offset = info.dev->of_offset;
-	sandbox_sf_unbind_emul(state_get_current(), busnum, cs);
 	device_remove(info.dev);
 	device_unbind(info.dev);
 
@@ -45,7 +44,7 @@ static int dm_test_spi_find(struct dm_test_state *dms)
 	 * reports that CS 0 is present
 	 */
 	ut_assertok(spi_cs_info(bus, cs, &info));
-	ut_asserteq_ptr(info.dev, NULL);
+	ut_asserteq_ptr(NULL, info.dev);
 
 	/* This finds nothing because we removed the device */
 	ut_asserteq(-ENODEV, spi_find_bus_and_cs(busnum, cs, &bus, &dev));
@@ -62,8 +61,9 @@ static int dm_test_spi_find(struct dm_test_state *dms)
 	ut_asserteq(-ENOENT, spi_get_bus_and_cs(busnum, cs, speed, mode,
 						"spi_flash_std", "name", &bus,
 						&slave));
+	sandbox_sf_unbind_emul(state_get_current(), busnum, cs);
 	ut_assertok(spi_cs_info(bus, cs, &info));
-	ut_asserteq_ptr(info.dev, NULL);
+	ut_asserteq_ptr(NULL, info.dev);
 
 	/* Add the emulation and try again */
 	ut_assertok(sandbox_sf_bind_emul(state, busnum, cs, bus, of_offset,
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 18/21] dm: i2c: Move slave details to child platdata
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (16 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 17/21] dm: spi: Move slave details to child platdata Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 19/21] dm: tegra: Drop unused COMPAT features for I2C, SPI Simon Glass
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

At present we go through various contortions to store the I2C's chip
address in its private data. This only exists when the chip is active so
must be set up when it is probed. Until the device is probed we don't
actually record what address it will appear on.

However, now that we can support per-child platform data, we can use that
instead. This allows us to set up the address when the child is bound,
and avoid the messy contortions.

Unfortunately this is a fairly large change and it seems to be difficult to
break it down further.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/i2c/i2c-uclass-compat.c |  2 +-
 drivers/i2c/i2c-uclass.c        | 53 +++++++++++++++++++++++++----------------
 drivers/i2c/i2c-uniphier-f.c    | 12 ----------
 drivers/i2c/i2c-uniphier.c      | 12 ----------
 drivers/i2c/s3c24x0_i2c.c       | 12 ----------
 drivers/i2c/sandbox_i2c.c       | 28 +++++-----------------
 drivers/i2c/tegra_i2c.c         | 18 --------------
 include/i2c.h                   |  4 ++--
 8 files changed, 41 insertions(+), 100 deletions(-)

diff --git a/drivers/i2c/i2c-uclass-compat.c b/drivers/i2c/i2c-uclass-compat.c
index c29fc89..11239da 100644
--- a/drivers/i2c/i2c-uclass-compat.c
+++ b/drivers/i2c/i2c-uclass-compat.c
@@ -20,7 +20,7 @@ static int i2c_compat_get_device(uint chip_addr, int alen,
 	ret = i2c_get_chip_for_busnum(cur_busnum, chip_addr, devp);
 	if (ret)
 		return ret;
-	chip = dev_get_parentdata(*devp);
+	chip = dev_get_parent_platdata(*devp);
 	if (chip->offset_len != alen) {
 		printf("Requested alen %d does not match chip offset_len %d\n",
 		       alen, chip->offset_len);
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
index 0048f11..d83049b 100644
--- a/drivers/i2c/i2c-uclass.c
+++ b/drivers/i2c/i2c-uclass.c
@@ -50,7 +50,7 @@ static int i2c_setup_offset(struct dm_i2c_chip *chip, uint offset,
 static int i2c_read_bytewise(struct udevice *dev, uint offset,
 			     uint8_t *buffer, int len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct udevice *bus = dev_get_parent(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct i2c_msg msg[2], *ptr;
@@ -79,7 +79,7 @@ static int i2c_read_bytewise(struct udevice *dev, uint offset,
 static int i2c_write_bytewise(struct udevice *dev, uint offset,
 			     const uint8_t *buffer, int len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct udevice *bus = dev_get_parent(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct i2c_msg msg[1];
@@ -102,7 +102,7 @@ static int i2c_write_bytewise(struct udevice *dev, uint offset,
 
 int dm_i2c_read(struct udevice *dev, uint offset, uint8_t *buffer, int len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct udevice *bus = dev_get_parent(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct i2c_msg msg[2], *ptr;
@@ -133,7 +133,7 @@ int dm_i2c_read(struct udevice *dev, uint offset, uint8_t *buffer, int len)
 int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer,
 		 int len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct udevice *bus = dev_get_parent(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct i2c_msg msg[1];
@@ -223,7 +223,7 @@ static int i2c_probe_chip(struct udevice *bus, uint chip_addr,
 static int i2c_bind_driver(struct udevice *bus, uint chip_addr,
 			   struct udevice **devp)
 {
-	struct dm_i2c_chip chip;
+	struct dm_i2c_chip *chip;
 	char name[30], *str;
 	struct udevice *dev;
 	int ret;
@@ -236,11 +236,11 @@ static int i2c_bind_driver(struct udevice *bus, uint chip_addr,
 		goto err_bind;
 
 	/* Tell the device what we know about it */
-	memset(&chip, '\0', sizeof(chip));
-	chip.chip_addr = chip_addr;
-	chip.offset_len = 1;	/* we assume */
-	ret = device_probe_child(dev, &chip);
-	debug("%s:  device_probe_child: ret=%d\n", __func__, ret);
+	chip = dev_get_parent_platdata(dev);
+	chip->chip_addr = chip_addr;
+	chip->offset_len = 1;	/* we assume */
+	ret = device_probe(dev);
+	debug("%s:  device_probe: ret=%d\n", __func__, ret);
 	if (ret)
 		goto err_probe;
 
@@ -248,6 +248,10 @@ static int i2c_bind_driver(struct udevice *bus, uint chip_addr,
 	return 0;
 
 err_probe:
+	/*
+	 * If the device failed to probe, unbind it. There is nothing there
+	 * on the bus so we don't want to leave it lying around
+	 */
 	device_unbind(dev);
 err_bind:
 	free(str);
@@ -262,15 +266,9 @@ int i2c_get_chip(struct udevice *bus, uint chip_addr, struct udevice **devp)
 	      bus->name, chip_addr);
 	for (device_find_first_child(bus, &dev); dev;
 			device_find_next_child(&dev)) {
-		struct dm_i2c_chip store;
-		struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+		struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 		int ret;
 
-		if (!chip) {
-			chip = &store;
-			i2c_chip_ofdata_to_platdata(gd->fdt_blob,
-						    dev->of_offset, chip);
-		}
 		if (chip->chip_addr == chip_addr) {
 			ret = device_probe(dev);
 			debug("found, ret=%d\n", ret);
@@ -365,7 +363,7 @@ int i2c_get_bus_speed(struct udevice *bus)
 int i2c_set_chip_flags(struct udevice *dev, uint flags)
 {
 	struct udevice *bus = dev->parent;
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	int ret;
 
@@ -381,7 +379,7 @@ int i2c_set_chip_flags(struct udevice *dev, uint flags)
 
 int i2c_get_chip_flags(struct udevice *dev, uint *flagsp)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 
 	*flagsp = chip->flags;
 
@@ -390,7 +388,7 @@ int i2c_get_chip_flags(struct udevice *dev, uint *flagsp)
 
 int i2c_set_chip_offset_len(struct udevice *dev, uint offset_len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 
 	if (offset_len > I2C_MAX_OFFSET_LEN)
 		return -EINVAL;
@@ -448,13 +446,26 @@ int i2c_post_bind(struct udevice *dev)
 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
 }
 
+int i2c_child_post_bind(struct udevice *dev)
+{
+	struct dm_i2c_chip *plat = dev_get_parent_platdata(dev);
+
+	if (dev->of_offset == -1)
+		return 0;
+
+	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, plat);
+}
+
 UCLASS_DRIVER(i2c) = {
 	.id		= UCLASS_I2C,
 	.name		= "i2c",
 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
-	.per_device_auto_alloc_size = sizeof(struct dm_i2c_bus),
 	.post_bind	= i2c_post_bind,
 	.post_probe	= i2c_post_probe,
+	.per_device_auto_alloc_size = sizeof(struct dm_i2c_bus),
+	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
+	.per_child_platdata_auto_alloc_size = sizeof(struct dm_i2c_chip),
+	.child_post_bind = i2c_child_post_bind,
 };
 
 UCLASS_DRIVER(i2c_generic) = {
diff --git a/drivers/i2c/i2c-uniphier-f.c b/drivers/i2c/i2c-uniphier-f.c
index b0d30f7..6707edd 100644
--- a/drivers/i2c/i2c-uniphier-f.c
+++ b/drivers/i2c/i2c-uniphier-f.c
@@ -145,16 +145,6 @@ static int uniphier_fi2c_remove(struct udevice *dev)
 	return 0;
 }
 
-static int uniphier_fi2c_child_pre_probe(struct udevice *dev)
-{
-	struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-	if (dev->of_offset == -1)
-		return 0;
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					   i2c_chip);
-}
-
 static int wait_for_irq(struct uniphier_fi2c_dev *dev, u32 flags,
 			bool *stop)
 {
@@ -372,8 +362,6 @@ U_BOOT_DRIVER(uniphier_fi2c) = {
 	.of_match = uniphier_fi2c_of_match,
 	.probe = uniphier_fi2c_probe,
 	.remove = uniphier_fi2c_remove,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-	.child_pre_probe = uniphier_fi2c_child_pre_probe,
 	.priv_auto_alloc_size = sizeof(struct uniphier_fi2c_dev),
 	.ops = &uniphier_fi2c_ops,
 };
diff --git a/drivers/i2c/i2c-uniphier.c b/drivers/i2c/i2c-uniphier.c
index bdac1f9..64a9ed8 100644
--- a/drivers/i2c/i2c-uniphier.c
+++ b/drivers/i2c/i2c-uniphier.c
@@ -75,16 +75,6 @@ static int uniphier_i2c_remove(struct udevice *dev)
 	return 0;
 }
 
-static int uniphier_i2c_child_pre_probe(struct udevice *dev)
-{
-	struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-	if (dev->of_offset == -1)
-		return 0;
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					   i2c_chip);
-}
-
 static int send_and_recv_byte(struct uniphier_i2c_dev *dev, u32 dtrm)
 {
 	writel(dtrm, &dev->regs->dtrm);
@@ -232,8 +222,6 @@ U_BOOT_DRIVER(uniphier_i2c) = {
 	.of_match = uniphier_i2c_of_match,
 	.probe = uniphier_i2c_probe,
 	.remove = uniphier_i2c_remove,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-	.child_pre_probe = uniphier_i2c_child_pre_probe,
 	.priv_auto_alloc_size = sizeof(struct uniphier_i2c_dev),
 	.ops = &uniphier_i2c_ops,
 };
diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
index c21d479..4002972 100644
--- a/drivers/i2c/s3c24x0_i2c.c
+++ b/drivers/i2c/s3c24x0_i2c.c
@@ -1404,16 +1404,6 @@ static int s3c_i2c_ofdata_to_platdata(struct udevice *dev)
 	return 0;
 }
 
-static int s3c_i2c_child_pre_probe(struct udevice *dev)
-{
-	struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-	if (dev->of_offset == -1)
-		return 0;
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					   i2c_chip);
-}
-
 static const struct dm_i2c_ops s3c_i2c_ops = {
 	.xfer		= s3c24x0_i2c_xfer,
 	.probe_chip	= s3c24x0_i2c_probe,
@@ -1431,8 +1421,6 @@ U_BOOT_DRIVER(i2c_s3c) = {
 	.id	= UCLASS_I2C,
 	.of_match = s3c_i2c_ids,
 	.ofdata_to_platdata = s3c_i2c_ofdata_to_platdata,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-	.child_pre_probe = s3c_i2c_child_pre_probe,
 	.priv_auto_alloc_size = sizeof(struct s3c24x0_i2c_bus),
 	.ops	= &s3c_i2c_ops,
 };
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c
index f0e9f51..0462d2f 100644
--- a/drivers/i2c/sandbox_i2c.c
+++ b/drivers/i2c/sandbox_i2c.c
@@ -25,24 +25,24 @@ struct dm_sandbox_i2c_emul_priv {
 static int get_emul(struct udevice *dev, struct udevice **devp,
 		    struct dm_i2c_ops **opsp)
 {
-	struct dm_i2c_chip *priv;
+	struct dm_i2c_chip *plat;
 	int ret;
 
 	*devp = NULL;
 	*opsp = NULL;
-	priv = dev_get_parentdata(dev);
-	if (!priv->emul) {
+	plat = dev_get_parent_platdata(dev);
+	if (!plat->emul) {
 		ret = dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset,
 				       false);
 		if (ret)
 			return ret;
 
-		ret = device_get_child(dev, 0, &priv->emul);
+		ret = device_get_child(dev, 0, &plat->emul);
 		if (ret)
 			return ret;
 	}
-	*devp = priv->emul;
-	*opsp = i2c_get_ops(priv->emul);
+	*devp = plat->emul;
+	*opsp = i2c_get_ops(plat->emul);
 
 	return 0;
 }
@@ -82,20 +82,6 @@ static const struct dm_i2c_ops sandbox_i2c_ops = {
 	.xfer		= sandbox_i2c_xfer,
 };
 
-static int sandbox_i2c_child_pre_probe(struct udevice *dev)
-{
-	struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-	/* Ignore our test address */
-	if (i2c_chip->chip_addr == SANDBOX_I2C_TEST_ADDR)
-		return 0;
-	if (dev->of_offset == -1)
-		return 0;
-
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					   i2c_chip);
-}
-
 static const struct udevice_id sandbox_i2c_ids[] = {
 	{ .compatible = "sandbox,i2c" },
 	{ }
@@ -105,7 +91,5 @@ U_BOOT_DRIVER(i2c_sandbox) = {
 	.name	= "i2c_sandbox",
 	.id	= UCLASS_I2C,
 	.of_match = sandbox_i2c_ids,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-	.child_pre_probe = sandbox_i2c_child_pre_probe,
 	.ops	= &sandbox_i2c_ops,
 };
diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c
index 87290c3..f414287 100644
--- a/drivers/i2c/tegra_i2c.c
+++ b/drivers/i2c/tegra_i2c.c
@@ -484,21 +484,6 @@ static const struct dm_i2c_ops tegra_i2c_ops = {
 	.set_bus_speed	= tegra_i2c_set_bus_speed,
 };
 
-static int tegra_i2c_child_pre_probe(struct udevice *dev)
-{
-	struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-	if (dev->of_offset == -1)
-		return 0;
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					   i2c_chip);
-}
-
-static int tegra_i2c_ofdata_to_platdata(struct udevice *dev)
-{
-	return 0;
-}
-
 static const struct udevice_id tegra_i2c_ids[] = {
 	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
 	{ .compatible = "nvidia,tegra20-i2c", .data = TYPE_STD },
@@ -510,10 +495,7 @@ U_BOOT_DRIVER(i2c_tegra) = {
 	.name	= "i2c_tegra",
 	.id	= UCLASS_I2C,
 	.of_match = tegra_i2c_ids,
-	.ofdata_to_platdata = tegra_i2c_ofdata_to_platdata,
 	.probe	= tegra_i2c_probe,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-	.child_pre_probe = tegra_i2c_child_pre_probe,
 	.priv_auto_alloc_size = sizeof(struct i2c_bus),
 	.ops	= &tegra_i2c_ops,
 };
diff --git a/include/i2c.h b/include/i2c.h
index 47529f4..d79c1fa 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -39,8 +39,8 @@ enum dm_i2c_chip_flags {
  * An I2C chip is a device on the I2C bus. It sits at a particular address
  * and normally supports 7-bit or 10-bit addressing.
  *
- * To obtain this structure, use dev_get_parentdata(dev) where dev is the
- * chip to examine.
+ * To obtain this structure, use dev_get_parent_platdata(dev) where dev is
+ * the chip to examine.
  *
  * @chip_addr:	Chip address on bus
  * @offset_len: Length of offset in bytes. A single byte offset can
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 19/21] dm: tegra: Drop unused COMPAT features for I2C, SPI
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (17 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 18/21] dm: i2c: " Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 20/21] dm: exynos: Drop unused COMPAT features for SPI Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 21/21] dm: Update documentation for new bus features Simon Glass
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

These have moved to driver model so we don't need the fdtdec support.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 include/fdtdec.h | 6 ------
 lib/fdtdec.c     | 6 ------
 2 files changed, 12 deletions(-)

diff --git a/include/fdtdec.h b/include/fdtdec.h
index f0d2412..094a8e3 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -115,9 +115,6 @@ enum fdt_compat_id {
 	COMPAT_NVIDIA_TEGRA20_USB,	/* Tegra20 USB port */
 	COMPAT_NVIDIA_TEGRA30_USB,	/* Tegra30 USB port */
 	COMPAT_NVIDIA_TEGRA114_USB,	/* Tegra114 USB port */
-	COMPAT_NVIDIA_TEGRA114_I2C,	/* Tegra114 I2C w/single clock source */
-	COMPAT_NVIDIA_TEGRA20_I2C,	/* Tegra20 i2c */
-	COMPAT_NVIDIA_TEGRA20_DVC,	/* Tegra20 dvc (really just i2c) */
 	COMPAT_NVIDIA_TEGRA20_EMC,	/* Tegra20 memory controller */
 	COMPAT_NVIDIA_TEGRA20_EMC_TABLE, /* Tegra20 memory timing table */
 	COMPAT_NVIDIA_TEGRA20_KBC,	/* Tegra20 Keyboard */
@@ -127,9 +124,6 @@ enum fdt_compat_id {
 	COMPAT_NVIDIA_TEGRA124_SDMMC,	/* Tegra124 SDMMC controller */
 	COMPAT_NVIDIA_TEGRA30_SDMMC,	/* Tegra30 SDMMC controller */
 	COMPAT_NVIDIA_TEGRA20_SDMMC,	/* Tegra20 SDMMC controller */
-	COMPAT_NVIDIA_TEGRA20_SFLASH,	/* Tegra 2 SPI flash controller */
-	COMPAT_NVIDIA_TEGRA20_SLINK,	/* Tegra 2 SPI SLINK controller */
-	COMPAT_NVIDIA_TEGRA114_SPI,	/* Tegra 114 SPI controller */
 	COMPAT_NVIDIA_TEGRA124_PCIE,	/* Tegra 124 PCIe controller */
 	COMPAT_NVIDIA_TEGRA30_PCIE,	/* Tegra 30 PCIe controller */
 	COMPAT_NVIDIA_TEGRA20_PCIE,	/* Tegra 20 PCIe controller */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 3306028..e8aa5e7 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -26,9 +26,6 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(NVIDIA_TEGRA20_USB, "nvidia,tegra20-ehci"),
 	COMPAT(NVIDIA_TEGRA30_USB, "nvidia,tegra30-ehci"),
 	COMPAT(NVIDIA_TEGRA114_USB, "nvidia,tegra114-ehci"),
-	COMPAT(NVIDIA_TEGRA114_I2C, "nvidia,tegra114-i2c"),
-	COMPAT(NVIDIA_TEGRA20_I2C, "nvidia,tegra20-i2c"),
-	COMPAT(NVIDIA_TEGRA20_DVC, "nvidia,tegra20-i2c-dvc"),
 	COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"),
 	COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"),
 	COMPAT(NVIDIA_TEGRA20_KBC, "nvidia,tegra20-kbc"),
@@ -38,9 +35,6 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(NVIDIA_TEGRA124_SDMMC, "nvidia,tegra124-sdhci"),
 	COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"),
 	COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"),
-	COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"),
-	COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"),
-	COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"),
 	COMPAT(NVIDIA_TEGRA124_PCIE, "nvidia,tegra124-pcie"),
 	COMPAT(NVIDIA_TEGRA30_PCIE, "nvidia,tegra30-pcie"),
 	COMPAT(NVIDIA_TEGRA20_PCIE, "nvidia,tegra20-pcie"),
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 20/21] dm: exynos: Drop unused COMPAT features for SPI
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (18 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 19/21] dm: tegra: Drop unused COMPAT features for I2C, SPI Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 21/21] dm: Update documentation for new bus features Simon Glass
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

This has moved to driver model so we don't need the fdtdec support.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 include/fdtdec.h | 1 -
 lib/fdtdec.c     | 1 -
 2 files changed, 2 deletions(-)

diff --git a/include/fdtdec.h b/include/fdtdec.h
index 094a8e3..4cc69de 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -134,7 +134,6 @@ enum fdt_compat_id {
 	COMPAT_SAMSUNG_S3C2440_I2C,	/* Exynos I2C Controller */
 	COMPAT_SAMSUNG_EXYNOS5_SOUND,	/* Exynos Sound */
 	COMPAT_WOLFSON_WM8994_CODEC,	/* Wolfson WM8994 Sound Codec */
-	COMPAT_SAMSUNG_EXYNOS_SPI,	/* Exynos SPI */
 	COMPAT_GOOGLE_CROS_EC,		/* Google CROS_EC Protocol */
 	COMPAT_GOOGLE_CROS_EC_KEYB,	/* Google CROS_EC Keyboard */
 	COMPAT_SAMSUNG_EXYNOS_EHCI,	/* Exynos EHCI controller */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index e8aa5e7..89dac4c 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -44,7 +44,6 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(SAMSUNG_S3C2440_I2C, "samsung,s3c2440-i2c"),
 	COMPAT(SAMSUNG_EXYNOS5_SOUND, "samsung,exynos-sound"),
 	COMPAT(WOLFSON_WM8994_CODEC, "wolfson,wm8994-codec"),
-	COMPAT(SAMSUNG_EXYNOS_SPI, "samsung,exynos-spi"),
 	COMPAT(GOOGLE_CROS_EC, "google,cros-ec"),
 	COMPAT(GOOGLE_CROS_EC_KEYB, "google,cros-ec-keyb"),
 	COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"),
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 21/21] dm: Update documentation for new bus features
       [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
                   ` (19 preceding siblings ...)
  2015-01-16 23:15 ` [U-Boot] [RFC PATCH 20/21] dm: exynos: Drop unused COMPAT features for SPI Simon Glass
@ 2015-01-16 23:15 ` Simon Glass
  20 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-16 23:15 UTC (permalink / raw
  To: u-boot

Now that we have new bus features, update README.txt to explain these.
Signed-off-by: Simon Glass <sjg@chromium.org>
---

 doc/driver-model/README.txt | 36 ++++++++++++++++++++++++++----------
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt
index 2fc900b..f12e23f 100644
--- a/doc/driver-model/README.txt
+++ b/doc/driver-model/README.txt
@@ -441,11 +441,18 @@ access to other devices. Example of buses include SPI and I2C. Typically
 the bus provides some sort of transport or translation that makes it
 possible to talk to the devices on the bus.
 
-Driver model provides a few useful features to help with implementing
-buses. Firstly, a bus can request that its children store some 'parent
-data' which can be used to keep track of child state. Secondly, the bus can
-define methods which are called when a child is probed or removed. This is
-similar to the methods the uclass driver provides.
+Driver model provides some useful features to help with implementing buses.
+Firstly, a bus can request that its children store some 'parent data' which
+can be used to keep track of child state. Secondly, the bus can define
+methods which are called when a child is probed or removed. This is similar
+to the methods the uclass driver provides. Thirdly, per-child platform data
+can be provided to specify things like the child's address on the bus. This
+persists across child probe()/remove() cycles.
+
+For consistency and ease of implementation, the bus uclass can specify the
+per-child platform data, so that it can be the same for all children of buses
+in that uclass. There are also uclass methods which can be called when
+children are bound and probed.
 
 Here an explanation of how a bus fits with a uclass may be useful. Consider
 a USB bus with several devices attached to it, each from a different (made
@@ -460,15 +467,23 @@ Each of the devices is connected to a different address on the USB bus.
 The bus device wants to store this address and some other information such
 as the bus speed for each device.
 
-To achieve this, the bus device can use dev->parent_priv in each of its
-three children. This can be auto-allocated if the bus driver has a non-zero
-value for per_child_auto_alloc_size. If not, then the bus device can
-allocate the space itself before the child device is probed.
+To achieve this, the bus device can use dev->parent_platdata in each of its
+three children. This can be auto-allocated if the bus driver (or bus uclass)
+has a non-zero value for per_child_platdata_auto_alloc_size. If not, then
+the bus device or uclass can allocate the space itself before the child
+device is probed.
 
 Also the bus driver can define the child_pre_probe() and child_post_remove()
 methods to allow it to do some processing before the child is activated or
 after it is deactivated.
 
+Similarly the bus uclass can define the child_post_bind() method to obtain
+the per-child platform data from the device tree and set it up for the child.
+The bus uclass can also provide a child_pre_probe() method. Very often it is
+the bus uclass that controls these features, since it avoids each driver
+having to do the same processing. Of course the driver can still tweak and
+override these activities.
+
 Note that the information that controls this behaviour is in the bus's
 driver, not the child's. In fact it is possible that child has no knowledge
 that it is connected to a bus. The same child device may even be used on two
@@ -495,7 +510,8 @@ bus device, regardless of its own views on the matter.
 The uclass for the device can also contain data private to that uclass.
 But note that each device on the bus may be a memeber of a different
 uclass, and this data has nothing to do with the child data for each child
-on the bus.
+on the bus. It is the bus' uclass that controls the child with respect to
+the bus.
 
 
 Driver Lifecycle
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2015-01-16 23:15 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1421450143-22442-1-git-send-email-sjg@chromium.org>
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 01/21] dm: Don't run tests if U-Boot cannot be built Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 02/21] dm: core: Improve comments for uclass_first/next_device() Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 03/21] dm: core: Set device tree node for root device Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 04/21] dm: core: Tidy up error handling in device_bind() Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 05/21] dm: core: Allocate platform data when binding a device Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 06/21] dm: core: Allow parents to have platform data for their children Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 07/21] dm: core: Allow uclasses to specific the platdata for a device's children Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 08/21] dm: core: Add a post_bind method for parents Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 09/21] dm: core: Add a function to get a device's uclass ID Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 10/21] dm: core: Add a flag to control sequence numbering Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 11/21] dm: core: Allow uclasses to specific the private data for a device's children Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 12/21] dm: spi: Move the per-child data size to the uclass Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 13/21] dm: core: Allow the uclass to set up a device's child after binding Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 14/21] dm: sandbox: sf: Tidy up the error handling in sandbox_sf_probe() Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 15/21] dm: core: Allow uclass to set up a device's child before it is probed Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 16/21] dm: spi: Set up the spi_slave device pointer in child_pre_probe() Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 17/21] dm: spi: Move slave details to child platdata Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 18/21] dm: i2c: " Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 19/21] dm: tegra: Drop unused COMPAT features for I2C, SPI Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 20/21] dm: exynos: Drop unused COMPAT features for SPI Simon Glass
2015-01-16 23:15 ` [U-Boot] [RFC PATCH 21/21] dm: Update documentation for new bus features Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.