PERFORCE change 173821 for review
Rafal Jaworowski
raj at FreeBSD.org
Thu Jan 28 11:46:36 UTC 2010
http://p4web.freebsd.org/chv.cgi?CH=173821
Change 173821 by raj at raj_fdt on 2010/01/28 11:46:08
Refactor FDT infrastructure to better suit multiple platforms and
architectures.
- Move fdt_pic_table[] and IRQ info parsing routines to platform
specific files.
- Introduce machine-specific fdt.h header which is a fron-end
interface between platform independent code of {fdt,simple}bus and
local platform-specific defines and other items (including IRQ lines
number, base VA of the internal registers etc.).
- Make the [early access] fdt_is_compatible() a common public routine,
as there's multiple consumers besides uart(4) attachment.
- Teach fdtbus, simplebus and helper code a bit more endian-safety.
- Eliminate diag output from early access routines (where console can
be unavailable yet, which could lead to a hang).
- Simplify parent #address-cells and #size-cells processing.
- There's still a couple of rough edges, but we are capable of running
{fdt,simple}bus driver on both ARM and PowerPC systems.
Affected files ...
.. //depot/projects/fdt/sys/dev/fdt/fdt_common.c#7 edit
.. //depot/projects/fdt/sys/dev/fdt/fdt_common.h#3 edit
.. //depot/projects/fdt/sys/dev/fdt/fdt_powerpc.c#1 add
.. //depot/projects/fdt/sys/dev/fdt/fdtbus.c#3 edit
.. //depot/projects/fdt/sys/dev/fdt/simplebus.c#4 edit
.. //depot/projects/fdt/sys/dev/uart/uart_cpu_powerpc.c#3 edit
.. //depot/projects/fdt/sys/powerpc/include/fdt.h#1 add
Differences ...
==== //depot/projects/fdt/sys/dev/fdt/fdt_common.c#7 (text+ko) ====
@@ -32,12 +32,11 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/ktr.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
-#include <machine/intr_machdep.h>
+#include <machine/resource.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -58,7 +57,48 @@
#define debugf(fmt, args...)
#endif
+/*
+ * This routine is an early-usage version of the ofw_bus_is_compatible() when
+ * the ofw_bus I/F is not available (like early console routines and similar).
+ * Note the buffer has to be on the stack since malloc() is usually not
+ * available in such cases either.
+ */
int
+fdt_is_compatible(phandle_t node, const char *compatstr)
+{
+#define FDT_COMPAT_LEN 255
+ char *buf[FDT_COMPAT_LEN];
+ char *compat;
+ int len, onelen, l, rv;
+
+ if ((len = OF_getproplen(node, "compatible")) <= 0)
+ return (0);
+
+ compat = (char *)&buf;
+ bzero(compat, FDT_COMPAT_LEN);
+
+ if (OF_getprop(node, "compatible", compat, len) < 0)
+ return (0);
+
+ onelen = strlen(compatstr);
+ rv = 0;
+ while (len > 0) {
+ if (strncasecmp(compat, compatstr, onelen) == 0) {
+ /* Found it. */
+ rv = 1;
+ break;
+ }
+ /* Slide to the next sub-string. */
+ l = strlen(compat) + 1;
+ compat += l;
+ len -= l;
+ }
+
+ return (rv);
+}
+
+
+int
fdt_is_enabled(phandle_t node)
{
char *stat;
@@ -90,7 +130,7 @@
sizeof(addr_cells)) <= 0)
addr_cells = 2;
- return ((int)addr_cells);
+ return (fdt32_to_cpu((int)addr_cells));
}
void
@@ -156,11 +196,11 @@
cell_size = sizeof(cell);
if (OF_getprop(node, "#address-cells", &cell, cell_size) < cell_size)
cell = 2;
- *addr_cells = (int)cell;
+ *addr_cells = fdt32_to_cpu((int)cell);
if (OF_getprop(node, "#size-cells", &cell, cell_size) < cell_size)
cell = 1;
- *size_cells = (int)cell;
+ *size_cells = fdt32_to_cpu((int)cell);
if (*addr_cells > 2 || *size_cells > 2)
return (ERANGE);
@@ -215,18 +255,16 @@
{
/* Address portion. */
- if (fdt_data_verify((void *)data, addr_cells)) {
- debugf("tuple #%d: unsupported addr value\n", addr_cells);
+ if (fdt_data_verify((void *)data, addr_cells))
return (ERANGE);
- }
+
*start = fdt_data_get((void *)data, addr_cells);
data += addr_cells;
/* Size portion. */
- if (fdt_data_verify((void *)data, size_cells)) {
- debugf("tuple #%d: unsupported size value\n", size_cells);
+ if (fdt_data_verify((void *)data, size_cells))
return (ERANGE);
- }
+
*count = fdt_data_get((void *)data, size_cells);
return (0);
}
@@ -240,14 +278,8 @@
int tuple_size, tuples;
int i, rv;
- addr_cells = fdt_parent_addr_cells(node);
- if (addr_cells > 0) {
- rv = OF_searchprop(OF_parent(node), "#size-cells",
- &size_cells, sizeof(size_cells));
- if (rv <= 0)
- size_cells = 1;
- } else
- size_cells = 0;
+ if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
+ return (ENXIO);
tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)®);
@@ -286,81 +318,6 @@
}
static int
-fdt_pic_decode_iic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
- int *pol)
-{
-
- /* TODO */
- return (ENXIO);
-}
-
-static int
-fdt_pic_decode_openpic(phandle_t node, pcell_t *intr, int *interrupt,
- int *trig, int *pol)
-{
- char *compat;
- ssize_t prop_len;
- int rv;
-
- prop_len = OF_getprop_alloc(node, "compatible", 1, (void **)&compat);
- if (prop_len <= 0)
- return (ENXIO);
-
- rv = 0;
- if (strncmp("open-pic", compat, 8) < 0) {
- rv = ENXIO;
- goto out;
- }
-
- /*
- * XXX The interrupt number read out from the device tree is already
- * offset by 16 to reflect the 'internal' IRQ range shift on the
- * OpenPIC. We still however need to account for the ISA IRQ block,
- * potentially in use as well.
- */
- *interrupt = ISA_IRQ_COUNT + intr[0];
-
- switch (intr[1]) {
- case 0:
- /* L to H edge */
- *trig = INTR_TRIGGER_EDGE;
- *pol = INTR_POLARITY_HIGH;
- break;
- case 1:
- /* Active L level */
- *trig = INTR_TRIGGER_LEVEL;
- *pol = INTR_POLARITY_LOW;
- break;
- case 2:
- /* Active H level */
- *trig = INTR_TRIGGER_LEVEL;
- *pol = INTR_POLARITY_HIGH;
- break;
- case 3:
- /* H to L edge */
- *trig = INTR_TRIGGER_EDGE;
- *pol = INTR_POLARITY_LOW;
- break;
- default:
- *trig = INTR_TRIGGER_CONFORM;
- *pol = INTR_POLARITY_CONFORM;
- }
-
-out:
- free(compat, M_OFWPROP);
- return (rv);
-}
-
-typedef int (*fdt_pic_decode_t)(phandle_t, pcell_t *, int *, int *,
- int *);
-
-static fdt_pic_decode_t fdt_pic_table[] = {
- &fdt_pic_decode_iic,
- &fdt_pic_decode_openpic,
- NULL
-};
-
-static int
fdt_intr_decode(phandle_t intr_parent, pcell_t *intr, int *interrupt,
int *trig, int *pol)
{
@@ -403,14 +360,17 @@
if (OF_getprop(node, "interrupt-parent", &iph, sizeof(iph)) <= 0) {
debugf("no intr-parent phandle\n");
intr_par = OF_parent(node);
- } else
+ } else {
+ iph = fdt32_to_cpu(iph);
intr_par = OF_instance_to_package(iph);
+ }
if (OF_getprop(intr_par, "#interrupt-cells", &intr_cells,
sizeof(intr_cells)) <= 0) {
debugf("no intr-cells defined, defaulting to 1\n");
intr_cells = 1;
}
+ intr_cells = fdt32_to_cpu(intr_cells);
intr_num = OF_getprop_alloc(node, "interrupts",
intr_cells * sizeof(pcell_t), (void **)&intr);
==== //depot/projects/fdt/sys/dev/fdt/fdt_common.h#3 (text+ko) ====
@@ -39,6 +39,10 @@
enum intr_polarity pol;
};
+typedef int (*fdt_pic_decode_t)(phandle_t, pcell_t *, int *, int *, int *);
+
+extern fdt_pic_decode_t fdt_pic_table[];
+
int fdt_addrsize_cells(phandle_t, int *, int *);
u_long fdt_data_get(void *, int);
int fdt_parent_addr_cells(phandle_t);
@@ -47,6 +51,7 @@
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_enabled(phandle_t);
#endif /* FDT_COMMON_H */
==== //depot/projects/fdt/sys/dev/fdt/fdtbus.c#3 (text+ko) ====
@@ -30,6 +30,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_platform.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ktr.h>
@@ -41,7 +42,7 @@
#include <dev/ofw/openfirm.h>
-#include <machine/intr_machdep.h>
+#include <machine/fdt.h>
#include "fdt_common.h"
#include "ofw_bus_if.h"
@@ -58,8 +59,6 @@
static MALLOC_DEFINE(M_FDTBUS, "fdtbus", "FDTbus devices information");
-extern struct bus_space bs_be_tag;
-
struct fdtbus_devinfo {
phandle_t di_node;
char *di_name;
@@ -174,7 +173,7 @@
* IRQ rman.
*/
start = 0;
- end = INTR_VECTORS - 1;
+ end = FDT_INTR_MAX - 1;
sc->sc_irq.rm_start = start;
sc->sc_irq.rm_end = end;
sc->sc_irq.rm_type = RMAN_ARRAY;
@@ -261,6 +260,7 @@
static device_t
newbus_device_from_fdt_node(device_t parent, phandle_t node)
{
+ u_long base;
device_t child;
struct fdtbus_devinfo *di;
char *name, *type, *compat;
@@ -286,13 +286,17 @@
di->di_compat = compat;
resource_list_init(&di->di_res);
-
+#ifdef MPC85XX
/*
* XXX this 0x1ef00000 offset is a gross hack, which assumes:
* - physical addresses in the DTS are 0xe0000000 range, and
* - virtual CCSR base in kernel is 0xfef00000
*/
- if (fdt_reg_to_rl(node, &di->di_res, 0x1ef00000)) {
+ base = 0x1ef00000;
+#else
+ base = 0;
+#endif
+ if (fdt_reg_to_rl(node, &di->di_res, base)) {
device_printf(child, "could not process 'reg' "
"property\n");
newbus_device_destroy(child);
@@ -383,7 +387,7 @@
if (type == SYS_RES_IOPORT || type == SYS_RES_MEMORY) {
/* XXX endianess should be set based on SOC node */
- rman_set_bustag(res, &bs_be_tag);
+ rman_set_bustag(res, fdtbus_bs_tag);
rman_set_bushandle(res, rman_get_start(res));
}
@@ -427,8 +431,12 @@
if (err)
return (err);
+#if defined(__powerpc__)
err = powerpc_setup_intr(device_get_nameunit(child),
rman_get_start(res), filter, ihand, arg, flags, cookiep);
+#elif defined(__arm__)
+ /* TODO */
+#endif
return (err);
}
@@ -455,7 +463,11 @@
void *cookie)
{
+#if defined(__powerpc__)
return (powerpc_teardown_intr(cookie));
+#elif defined(__arm__)
+ return (arm_remove_irqhandler(rman_get_start(res), cookie));
+#endif
}
static const char *
==== //depot/projects/fdt/sys/dev/fdt/simplebus.c#4 (text+ko) ====
@@ -30,6 +30,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_platform.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ktr.h>
@@ -39,8 +40,7 @@
#include <sys/rman.h>
#include <sys/malloc.h>
-#include <machine/intr_machdep.h>
-#include <machine/vmparam.h>
+#include <machine/fdt.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -140,11 +140,16 @@
static int
simplebus_probe(device_t dev)
{
+ struct simplebus_softc *sc;
if (!ofw_bus_is_compatible(dev, "simple-bus"))
return (ENXIO);
device_set_desc(dev, "Flattened device tree simple bus");
+
+ sc = device_get_softc(dev);
+ sc->sc_start_va = FDT_SIMPLEBUS_VA;
+
return (BUS_PROBE_DEFAULT);
}
@@ -240,7 +245,6 @@
}
debugf("start = %lx, size = %lx\n", start, size);
sc->sc_start_pa = start;
- sc->sc_start_va = CCSRBAR_VA;
sc->sc_size = size;
/*
@@ -387,7 +391,13 @@
debugf("intr config: irq = %d, trig = %d, pol = %d\n", irq, trig, pol);
+#if defined(__powerpc__)
err = powerpc_config_intr(irq, trig, pol);
+#elif defined(__arm__)
+ arm_setup_irqhandler(device_get_nameunit(child), filter, ihand, arg,
+ irq, flags, cookiep);
+ return (0);
+#endif
if (err)
return (err);
==== //depot/projects/fdt/sys/dev/uart/uart_cpu_powerpc.c#3 (text) ====
@@ -40,7 +40,7 @@
#include <sys/bus.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
-#include <machine/vmparam.h>
+#include <machine/fdt.h>
#endif
#include <dev/ofw/openfirm.h>
@@ -92,45 +92,6 @@
}
#ifdef FDT
-/*
- * Since ofw_bus_is_compatible() cannot be used at this early stage, we need
- * a similar function locally. Note the buffer has to be on the stack since
- * malloc() is not yet available.
- */
-static int
-fdt_is_compatible(phandle_t node, const char *compatstr)
-{
-#define FDT_COMPAT_LEN 255
- char *buf[FDT_COMPAT_LEN];
- char *compat;
- int len, onelen, l, rv;
-
- if ((len = OF_getproplen(node, "compatible")) <= 0)
- return (0);
-
- compat = (char *)&buf;
- bzero(compat, FDT_COMPAT_LEN);
-
- if (OF_getprop(node, "compatible", compat, len) < 0)
- return (0);
-
- onelen = strlen(compatstr);
- rv = 0;
- while (len > 0) {
- if (strncasecmp(compat, compatstr, onelen) == 0) {
- /* Found it. */
- rv = 1;
- break;
- }
- /* Slide to the next sub-string. */
- l = strlen(compat) + 1;
- compat += l;
- len -= l;
- }
-
- return (rv);
-}
-
static int
fdt_uart_addr(phandle_t node, bus_space_tag_t *tag, bus_space_handle_t *handle)
{
@@ -179,8 +140,7 @@
rv = fdt_data_to_res(prop, par_addr_cells, par_size_cells,
&start, &size);
- /* XXX this is an MPC85XX specific hack and needs to go away. */
- start += CCSRBAR_VA;
+ start += FDT_SIMPLEBUS_VA;
rv = bus_space_map(*tag, start, size, 0, handle);
if (rv)
More information about the p4-projects
mailing list