Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F110775016
D26344.id76962.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D26344.id76962.diff
View Options
Index: head/sys/arm/broadcom/bcm2835/bcm2838_pci.c
===================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2838_pci.c
+++ head/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,27 @@
#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 memory size available for purchase
+ * is 8 GiB). However, the system DMA controller is capable of accessing only a
+ * limited portion of the address space. Worse, the PCI-e controller has further
+ * constraints for DMA, and those limitations are not wholly clear to the
+ * author. NetBSD and Linux allow DMA on the lower 3 GiB of the physical memory,
+ * but experimentation shows DMA performed above 960 MiB results in data
+ * corruption with this driver. The limit of 960 MiB is taken from OpenBSD, but
+ * apparently that value was chosen for satisfying a constraint of an unrelated
+ * peripheral.
+ *
+ * Whatever the true maximum address, 960 MiB works.
*/
-#define REG_VALUE_4GB_WINDOW 0x11
-#define REG_VALUE_4GB_CONFIG 0x88003000
+#define DMA_HIGH_LIMIT 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 +124,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;
@@ -142,6 +155,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 +636,24 @@
sc = device_get_softc(dev);
sc->dev = dev;
+ /*
+ * 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 */
+ DMA_HIGH_LIMIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ DMA_HIGH_LIMIT, /* maxsize */
+ BUS_SPACE_UNRESTRICTED, /* nsegments */
+ DMA_HIGH_LIMIT, /* 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 +672,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 +719,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 +755,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 +779,4 @@
static devclass_t bcm_pcib_devclass;
DRIVER_MODULE(bcm_pcib, simplebus, bcm_pcib_driver, bcm_pcib_devclass, 0, 0);
+
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 23, 11:31 PM (10 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16787582
Default Alt Text
D26344.id76962.diff (6 KB)
Attached To
Mode
D26344: bcm2838_pci.c: Respect DMA limits of controller.
Attached
Detach File
Event Timeline
Log In to Comment