Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Aug 2012 03:49:11 +0000 (UTC)
From:      Oleksandr Tymoshenko <gonzo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r239274 - in head/sys/dev: fdt uart
Message-ID:  <201208150349.q7F3nBGi095921@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gonzo
Date: Wed Aug 15 03:49:10 2012
New Revision: 239274
URL: http://svn.freebsd.org/changeset/base/239274

Log:
  Merging of projects/armv6, part 4
  
  r233822:
    Remove useless and wrong piece of code in fdt_get_range() which i
    overwrites passed phandle_t node. Modify debug printf in fdt_reg_to_rl()
    to be consistent (that is, print start and end *virtual* addresses).
  
  r230560:
    Handle "ranges;"
    Make fdt_reg_to_rl() responsible for mapping the device memory, instead
    on just hoping that there's only one simplebus, and using fdt_immr_va as
    the base VA.
  
  r230315
    Add a function to get the PA from range, instead of (ab)using
    fdt_immr_pa, and use it for the UART driver

Modified:
  head/sys/dev/fdt/fdt_common.c
  head/sys/dev/fdt/fdt_common.h
  head/sys/dev/fdt/fdtbus.c
  head/sys/dev/fdt/simplebus.c
  head/sys/dev/uart/uart_bus_fdt.c

Modified: head/sys/dev/fdt/fdt_common.c
==============================================================================
--- head/sys/dev/fdt/fdt_common.c	Wed Aug 15 03:33:57 2012	(r239273)
+++ head/sys/dev/fdt/fdt_common.c	Wed Aug 15 03:49:10 2012	(r239274)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/module.h>
 #include <sys/bus.h>
+#include <sys/limits.h>
 
 #include <machine/fdt.h>
 #include <machine/resource.h>
@@ -63,30 +64,12 @@ vm_offset_t fdt_immr_va;
 vm_offset_t fdt_immr_size;
 
 int
-fdt_immr_addr(vm_offset_t immr_va)
+fdt_get_range(phandle_t node, int range_id, u_long *base, u_long *size)
 {
 	pcell_t ranges[6], *rangesptr;
-	phandle_t node;
-	u_long base, size;
 	pcell_t addr_cells, size_cells, par_addr_cells;
 	int len, tuple_size, tuples;
 
-	/*
-	 * Try to access the SOC node directly i.e. through /aliases/.
-	 */
-	if ((node = OF_finddevice("soc")) != -1)
-		if (fdt_is_compatible_strict(node, "simple-bus"))
-			goto moveon;
-	/*
-	 * Find the node the long way.
-	 */
-	if ((node = OF_finddevice("/")) == -1)
-		return (ENXIO);
-
-	if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0)
-		return (ENXIO);
-
-moveon:
 	if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0)
 		return (ENXIO);
 	/*
@@ -99,6 +82,14 @@ moveon:
 	len = OF_getproplen(node, "ranges");
 	if (len > sizeof(ranges))
 		return (ENOMEM);
+	if (len == 0) {
+		*base = 0;
+		*size = ULONG_MAX;
+		return (0);
+	}
+
+	if (!(range_id < len))
+		return (ERANGE);
 
 	if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0)
 		return (EINVAL);
@@ -111,21 +102,48 @@ moveon:
 	    addr_cells, size_cells)) {
 		return (ERANGE);
 	}
-	base = 0;
-	size = 0;
-	rangesptr = &ranges[0];
+	*base = 0;
+	*size = 0;
+	rangesptr = &ranges[range_id];
 
-	base = fdt_data_get((void *)rangesptr, addr_cells);
+	*base = fdt_data_get((void *)rangesptr, addr_cells);
 	rangesptr += addr_cells;
-	base += fdt_data_get((void *)rangesptr, par_addr_cells);
+	*base += fdt_data_get((void *)rangesptr, par_addr_cells);
 	rangesptr += par_addr_cells;
-	size = fdt_data_get((void *)rangesptr, size_cells);
+	*size = fdt_data_get((void *)rangesptr, size_cells);
+	return (0);
+}
 
-	fdt_immr_pa = base;
-	fdt_immr_va = immr_va;
-	fdt_immr_size = size;
+int
+fdt_immr_addr(vm_offset_t immr_va)
+{
+	phandle_t node;
+	u_long base, size;
+	int r;
 
-	return (0);
+	/*
+	 * Try to access the SOC node directly i.e. through /aliases/.
+	 */
+	if ((node = OF_finddevice("soc")) != 0)
+		if (fdt_is_compatible_strict(node, "simple-bus"))
+			goto moveon;
+	/*
+	 * Find the node the long way.
+	 */
+	if ((node = OF_finddevice("/")) == 0)
+		return (ENXIO);
+
+	if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0)
+		return (ENXIO);
+
+moveon:
+	if ((r = fdt_get_range(node, 0, &base, &size)) == 0) {
+		fdt_immr_pa = base;
+		fdt_immr_va = immr_va;
+		fdt_immr_size = size;
+	}
+
+	return (r);
 }
 
 /*
@@ -401,16 +419,19 @@ fdt_regsize(phandle_t node, u_long *base
 }
 
 int
-fdt_reg_to_rl(phandle_t node, struct resource_list *rl, u_long base)
+fdt_reg_to_rl(phandle_t node, struct resource_list *rl)
 {
 	u_long start, end, count;
 	pcell_t *reg, *regptr;
 	pcell_t addr_cells, size_cells;
 	int tuple_size, tuples;
 	int i, rv;
+	long vaddr;
+	long busaddr, bussize;
 
 	if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
 		return (ENXIO);
+	fdt_get_range(OF_parent(node), 0, &busaddr, &bussize);
 
 	tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
 	tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)&reg);
@@ -432,14 +453,15 @@ fdt_reg_to_rl(phandle_t node, struct res
 		reg += addr_cells + size_cells;
 
 		/* Calculate address range relative to base. */
