Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 2 Mar 2014 18:56:17 -0500
From:      Patrick Kelsey <kelsey@ieee.org>
To:        freebsd-embedded@freebsd.org
Cc:        "freebsd-hackers@freebsd.org" <freebsd-hackers@freebsd.org>, freebsd-arm@freebsd.org
Subject:   [PATCH] simplebus child device probe order control via FDT (motivated by BeagleBone Black)
Message-ID:  <CAD44qMUyqzaFtjgXdgThgHcHjPctx-oZAdhvHp4Kf0G7N4HVog@mail.gmail.com>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hi,

The attached patch (fdt_probe_order_control.patch) allows control over the
probe order of simplebus child devices by using a "probe-order" property in
simplebus child nodes in the .dts file.

This was motivated by booting FreeBSD from the eMMC on a BeagleBone Black,
which has a pluggable microSD card slot in addition to the eMMC.  The order
that the mmc units are defined in sys/boot/fdt/dts/am335x.dtsi causes the
pluggable slot to be probed/attached first, so the device name assigned to
the eMMC soldered to the board changes depending on whether there is a card
in the pluggable slot, which makes establishing appropriate /etc/fstab
contents less than convenient.

By using the "probe-order" property in
sys/boot/fdt/dts/beaglebone-black.dts (see attached
beaglebone_black_mmc_probe_order.patch), I am able to swap the order in
which the mmc units are probed/attached for that board.  This avoids
inappropriate hacking of the mmc definition order in am335x.dtsi, which is
shared among multiple boards.

This is not a general solution to the problem of wanting stable device
names for hard-wired MMC devices when pluggable slots are present in the
system.  There could, for example, be a multi-slot MMC controller with a
mixture of hard-wired and pluggable devices attached, and this would not
address that case.  However, it does address the needs of BeagleBone Black,
and the mechanism may be of use for similar issues on other platforms.

Both patches were generated against 10-STABLE, r262447.

-Patrick

[-- Attachment #2 --]
Index: sys/dev/fdt/simplebus.c
===================================================================
--- sys/dev/fdt/simplebus.c	(revision 262447)
+++ sys/dev/fdt/simplebus.c	(working copy)
@@ -161,16 +161,61 @@
 	struct simplebus_devinfo *di;
 	struct simplebus_softc *sc;
 	phandle_t dt_node, dt_child;
+#define PROBE_UNORDERED INT32_MIN
+	int32_t probe_order;
+	struct sortq_entry {
+		TAILQ_ENTRY(sortq_entry) link;
+		int32_t probe_order;
+		phandle_t dt_child;
+	} *new_sqe, *sqe, *sqe_tmp;
+	TAILQ_HEAD(sortq_head, sortq_entry) sq = TAILQ_HEAD_INITIALIZER(sq);
 
 	sc = device_get_softc(dev);
 
 	/*
-	 * Walk simple-bus and add direct subordinates as our children.
+	 * Walk simple-bus and queue direct subordinates to be added as our
+	 * children below, respecting any specified probe ordering.
 	 */
 	dt_node = ofw_bus_get_node(dev);
 	for (dt_child = OF_child(dt_node); dt_child != 0;
 	    dt_child = OF_peer(dt_child)) {
 
+		new_sqe = malloc(sizeof(*sqe), M_SIMPLEBUS, M_WAITOK);
+		new_sqe->dt_child = dt_child;
+
+		/*
+		 * Preserve the existing order, unless this child has a
+		 * specified probe-order and it is less than the specified
+		 * probe order of a previous child, in which case this child
+		 * is inserted just prior to that previous child.
+		 */
+		if (OF_getprop(dt_child, "probe-order", &probe_order, sizeof(probe_order)) > 0) {
+			new_sqe->probe_order = (int32_t)fdt_data_get(&probe_order, 1);
+
+			TAILQ_FOREACH(sqe, &sq, link) {
+				if ((PROBE_UNORDERED != sqe->probe_order) &&
+				    (new_sqe->probe_order < sqe->probe_order)) {
+					TAILQ_INSERT_BEFORE(sqe, new_sqe, link);
+					break;
+				}
+			}
+
+			if (NULL == sqe) {
+				TAILQ_INSERT_TAIL(&sq, new_sqe, link);
+			}
+		} else {
+			new_sqe->probe_order = PROBE_UNORDERED;
+			TAILQ_INSERT_TAIL(&sq, new_sqe, link);
+		}
+	}
+
+	/*
+	 * Add the queued subordinates as children.
+	 */
+	TAILQ_FOREACH_SAFE(sqe, &sq, link, sqe_tmp) {
+		dt_child = sqe->dt_child;
+		free(sqe, M_SIMPLEBUS);
+
 		/* Check and process 'status' property. */
 		if (!(fdt_is_enabled(dt_child)))
 			continue;

[-- Attachment #3 --]
Index: sys/boot/fdt/dts/beaglebone-black.dts
===================================================================
--- sys/boot/fdt/dts/beaglebone-black.dts	(revision 262447)
+++ sys/boot/fdt/dts/beaglebone-black.dts	(working copy)
@@ -136,8 +136,12 @@
 		mmchs1@481D8000 {
                 	bus-width = <8>;
 			status = "okay";
+			probe-order = <1000>;
 		};
 
+		mmchs0@48060000 {
+			probe-order = <1001>;
+		};
  
 		i2c@44e0b000 {
 			pmic@24 {

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAD44qMUyqzaFtjgXdgThgHcHjPctx-oZAdhvHp4Kf0G7N4HVog>