Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Nov 2014 11:16:23 +0000
From:      Andrew Turner <andrew@fubar.geek.nz>
To:        freebsd-arm@freebsd.org, freebsd-embedded@freebsd.org
Subject:   FDT patch for testing
Message-ID:  <20141118111623.398d95ae@bender.lan>

index | next in thread | raw e-mail

[-- Attachment #1 --]
I'm looking for a review and testing of the attached fdt patch. It is
from a review at [1].

It updates fdt_get_range to remove the assumption it's parent bus
address is directly usable. Instead it checks if the parent has a
ranges property and looks up the bus address there. If there is no such
property it keeps the existing behaviour.

The two users of this function are the FDT uart and Marvell interrupt
controller. Because it has a chance to stop the uart from woking I
would like it if it could be tested on a few boards before I commit it.
I have tested it on a Pandaboard so would be interested in the results
on other FDT enabled boards.

Andrew

[1] https://reviews.freebsd.org/D1160
[-- Attachment #2 --]
Index: sys/dev/fdt/fdt_common.c
===================================================================
--- sys/dev/fdt/fdt_common.c
+++ sys/dev/fdt/fdt_common.c
@@ -64,12 +64,84 @@
 
 struct fdt_ic_list fdt_ic_list_head = SLIST_HEAD_INITIALIZER(fdt_ic_list_head);
 
+static int
+fdt_get_range_by_busaddr(phandle_t node, u_long addr, u_long *base,
+    u_long *size)
+{
+	pcell_t ranges[32], *rangesptr;
+	pcell_t addr_cells, size_cells, par_addr_cells;
+	u_long bus_addr, par_bus_addr, pbase, psize;
+	int err, i, len, tuple_size, tuples;
+
+	if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0)
+		return (ENXIO);
+	/*
+	 * Process 'ranges' property.
+	 */
+	par_addr_cells = fdt_parent_addr_cells(node);
+	if (par_addr_cells > 2) {
+		return (ERANGE);
+	}
+
+	len = OF_getproplen(node, "ranges");
+	if (len < 0)
+		return (-1);
+	if (len > sizeof(ranges))
+		return (ENOMEM);
+	if (len == 0) {
+		*base = 0;
+		*size = ULONG_MAX;
+		return (0);
+	}
+
+	if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0)
+		return (EINVAL);
+
+	tuple_size = addr_cells + par_addr_cells + size_cells;
+	tuples = len / (tuple_size * sizeof(cell_t));
+
+	if (fdt_ranges_verify(ranges, tuples, par_addr_cells,
+	    addr_cells, size_cells)) {
+		return (ERANGE);
+	}
+	*base = 0;
+	*size = 0;
+
+	for (i = 0; i < tuples; i++) {
+		rangesptr = &ranges[i * tuple_size];
+
+		bus_addr = fdt_data_get((void *)rangesptr, addr_cells);
+		if (bus_addr != addr)
+			continue;
+		rangesptr += addr_cells;
+
+		par_bus_addr = fdt_data_get((void *)rangesptr, par_addr_cells);
+		rangesptr += par_addr_cells;
+
+		err = fdt_get_range_by_busaddr(OF_parent(node), par_bus_addr,
+		    &pbase, &psize);
+		if (err > 0)
+			return (err);
+		if (err == 0)
+			*base = pbase;
+		else
+			*base = par_bus_addr;
+
+		*size = fdt_data_get((void *)rangesptr, size_cells);
+
+		return (0);
+	}
+
+	return (EINVAL);
+}
+
 int
 fdt_get_range(phandle_t node, int range_id, u_long *base, u_long *size)
 {
 	pcell_t ranges[6], *rangesptr;
 	pcell_t addr_cells, size_cells, par_addr_cells;
-	int len, tuple_size, tuples;
+	u_long par_bus_addr, pbase, psize;
+	int err, len, tuple_size, tuples;
 
 	if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0)
 		return (ENXIO);
@@ -109,8 +181,17 @@
 
 	*base = fdt_data_get((void *)rangesptr, addr_cells);
 	rangesptr += addr_cells;
-	*base += fdt_data_get((void *)rangesptr, par_addr_cells);
+
+	par_bus_addr = fdt_data_get((void *)rangesptr, par_addr_cells);
 	rangesptr += par_addr_cells;
+
+	err = fdt_get_range_by_busaddr(OF_parent(node), par_bus_addr,
+	   &pbase, &psize);
+	if (err == 0)
+		*base += pbase;
+	else
+		*base += par_bus_addr;
+
 	*size = fdt_data_get((void *)rangesptr, size_cells);
 	return (0);
 }
@@ -292,7 +373,7 @@
 	/* Find out #address-cells of the superior bus. */
 	if (OF_searchprop(OF_parent(node), "#address-cells", &addr_cells,
 	    sizeof(addr_cells)) <= 0)
-		addr_cells = 2;
+		return (2);
 
 	return ((int)fdt32_to_cpu(addr_cells));
 }
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20141118111623.398d95ae>