Index: sys/arm/broadcom/bcm2835/bcm2838_pci.c =================================================================== --- sys/arm/broadcom/bcm2835/bcm2838_pci.c +++ sys/arm/broadcom/bcm2835/bcm2838_pci.c @@ -57,9 +57,6 @@ #include "pcib_if.h" #include "msi_if.h" -extern struct bus_space memmap_bus; - -#define BUS_SPACE_3G_MAXADDR 0xc0000000 #define PCI_ID_VAL3 0x43c #define CLASS_SHIFT 0x10 #define SUBCLASS_SHIFT 0x8 @@ -69,18 +66,18 @@ #define BRIDGE_DISABLE_FLAG 0x1 #define BRIDGE_RESET_FLAG 0x2 #define REG_BRIDGE_SERDES_MODE 0x4204 -#define REG_BRIDGE_CONFIG 0x4008 -#define REG_BRIDGE_MEM_WINDOW_LOW 0x4034 -#define REG_BRIDGE_MEM_WINDOW_HIGH 0x4038 -#define REG_BRIDGE_MEM_WINDOW_1 0x403c +#define REG_DMA_CONFIG 0x4008 +#define REG_DMA_WINDOW_LOW 0x4034 +#define REG_DMA_WINDOW_HIGH 0x4038 +#define REG_DMA_WINDOW_1 0x403c #define REG_BRIDGE_GISB_WINDOW 0x402c #define REG_BRIDGE_STATE 0x4068 #define REG_BRIDGE_LINK_STATE 0x00bc -#define REG_BRIDGE_BUS_WINDOW_LOW 0x400c -#define REG_BRIDGE_BUS_WINDOW_HIGH 0x4010 -#define REG_BRIDGE_CPU_WINDOW_LOW 0x4070 -#define REG_BRIDGE_CPU_WINDOW_START_HIGH 0x4080 -#define REG_BRIDGE_CPU_WINDOW_END_HIGH 0x4084 +#define REG_BUS_WINDOW_LOW 0x400c +#define REG_BUS_WINDOW_HIGH 0x4010 +#define REG_CPU_WINDOW_LOW 0x4070 +#define REG_CPU_WINDOW_START_HIGH 0x4080 +#define REG_CPU_WINDOW_END_HIGH 0x4084 #define REG_MSI_ADDR_LOW 0x4044 #define REG_MSI_ADDR_HIGH 0x4048 @@ -95,12 +92,18 @@ #define REG_EP_CONFIG_DATA 0x8000 /* - * These values were obtained from runtime inspection of a Linux system using a - * JTAG. The very limited documentation I have obtained from Broadcom does not - * explain how to compute them. + * The system memory controller can address up to 16 GiB of physical memory + * (although at time of writing the largest size available for purchase is + * 8 GiB). The PCI-E controller can only perform DMA on the lower 1 GiB. */ -#define REG_VALUE_4GB_WINDOW 0x11 -#define REG_VALUE_4GB_CONFIG 0x88003000 +#define BUS_SPACE_DMA_MAXADDR 0x3c000000 +#define MAX_MEMORY_LOG2 0x21 +#define REG_VALUE_DMA_WINDOW_LOW (MAX_MEMORY_LOG2 - 0xf) +#define REG_VALUE_DMA_WINDOW_HIGH 0x0 +#define DMA_WINDOW_ENABLE 0x3000 +#define REG_VALUE_DMA_WINDOW_CONFIG \ + (((MAX_MEMORY_LOG2 - 0xf) << 0x1b) | DMA_WINDOW_ENABLE) + #define REG_VALUE_MSI_CONFIG 0xffe06540 struct bcm_pcib_irqsrc { @@ -112,6 +115,7 @@ struct bcm_pcib_softc { struct generic_pcie_fdt_softc base; device_t dev; + bus_dma_tag_t dmat; struct mtx config_mtx; struct mtx msi_mtx; struct resource *msi_irq_res; @@ -124,6 +128,7 @@ {"brcm,bcm2711-pcie", 1}, {"brcm,bcm7211-pcie", 1}, {"brcm,bcm7445-pcie", 1}, + {NULL, 0} }; @@ -142,6 +147,15 @@ return (BUS_PROBE_DEFAULT); } +static bus_dma_tag_t +bcm_pcib_get_dma_tag(device_t dev, device_t child) +{ + struct bcm_pcib_softc *sc; + + sc = device_get_softc(dev); + return (sc->dmat); +} + static void bcm_pcib_set_reg(struct bcm_pcib_softc *sc, uint32_t reg, uint32_t val) { @@ -614,6 +628,25 @@ sc = device_get_softc(dev); sc->dev = dev; + /* + * The controller can only perform DMA on the lower 1 GiB of physical + * memory. This tag will be used in preference to the one created in + * pci_host_generic.c. + */ + error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ + 1, 0, /* alignment, bounds */ + BUS_SPACE_DMA_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + BUS_SPACE_MAXSIZE, /* maxsize */ + BUS_SPACE_UNRESTRICTED, /* nsegments */ + BUS_SPACE_MAXSIZE, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &sc->dmat); + if (error) + return (error); + error = pci_host_generic_setup_fdt(dev); if (error) return (error); @@ -632,17 +665,14 @@ /* * Set PCI->CPU memory window. This encodes the inbound window showing - * up to 4 GiB of system memory to the controller, with zero offset. - * Thus, from the perspective of a device on the PCI-E bus, there is a - * 1:1 map from PCI-E bus addresses to system memory addresses. However, - * a hardware limitation means that the controller can only perform DMA - * on the lower 3 GiB of system memory. + * the system memory to the controller. */ - bcm_pcib_set_reg(sc, REG_BRIDGE_MEM_WINDOW_LOW, REG_VALUE_4GB_WINDOW); - bcm_pcib_set_reg(sc, REG_BRIDGE_MEM_WINDOW_HIGH, 0); - bcm_pcib_set_reg(sc, REG_BRIDGE_CONFIG, REG_VALUE_4GB_CONFIG); + bcm_pcib_set_reg(sc, REG_DMA_WINDOW_LOW, REG_VALUE_DMA_WINDOW_LOW); + bcm_pcib_set_reg(sc, REG_DMA_WINDOW_HIGH, REG_VALUE_DMA_WINDOW_HIGH); + bcm_pcib_set_reg(sc, REG_DMA_CONFIG, REG_VALUE_DMA_WINDOW_CONFIG); + bcm_pcib_set_reg(sc, REG_BRIDGE_GISB_WINDOW, 0); - bcm_pcib_set_reg(sc, REG_BRIDGE_MEM_WINDOW_1, 0); + bcm_pcib_set_reg(sc, REG_DMA_WINDOW_1, 0); bcm_pcib_enable_controller(sc); @@ -682,14 +712,14 @@ phys_base = sc->base.base.ranges[0].phys_base; size = sc->base.base.ranges[0].size; - bcm_pcib_set_reg(sc, REG_BRIDGE_BUS_WINDOW_LOW, pci_base & 0xffffffff); - bcm_pcib_set_reg(sc, REG_BRIDGE_BUS_WINDOW_HIGH, pci_base >> 32); + bcm_pcib_set_reg(sc, REG_BUS_WINDOW_LOW, pci_base & 0xffffffff); + bcm_pcib_set_reg(sc, REG_BUS_WINDOW_HIGH, pci_base >> 32); - bcm_pcib_set_reg(sc, REG_BRIDGE_CPU_WINDOW_LOW, + bcm_pcib_set_reg(sc, REG_CPU_WINDOW_LOW, encode_cpu_window_low(phys_base, size)); - bcm_pcib_set_reg(sc, REG_BRIDGE_CPU_WINDOW_START_HIGH, + bcm_pcib_set_reg(sc, REG_CPU_WINDOW_START_HIGH, encode_cpu_window_start_high(phys_base)); - bcm_pcib_set_reg(sc, REG_BRIDGE_CPU_WINDOW_END_HIGH, + bcm_pcib_set_reg(sc, REG_CPU_WINDOW_END_HIGH, encode_cpu_window_end_high(phys_base, size)); /* @@ -718,6 +748,9 @@ * Device method table. */ static device_method_t bcm_pcib_methods[] = { + /* Bus interface. */ + DEVMETHOD(bus_get_dma_tag, bcm_pcib_get_dma_tag), + /* Device interface. */ DEVMETHOD(device_probe, bcm_pcib_probe), DEVMETHOD(device_attach, bcm_pcib_attach), @@ -739,3 +772,4 @@ static devclass_t bcm_pcib_devclass; DRIVER_MODULE(bcm_pcib, simplebus, bcm_pcib_driver, bcm_pcib_devclass, 0, 0); +