[U-Boot] [RFC] fdt expert advice needed

Matthias Fuchs matthias.fuchs at esd-electronics.com
Fri Jan 30 22:11:18 CET 2009


Hi FDT experts,

some time ago I posted a patch to fix U-Boot's approach to
set all ns16550 compatible nodes' clock-frequency property
in ppc4xx device tree's:

do_fixup_by_compat_u32(blob, "ns16550", "clock-frequency", gd->uart_clk, 1);

Typically this works fine. It is intended to configure all CPU internal UART's clock.
We have some additional UARTs attached to an external bus. From the device
tree's point of view they have a different path, but are also ns16550 compatible.

So the above line will also overwrite thier clock-frequency. This must not be done,
because they have a separate external clock and the value in the device tree is correct!

Now I want to replace the above code to only touch the ns16550 compatible nodes
that are direct childs of /plb/opb. Not those under /plb/ebc and even not those under 
/plb/opb/ebc. This is not easy to do with the fdt API. Below you find my first and dirty
hack.

Isn't there a more simple way to do so? Don't bother me about the printf, variable names etc.
It's just for discussion.

Please tell me if I have to explain my code :-)

Matthias

From c915c5a8f38940cf0a5047863fb953712049e0be Mon Sep 17 00:00:00 2001
From: Matthias Fuchs <matthias.fuchs at esd-electronics.com>
Date: Fri, 30 Jan 2009 11:00:33 +0100
Subject: [PATCH] ppc4xx: Only fixup opb attached (CPU internal) UARTs

Signed-off-by: Matthias Fuchs <matthias.fuchs at esd-electronics.com>
---
 cpu/ppc4xx/fdt.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/cpu/ppc4xx/fdt.c b/cpu/ppc4xx/fdt.c
index c55e1cf..f668ac6 100644
--- a/cpu/ppc4xx/fdt.c
+++ b/cpu/ppc4xx/fdt.c
@@ -110,9 +110,48 @@ void fdt_pcie_setup(void *blob)
 	}
 }
 
+int ft_path_end_offset(void *blob, char *path)
+{
+	int start, stop;
+	int off;
+	uint32_t tag;
+	int  nextoffset;
+	int level = 0;
+
+	off = fdt_path_offset(blob, path);
+	if (off < 0)
+		return -1;
+
+	stop = start = off;
+
+	while (stop == start) {
+		tag = fdt_next_tag(blob, off, &nextoffset);
+		switch(tag) {
+		case FDT_BEGIN_NODE:
+			level++;
+			break;
+
+		case FDT_END_NODE:
+			if (level == 1)
+				stop = off;
+			level--;
+			break;
+
+		default:
+			break;
+		}
+		off = nextoffset;
+	}
+
+	return stop;
+}
+
 void ft_cpu_setup(void *blob, bd_t *bd)
 {
 	sys_info_t sys_info;
+	int start, stop;
+	int start2, stop2;
+	int off;
 
 	get_sys_info(&sys_info);
 
@@ -135,7 +174,33 @@ void ft_cpu_setup(void *blob, bd_t *bd)
 	/*
 	 * Setup all baudrates for the UARTs
 	 */
+#if 0
 	do_fixup_by_compat_u32(blob, "ns16550", "clock-frequency", gd->uart_clk, 1);
+#endif
+	start = fdt_path_offset(blob, "/plb/opb");
+	stop = ft_path_end_offset(blob, "/plb/opb");
+	printf("/plb/opb start=%d, stop=%d\n", start, stop);
+
+	start2 = fdt_path_offset(blob, "/plb/opb/ebc");
+	stop2 = ft_path_end_offset(blob, "/plb/opb/ebc");
+	printf("/plb/opb/obc start=%d, stop=%d\n", start, stop);
+
+	off = start;
+	while (off != -FDT_ERR_NOTFOUND) {
+		off = fdt_node_offset_by_compatible(blob, off, "ns16550");
+		printf("off=%d\n", off);
+		if ((off > start) && (off < stop)) {
+			if ((start2 < 0) || (off < start2) || (off > stop2)) {
+				printf("ns16550 directly on OPB\n");
+				if (fdt_get_property(blob, off,
+						     "clock-frequency",
+						     0) != NULL)
+					fdt_setprop(blob, off,
+						    "clock-frequency",
+						    (void*)&(gd->uart_clk), 4);
+			}
+		}
+	}
 
 	/*
 	 * Fixup all ethernet nodes
-- 
1.6.1



More information about the U-Boot mailing list