Skip to contentSkip to conversation

fdt, mpc5xxx: Adapt MPC5xxx to use libfdt in ft_cpu_setup()

PATCH New Bartlomiej Sieka 8 participants 20 messages Aug 2, 2007 – Aug 30, 2007

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 fdt, mpc5xxx: Adapt MPC5xxx to use libfdt in ft_cpu_setup()

---
Not sure where this should be merged, it was applied to u-boot-fdt#fdt (as of 01f771763ed822145b54819abb9c4516c8216d48) merged with the master (as of cc3023b9f95d7ac959a764471a65001062aecf41). Tested on two MPC5200B-based boards, one using CONFIG_OF_LIBFDT, the other using CONFIG_OF_FLAT_TREE.

cpu/mpc5xxx/cpu.c +123 -3
index 1eac2bb..c4484ef 100644
@@ -33,6 +33,9 @@
 
 #if defined(CONFIG_OF_FLAT_TREE)
 #include <ft_build.h>
+#elif defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
 #endif
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -109,9 +112,125 @@ unsigned long get_tbclk (void)
 	return (tbclk);
 }
 
+#if defined(CONFIG_OF_LIBFDT)
+/*
+ * "Setter" functions used to add/modify FDT entries.
+ */
+static int fdt_set_tbfreq(void *fdt, int nodeoffset, const char *name, bd_t *bd)
+{
+	u32 tmp;
+	/*
+	 * Create or update the property.
+	 */
+	tmp = cpu_to_be32(OF_TBCLK);
+	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name,
+				bd_t *bd)
+{
+	u32 tmp;
+	/*
+	 * Create or update the property.
+	 */
+	tmp = cpu_to_be32(bd->bi_busfreq);
+	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_clockfreq(void *fdt, int nodeoffset, const char *name,
+				bd_t *bd)
+{
+	u32 tmp;
+	/*
+	 * Create or update the property.
+	 */
+	tmp = cpu_to_be32(bd->bi_intfreq);
+	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_ipbusfreq(void *fdt, int nodeoffset, const char *name,
+				bd_t *bd)
+{
+	u32 tmp;
+	/*
+	 * Create or update the property.
+	 */
+	tmp = cpu_to_be32(bd->bi_ipbfreq);
+	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_macaddress(void *fdt, int nodeoffset, const char *name,
+				bd_t *bd)
+{
+	/*
+	 * Fix it up if it exists, don't create it if it doesn't exist.
+	 */
+	if (fdt_get_property(fdt, nodeoffset, name, 0)) {
+		return fdt_setprop(fdt, nodeoffset, name, bd->bi_enetaddr, 6);
+	}
+	return 0;
+}
+
 /* ------------------------------------------------------------------------- */
+/*
+ * Fixups to the fdt.
+ */
+static const struct {
+	char *node;
+	char *prop;
+	int (*set_fn)(void *fdt, int nodeoffset, const char *name, bd_t *bd);
+} fixup_props[] = {
+	{	"/cpus/" OF_CPU,
+		"timebase-frequency",
+		fdt_set_tbfreq
+	},
+	{	"/cpus/" OF_CPU,
+		"bus-frequency",
+		fdt_set_busfreq
+	},
+	{	"/cpus/" OF_CPU,
+		"clock-frequency",
+		fdt_set_clockfreq
+	},
+	{	"/" OF_SOC,
+		"bus-frequency",
+		fdt_set_ipbusfreq
+	},
+	{	"/" OF_SOC "/ethernet at 3000",
+		"mac-address",
+		fdt_set_macaddress
+	},
+	{	"/" OF_SOC "/ethernet at 3000",
+		"local-mac-address",
+		fdt_set_macaddress
+	}
+};
 
-#ifdef CONFIG_OF_FLAT_TREE
+void
+ft_cpu_setup(void *blob, bd_t *bd)
+{
+	int nodeoffset;
+	int err;
+	int j;
+	
+	for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) {
+		nodeoffset = fdt_find_node_by_path(blob, fixup_props[j].node);
+		if (nodeoffset >= 0) {
+			err = fixup_props[j].set_fn(blob, nodeoffset,
+						fixup_props[j].prop, bd);
+			if (err < 0)
+				printf("Problem setting %s = %s: %s\n",
+					fixup_props[j].node,
+					fixup_props[j].prop,
+					fdt_strerror(err));
+		} else {
+			printf("Couldn't find %s: %s\n",
+				fixup_props[j].node,
+				fdt_strerror(nodeoffset));
+		}
+	}
+}
+#elif defined(CONFIG_OF_FLAT_TREE)
 void
 ft_cpu_setup(void *blob, bd_t *bd)
 {
@@ -132,8 +251,9 @@ ft_cpu_setup(void *blob, bd_t *bd)
 	if (p != NULL)
 		memcpy(p, bd->bi_enetaddr, 6);
 
-	p = ft_get_prop(blob, "/" OF_SOC "/ethernet at 3000/local-mac-address", &len);
+	p = ft_get_prop(blob, "/" OF_SOC "/ethernet at 3000/local-mac-address",
+			 &len);
 	if (p != NULL)
 		memcpy(p, bd->bi_enetaddr, 6);
 }
-#endif
+#endif /* defined(CONFIG_OF_LIBFDT) */
#1 lore raw

PATCH 1/1 fdt, mpc5xxx: Adapt MPC5xxx to use libfdt in ft_cpu_setup().

Add necessary functions to allow MPC5XXX machines to use libfdt. Code was derived from analogous MPC83xx implementation. Also, add a small coding style fix while in the area.

---
I have sent a wrong patch with wrong comments before, please disregard my previous email on the same topic; and sorry for the noise.

The baseline used to generate the patch was the master (as of cc3023b9f95d7ac959a764471a65001062aecf41) with pulled u-boot-fdt#fdt branch (as of 01f771763ed822145b54819abb9c4516c8216d48).

The patch has been tested on two MPC5200B-based boards, one using CONFIG_OF_LIBFDT, the other using CONFIG_OF_FLAT_TREE.

cpu/mpc5xxx/cpu.c +125 -3
index 1eac2bb..2be5caa 100644
@@ -19,6 +19,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
+ *
+ * Libfdt related routines derived from the MPC83xx.
  */
 
 /*
@@ -33,6 +35,9 @@
 
 #if defined(CONFIG_OF_FLAT_TREE)
 #include <ft_build.h>
+#elif defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
 #endif
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -109,9 +114,125 @@ unsigned long get_tbclk (void)
 	return (tbclk);
 }
 
+#if defined(CONFIG_OF_LIBFDT)
+/*
+ * "Setter" functions used to add/modify FDT entries.
+ */
+static int fdt_set_tbfreq(void *fdt, int nodeoffset, const char *name, bd_t *bd)
+{
+	u32 tmp;
+	/*
+	 * Create or update the property.
+	 */
+	tmp = cpu_to_be32(OF_TBCLK);
+	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name,
+				bd_t *bd)
+{
+	u32 tmp;
+	/*
+	 * Create or update the property.
+	 */
+	tmp = cpu_to_be32(bd->bi_busfreq);
+	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_clockfreq(void *fdt, int nodeoffset, const char *name,
+				bd_t *bd)
+{
+	u32 tmp;
+	/*
+	 * Create or update the property.
+	 */
+	tmp = cpu_to_be32(bd->bi_intfreq);
+	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_ipbusfreq(void *fdt, int nodeoffset, const char *name,
+				bd_t *bd)
+{
+	u32 tmp;
+	/*
+	 * Create or update the property.
+	 */
+	tmp = cpu_to_be32(bd->bi_ipbfreq);
+	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_macaddress(void *fdt, int nodeoffset, const char *name,
+				bd_t *bd)
+{
+	/*
+	 * Fix it up if it exists, don't create it if it doesn't exist.
+	 */
+	if (fdt_get_property(fdt, nodeoffset, name, 0)) {
+		return fdt_setprop(fdt, nodeoffset, name, bd->bi_enetaddr, 6);
+	}
+	return 0;
+}
+
 /* ------------------------------------------------------------------------- */
+/*
+ * Fixups to the fdt.
+ */
+static const struct {
+	char *node;
+	char *prop;
+	int (*set_fn)(void *fdt, int nodeoffset, const char *name, bd_t *bd);
+} fixup_props[] = {
+	{	"/cpus/" OF_CPU,
+		"timebase-frequency",
+		fdt_set_tbfreq
+	},
+	{	"/cpus/" OF_CPU,
+		"bus-frequency",
+		fdt_set_busfreq
+	},
+	{	"/cpus/" OF_CPU,
+		"clock-frequency",
+		fdt_set_clockfreq
+	},
+	{	"/" OF_SOC,
+		"bus-frequency",
+		fdt_set_ipbusfreq
+	},
+	{	"/" OF_SOC "/ethernet at 3000",
+		"mac-address",
+		fdt_set_macaddress
+	},
+	{	"/" OF_SOC "/ethernet at 3000",
+		"local-mac-address",
+		fdt_set_macaddress
+	}
+};
 
-#ifdef CONFIG_OF_FLAT_TREE
+void
+ft_cpu_setup(void *blob, bd_t *bd)
+{
+	int nodeoffset;
+	int err;
+	int j;
+	
+	for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) {
+		nodeoffset = fdt_find_node_by_path(blob, fixup_props[j].node);
+		if (nodeoffset >= 0) {
+			err = fixup_props[j].set_fn(blob, nodeoffset,
+						fixup_props[j].prop, bd);
+			if (err < 0)
+				debug("Problem setting %s = %s: %s\n",
+					fixup_props[j].node,
+					fixup_props[j].prop,
+					fdt_strerror(err));
+		} else {
+			debug("Couldn't find %s: %s\n",
+				fixup_props[j].node,
+				fdt_strerror(nodeoffset));
+		}
+	}
+}
+#elif defined(CONFIG_OF_FLAT_TREE)
 void
 ft_cpu_setup(void *blob, bd_t *bd)
 {
@@ -132,8 +253,9 @@ ft_cpu_setup(void *blob, bd_t *bd)
 	if (p != NULL)
 		memcpy(p, bd->bi_enetaddr, 6);
 
-	p = ft_get_prop(blob, "/" OF_SOC "/ethernet at 3000/local-mac-address", &len);
+	p = ft_get_prop(blob, "/" OF_SOC "/ethernet at 3000/local-mac-address",
+			 &len);
 	if (p != NULL)
 		memcpy(p, bd->bi_enetaddr, 6);
 }
-#endif
+#endif /* defined(CONFIG_OF_FLAT_TREE) */
#2 lore raw

PATCH 1/1 fdt, mpc5xxx: Adapt MPC5xxx to use libfdt in ft_cpu_setup().

Quoted 5 lines · Bartlomiej Sieka

Add necessary functions to allow MPC5XXX machines to use libfdt. Code was derived from analogous MPC83xx implementation. Also, add a small coding style fix while in the area.

Comments below
g.

Quoted 10 lines

---
I have sent a wrong patch with wrong comments before, please disregard my previous email on the same topic; and sorry for the noise.

The baseline used to generate the patch was the master (as of cc3023b9f95d7ac959a764471a65001062aecf41) with pulled u-boot-fdt#fdt branch (as of 01f771763ed822145b54819abb9c4516c8216d48).

The patch has been tested on two MPC5200B-based boards, one using CONFIG_OF_LIBFDT, the other using CONFIG_OF_FLAT_TREE.

Isn't OF_LIBFDT supposed to replace OF_FLAT_TREE? There aren't many 5xxx boards using OF_FLAT_TREE. You should craft your patch to update all the OF_FLAT_TREE users to OF_LIBFDT.

Quoted 64 lines
cpu/mpc5xxx/cpu.c +41 -0
index 1eac2bb..2be5caa 100644
@@ -19,6 +19,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
+ *
+ * Libfdt related routines derived from the MPC83xx.
  */
 
 /*
@@ -33,6 +35,9 @@
 
 #if defined(CONFIG_OF_FLAT_TREE)
 #include <ft_build.h>
+#elif defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
 #endif
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -109,9 +114,125 @@ unsigned long get_tbclk (void)
        return (tbclk);
 }
 
+#if defined(CONFIG_OF_LIBFDT)
+/*
+ * "Setter" functions used to add/modify FDT entries.
+ */
+static int fdt_set_tbfreq(void *fdt, int nodeoffset, const char *name, bd_t *bd)
+{
+       u32 tmp;
+       /*
+        * Create or update the property.
+        */
+       tmp = cpu_to_be32(OF_TBCLK);
+       return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name,
+                               bd_t *bd)
+{
+       u32 tmp;
+       /*
+        * Create or update the property.
+        */
+       tmp = cpu_to_be32(bd->bi_busfreq);
+       return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_clockfreq(void *fdt, int nodeoffset, const char *name,
+                               bd_t *bd)
+{
+       u32 tmp;
+       /*
+        * Create or update the property.
+        */
+       tmp = cpu_to_be32(bd->bi_intfreq);
+       return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+

cpu/mpc5xxx/cpu.c unsigned long get_tbclk (void) · line 162

Quoted 10 lines
cpu/mpc5xxx/cpu.c +10 -0
+static int fdt_set_ipbusfreq(void *fdt, int nodeoffset, const char *name,
+                               bd_t *bd)
+{
+       u32 tmp;
+       /*
+        * Create or update the property.
+        */
+       tmp = cpu_to_be32(bd->bi_ipbfreq);
+       return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}

These 4 functions are pretty close to identical (except for the parameter to cpu_to_be32()). Surely there is a more compact way to do this. In addition, these function don't really contain anything that screams out "5xxx only!". Can this be common support code usable by all boards?

Alternately, this is a very verbose block of code. If it cannot be consolidated and simplified, then it should all just be rolled into ft_cpu_setup. (Table driven works well when there is a lot of entries using common functions/data, which is not currently the case).

Quoted 100 lines
cpu/mpc5xxx/cpu.c +74 -4
+
+static int fdt_set_macaddress(void *fdt, int nodeoffset, const char *name,
+                               bd_t *bd)
+{
+       /*
+        * Fix it up if it exists, don't create it if it doesn't exist.
+        */
+       if (fdt_get_property(fdt, nodeoffset, name, 0)) {
+               return fdt_setprop(fdt, nodeoffset, name, bd->bi_enetaddr, 6);
+       }
+       return 0;
+}
+
 /* ------------------------------------------------------------------------- */
+/*
+ * Fixups to the fdt.
+ */
+static const struct {
+       char *node;
+       char *prop;
+       int (*set_fn)(void *fdt, int nodeoffset, const char *name, bd_t *bd);
+} fixup_props[] = {
+       {       "/cpus/" OF_CPU,
+               "timebase-frequency",
+               fdt_set_tbfreq
+       },
+       {       "/cpus/" OF_CPU,
+               "bus-frequency",
+               fdt_set_busfreq
+       },
+       {       "/cpus/" OF_CPU,
+               "clock-frequency",
+               fdt_set_clockfreq
+       },
+       {       "/" OF_SOC,
+               "bus-frequency",
+               fdt_set_ipbusfreq
+       },
+       {       "/" OF_SOC "/ethernet at 3000",
+               "mac-address",
+               fdt_set_macaddress
+       },
+       {       "/" OF_SOC "/ethernet at 3000",
+               "local-mac-address",
+               fdt_set_macaddress
+       }
+};
 
-#ifdef CONFIG_OF_FLAT_TREE
+void
+ft_cpu_setup(void *blob, bd_t *bd)
+{
+       int nodeoffset;
+       int err;
+       int j;
+
+       for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) {
+               nodeoffset = fdt_find_node_by_path(blob, fixup_props[j].node);
+               if (nodeoffset >= 0) {
+                       err = fixup_props[j].set_fn(blob, nodeoffset,
+                                               fixup_props[j].prop, bd);
+                       if (err < 0)
+                               debug("Problem setting %s = %s: %s\n",
+                                       fixup_props[j].node,
+                                       fixup_props[j].prop,
+                                       fdt_strerror(err));
+               } else {
+                       debug("Couldn't find %s: %s\n",
+                               fixup_props[j].node,
+                               fdt_strerror(nodeoffset));
+               }
+       }
+}
+#elif defined(CONFIG_OF_FLAT_TREE)
 void
 ft_cpu_setup(void *blob, bd_t *bd)
 {
@@ -132,8 +253,9 @@ ft_cpu_setup(void *blob, bd_t *bd)
        if (p != NULL)
                memcpy(p, bd->bi_enetaddr, 6);
 
-       p = ft_get_prop(blob, "/" OF_SOC "/ethernet at 3000/local-mac-address", &len);
+       p = ft_get_prop(blob, "/" OF_SOC "/ethernet at 3000/local-mac-address",
+                        &len);
        if (p != NULL)
                memcpy(p, bd->bi_enetaddr, 6);
 }
-#endif
+#endif /* defined(CONFIG_OF_FLAT_TREE) */
 
-------------------------------------------------------------------------

This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
U-Boot-Users mailing list
U-Boot-Users at lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/u-boot-users

Signature · 4 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely at secretlab.ca
(403) 399-0195
#3 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

On Fri, Aug 03, 2007 at 08:25:56AM -0600, Grant Likely wrote:
[...]

Quoted 40 lines
Quoted 40 lines
(quoted diff) +40 -0
+static int fdt_set_tbfreq(void *fdt, int nodeoffset, const char *name, bd_t *bd)
+{
+       u32 tmp;
+       /*
+        * Create or update the property.
+        */
+       tmp = cpu_to_be32(OF_TBCLK);
+       return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name,
+                               bd_t *bd)
+{
+       u32 tmp;
+       /*
+        * Create or update the property.
+        */
+       tmp = cpu_to_be32(bd->bi_busfreq);
+       return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_clockfreq(void *fdt, int nodeoffset, const char *name,
+                               bd_t *bd)
+{
+       u32 tmp;
+       /*
+        * Create or update the property.
+        */
+       tmp = cpu_to_be32(bd->bi_intfreq);
+       return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_ipbusfreq(void *fdt, int nodeoffset, const char *name,
+                               bd_t *bd)
+{
+       u32 tmp;
+       /*
+        * Create or update the property.
+        */
+       tmp = cpu_to_be32(bd->bi_ipbfreq);
Quoted 8 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+       return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}

These 4 functions are pretty close to identical (except for the parameter to cpu_to_be32()). Surely there is a more compact way to do this. In addition, these function don't really contain anything that screams out "5xxx only!". Can this be common support code usable by all boards?

Please see the patch below for a more generic approach to property fixups. The patch updates mpc5xxx-related code, but I've looked at mpc83xx fixups and it seems like they can be adapted to this approach as well.

I am interested in the comments people might have before proceeding further (i.e., getting rid of OF_FLAT_TREE in mpc5xxx).

Regards,
Bartlomiej

cpu/mpc5xxx/cpu.c +77 -2
index 1eac2bb..1e661c2 100644
@@ -33,6 +33,9 @@
 
 #if defined(CONFIG_OF_FLAT_TREE)
 #include <ft_build.h>
+#elif defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
 #endif
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -109,9 +112,81 @@ unsigned long get_tbclk (void)
 	return (tbclk);
 }
 
+#if defined(CONFIG_OF_LIBFDT)
 /* ------------------------------------------------------------------------- */
-
-#ifdef CONFIG_OF_FLAT_TREE
+/*
+ * Fixups to the fdt.
+ */
+void
+ft_cpu_setup(void *blob, bd_t *bd)
+{
+	u32 tbfreq;
+	u32 busfreq;
+	u32 intfreq;
+	u32 ipbfreq;
+
+	/* fixup properties */
+	fdt_fixup_props_t fixup_props[] = {
+		{	"/cpus/" OF_CPU,
+			"timebase-frequency",
+			NULL,	/* to be set manually */
+			0,	/* to be set manually */
+			1
+		},
+		{	"/cpus/" OF_CPU,
+			"bus-frequency",
+			NULL,	/* to be set manually */
+			0,	/* to be set manually */
+			1
+		},
+		{	"/cpus/" OF_CPU,
+			"clock-frequency",
+			NULL,	/* to be set manually */
+			0,	/* to be set manually */
+			1
+		},
+		{	"/" OF_SOC,
+			"bus-frequency",
+			NULL,	/* to be set manually */
+			0,	/* to be set manually */
+			1
+		},
+		{	"/" OF_SOC "/ethernet at 3000",
+			"mac-address",
+			bd->bi_enetaddr,
+			6,
+			0
+		},
+		{	"/" OF_SOC "/ethernet at 3000",
+			"local-mac-address",
+			bd->bi_enetaddr,
+			6,
+			0
+		}
+	};
+
+	/* manually set members that can't be initialized in the definition */
+	tbfreq = cpu_to_be32(OF_TBCLK);
+	fixup_props[0].val = &tbfreq;
+	fixup_props[0].len = sizeof(tbfreq);
+
+	busfreq = cpu_to_be32(bd->bi_busfreq);
+	fixup_props[1].val = &busfreq;
+	fixup_props[1].len = sizeof(busfreq);
+
+	intfreq = cpu_to_be32(bd->bi_intfreq);
+	fixup_props[2].val = &intfreq;
+	fixup_props[2].len = sizeof(intfreq);
+
+	ipbfreq = cpu_to_be32(bd->bi_ipbfreq);
+	fixup_props[3].val = &ipbfreq;
+	fixup_props[3].len = sizeof(ipbfreq);
+
+
+	fdt_fixup_props(blob, fixup_props,
+			sizeof(fixup_props) / sizeof(fixup_props[0]));
+}
+#elif defined(CONFIG_OF_FLAT_TREE)
 void
 ft_cpu_setup(void *blob, bd_t *bd)
 {
include/libfdt.h +12 -0
index 340e89d..065c580 100644
@@ -23,6 +23,17 @@
 #include <fdt.h>
 #include <libfdt_env.h>
 
+
+/* Structure describing property to be fixed-up in cpu-specific code */
+typedef struct {
+        char *node;
+        char *prop;
+        void *val;
+        int len;        /* sizeof(val) */
+        char create;    /* whether to create non-existing properties */
+} fdt_fixup_props_t;
+
+
 #define FDT_FIRST_SUPPORTED_VERSION	0x10
 #define FDT_LAST_SUPPORTED_VERSION	0x11
 
@@ -145,6 +156,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
 			    const char *name, int namelen);
 int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
 int fdt_del_node(void *fdt, int nodeoffset);
+void fdt_fixup_props(void *blob, fdt_fixup_props_t fixup_props[], int count);
 
 /* Extra functions */
 const char *fdt_strerror(int errval);
libfdt/fdt_rw.c +38 -0
index 693bfe4..572a4e6 100644
@@ -19,6 +19,8 @@
 #include "config.h"
 #if CONFIG_OF_LIBFDT
 
+#include <common.h>
+
 #include "libfdt_env.h"
 
 #include <fdt.h>
@@ -295,4 +297,40 @@ int fdt_pack(void *fdt)
 	return 0;
 }
 
+
+/*
+ * Function fixes up properties in passed 'blob'. It uses the array
+ * 'fixup_props' to take the description of properites to be fixed up, and
+ * processes 'count' elements from this array.
+ */
+void fdt_fixup_props(void *blob, fdt_fixup_props_t fixup_props[], int count)
+{
+	int nodeoffset;
+	int err;
+	int j;
+
+	for (j = 0; j < count; j++) {
+		nodeoffset = fdt_find_node_by_path(blob, fixup_props[j].node);
+		if (nodeoffset >= 0) {
+			if (fixup_props[j].create ||
+				fdt_get_property(blob, nodeoffset,
+					fixup_props[j].prop, 0))
+				err = fdt_setprop(blob, nodeoffset,
+							fixup_props[j].prop,
+							fixup_props[j].val,
+							fixup_props[j].len);
+			else
+				err = 0;
+			if (err < 0)
+				debug("Problem setting %s = %s: %s\n",
+					fixup_props[j].node,
+					fixup_props[j].prop,
+					fdt_strerror(err));
+
+		} else
+			debug("Couldn't find %s: %s\n",
+				fixup_props[j].node,
+				fdt_strerror(nodeoffset));
+	}
+}
 #endif /* CONFIG_OF_LIBFDT */
#4 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

Quoted 12 lines · Bartlomiej Sieka

On Fri, Aug 03, 2007 at 08:25:56AM -0600, Grant Likely wrote:
[...]

Quoted 10 lines
Quoted 10 lines
(quoted diff) +10 -0
+static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name,
+                               bd_t *bd)
+{
+       u32 tmp;
+       /*
+        * Create or update the property.
+        */
+       tmp = cpu_to_be32(bd->bi_busfreq);
+       return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}

[snip]

Quoted 42 lines

Please see the patch below for a more generic approach to property fixups. The patch updates mpc5xxx-related code, but I've looked at mpc83xx fixups and it seems like they can be adapted to this approach as well.

I am interested in the comments people might have before proceeding further (i.e., getting rid of OF_FLAT_TREE in mpc5xxx).

Regards,
Bartlomiej

cpu/mpc5xxx/cpu.c +13 -2
index 1eac2bb..1e661c2 100644
@@ -33,6 +33,9 @@
 
 #if defined(CONFIG_OF_FLAT_TREE)
 #include <ft_build.h>
+#elif defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
 #endif
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -109,9 +112,81 @@ unsigned long get_tbclk (void)
 	return (tbclk);
 }
 
+#if defined(CONFIG_OF_LIBFDT)
 /* ------------------------------------------------------------------------- */
-
-#ifdef CONFIG_OF_FLAT_TREE
+/*
+ * Fixups to the fdt.
+ */
+void
+ft_cpu_setup(void *blob, bd_t *bd)
+{
+	u32 tbfreq;
+	u32 busfreq;
+	u32 intfreq;

cpu/mpc5xxx/cpu.c unsigned long get_tbclk (void) · line 135

Quoted 10 lines
cpu/mpc5xxx/cpu.c +10 -0
+	u32 ipbfreq;
+
+	/* fixup properties */
+	fdt_fixup_props_t fixup_props[] = {
+		{	"/cpus/" OF_CPU,
+			"timebase-frequency",
+			NULL,	/* to be set manually */
+			0,	/* to be set manually */
+			1
+		},

If it must be set manually, what is the point of having it in the table?

[snip more manuals]

Quoted 20 lines
cpu/mpc5xxx/cpu.c +20 -0
+		{	"/" OF_SOC "/ethernet at 3000",
+			"mac-address",
+			bd->bi_enetaddr,
+			6,
+			0
+		},
+		{	"/" OF_SOC "/ethernet at 3000",
+			"local-mac-address",
+			bd->bi_enetaddr,
+			6,
+			0
+		}
+	};
+
+	/* manually set members that can't be initialized in the definition */
+	tbfreq = cpu_to_be32(OF_TBCLK);
+	fixup_props[0].val = &tbfreq;
+	fixup_props[0].len = sizeof(tbfreq);
+
+	busfreq = cpu_to_be32(bd->bi_busfreq);

cpu/mpc5xxx/cpu.c unsigned long get_tbclk (void) · line 183

Quoted 10 lines
cpu/mpc5xxx/cpu.c +10 -0
+	fixup_props[1].val = &busfreq;
+	fixup_props[1].len = sizeof(busfreq);
+
+	intfreq = cpu_to_be32(bd->bi_intfreq);
+	fixup_props[2].val = &intfreq;
+	fixup_props[2].len = sizeof(intfreq);
+
+	ipbfreq = cpu_to_be32(bd->bi_ipbfreq);
+	fixup_props[3].val = &ipbfreq;
+	fixup_props[3].len = sizeof(ipbfreq);

Ouch, we just lost a big part of the advantage of being table driven if we have to rewrite the table on the fly by hand. Now I see what "manual" (above) means, and it is worse than I thought originally. :-(

What happens when someone puts another property in the table between fixup_props[1] and fixup_props[2]? BAD THINGS!!!!!

Quoted 81 lines
cpu/mpc5xxx/cpu.c +4 -0
+	fdt_fixup_props(blob, fixup_props,
+			sizeof(fixup_props) / sizeof(fixup_props[0]));
+}
+#elif defined(CONFIG_OF_FLAT_TREE)
 void
 ft_cpu_setup(void *blob, bd_t *bd)
 {
include/libfdt.h +12 -0
index 340e89d..065c580 100644
@@ -23,6 +23,17 @@
 #include <fdt.h>
 #include <libfdt_env.h>
 
+
+/* Structure describing property to be fixed-up in cpu-specific code */
+typedef struct {
+        char *node;
+        char *prop;
+        void *val;
+        int len;        /* sizeof(val) */
+        char create;    /* whether to create non-existing properties */
+} fdt_fixup_props_t;
+
+
 #define FDT_FIRST_SUPPORTED_VERSION	0x10
 #define FDT_LAST_SUPPORTED_VERSION	0x11
 
@@ -145,6 +156,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
 			    const char *name, int namelen);
 int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
 int fdt_del_node(void *fdt, int nodeoffset);
+void fdt_fixup_props(void *blob, fdt_fixup_props_t fixup_props[], int count);
 
 /* Extra functions */
 const char *fdt_strerror(int errval);
libfdt/fdt_rw.c +29 -0
index 693bfe4..572a4e6 100644
@@ -19,6 +19,8 @@
 #include "config.h"
 #if CONFIG_OF_LIBFDT
 
+#include <common.h>
+
 #include "libfdt_env.h"
 
 #include <fdt.h>
@@ -295,4 +297,40 @@ int fdt_pack(void *fdt)
 	return 0;
 }
 
+
+/*
+ * Function fixes up properties in passed 'blob'. It uses the array
+ * 'fixup_props' to take the description of properites to be fixed up, and
+ * processes 'count' elements from this array.
+ */
+void fdt_fixup_props(void *blob, fdt_fixup_props_t fixup_props[], int count)
+{
+	int nodeoffset;
+	int err;
+	int j;
+
+	for (j = 0; j < count; j++) {
+		nodeoffset = fdt_find_node_by_path(blob, fixup_props[j].node);
+		if (nodeoffset >= 0) {
+			if (fixup_props[j].create ||
+				fdt_get_property(blob, nodeoffset,
+					fixup_props[j].prop, 0))
+				err = fdt_setprop(blob, nodeoffset,
+							fixup_props[j].prop,
+							fixup_props[j].val,
+							fixup_props[j].len);
+			else
+				err = 0;
+			if (err < 0)
+				debug("Problem setting %s = %s: %s\n",
+					fixup_props[j].node,

libfdt/fdt_rw.c int fdt_pack(void *fdt) · line 336

Quoted 10 lines
libfdt/fdt_rw.c +9 -0
+					fixup_props[j].prop,
+					fdt_strerror(err));
+
+		} else
+			debug("Couldn't find %s: %s\n",
+				fixup_props[j].node,
+				fdt_strerror(nodeoffset));
+	}
+}
 #endif /* CONFIG_OF_LIBFDT */

This looks similar to what I originally wrote, which was table driven.
<http://www.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=blob;f=cpu/mpc83xx/cpu.c;hb=64dbbd40c58349b64f43fd33dbb5ca0adb67d642>

Your implementation is better than my original implementation, but the current cpu/mpc83xx/cpu.c implementation: simple table and "setter" functions (Grant's suggested approach, above) is much better.

Both my original implementation and your implementation has pretty severe problems when a value has to be manipulated (byteswapping is the primary culprit, but arithmetic scaling could also pop up). Your table driven implementation deals with this problem by rewriting values in the table at runtime. That is a nasty thing to do and scales horribly. In addition, your "manual" fixups are all hardcoded, which totally destroys any benefit of having a table.

The "setter" functions have almost unlimited flexibility. The cost is that there potentially needs to be quite a few setter functions. The reality (so far) is that it is a reasonable number and each one is trivial. In addition, some of them are used in multiple places. On the "plus" side, the table becomes much simpler, which saves space and counterbalances the cost of the "setter" functions.

IMO your proposal is not acceptable. Follow Grant's advice and the current cpu/mpc83xx/cpu.c methodology.

Sorry for the heavy handed critique,
gvb

#5 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

Quoted 2 lines · On Wed, 22 Aug 2007 09:18:20 -0400 Jerry Van Baren…

IMO your proposal is not acceptable. Follow Grant's advice and the current cpu/mpc83xx/cpu.c methodology.

? Bartlomiej's first patch followed the 83xx 'methodology', which Grant commented on, which is what Bartlomiej tried to fix here. Maybe I missed something, but anyway, now that the window has closed, we can arrange to fix libfdt support for all powerpc boards for the next release.

What about having a list of functions to call? It could be called something like fdt_update_sequence, and be similar in implementation to lib_ppc/board.c's init_sequence. It could also reside in lib_ppc, esp. since, e.g. all powerpc's have a timebase, and to help naturally enforce a certain level of consistency among powerpc board code. The updater/fixup/"setter" functions would only need be passed the pointer to the base of the blob to update.

The update functions need to be rewritten to be independent of the OF_CPU, OF_SOC, OF_QE, OF_STDOUT_PATH defines. Those should all be removed (OF_TBCLK might be a bit harder to get rid of though -- implement TBCLK_DIVISOR instead?). btw, Linux is changing the name of the soc node from, e.g. "soc8360", to simply "soc", and u-boot needs to handle transitions like these better. Instead of adding support for both name types, the update functions can handle these situations by using some of the higher level functions available in libfdt, such as fdt_find_node_by_type or even fdt_find_compatible_node.

Kim

#6 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

Quoted 11 lines · Kim Phillips
Quoted 2 lines · On Wed, 22 Aug 2007 09:18:20 -0400 Jerry Van Baren…

IMO your proposal is not acceptable. Follow Grant's advice and the current cpu/mpc83xx/cpu.c methodology.

? Bartlomiej's first patch followed the 83xx 'methodology', which Grant commented on, which is what Bartlomiej tried to fix here. Maybe I missed something, but anyway, now that the window has closed, we can arrange to fix libfdt support for all powerpc boards for the next release.

Well, perhaps Grant can speak to the issue better than me, but I read Grant's reply as a request to coelesce the four "setter" functions into one, not to remove all setter functions and change it back to the original table mechanism. IMHO, using hardcoded [0] [1]... indexes is MUCH MORE EVIL than having four similar setter functions.

While I agree that extra setter functions are undesirable, I don't know if Grant's suggestion can be achieved in a way better than the current way (that is a challenge ;-).

Quoted 7 lines

What about having a list of functions to call? It could be called something like fdt_update_sequence, and be similar in implementation to lib_ppc/board.c's init_sequence. It could also reside in lib_ppc, esp. since, e.g. all powerpc's have a timebase, and to help naturally enforce a certain level of consistency among powerpc board code. The updater/fixup/"setter" functions would only need be passed the pointer to the base of the blob to update.

We _have_ "a list of functions to call". That is what is done with the 83xx which is what I advocated and what Bartlomiej had before rewriting it back into a table without functions.

If the "setter" functions can be segregated into general PPC ones and CPU-specific ones, that would be great. If the number of "setter" functions can be reduced without degrading reliability etc, that would be greate.

Quoted 9 lines

The update functions need to be rewritten to be independent of the OF_CPU, OF_SOC, OF_QE, OF_STDOUT_PATH defines. Those should all be removed (OF_TBCLK might be a bit harder to get rid of though -- implement TBCLK_DIVISOR instead?). btw, Linux is changing the name of the soc node from, e.g. "soc8360", to simply "soc", and u-boot needs to handle transitions like these better. Instead of adding support for both name types, the update functions can handle these situations by using some of the higher level functions available in libfdt, such as fdt_find_node_by_type or even fdt_find_compatible_node.

Yes, that needs to go on the list. Done.
<http://www.denx.de/wiki/view/UBoot/UBootFdtInfo#ToDo>

Best regards,
gvb

#7 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

Quoted 13 lines · On Wed, 22 Aug 2007 19:16:16 -0400 Jerry Van Baren <[email protected]> wrote:
Quoted 11 lines · Kim Phillips
Quoted 2 lines · On Wed, 22 Aug 2007 09:18:20 -0400 Jerry Van Baren…

IMO your proposal is not acceptable. Follow Grant's advice and the current cpu/mpc83xx/cpu.c methodology.

? Bartlomiej's first patch followed the 83xx 'methodology', which Grant commented on, which is what Bartlomiej tried to fix here. Maybe I missed something, but anyway, now that the window has closed, we can arrange to fix libfdt support for all powerpc boards for the next release.

Quoted 4 lines

Well, perhaps Grant can speak to the issue better than me, but I read Grant's reply as a request to coelesce the four "setter" functions into one, not to remove all setter functions and change it back to the original table mechanism. IMHO, using hardcoded [0] [1]... indexes is

sounds good. Thanks for clarifying this.

Quoted 11 lines
Quoted 7 lines

What about having a list of functions to call? It could be called something like fdt_update_sequence, and be similar in implementation to lib_ppc/board.c's init_sequence. It could also reside in lib_ppc, esp. since, e.g. all powerpc's have a timebase, and to help naturally enforce a certain level of consistency among powerpc board code. The updater/fixup/"setter" functions would only need be passed the pointer to the base of the blob to update.

We _have_ "a list of functions to call". That is what is done with the 83xx which is what I advocated and what Bartlomiej had before rewriting it back into a table without functions.

yeah, I meant /just/ a list of functions to call, without all the extra fluff in both the existing 83xx and Bartlomiej's implementations.

Kim

#8 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

Quoted 3 lines · Kim Phillips
Quoted 1 line · On Wed, 22 Aug 2007 19:16:16 -0400 Jerry Van Baren <[email protected]> wrote:

Kim Phillips wrote:

[snip]

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

What about having a list of functions to call? It could be called something like fdt_update_sequence, and be similar in implementation to lib_ppc/board.c's init_sequence. It could also reside in lib_ppc, esp. since, e.g. all powerpc's have a timebase, and to help naturally enforce a certain level of consistency among powerpc board code. The updater/fixup/"setter" functions would only need be passed the pointer to the base of the blob to update.

Quoted 8 lines
Quoted 3 lines

We _have_ "a list of functions to call". That is what is done with the 83xx which is what I advocated and what Bartlomiej had before rewriting it back into a table without functions.

yeah, I meant /just/ a list of functions to call, without all the extra fluff in both the existing 83xx and Bartlomiej's implementations.

Kim

Well, the table has the node, the property, and the "setter" routine. This allows us to re-use the "setter" routine where possible. Where there are multiple setter routines is where, for instance, the property is based on a different clock or a different MAC address. In those cases the setters are identical except for one line, but that one line is *why* they are different.

The first half of Grant's comment was:

Quoted 3 lines

These 4 functions are pretty close to identical (except for the parameter to cpu_to_be32()). Surely there is a more compact way to do this.

My answer is "no, the whole reason there is one line different is because it *has to be*." As the French say about the "Y" chromosome "...and viva la difference." My first attempt, and Bartlomiej's proposed patch, tried (tries) to put the value in the table, but it is a *WORSE* solution because you have the problem with byteswapping or not and different sizes of values. The scorecard for putting the values in the tables and also having it maintainable is 0 for 2.

Note that the original code is a repetitive in-line coding of what is inside the "setter" functions, with 100% duplication of code. My change to a table driven method with "setter" functions drops the 100% duplication of code to less, probably 80%.

I would lay down a challenge to make the code both more compact *and* not lose maintainability.

"Make everything as simple as possible, but not simpler."
-- Albert Einstein <http://www.quotedb.com/quotes/1360>

The second half of Grant's comment was:

Quoted 3 lines

In addition, these function don't really contain anything that screams out "5xxx only!". Can this be common support code usable by all boards?

To this I simply say "yup." To date, this has been 83xx only (mostly?).
With more PPC CPU types comes the opportunity to identify and abstract
the common "setter" functions.

*This* is where Bartlomiej should start IMHO. It is where the payback is.

Best regards,
gvb

#9 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

Quoted 5 lines · Jerry Van Baren

The first half of Grant's comment was:

Quoted 3 lines

These 4 functions are pretty close to identical (except for the parameter to cpu_to_be32()). Surely there is a more compact way to do this.

Quoted 7 lines

My answer is "no, the whole reason there is one line different is because it *has to be*." As the French say about the "Y" chromosome "...and viva la difference." My first attempt, and Bartlomiej's proposed patch, tried (tries) to put the value in the table, but it is a *WORSE* solution because you have the problem with byteswapping or not and different sizes of values. The scorecard for putting the values in the tables and also having it maintainable is 0 for 2.

Yes, this is the icky bit; but I still argue that there is a more compact way to do it. Table driven is nice when it works; but (as I also mentioned in my original comment) whie it doesn't its probably better to just fall back to something programatic

ie (totally untested):

static int fixup_prop(void *fdt, char *node, char *prop, void *val, int size)

{
        int nodeoffset;
        int rc;

        nodeoffset = fdt_find_node_by_path(fdt, node);
        if (nodeoffset < 0) {
                debug("Couldn't find %s: %s\n", node, fdt_strerror(nodeoffset));
                return nodeoffset;
        }

        rc = fdt_get_property(fdt, nodeoffset, prop, 0)
        if (rc)
                goto err;

        rc = fdt_setprop(fdt, nodeoffset, prop, val, size);
        if (rc)
                goto err;

err:

        debug("Problem setting %s = %s: %s\n", node, prop, fdt_strerror(rc));
        return rc;
}

static int fixup_int_prop(void *fdt, char *node, char *prop, u32 val)

{
        val = cpu_to_be32(val);
        return ft_fixup_int_prop(fdt, node, prop, &val, sizeof(val));
}

void
ft_cpu_setup(void *blob, bd_t *bd)

{
        fixup_int_prop(blob, "/cpus/" OF_CPU, "timebase-frequency", OF_TBCLK);
        fixup_int_prop(blob, "/cpus/" OF_CPU, "bus-frequency", bd->bi_busfreq);
        fixup_int_prop(blob, "/cpus/" OF_CPU, "clock-frequency",
bd->bi_intfreq);
        fixup_int_prop(blob, "/cpus/" OF_CPU, "bus-frequency", bd->ipbfreq);
        fixup_prop(blob, "/" OF_SOC "/ethernet at 3000", "mac-address",
                   bd->bi_enetaddr, 6);
        fixup_prop(blob, "/" OF_SOC "/ethernet at 3000", "local-mac-address",
                   bd->bi_enetaddr, 6);
}

This adds 2 helper functions instead of 5, and one of them is the same path for all of the fixups. Drops the table approach entirely due to the problems with extracting values out of bd. (Which is what I meant in the third part of my original comment)

The 2 new helpers could also be generalized for use by all boards.

Cheers,
g.

Signature · 4 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely at secretlab.ca
(403) 399-0195
#10 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

Quoted 32 lines · Grant Likely
Quoted 5 lines · Jerry Van Baren

The first half of Grant's comment was:

Quoted 3 lines

These 4 functions are pretty close to identical (except for the parameter to cpu_to_be32()). Surely there is a more compact way to do this.

Quoted 7 lines

My answer is "no, the whole reason there is one line different is because it *has to be*." As the French say about the "Y" chromosome "...and viva la difference." My first attempt, and Bartlomiej's proposed patch, tried (tries) to put the value in the table, but it is a *WORSE* solution because you have the problem with byteswapping or not and different sizes of values. The scorecard for putting the values in the tables and also having it maintainable is 0 for 2.

Yes, this is the icky bit; but I still argue that there is a more compact way to do it. Table driven is nice when it works; but (as I also mentioned in my original comment) whie it doesn't its probably better to just fall back to something programatic

ie (totally untested):

static int fixup_prop(void *fdt, char *node, char *prop, void *val, int size)

{
        int nodeoffset;
        int rc;

        nodeoffset = fdt_find_node_by_path(fdt, node);
        if (nodeoffset < 0) {
                debug("Couldn't find %s: %s\n", node, fdt_strerror(nodeoffset));
                return nodeoffset;
        }
Quoted 7 lines
        rc = fdt_get_property(fdt, nodeoffset, prop, 0)
        if (rc)
                goto err;

        rc = fdt_setprop(fdt, nodeoffset, prop, val, size);
        if (rc)
                goto err;
	goto ret;
Quoted 2 lines

err:

        debug("Problem setting %s = %s: %s\n", node, prop, fdt_strerror(rc));

ret: // hey, we *CAN* program FORTRAN in C ;-)

Quoted 2 lines
        return rc;
}

This is too simplistic for the known cases.
* You pass in a size, but can only handle integers (rc is int). If the size is 6 bytes (MAC), Bad Things[tm] will happen. If it is 1 or 2 bytes, it probably will work, but is unclean type-wise.

* The rules are different for some properties: some are set-always and some are set only if it already exists (e.g. local-mac-address).

By the time you write enough "general" functions to cover all the cases currently covered, I suspect you will have the same number of functions as the current implementation. If not, we have too many "setter" functions in the current implementation and they should be coalesced. :-)

It is possible that I _did_ write more "setter" functions than necessary. I plan to look at it, but have been busy. :-/ Adding LIBFDT support to other CPUs and factoring out the common routines would help with a review.

Quoted 20 lines

static int fixup_int_prop(void *fdt, char *node, char *prop, u32 val)

{
        val = cpu_to_be32(val);
        return ft_fixup_int_prop(fdt, node, prop, &val, sizeof(val));
}

void
ft_cpu_setup(void *blob, bd_t *bd)

{
        fixup_int_prop(blob, "/cpus/" OF_CPU, "timebase-frequency", OF_TBCLK);
        fixup_int_prop(blob, "/cpus/" OF_CPU, "bus-frequency", bd->bi_busfreq);
        fixup_int_prop(blob, "/cpus/" OF_CPU, "clock-frequency",
bd->bi_intfreq);
        fixup_int_prop(blob, "/cpus/" OF_CPU, "bus-frequency", bd->ipbfreq);
        fixup_prop(blob, "/" OF_SOC "/ethernet at 3000", "mac-address",
                   bd->bi_enetaddr, 6);
        fixup_prop(blob, "/" OF_SOC "/ethernet at 3000", "local-mac-address",
                   bd->bi_enetaddr, 6);
}
Quoted 4 lines

This adds 2 helper functions instead of 5, and one of them is the same path for all of the fixups. Drops the table approach entirely due to the problems with extracting values out of bd. (Which is what I meant in the third part of my original comment)

I think 2 is too optimistic, but it is still possible this approach would be better than the current 5. The above looks better, but I claim only because it is oversimplified - I contend the 2 helper functions will expand to 5 functions that basically are the current "setter" functions. On the other hand, maybe not. It is worth trying.

I thought a table approach would be more obvious than the #ifdef spaghetti that was in the original code, but I'm not all that wild about the resulting code. In my implementation, with the table and the "setter" functions separated, it still results in obfuscation, especially where table entries and corresponding "setter" functions are #ifdefed. :-( Note that the above proposal doesn't help a lot because the routine calling the new helper function and the helper functions are still separated. :-/

Part of what I'm unhappy about is that I ended up with two sets of #ifdefs where there is conditional code: one in the table and one for the corresponding "setter" function. The above proposal may help, but only if the "helper" functions are truly generalized and I am somewhat skeptical about 100% success.

Quoted 1 line

The 2 new helpers could also be generalized for use by all boards.

s/2/n/ (where n is probably 5) and I would agree 100%. :-/

Quoted 2 lines

Cheers,
g.

Best regards,
gvb

#11 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

Quoted 14 lines · Jerry Van Baren
Quoted 13 lines · Grant Likely
Quoted 12 lines · Jerry Van Baren

The first half of Grant's comment was:

Quoted 3 lines

These 4 functions are pretty close to identical (except for the parameter to cpu_to_be32()). Surely there is a more compact way to do this.

My answer is "no, the whole reason there is one line different is because it *has to be*." As the French say about the "Y" chromosome "...and viva la difference." My first attempt, and Bartlomiej's proposed patch, tried (tries) to put the value in the table, but it is a *WORSE* solution because you have the problem with byteswapping or not and different sizes of values. The scorecard for putting the values in the tables and also having it maintainable is 0 for 2.

Quoted 4 lines
Quoted 4 lines

Yes, this is the icky bit; but I still argue that there is a more compact way to do it. Table driven is nice when it works; but (as I also mentioned in my original comment) whie it doesn't its probably better to just fall back to something programatic

[snip pseudo code any my reply]

Quoted 10 lines
Quoted 10 lines

void
ft_cpu_setup(void *blob, bd_t *bd)

{
        fixup_int_prop(blob, "/cpus/" OF_CPU, "timebase-frequency", OF_TBCLK);
        fixup_int_prop(blob, "/cpus/" OF_CPU, "bus-frequency", bd->bi_busfreq);
        fixup_int_prop(blob, "/cpus/" OF_CPU, "clock-frequency",
bd->bi_intfreq);
        fixup_int_prop(blob, "/cpus/" OF_CPU, "bus-frequency", bd->ipbfreq);
        fixup_prop(blob, "/" OF_SOC "/ethernet at 3000", "mac-address",
                   bd->bi_enetaddr, 6);
	fixup_mac_prop(blob, "/" OF_SOC "/ethernet at 3000", "mac-address",
		bd->bi_enetaddr, 1);
Quoted 2 lines
Quoted 2 lines
        fixup_prop(blob, "/" OF_SOC "/ethernet at 3000", "local-mac-address",
                   bd->bi_enetaddr, 6);
	fixup_mac_prop(blob, "/" OF_SOC "/ethernet at 3000",
		"local-mac-address", bd->bi_enetaddr, 0);
Quoted 7 lines
Quoted 6 lines

}

This adds 2 helper functions instead of 5, and one of them is the same path for all of the fixups. Drops the table approach entirely due to the problems with extracting values out of bd. (Which is what I meant in the third part of my original comment)

Quoted 5 lines

I think 2 is too optimistic, but it is still possible this approach would be better than the current 5. The above looks better, but I claim only because it is oversimplified - I contend the 2 helper functions will expand to 5 functions that basically are the current "setter" functions. On the other hand, maybe not. It is worth trying.

[more snippage]

Quoted 6 lines
Quoted 1 line

The 2 new helpers could also be generalized for use by all boards.

s/2/n/ (where n is probably 5) and I would agree 100%. :-/

Quoted 2 lines

Cheers,
g.

Thinking about it and a quick glance (I'm running remotely), I think we could do the job with three "setter" functions based on Grant's proposal, which would be a Good Thing[tm].

static int fixup_int_prop(void *fdt, char *node, char *prop, u32 val)
- Like Grant proposes, note it does a cpu_to_be32()

static int fixup_mac_prop(void *fdt, char *node, char *prop, void *val, int force)
- Note I replaced "size" with "force". We know the size (6). The "force" flag (better name, anyone?) would be whether the MAC addr should be created if it _doesn't_ exist.

Best regards from the lovely Sault Ste. Marie,
gvb

<https://webcam.crrel.usace.army.mil/soo/camera2.html>
<http://maps.google.com/maps?q=sault+ste+marie&ie=UTF8&oe=utf-8&ll=46.503429,-84.351032&spn=0.005952,0.015814&t=h&z=16&om=1>

#12 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

Quoted 2 lines · Jerry Van Baren
Quoted 1 line · Jerry Van Baren

Grant Likely wrote:

[...]

Quoted 39 lines
Quoted 9 lines
Quoted 9 lines

ft_cpu_setup(void *blob, bd_t *bd)

{
        fixup_int_prop(blob, "/cpus/" OF_CPU, "timebase-frequency", OF_TBCLK);
        fixup_int_prop(blob, "/cpus/" OF_CPU, "bus-frequency", bd->bi_busfreq);
        fixup_int_prop(blob, "/cpus/" OF_CPU, "clock-frequency",
bd->bi_intfreq);
        fixup_int_prop(blob, "/cpus/" OF_CPU, "bus-frequency", bd->ipbfreq);
        fixup_prop(blob, "/" OF_SOC "/ethernet at 3000", "mac-address",
                   bd->bi_enetaddr, 6);
	fixup_mac_prop(blob, "/" OF_SOC "/ethernet at 3000", "mac-address",
		bd->bi_enetaddr, 1);
Quoted 2 lines
Quoted 2 lines
        fixup_prop(blob, "/" OF_SOC "/ethernet at 3000", "local-mac-address",
                   bd->bi_enetaddr, 6);
	fixup_mac_prop(blob, "/" OF_SOC "/ethernet at 3000",
		"local-mac-address", bd->bi_enetaddr, 0);
Quoted 11 lines
Quoted 6 lines

}

This adds 2 helper functions instead of 5, and one of them is the same path for all of the fixups. Drops the table approach entirely due to the problems with extracting values out of bd. (Which is what I meant in the third part of my original comment)

I think 2 is too optimistic, but it is still possible this approach would be better than the current 5. The above looks better, but I claim only because it is oversimplified - I contend the 2 helper functions will expand to 5 functions that basically are the current "setter" functions. On the other hand, maybe not. It is worth trying.

[more snippage]

Quoted 5 lines
Quoted 1 line

The 2 new helpers could also be generalized for use by all boards.

s/2/n/ (where n is probably 5) and I would agree 100%. :-/

Quoted 2 lines

Cheers,
g.

Thinking about it and a quick glance (I'm running remotely), I think we could do the job with three "setter" functions based on Grant's proposal, which would be a Good Thing[tm].

Quoted 8 lines

static int fixup_int_prop(void *fdt, char *node, char *prop, u32 val)
- Like Grant proposes, note it does a cpu_to_be32()

static int fixup_mac_prop(void *fdt, char *node, char *prop, void *val, int force)
- Note I replaced "size" with "force". We know the size (6). The "force" flag (better name, anyone?) would be whether the MAC addr should be created if it _doesn't_ exist.

How about having two functions lite this:

static int fixup_int_prop(void *fdt, char *node, char *prop, u32 val, int create);

static int fixup_str_prop(void *fdt, char *node, char *prop, char *val, int len, int create)

?

The last argument ('create' i.e., Jerry's 'force') tells whether the property should be created if it doesn't exist. fixup_str_prop() (a better name?) takes a len argument just in case we ever wanted to set properties with length different than the MAC address' length.

The above functions are generic and can be used by all boards; the following specific code would go into ft_cpu_setup():

fixup_int_prop(blob, "/cpus/" OF_CPU, "timebase-frequency", OF_TBCLK, 1); fixup_int_prop(blob, "/cpus/" OF_CPU, "bus-frequency", bd->bi_busfreq, 1); fixup_int_prop(blob, "/cpus/" OF_CPU, "clock-frequency", bd->bi_intfreq, 1); fixup_int_prop(blob, "/cpus/" OF_CPU, "bus-frequency", bd->ipbfreq, 1); fixup_str_prop(blob, "/" OF_SOC "/ethernet at 3000", "mac-address", bd->bi_enetaddr, 6, 0);
fixup_str_prop(blob, "/" OF_SOC "/ethernet at 3000", "local-mac-address", bd->bi_enetaddr, 6, 0);

If in the future there's a need for setting a property other than int or char[], a function similar to the two ones above can be added.

Regards,
Bartlomiej

#13 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

In reply to Kim Phillips
Quoted 11 lines · In message <[email protected]> you wrote:
Quoted 2 lines · Jerry Van Baren

IMO your proposal is not acceptable. Follow Grant's advice and the current cpu/mpc83xx/cpu.c methodology.

? Bartlomiej's first patch followed the 83xx 'methodology', which Grant commented on, which is what Bartlomiej tried to fix here. Maybe I missed something, but anyway, now that the window has closed, we can arrange to fix libfdt support for all powerpc boards for the next release.

We still accept patches that fix bugs and solve urgent problems, and if I understand correctly, Bartek's patch attempts to fix a real problem.

Best regards,

Wolfgang Denk

Signature · 7 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
There is an old custom among my people. When a woman  saves  a  man's
life, he is grateful.
	-- Nona, the Kanuto which woman, "A Private Little War",
	   stardate 4211.8.
#14 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

Quoted 13 lines · On Thu, 23 Aug 2007 01:30:29 +0200 Wolfgang Denk <[email protected]> wrote:
Quoted 11 lines · In message <[email protected]> you wrote:
Quoted 2 lines · Jerry Van Baren

IMO your proposal is not acceptable. Follow Grant's advice and the current cpu/mpc83xx/cpu.c methodology.

? Bartlomiej's first patch followed the 83xx 'methodology', which Grant commented on, which is what Bartlomiej tried to fix here. Maybe I missed something, but anyway, now that the window has closed, we can arrange to fix libfdt support for all powerpc boards for the next release.

Quoted 3 lines

We still accept patches that fix bugs and solve urgent problems, and if I understand correctly, Bartek's patch attempts to fix a real problem.

maybe I misunderstood then. I just don't want to see code being duplicated among two subplatforms (83xx and 52xx) without some stuff being refactored into common powerpc areas.

Kim

#15 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

Quoted 17 lines · Kim Phillips
Quoted 5 lines · On Thu, 23 Aug 2007 01:30:29 +0200 Wolfgang Denk <[email protected]> wrote:
Quoted 4 lines · In message <[email protected]> you wrote:
Quoted 2 lines · Jerry Van Baren

IMO your proposal is not acceptable. Follow Grant's advice and the current cpu/mpc83xx/cpu.c methodology.

Quoted 8 lines
Quoted 5 lines

? Bartlomiej's first patch followed the 83xx 'methodology', which Grant commented on, which is what Bartlomiej tried to fix here. Maybe I missed something, but anyway, now that the window has closed, we can arrange to fix libfdt support for all powerpc boards for the next release.

We still accept patches that fix bugs and solve urgent problems, and if I understand correctly, Bartek's patch attempts to fix a real problem.

Quoted 5 lines

maybe I misunderstood then. I just don't want to see code being duplicated among two subplatforms (83xx and 52xx) without some stuff being refactored into common powerpc areas.

Kim

I didn't jump into this one because it really is Grant's call, but my understanding is this is new 5xxx functionality which would imply it goes into the next window. *Good* functionality, but new.

The refactoring should be an effort across 5xxx and 8[356]xx (and possibly 4xx, 82xx, 8xx) platforms and I would love to see it adopted in the next window.

gvb

#16 lore raw

PATCH 1/1 RFC: generic property fixup mechanism for LIBFDT

In reply to Kim Phillips
Quoted 4 lines · In message <[email protected]> you wrote:

maybe I misunderstood then. I just don't want to see code being duplicated among two subplatforms (83xx and 52xx) without some stuff being refactored into common powerpc areas.

Agreed.

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Disc space - the final frontier!
#17 lore raw

PATCH 1/1 fdt, mpc5xxx: Adapt MPC5xxx to use libfdt in ft_cpu_setup().

In reply to Grant Likely
Quoted 8 lines · In message <[email protected]> you…
Quoted 5 lines · Bartlomiej Sieka

Add necessary functions to allow MPC5XXX machines to use libfdt. Code was derived from analogous MPC83xx implementation. Also, add a small coding style fix while in the area.

Comments below

Grant - how do we proceed with this?

From the following discussion [see thread "RFC: generic property fixup mechanism for LIBFDT"] I got the impression that an improved implementation is not available yet, so it will have to wait for the next release.

Do you agree to include this patch (which fixes a few build problems) into the current release and clean it up in the next one?

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
In theory, there is no difference between  theory  and  practice.  In
practice, however, there is.
#18 lore raw

PATCH 1/1 fdt, mpc5xxx: Adapt MPC5xxx to use libfdt in ft_cpu_setup().

Quoted 7 lines · Wolfgang Denk

From the following discussion [see thread "RFC: generic property fixup mechanism for LIBFDT"] I got the impression that an improved implementation is not available yet, so it will have to wait for the next release.

Do you agree to include this patch (which fixes a few build problems) into the current release and clean it up in the next one?

I'm confused. What build problems does it solve? As far as I can tell, this patch only adds support for CONFIG_OF_LIBFDT, but it leaves the old code alone. What am I missing?

As it stands, I don't like this patch. It seems rather schizophrenic to me by adding the new mechanism (CONFIG_OF_LIBFDT) without removing the old one (CONFIG_OF_FLAT_TREE). I don't see any advantage to keeping both mechanisms around. I'd rather see the patch switch entirely to the new method.

Cheers,
g.

Signature · 4 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely at secretlab.ca
(403) 399-0195
#19 lore raw

PATCH 1/1 fdt, mpc5xxx: Adapt MPC5xxx to use libfdt in ft_cpu_setup()

In reply to Bartlomiej Sieka
Quoted 6 lines · Bartlomiej Sieka

---
Not sure where this should be merged, it was applied to u-boot-fdt#fdt (as of 01f771763ed822145b54819abb9c4516c8216d48) merged with the master (as of cc3023b9f95d7ac959a764471a65001062aecf41). Tested on two MPC5200B-based boards, one using CONFIG_OF_LIBFDT, the other using CONFIG_OF_FLAT_TREE.

Hi Bartlomiej,

This should be applied via the 5xxx repo. Since Grant is in charge of that repo and replied already, it looks like things are progressing...

Thanks,
gvb