diff -x .svn -I '$FreeBSD.*$' -Naur head/sys/dev/fdt/fdt_common.c armv6/sys/dev/fdt/fdt_common.c --- head/sys/dev/fdt/fdt_common.c 2012-08-08 12:42:44.351723990 -0700 +++ armv6/sys/dev/fdt/fdt_common.c 2012-08-08 12:44:17.593723912 -0700 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -63,30 +64,12 @@ 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 @@ 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 @@ 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 @@ } 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 **)®); @@ -432,14 +453,15 @@ 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; diff -x .svn -I '$FreeBSD.*$' -Naur head/sys/dev/fdt/fdt_common.h armv6/sys/dev/fdt/fdt_common.h --- head/sys/dev/fdt/fdt_common.h 2012-08-08 13:43:37.696723982 -0700 +++ armv6/sys/dev/fdt/fdt_common.h 2012-08-09 12:08:29.214724373 -0700 @@ -91,6 +91,7 @@ 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 @@ 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_ */ diff -x .svn -I '$FreeBSD.*$' -Naur head/sys/dev/fdt/fdtbus.c armv6/sys/dev/fdt/fdtbus.c --- head/sys/dev/fdt/fdtbus.c 2012-08-08 13:43:37.695723859 -0700 +++ armv6/sys/dev/fdt/fdtbus.c 2012-08-09 12:08:29.218724640 -0700 @@ -289,7 +289,7 @@ 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; diff -x .svn -I '$FreeBSD.*$' -Naur head/sys/dev/fdt/simplebus.c armv6/sys/dev/fdt/simplebus.c --- head/sys/dev/fdt/simplebus.c 2012-08-08 13:43:37.694723886 -0700 +++ armv6/sys/dev/fdt/simplebus.c 2012-08-09 12:08:29.219724463 -0700 @@ -61,9 +61,6 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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; diff -x .svn -I '$FreeBSD.*$' -Naur head/sys/dev/ofw/ofw_iicbus.c armv6/sys/dev/ofw/ofw_iicbus.c --- head/sys/dev/ofw/ofw_iicbus.c 2012-08-08 12:43:00.131723769 -0700 +++ armv6/sys/dev/ofw/ofw_iicbus.c 2012-08-08 12:44:46.423723812 -0700 @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -101,6 +102,7 @@ struct iicbus_softc *sc = IICBUS_SOFTC(dev); struct ofw_iicbus_devinfo *dinfo; phandle_t child; + pcell_t paddr; device_t childdev; uint32_t addr; @@ -121,10 +123,11 @@ * property, then try the reg property. It moves around * on different systems. */ - if (OF_getprop(child, "i2c-address", &addr, sizeof(addr)) == -1) - if (OF_getprop(child, "reg", &addr, sizeof(addr)) == -1) + if (OF_getprop(child, "i2c-address", &paddr, sizeof(paddr)) == -1) + if (OF_getprop(child, "reg", &paddr, sizeof(paddr)) == -1) continue; + addr = fdt32_to_cpu(paddr); /* * Now set up the I2C and OFW bus layer devinfo and add it * to the bus.