diff options
-rw-r--r-- | sys/dev/fdt/fdt_common.c | 92 | ||||
-rw-r--r-- | sys/dev/fdt/fdt_common.h | 3 | ||||
-rw-r--r-- | sys/dev/fdt/fdtbus.c | 2 | ||||
-rw-r--r-- | sys/dev/fdt/simplebus.c | 16 | ||||
-rw-r--r-- | sys/dev/uart/uart_bus_fdt.c | 6 |
5 files changed, 70 insertions, 49 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 **)®); @@ -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; diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h index 7947428..4dea494 100644 --- a/sys/dev/fdt/fdt_common.h +++ b/sys/dev/fdt/fdt_common.h @@ -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, struct fdt_pci_range *, 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 --git a/sys/dev/fdt/fdtbus.c b/sys/dev/fdt/fdtbus.c index a18ae57..2ca7ab5 100644 --- a/sys/dev/fdt/fdtbus.c +++ b/sys/dev/fdt/fdtbus.c @@ -289,7 +289,7 @@ newbus_device_create(device_t dev_par, phandle_t node, char *name, char *type, 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 --git a/sys/dev/fdt/simplebus.c b/sys/dev/fdt/simplebus.c index 0868fb0..db9ade0 100644 --- a/sys/dev/fdt/simplebus.c +++ b/sys/dev/fdt/simplebus.c @@ -61,9 +61,6 @@ static MALLOC_DEFINE(M_SIMPLEBUS, "simplebus", "simplebus devices information"); 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; diff --git a/sys/dev/uart/uart_bus_fdt.c b/sys/dev/uart/uart_bus_fdt.c index 8bb62ea..88523b5 100644 --- a/sys/dev/uart/uart_bus_fdt.c +++ b/sys/dev/uart/uart_bus_fdt.c @@ -137,7 +137,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) 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_devinfo *di) 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)); } |