From owner-freebsd-embedded@FreeBSD.ORG Tue Nov 18 11:16:36 2014 Return-Path: Delivered-To: freebsd-embedded@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 32C7364A; Tue, 18 Nov 2014 11:16:36 +0000 (UTC) Received: from nibbler.fubar.geek.nz (nibbler.fubar.geek.nz [199.48.134.198]) by mx1.freebsd.org (Postfix) with ESMTP id F20D7650; Tue, 18 Nov 2014 11:16:35 +0000 (UTC) Received: from bender.lan (97e078e7.skybroadband.com [151.224.120.231]) by nibbler.fubar.geek.nz (Postfix) with ESMTPSA id A0F0E7328F; Tue, 18 Nov 2014 11:16:28 +0000 (UTC) Date: Tue, 18 Nov 2014 11:16:23 +0000 From: Andrew Turner To: freebsd-arm@freebsd.org, freebsd-embedded@freebsd.org Subject: FDT patch for testing Message-ID: <20141118111623.398d95ae@bender.lan> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="MP_/XVDG2gO_jWjC=1=jAs3RNpI" X-BeenThere: freebsd-embedded@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Dedicated and Embedded Systems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Nov 2014 11:16:36 -0000 --MP_/XVDG2gO_jWjC=1=jAs3RNpI Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Content-Disposition: inline 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 --MP_/XVDG2gO_jWjC=1=jAs3RNpI Content-Type: text/x-patch Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=D1160.diff 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)); } --MP_/XVDG2gO_jWjC=1=jAs3RNpI--