-		start &= 0x000ffffful;
-		start = base + start;
-		end = start + count - 1;
+		start += busaddr;
+		if (bus_space_map(fdtbus_bs_tag, start, count, 0, &vaddr) != 0)
+			panic("Couldn't map the device memory");
+		end = vaddr + count - 1;
 
-		debugf("reg addr start = %lx, end = %lx, count = %lx\n", start,
+		debugf("reg addr start = %lx, end = %lx, count = %lx\n", vaddr,
 		    end, count);
 
-		resource_list_add(rl, SYS_RES_MEMORY, i, start, end,
+		resource_list_add(rl, SYS_RES_MEMORY, i, vaddr, end,
 		    count);
 	}
 	rv = 0;

Modified: head/sys/dev/fdt/fdt_common.h
==============================================================================
--- head/sys/dev/fdt/fdt_common.h	Wed Aug 15 03:33:57 2012	(r239273)
+++ head/sys/dev/fdt/fdt_common.h	Wed Aug 15 03:49:10 2012	(r239274)
@@ -91,6 +91,7 @@ int fdt_data_verify(void *, int);
 phandle_t fdt_find_compatible(phandle_t, const char *, int);
 int fdt_get_mem_regions(struct mem_region *, int *, uint32_t *);
 int fdt_get_phyaddr(phandle_t, device_t, int *, void **);
+int fdt_get_range(phandle_t, int, u_long *, u_long *);
 int fdt_immr_addr(vm_offset_t);
 int fdt_regsize(phandle_t, u_long *, u_long *);
 int fdt_intr_decode(phandle_t, pcell_t *, int *, int *, int *);
@@ -107,7 +108,7 @@ int fdt_pci_ranges_decode(phandle_t, str
     struct fdt_pci_range *);
 int fdt_pci_route_intr(int, int, int, int, struct fdt_pci_intr *, int *);
 int fdt_ranges_verify(pcell_t *, int, int, int, int);
-int fdt_reg_to_rl(phandle_t, struct resource_list *, u_long);
+int fdt_reg_to_rl(phandle_t, struct resource_list *);
 int fdt_pm(phandle_t);
 
 #endif /* _FDT_COMMON_H_ */

Modified: head/sys/dev/fdt/fdtbus.c
==============================================================================
--- head/sys/dev/fdt/fdtbus.c	Wed Aug 15 03:33:57 2012	(r239273)
+++ head/sys/dev/fdt/fdtbus.c	Wed Aug 15 03:49:10 2012	(r239274)
@@ -289,7 +289,7 @@ newbus_device_create(device_t dev_par, p
 
 	resource_list_init(&di->di_res);
 
-	if (fdt_reg_to_rl(node, &di->di_res, fdt_immr_va)) {
+	if (fdt_reg_to_rl(node, &di->di_res)) {
 		device_printf(child, "could not process 'reg' property\n");
 		newbus_device_destroy(child);
 		child = NULL;

Modified: head/sys/dev/fdt/simplebus.c
==============================================================================
--- head/sys/dev/fdt/simplebus.c	Wed Aug 15 03:33:57 2012	(r239273)
+++ head/sys/dev/fdt/simplebus.c	Wed Aug 15 03:49:10 2012	(r239274)
@@ -61,9 +61,6 @@ static MALLOC_DEFINE(M_SIMPLEBUS, "simpl
 struct simplebus_softc {
 	int	sc_addr_cells;
 	int	sc_size_cells;
-	u_long	sc_start_pa;
-	u_long	sc_start_va;
-	u_long	sc_size;
 };
 
 struct simplebus_devinfo {
@@ -155,10 +152,6 @@ simplebus_attach(device_t dev)
 
 	sc = device_get_softc(dev);
 
-	sc->sc_start_pa = fdt_immr_pa;
-	sc->sc_start_va = fdt_immr_va;
-	sc->sc_size = fdt_immr_size;
-
 	/*
 	 * Walk simple-bus and add direct subordinates as our children.
 	 */
@@ -182,10 +175,11 @@ simplebus_attach(device_t dev)
 		}
 
 		resource_list_init(&di->di_res);
-
-		if (fdt_reg_to_rl(dt_child, &di->di_res, sc->sc_start_va)) {
-			device_printf(dev, "%s: could not process 'reg' "
+		if (fdt_reg_to_rl(dt_child, &di->di_res)) {
+			device_printf(dev,
+			    "%s: could not process 'reg' "
 			    "property\n", di->di_ofw.obd_name);
+			/* XXX should unmap */
 			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
 			free(di, M_SIMPLEBUS);
 			continue;
@@ -195,6 +189,7 @@ simplebus_attach(device_t dev)
 			device_printf(dev, "%s: could not process "
 			    "'interrupts' property\n", di->di_ofw.obd_name);
 			resource_list_free(&di->di_res);
+			/* XXX should unmap */
 			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
 			free(di, M_SIMPLEBUS);
 			continue;
@@ -206,6 +201,7 @@ simplebus_attach(device_t dev)
 			device_printf(dev, "could not add child: %s\n",
 			    di->di_ofw.obd_name);
 			resource_list_free(&di->di_res);
+			/* XXX should unmap */
 			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
 			free(di, M_SIMPLEBUS);
 			continue;

Modified: head/sys/dev/uart/uart_bus_fdt.c
==============================================================================
--- head/sys/dev/uart/uart_bus_fdt.c	Wed Aug 15 03:33:57 2012	(r239273)
+++ head/sys/dev/uart/uart_bus_fdt.c	Wed Aug 15 03:49:10 2012	(r239274)
@@ -137,7 +137,7 @@ uart_cpu_getdev(int devtype, struct uart
 	struct uart_class *class;
 	phandle_t node, chosen;
 	pcell_t shift, br, rclk;
-	u_long start, size;
+	u_long start, size, pbase, psize;
 	int err;
 
 	uart_bus_space_mem = fdtbus_bs_tag;
@@ -197,7 +197,9 @@ uart_cpu_getdev(int devtype, struct uart
 	err = fdt_regsize(node, &start, &size);
 	if (err)
 		return (ENXIO);
-	start += fdt_immr_va;
+
+	fdt_get_range(OF_parent(node), 0, &pbase, &psize);
+	start += pbase;
 
 	return (bus_space_map(di->bas.bst, start, size, 0, &di->bas.bsh));
 }



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