PERFORCE change 174731 for review
Rafal Jaworowski
raj at FreeBSD.org
Mon Feb 15 17:53:30 UTC 2010
http://p4web.freebsd.org/chv.cgi?CH=174731
Change 174731 by raj at raj_fdt on 2010/02/15 17:53:15
Refactor and optimize FDT infrastructure.
- Extend 'compatible'-related routines so that we can do strict
checking i.e. if a node is only compatible with a single entry. This
is required for nodes like 'simple-bus' as sometimes other nodes
claim their compatibility and we need to have a way to identify such
cases.
- Push fixups handling from simplebus level to much earlier stage, so
that the DT is complete for further use at the very beginnig of its
processing; this way the early init code (console, GPIO etc.) can
safely retrieve final information from the device tree.
- Provide a fake capability of OF_interpret(): FDT does not support
this notion, but we abuse the interface to perform various
non-standard operations on the device tree. In this case it will
allow for fine grained control over when device tree fixups are
performed.
- Other improvements and corrections.
Affected files ...
.. //depot/projects/fdt/sys/arm/mv/common.c#4 edit
.. //depot/projects/fdt/sys/arm/mv/mv_machdep.c#7 edit
.. //depot/projects/fdt/sys/dev/fdt/fdt_arm.c#4 edit
.. //depot/projects/fdt/sys/dev/fdt/fdt_common.c#10 edit
.. //depot/projects/fdt/sys/dev/fdt/fdt_common.h#6 edit
.. //depot/projects/fdt/sys/dev/fdt/fdt_powerpc.c#3 edit
.. //depot/projects/fdt/sys/dev/fdt/simplebus.c#7 edit
.. //depot/projects/fdt/sys/dev/ofw/ofw_bus_subr.c#3 edit
.. //depot/projects/fdt/sys/dev/ofw/ofw_bus_subr.h#3 edit
.. //depot/projects/fdt/sys/dev/ofw/ofw_fdt.c#4 edit
.. //depot/projects/fdt/sys/dev/ofw/openfirm.c#5 edit
.. //depot/projects/fdt/sys/powerpc/booke/machdep.c#6 edit
Differences ...
==== //depot/projects/fdt/sys/arm/mv/common.c#4 (text+ko) ====
@@ -78,7 +78,6 @@
static void decode_win_usb_dump(void);
static int fdt_get_ranges(const char *, void *, int, int *, int *);
-static int fdt_get_regsize(phandle_t, u_long *, u_long *);
static int win_cpu_from_dt(void);
static int win_soc_from_dt(void);
@@ -1704,27 +1703,6 @@
}
static int
-fdt_get_regsize(phandle_t node, u_long *base, u_long *size)
-{
- pcell_t reg[4];
- int addr_cells, len, size_cells;
-
- if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells))
- return (ENXIO);
-
- if ((sizeof(pcell_t) * (addr_cells + size_cells)) > sizeof(reg))
- return (ENOMEM);
-
- len = OF_getprop(node, "reg", ®, sizeof(reg));
- if (len <= 0)
- return (EINVAL);
-
- *base = fdt_data_get(®[0], addr_cells);
- *size = fdt_data_get(®[addr_cells], size_cells);
- return (0);
-}
-
-static int
win_soc_from_dt(void)
{
phandle_t node, child;
@@ -1736,7 +1714,7 @@
if (node == 0)
panic("win_soc_from_dt: no root node");
- node = fdt_find_compatible(node, "simple-bus");
+ node = fdt_find_compatible(node, "simple-bus", 0);
if (node == 0)
return (ENXIO);
==== //depot/projects/fdt/sys/arm/mv/mv_machdep.c#7 (text+ko) ====
@@ -563,6 +563,12 @@
cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2));
/*
+ * Only after the SOC registers block is mapped we can perform device
+ * tree fixups, as they may attempt to read parameters from hardware.
+ */
+ OF_interpret("perform-fixup", 0);
+
+ /*
* Re-initialise MPP. It is important to call this prior to using
* console as the physical connection can be routed via MPP.
*/
@@ -696,10 +702,10 @@
if ((node = OF_finddevice("/")) == 0)
return (ENXIO);
- if ((node = fdt_find_compatible(node, "simple-bus")) == 0)
+ if ((node = fdt_find_compatible(node, "simple-bus", 0)) == 0)
return (ENXIO);
- if ((node = fdt_find_compatible(node, "mrvl,mpp")) == 0)
+ if ((node = fdt_find_compatible(node, "mrvl,mpp", 0)) == 0)
return (ENXIO);
moveon:
==== //depot/projects/fdt/sys/dev/fdt/fdt_arm.c#4 (text+ko) ====
@@ -48,15 +48,20 @@
#include "ofw_bus_if.h"
static void
-fdt_fixup_busfreq(phandle_t node)
+fdt_fixup_busfreq(phandle_t root)
{
+ phandle_t sb;
pcell_t freq;
/*
* This fixup sets the simple-bus bus-frequency property.
*/
+
+ if ((sb = fdt_find_compatible(root, "simple-bus", 1)) == 0)
+ return;
+
freq = cpu_to_fdt32(get_tclk());
- OF_setprop(node, "bus-frequency", (void *)&freq, sizeof(freq));
+ OF_setprop(sb, "bus-frequency", (void *)&freq, sizeof(freq));
}
struct fdt_fixup_entry fdt_fixup_table[] = {
==== //depot/projects/fdt/sys/dev/fdt/fdt_common.c#10 (text+ko) ====
@@ -65,7 +65,7 @@
fdt_is_compatible(phandle_t node, const char *compatstr)
{
#define FDT_COMPAT_LEN 255
- char *buf[FDT_COMPAT_LEN];
+ char buf[FDT_COMPAT_LEN];
char *compat;
int len, onelen, l, rv;
@@ -75,7 +75,7 @@
compat = (char *)&buf;
bzero(compat, FDT_COMPAT_LEN);
- if (OF_getprop(node, "compatible", compat, len) < 0)
+ if (OF_getprop(node, "compatible", compat, FDT_COMPAT_LEN) < 0)
return (0);
onelen = strlen(compatstr);
@@ -95,8 +95,26 @@
return (rv);
}
+int
+fdt_is_compatible_strict(phandle_t node, const char *compatible)
+{
+ char compat[FDT_COMPAT_LEN];
+
+ if (OF_getproplen(node, "compatible") <= 0)
+ return (0);
+
+ if (OF_getprop(node, "compatible", compat, FDT_COMPAT_LEN) < 0)
+ return (0);
+
+ if (strncasecmp(compat, compatible, FDT_COMPAT_LEN) == 0)
+ /* This fits. */
+ return (1);
+
+ return (0);
+}
+
phandle_t
-fdt_find_compatible(phandle_t start, const char *compat)
+fdt_find_compatible(phandle_t start, const char *compat, int strict)
{
phandle_t child;
@@ -105,8 +123,12 @@
* matching 'compatible' property.
*/
for (child = OF_child(start); child != 0; child = OF_peer(child))
- if (fdt_is_compatible(child, compat))
+ if (fdt_is_compatible(child, compat)) {
+ if (strict)
+ if (!fdt_is_compatible_strict(child, compat))
+ continue;
return (child);
+ }
return (0);
}
@@ -282,6 +304,27 @@
}
int
+fdt_get_regsize(phandle_t node, u_long *base, u_long *size)
+{
+ pcell_t reg[4];
+ int addr_cells, len, size_cells;
+
+ if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells))
+ return (ENXIO);
+
+ if ((sizeof(pcell_t) * (addr_cells + size_cells)) > sizeof(reg))
+ return (ENOMEM);
+
+ len = OF_getprop(node, "reg", ®, sizeof(reg));
+ if (len <= 0)
+ return (EINVAL);
+
+ *base = fdt_data_get(®[0], addr_cells);
+ *size = fdt_data_get(®[addr_cells], size_cells);
+ return (0);
+}
+
+int
fdt_reg_to_rl(phandle_t node, struct resource_list *rl, u_long base)
{
u_long start, end, count;
==== //depot/projects/fdt/sys/dev/fdt/fdt_common.h#6 (text+ko) ====
@@ -55,11 +55,13 @@
int fdt_parent_addr_cells(phandle_t);
void fdt_ranges_dump(pcell_t *, int, int, int, int);
int fdt_ranges_verify(pcell_t *, int, int, int, int);
+int fdt_get_regsize(phandle_t, u_long *, u_long *);
int fdt_reg_to_rl(phandle_t, struct resource_list *, u_long);
int fdt_intr_to_rl(phandle_t, struct resource_list *, struct sense_level *);
int fdt_data_to_res(pcell_t *, int, int, u_long *, u_long *);
int fdt_is_compatible(phandle_t, const char *);
+int fdt_is_compatible_strict(phandle_t, const char *);
int fdt_is_enabled(phandle_t);
-phandle_t fdt_find_compatible(phandle_t start, const char *compat);
+phandle_t fdt_find_compatible(phandle_t, const char *, int);
#endif /* _FDT_COMMON_H_ */
==== //depot/projects/fdt/sys/dev/fdt/fdt_powerpc.c#3 (text+ko) ====
@@ -46,17 +46,24 @@
#include "fdt_common.h"
static void
-fdt_fixup_busfreq(phandle_t node)
+fdt_fixup_busfreq(phandle_t root)
{
- phandle_t cpus, child;
+ phandle_t sb, cpus, child;
pcell_t freq;
/*
+ * Do a strict check so as to skip non-SOC nodes, which also claim
+ * simple-bus compatibility such as eLBC etc.
+ */
+ if ((sb = fdt_find_compatible(root, "simple-bus", 1)) == 0)
+ return;
+
+ /*
* This fixup uses /cpus/ bus-frequency prop value to set simple-bus
* bus-frequency property.
*/
if ((cpus = OF_finddevice("/cpus")) == 0)
- panic("simplebus: no /cpus node");
+ return;
if ((child = OF_child(cpus)) == 0)
return;
@@ -65,11 +72,11 @@
sizeof(freq)) <= 0)
return;
- OF_setprop(node, "bus-frequency", (void *)&freq, sizeof(freq));
+ OF_setprop(sb, "bus-frequency", (void *)&freq, sizeof(freq));
}
struct fdt_fixup_entry fdt_fixup_table[] = {
- { "fsl,MPC8572DS", &fdt_fixup_busfreq},
+ { "fsl,MPC8572DS", &fdt_fixup_busfreq },
{ "MPC8555CDS", &fdt_fixup_busfreq },
{ NULL, NULL }
};
==== //depot/projects/fdt/sys/dev/fdt/simplebus.c#7 (text+ko) ====
@@ -142,7 +142,7 @@
{
struct simplebus_softc *sc;
- if (!ofw_bus_is_compatible(dev, "simple-bus"))
+ if (!ofw_bus_is_compatible_strict(dev, "simple-bus"))
return (ENXIO);
device_set_desc(dev, "Flattened device tree simple bus");
@@ -153,34 +153,6 @@
return (BUS_PROBE_DEFAULT);
}
-static void
-simplebus_fixup(phandle_t node)
-{
- phandle_t root;
- char *model;
- int i, len;
-
- if ((root = OF_finddevice("/")) == 0)
- panic("simplebus: no root node");
-
- len = OF_getprop_alloc(root, "model", 1, (void **)&model);
- if (len <= 0)
- return;
-
- for (i = 0; fdt_fixup_table[i].model != NULL; i++) {
- if (strcmp(model, fdt_fixup_table[i].model) != 0)
- continue;
-
- if (fdt_fixup_table[i].handler != NULL) {
- if (bootverbose)
- printf("simplebus: using fixup for '%s'\n",
- model);
- (*fdt_fixup_table[i].handler)(node);
- }
- }
- free(model, M_OFWPROP);
-}
-
static int
simplebus_attach(device_t dev)
{
@@ -200,8 +172,6 @@
&sc->sc_size_cells)) != 0)
return (ENXIO);
- simplebus_fixup(node);
-
/*
* Process 'ranges' property.
*/
==== //depot/projects/fdt/sys/dev/ofw/ofw_bus_subr.c#3 (text+ko) ====
@@ -178,6 +178,20 @@
return (0);
}
+int
+ofw_bus_is_compatible_strict(device_t dev, const char *compatible)
+{
+ const char *compat;
+
+ if ((compat = ofw_bus_get_compat(dev)) == NULL)
+ return (0);
+
+ if (strncasecmp(compat, compatible, strlen(compatible)) == 0)
+ return (1);
+
+ return (0);
+}
+
void
ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz)
{
==== //depot/projects/fdt/sys/dev/ofw/ofw_bus_subr.h#3 (text+ko) ====
@@ -69,5 +69,6 @@
/* Helper routine for checking compat prop */
int ofw_bus_is_compatible(device_t, const char *);
+int ofw_bus_is_compatible_strict(device_t, const char *);
#endif /* !_DEV_OFW_OFW_BUS_SUBR_H_ */
==== //depot/projects/fdt/sys/dev/ofw/ofw_fdt.c#4 (text+ko) ====
@@ -39,6 +39,7 @@
#include <machine/stdarg.h>
+#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofwvar.h>
#include <dev/ofw/openfirm.h>
@@ -54,26 +55,21 @@
#define debugf(fmt, args...)
#endif
-static int ofw_fdt_init(ofw_t ofw, void *openfirm);
-static phandle_t ofw_fdt_peer(ofw_t ofw, phandle_t node);
-static phandle_t ofw_fdt_child(ofw_t ofw, phandle_t node);
-static phandle_t ofw_fdt_parent(ofw_t ofw, phandle_t node);
-static phandle_t ofw_fdt_instance_to_package(ofw_t ofw, ihandle_t instance);
-static ssize_t ofw_fdt_getproplen(ofw_t ofw, phandle_t package,
- const char *propname);
-static ssize_t ofw_fdt_getprop(ofw_t ofw, phandle_t package,
- const char *propname, void *buf, size_t buflen);
-static int ofw_fdt_nextprop(ofw_t ofw, phandle_t package, const char *previous,
- char *buf, size_t);
-static int ofw_fdt_setprop(ofw_t ofw, phandle_t package, const char *propname,
- const void *buf, size_t len);
-static ssize_t ofw_fdt_canon(ofw_t ofw, const char *device, char *buf,
- size_t len);
-static phandle_t ofw_fdt_finddevice(ofw_t ofw, const char *device);
-static ssize_t ofw_fdt_instance_to_path(ofw_t ofw, ihandle_t instance,
- char *buf, size_t len);
-static ssize_t ofw_fdt_package_to_path(ofw_t ofw, phandle_t package, char *buf,
- size_t len);
+static int ofw_fdt_init(ofw_t, void *);
+static phandle_t ofw_fdt_peer(ofw_t, phandle_t);
+static phandle_t ofw_fdt_child(ofw_t, phandle_t);
+static phandle_t ofw_fdt_parent(ofw_t, phandle_t);
+static phandle_t ofw_fdt_instance_to_package(ofw_t, ihandle_t);
+static ssize_t ofw_fdt_getproplen(ofw_t, phandle_t, const char *);
+static ssize_t ofw_fdt_getprop(ofw_t, phandle_t, const char *, void *, size_t);
+static int ofw_fdt_nextprop(ofw_t, phandle_t, const char *, char *, size_t);
+static int ofw_fdt_setprop(ofw_t, phandle_t, const char *, const void *,
+ size_t);
+static ssize_t ofw_fdt_canon(ofw_t, const char *, char *, size_t);
+static phandle_t ofw_fdt_finddevice(ofw_t, const char *);
+static ssize_t ofw_fdt_instance_to_path(ofw_t, ihandle_t, char *, size_t);
+static ssize_t ofw_fdt_package_to_path(ofw_t, phandle_t, char *, size_t);
+static int ofw_fdt_interpret(ofw_t, const char *, int, unsigned long *);
static ofw_method_t ofw_fdt_methods[] = {
OFWMETHOD(ofw_init, ofw_fdt_init),
@@ -89,7 +85,7 @@
OFWMETHOD(ofw_finddevice, ofw_fdt_finddevice),
OFWMETHOD(ofw_instance_to_path, ofw_fdt_instance_to_path),
OFWMETHOD(ofw_package_to_path, ofw_fdt_package_to_path),
-
+ OFWMETHOD(ofw_interpret, ofw_fdt_interpret),
{ 0, 0 }
};
@@ -406,3 +402,60 @@
return (-1);
}
+
+static int
+ofw_fdt_fixup(ofw_t ofw)
+{
+#define FDT_MODEL_LEN 80
+ char model[FDT_MODEL_LEN];
+ phandle_t root;
+ ssize_t len;
+ int i;
+
+ if ((root = ofw_fdt_finddevice(ofw, "/")) == 0)
+ return (ENODEV);
+
+ if ((len = ofw_fdt_getproplen(ofw, root, "model")) <= 0)
+ return (0);
+
+ bzero(model, FDT_MODEL_LEN);
+ if (ofw_fdt_getprop(ofw, root, "model", model, FDT_MODEL_LEN) <= 0)
+ return (0);
+
+ /*
+ * Search fixup table and call handler if appropriate.
+ */
+ for (i = 0; fdt_fixup_table[i].model != NULL; i++) {
+ if (strncmp(model, fdt_fixup_table[i].model,
+ FDT_MODEL_LEN) != 0)
+ continue;
+
+ if (fdt_fixup_table[i].handler != NULL)
+ (*fdt_fixup_table[i].handler)(root);
+ }
+
+ return (0);
+}
+
+static int
+ofw_fdt_interpret(ofw_t ofw, const char *cmd, int nret, unsigned long *retvals)
+{
+ int rv;
+
+ /*
+ * Note: FDT does not have the possibility to 'interpret' commands,
+ * but we abuse the interface a bit to use it for doing non-standard
+ * operations on the device tree blob.
+ *
+ * Currently the only supported 'command' is to trigger performing
+ * fixups.
+ */
+ if (strncmp("perform-fixup", cmd, 13) != 0)
+ return (0);
+
+ rv = ofw_fdt_fixup(ofw);
+ if (nret > 0)
+ retvals[0] = rv;
+
+ return (rv);
+}
==== //depot/projects/fdt/sys/dev/ofw/openfirm.c#5 (text+ko) ====
@@ -159,6 +159,7 @@
return (OFW_TEST(ofw_obj, name));
}
+#endif
int
OF_interpret(const char *cmd, int nreturns, ...)
@@ -179,7 +180,6 @@
return (status);
}
-#endif
/*
* Device tree functions
==== //depot/projects/fdt/sys/powerpc/booke/machdep.c#6 (text+ko) ====
@@ -313,22 +313,6 @@
return ((struct bi_mem_region *)bootinfo->bi_data);
}
-struct bi_eth_addr *
-bootinfo_eth(void)
-{
- struct bi_mem_region *mr;
- struct bi_eth_addr *eth;
- int i;
-
- /* Advance to the eth section */
- mr = bootinfo_mr();
- for (i = 0; i < bootinfo->bi_mem_reg_no; i++, mr++)
- ;
-
- eth = (struct bi_eth_addr *)mr;
- return (eth);
-}
-
u_int
e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
{
@@ -383,6 +367,8 @@
if (OF_init((void *)dtbp) != 0)
while (1);
+ OF_interpret("perform-fixup", 0);
+
/* Initialize TLB1 handling */
tlb1_init(bootinfo->bi_bar_base);
More information about the p4-projects
mailing list