diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c index d31989b7dde..a50d50baaf2 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c @@ -316,8 +316,8 @@ bcm2835_mbox_init_dma(device_t dev, size_t len, bus_dma_tag_t *tag, int err; err = bus_dma_tag_create(bus_get_dma_tag(dev), 16, 0, - bcm283x_dmabus_peripheral_lowaddr(), BUS_SPACE_MAXADDR, NULL, NULL, - len, 1, len, 0, NULL, NULL, tag); + bcm283x_dmabus_peripheral_lowaddr(dev), BUS_SPACE_MAXADDR, NULL, + NULL, len, 1, len, 0, NULL, NULL, tag); if (err != 0) { device_printf(dev, "can't create DMA tag\n"); return (NULL); diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c index cd9b60743be..359b3d78341 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c @@ -333,7 +333,7 @@ bcm_sdhci_attach(device_t dev) /* Allocate bus_dma resources. */ err = bus_dma_tag_create(bus_get_dma_tag(dev), - 1, 0, bcm283x_dmabus_peripheral_lowaddr(), + 1, 0, bcm283x_dmabus_peripheral_lowaddr(dev), BUS_SPACE_MAXADDR, NULL, NULL, BCM_DMA_MAXSIZE, ALLOCATED_DMA_SEGS, BCM_SDHCI_BUFFER_SIZE, BUS_DMA_ALLOCNOW, NULL, NULL, diff --git a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.c b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.c index 7e5033f032c..c64e36a8225 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.c @@ -271,10 +271,45 @@ bcm283x_vcbus_to_armc(vm_paddr_t vca) } bus_addr_t -bcm283x_dmabus_peripheral_lowaddr(void) +bcm283x_dmabus_peripheral_lowaddr(device_t dev) { + cell_t dma_range[5]; struct bcm283x_memory_soc_cfg *cfg; + bus_addr_t cpu_addr; + ssize_t ndma_range; + phandle_t node, parent_node; + uint32_t max_len; + int num_props; cfg = bcm283x_get_current_memcfg(); - return (cfg->busdma_lowaddr); + node = ofw_bus_get_node(dev); + parent_node = OF_parent(node); + if (parent_node <= 0) { + printf("WARNING: Improper peripheral attachment ('%s')!", + device_get_name(dev)); + return (cfg->busdma_lowaddr); + } + + ndma_range = OF_getproplen(parent_node, "dma-ranges"); + if (ndma_range < 0) { + printf("WARNING: bus for '%s' missing dma-ranges", + device_get_name(dev)); + return (cfg->busdma_lowaddr); + } + + KASSERT(ndma_range <= sizeof(dma_range), + ("Improperly sized dma_range; expected %ju, got %ju\n", + nitems(dma_range), ndma_range / sizeof(cell_t))); + + OF_getencprop(parent_node, "dma-ranges", dma_range, ndma_range); + num_props = ndma_range / sizeof(cell_t); + KASSERT(num_props >= 3, ("Too few dma-ranges entries: %d", num_props)); + + max_len = dma_range[num_props - 1]; + if (num_props == 3) + cpu_addr = dma_range[1]; + else + cpu_addr = ((uint64_t)dma_range[num_props - 3] << 32) | + dma_range[num_props - 2]; + return (cpu_addr + (max_len - 1)); } diff --git a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h index 77b408311e6..e15a94ee8d6 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h +++ b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h @@ -70,7 +70,7 @@ vm_paddr_t bcm283x_armc_to_vcbus(vm_paddr_t pa); vm_paddr_t bcm283x_vcbus_to_armc(vm_paddr_t vca); -bus_addr_t bcm283x_dmabus_peripheral_lowaddr(void); +bus_addr_t bcm283x_dmabus_peripheral_lowaddr(device_t); #define ARMC_TO_VCBUS(pa) bcm283x_armc_to_vcbus(pa) #define VCBUS_TO_ARMC(vca) bcm283x_vcbus_to_armc(vca)