PERFORCE change 200220 for review
Jakub Wojciech Klama
jceel at FreeBSD.org
Sat Oct 15 01:11:29 UTC 2011
http://p4web.freebsd.org/@@200220?ac=10
Change 200220 by jceel at jceel_cyclone on 2011/10/15 01:10:46
Improvements in FDT bus ranges handling code.
Affected files ...
.. //depot/projects/soc2011/jceel_lpc/sys/dev/fdt/fdt_common.c#3 edit
.. //depot/projects/soc2011/jceel_lpc/sys/dev/fdt/fdt_common.h#3 edit
.. //depot/projects/soc2011/jceel_lpc/sys/dev/fdt/fdtbus.c#3 edit
.. //depot/projects/soc2011/jceel_lpc/sys/dev/fdt/simplebus.c#3 edit
.. //depot/projects/soc2011/jceel_lpc/sys/dev/uart/uart_bus_fdt.c#3 edit
Differences ...
==== //depot/projects/soc2011/jceel_lpc/sys/dev/fdt/fdt_common.c#3 (text+ko) ====
@@ -130,6 +130,58 @@
return (0);
}
+ int
+fdt_read_ranges(phandle_t node, struct fdt_range **ranges, int addr_cells,
+ int par_addr_cells, int size_cells)
+{
+ static pcell_t data[128];
+ pcell_t *ptr;
+ int i, len, tuple_size, ranges_count;
+
+ len = OF_getprop(node, "ranges", (void *)&data, sizeof data);
+ tuple_size = addr_cells + par_addr_cells + size_cells;
+ ranges_count = len / tuple_size / sizeof(pcell_t);
+
+ debugf("tuple_size=%d ranges_count=%d\n", tuple_size, ranges_count);
+
+ ptr = data;
+
+ if (*ranges == NULL)
+ *ranges = malloc(sizeof(struct fdt_range) * ranges_count,
+ M_TEMP, M_WAITOK | M_ZERO);
+
+ for (i = 0; i < ranges_count; i++) {
+ (*ranges)[i].base = fdt_data_get((void *)ptr, addr_cells);
+ ptr += addr_cells;
+ (*ranges)[i].parent = fdt_data_get((void *)ptr, par_addr_cells);
+ ptr += par_addr_cells;
+ (*ranges)[i].size = fdt_data_get((void *)ptr, size_cells);
+ ptr += size_cells;
+
+ debugf("new range: base=%lx parent=%lx size=%lx\n",
+ (*ranges)[i].base, (*ranges[i]).parent,
+ (*ranges)[i].size);
+ }
+
+ return (ranges_count);
+}
+
+__inline u_long
+fdt_ranges_lookup(struct fdt_range *ranges, int nranges, u_long addr,
+ u_long size)
+{
+ int n;
+
+ for (n = 0; n < nranges; n++) {
+ if (ranges[n].base <= addr && (ranges[n].base +
+ ranges[n].size >= addr + size - 1)) {
+ return ranges[n].parent;
+ }
+ }
+
+ return 0;
+}
+
/*
* 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).
@@ -410,7 +462,7 @@
pcell_t *reg, *regptr;
pcell_t addr_cells, size_cells;
int tuple_size, tuples;
- int i, n, rv;
+ int i, rv;
if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
return (ENXIO);
@@ -440,13 +492,8 @@
if (ranges == NULL)
goto moveon;
- for (n = 0; n < ranges_count; n++) {
- if (ranges[n].base <= start && (ranges[n].base +
- ranges[n].size >= start + count - 1)) {
- parent = ranges[n].parent;
- break;
- }
- }
+ parent = fdt_ranges_lookup(ranges, ranges_count, start, count);
+
moveon:
start = parent + start;
==== //depot/projects/soc2011/jceel_lpc/sys/dev/fdt/fdt_common.h#3 (text+ko) ====
@@ -97,6 +97,10 @@
int fdt_get_mem_regions(struct mem_region *, int *, uint32_t *);
int fdt_get_phyaddr(phandle_t node, int *);
int fdt_immr_addr(vm_offset_t);
+int fdt_read_ranges(phandle_t node, struct fdt_range **ranges, int addr_cells,
+ int par_addr_cells, int size_cels);
+u_long fdt_ranges_lookup(struct fdt_range *ranges, int nranges, u_long addr,
+ u_long size);
int fdt_regsize(phandle_t, u_long *, u_long *);
int fdt_intr_decode(phandle_t, pcell_t *, int *, int *, int *);
int fdt_intr_to_rl(phandle_t, struct resource_list *, struct fdt_sense_level *);
==== //depot/projects/soc2011/jceel_lpc/sys/dev/fdt/fdtbus.c#3 (text+ko) ====
@@ -381,9 +381,7 @@
}
/* Calculate address range relative to base. */
- //par_base &= 0x000ffffful;
- //start &= 0x000ffffful;
- start += par_base;// + fdt_immr_va;
+ start += par_base;
if (count == 0)
count = par_size;
end = start + count - 1;
==== //depot/projects/soc2011/jceel_lpc/sys/dev/fdt/simplebus.c#3 (text+ko) ====
@@ -154,8 +154,7 @@
struct simplebus_devinfo *di;
struct simplebus_softc *sc;
phandle_t dt_node, dt_child;
- pcell_t *ranges, *ptr;
- int i, tuple_size, len, par_addr_cells;
+ int par_addr_cells;
sc = device_get_softc(dev);
dt_node = ofw_bus_get_node(dev);
@@ -170,33 +169,11 @@
if (par_addr_cells > 2)
return (ERANGE);
- len = OF_getprop_alloc(dt_node, "ranges", sizeof(pcell_t), (void **)&ranges);
- if (len <= 0)
- device_printf(dev, "WARNING: bus has no 'ranges' property\n");
-
- tuple_size = sc->sc_addr_cells + par_addr_cells + sc->sc_size_cells;
- sc->sc_ranges_count = len / tuple_size;
-
- printf("### tuple_size=%d ranges_count=%d\n", tuple_size, sc->sc_ranges_count);
-
- ptr = ranges;
+ sc->sc_ranges_count = fdt_read_ranges(dt_node, &sc->sc_ranges,
+ sc->sc_addr_cells, par_addr_cells, sc->sc_size_cells);
+ if (sc->sc_ranges_count <= 0)
+ device_printf(dev, "WARNING: could not read bus ranges.");
- sc->sc_ranges = malloc(sizeof(struct fdt_range) * sc->sc_ranges_count,
- M_SIMPLEBUS, M_WAITOK | M_ZERO);
-
- for (i = 0; i < sc->sc_ranges_count; i++) {
- sc->sc_ranges[i].base = fdt_data_get((void *)ptr, sc->sc_addr_cells);
- ptr += sc->sc_addr_cells;
- sc->sc_ranges[i].parent = fdt_data_get((void *)ptr, par_addr_cells);
- ptr += par_addr_cells;
- sc->sc_ranges[i].size = fdt_data_get((void *)ptr, sc->sc_size_cells);
- ptr += sc->sc_size_cells;
-
- printf("### new range: base=%lx parent=%lx size=%lx\n",
- sc->sc_ranges[i].base, sc->sc_ranges[i].parent,
- sc->sc_ranges[i].size);
- }
-
/*
* Walk simple-bus and add direct subordinates as our children.
*/
==== //depot/projects/soc2011/jceel_lpc/sys/dev/uart/uart_bus_fdt.c#3 (text+ko) ====
@@ -135,10 +135,13 @@
{
char buf[64];
struct uart_class *class;
- phandle_t node, chosen;
+ phandle_t node, parent, chosen;
pcell_t shift, br, rclk;
u_long start, size;
- int err;
+ struct fdt_range ranges[8];
+ struct fdt_range *rptr = ranges;
+ int err, addr_cells, par_addr_cells, size_cells;
+ int nranges;
uart_bus_space_mem = fdtbus_bs_tag;
uart_bus_space_io = NULL;
@@ -166,6 +169,24 @@
if (OF_finddevice(buf) != node)
/* Only stdin == stdout is supported. */
return (ENXIO);
+
+ /*
+ * Retrieve UART device parent bus
+ */
+ if ((parent = OF_parent(node)) <= 0)
+ return (ENXIO);
+
+ if (fdt_addrsize_cells(parent, &addr_cells, &size_cells))
+ return (ENXIO);
+
+ if ((par_addr_cells = fdt_parent_addr_cells(parent)) > 2)
+ return (ENXIO);
+
+ nranges = fdt_read_ranges(parent, &rptr, addr_cells,
+ par_addr_cells, size_cells);
+ if (nranges <= 0)
+ return (ENXIO);
+
/*
* Retrieve serial attributes.
*/
@@ -197,7 +218,12 @@
err = fdt_regsize(node, &start, &size);
if (err)
return (ENXIO);
- start += fdt_immr_pa;
+
+ /*
+ * XXX this will not work with uart sitting on
+ * simplebus nested in other simplebus.
+ */
+ start += fdt_ranges_lookup(ranges, nranges, start, size);
return (bus_space_map(di->bas.bst, start, size, 0, &di->bas.bsh));
}
More information about the p4-projects
mailing list