summaryrefslogtreecommitdiffstats
path: root/sys/dev/fdt/fdt_common.c
diff options
context:
space:
mode:
authorgonzo <gonzo@FreeBSD.org>2012-08-15 03:49:10 +0000
committergonzo <gonzo@FreeBSD.org>2012-08-15 03:49:10 +0000
commita86619e32d43f67acebfca6f18e523a14bce37c8 (patch)
treed91a083208aa6a56ef7a654eca6f01ee88016949 /sys/dev/fdt/fdt_common.c
parent7dcf863fe4ae5e10c9c55e6c27387d8d389687d9 (diff)
downloadFreeBSD-src-a86619e32d43f67acebfca6f18e523a14bce37c8.zip
FreeBSD-src-a86619e32d43f67acebfca6f18e523a14bce37c8.tar.gz
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
Diffstat (limited to 'sys/dev/fdt/fdt_common.c')
-rw-r--r--sys/dev/fdt/fdt_common.c92
1 files changed, 57 insertions, 35 deletions
diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c
index bf18e34..0504c67 100644
--- a/sys/dev/fdt/fdt_common.c
+++ b/sys/dev/fdt/fdt_common.c
@@ -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, u_long *size)
}
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 resource_list *rl, u_long base)
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;
OpenPOWER on IntegriCloud