
This code adds a generic fixup mechanism that allows us to get ride of needing explicit paths to device nodes.
diff --git a/common/fdt_support.c b/common/fdt_support.c index 7a81469..2c1e8ac 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -363,4 +363,125 @@ int fdt_bd_t(void *fdt) } #endif /* ifdef CONFIG_OF_HAS_BD_T */
+/* + * "Setter" functions used to add/modify FDT entries. + */ +#ifdef CONFIG_HAS_ETH0 +static int fdt_set_eth0(void *blob, 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(blob, nodeoffset, name, 0)) { + return fdt_setprop(blob, nodeoffset, name, bd->bi_enetaddr, 6); + } + return 0; +} +#endif +#ifdef CONFIG_HAS_ETH1 +/* second onboard ethernet port */ +static int fdt_set_eth1(void *blob, 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(blob, nodeoffset, name, 0)) { + return fdt_setprop(blob, nodeoffset, name, bd->bi_enet1addr, 6); + } + return 0; +} +#endif +#ifdef CONFIG_HAS_ETH2 +/* third onboard ethernet port */ +static int fdt_set_eth2(void *blob, 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(blob, nodeoffset, name, 0)) { + return fdt_setprop(blob, nodeoffset, name, bd->bi_enet2addr, 6); + } + return 0; +} +#endif +#ifdef CONFIG_HAS_ETH3 +/* fourth onboard ethernet port */ +static int fdt_set_eth3(void *blob, 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(blob, nodeoffset, name, 0)) { + return fdt_setprop(blob, nodeoffset, name, bd->bi_enet3addr, 6); + } + return 0; +} +#endif + +static int fdt_set_busfreq(void *blob, 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(blob, nodeoffset, name, &tmp, sizeof(tmp)); +} + +static int fdt_set_tbfreq(void *blob, int nodeoffset, const char *name, bd_t *bd) +{ + u32 tmp; + /* Create or update the property */ + tmp = cpu_to_be32(bd->bi_busfreq / 8); + return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp)); +} + +static int fdt_set_stdout_path(void *blob, int nodeoffset, const char *name, bd_t *bd) +{ + char buf[256]; + int err, off; + + off = fdt_path_offset(blob, "/chosen"); + if (off < 0) + return off; + + err = fdt_get_path(blob, nodeoffset, &buf, 256); + if (err < 0) + return err; + + err = fdt_setprop(blob, off, "linux,stdout-path", buf, err + 1); + + return err; +} + +/* + * Fixups to the fdt. + */ + +void fdt_fixups(struct fdt_fixup *tbl, int num, void *blob, bd_t *bd) +{ + int j, err, off; + + for (j = 0; j < num; j++) { + off = -1; + do { + if (tbl[j].compat) + off = fdt_node_offset_by_prop_and_compat(blob, + off, tbl[j].compat, "device_type", + tbl[j].type, strlen(tbl[j].type) + 1); + else + off = fdt_node_offset_by_prop_value(blob, off, + "device_type", + tbl[j].type, strlen(tbl[j].type) + 1); + + if (off >= 0) { + if (tbl[j].name) { + int len; + const char *name; + + name = fdt_get_name(blob, off, &len); + if (strncmp(name, tbl[j].name, len) != 0) + continue; + } + + err = tbl[j].set_fn(blob, off, tbl[j].prop, bd); + if (err < 0) + debug("Problem setting %s = %s: %s\n", + tbl[j].node, tbl[j].prop, + fdt_strerror(err)); + } + } while (off >= 0); + } +} + #endif /* CONFIG_OF_LIBFDT */ diff --git a/include/fdt_support.h b/include/fdt_support.h index 60fa423..f66e562 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -28,7 +28,18 @@
#include <fdt.h>
+typedef int (*set_fn_t)(void *blob, int nodeoffset, const char *name, bd_t *bd); + +struct fdt_fixup { + const char *type; + const char *compat; + const char *prop; + const char *name; + set_fn_t set_fn; +}; + int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force); +void fdt_fixups(struct fdt_fixup *tbl, int num, void *blob, bd_t *bd);
#ifdef CONFIG_OF_HAS_UBOOT_ENV int fdt_env(void *fdt);