Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115647687
D31029.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D31029.diff
View Options
diff --git a/sys/dev/pci/pci_dw.h b/sys/dev/pci/pci_dw.h
--- a/sys/dev/pci/pci_dw.h
+++ b/sys/dev/pci/pci_dw.h
@@ -63,6 +63,7 @@
#define DW_MISC_CONTROL_1 0x8BC
#define DBI_RO_WR_EN (1 << 0)
+/* Legacy (pre-4.80) iATU mode */
#define DW_IATU_VIEWPORT 0x900
#define IATU_REGION_INBOUND (1U << 31)
#define IATU_REGION_INDEX(x) ((x) & 0x7)
@@ -80,6 +81,20 @@
#define DW_IATU_LWR_TARGET_ADDR 0x918
#define DW_IATU_UPPER_TARGET_ADDR 0x91C
+/* Modern (4.80+) "unroll" iATU mode */
+#define DW_IATU_UR_STEP 0x200
+#define DW_IATU_UR_REG(r, n) (r) * DW_IATU_UR_STEP + IATU_UR_##n
+#define IATU_UR_CTRL1 0x00
+#define IATU_UR_CTRL2 0x04
+#define IATU_UR_LWR_BASE_ADDR 0x08
+#define IATU_UR_UPPER_BASE_ADDR 0x0C
+#define IATU_UR_LIMIT_ADDR 0x10
+#define IATU_UR_LWR_TARGET_ADDR 0x14
+#define IATU_UR_UPPER_TARGET_ADDR 0x18
+
+#define DW_DEFAULT_IATU_UR_DBI_OFFSET 0x300000
+#define DW_DEFAULT_IATU_UR_DBI_SIZE 0x1000
+
struct pci_dw_softc {
struct ofw_pci_softc ofw_pci; /* Must be first */
@@ -101,6 +116,9 @@
int num_lanes;
int num_viewport;
+ struct resource *iatu_ur_res; /* NB: May be dbi_res */
+ bus_addr_t iatu_ur_offset;
+ bus_size_t iatu_ur_size;
bus_addr_t cfg_pa; /* PA of config memoty */
bus_size_t cfg_size; /* size of config region */
diff --git a/sys/dev/pci/pci_dw.c b/sys/dev/pci/pci_dw.c
--- a/sys/dev/pci/pci_dw.c
+++ b/sys/dev/pci/pci_dw.c
@@ -73,6 +73,11 @@
#define DBI_RD2(sc, reg) pci_dw_dbi_rd2((sc)->dev, reg)
#define DBI_RD4(sc, reg) pci_dw_dbi_rd4((sc)->dev, reg)
+#define IATU_UR_WR4(sc, reg, val) \
+ bus_write_4((sc)->iatu_ur_res, (sc)->iatu_ur_offset + (reg), (val))
+#define IATU_UR_RD4(sc, reg) \
+ bus_read_4((sc)->iatu_ur_res, (sc)->iatu_ur_offset + (reg))
+
#define PCI_BUS_SHIFT 20
#define PCI_SLOT_SHIFT 15
#define PCI_FUNC_SHIFT 12
@@ -168,9 +173,52 @@
return (true);
}
-/* Map one uoutbound ATU region */
+static bool
+pci_dw_detect_atu_unroll(struct pci_dw_softc *sc)
+{
+ return (DBI_RD4(sc, DW_IATU_VIEWPORT) == 0xFFFFFFFFU);
+}
+
static int
-pci_dw_map_out_atu(struct pci_dw_softc *sc, int idx, int type,
+pci_dw_map_out_atu_unroll(struct pci_dw_softc *sc, int idx, int type,
+ uint64_t pa, uint64_t pci_addr, uint32_t size)
+{
+ uint32_t reg;
+ int i;
+
+ if (size == 0)
+ return (0);
+
+ IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, LWR_BASE_ADDR),
+ pa & 0xFFFFFFFF);
+ IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, UPPER_BASE_ADDR),
+ (pa >> 32) & 0xFFFFFFFF);
+ IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, LIMIT_ADDR),
+ (pa + size - 1) & 0xFFFFFFFF);
+ IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, LWR_TARGET_ADDR),
+ pci_addr & 0xFFFFFFFF);
+ IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, UPPER_TARGET_ADDR),
+ (pci_addr >> 32) & 0xFFFFFFFF);
+ IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, CTRL1),
+ IATU_CTRL1_TYPE(type));
+ IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, CTRL2),
+ IATU_CTRL2_REGION_EN);
+
+ /* Wait until setup becomes valid */
+ for (i = 10; i > 0; i--) {
+ reg = IATU_UR_RD4(sc, DW_IATU_UR_REG(idx, CTRL2));
+ if (reg & IATU_CTRL2_REGION_EN)
+ return (0);
+ DELAY(5);
+ }
+
+ device_printf(sc->dev,
+ "Cannot map outbound region %d in unroll mode iATU\n", idx);
+ return (ETIMEDOUT);
+}
+
+static int
+pci_dw_map_out_atu_legacy(struct pci_dw_softc *sc, int idx, int type,
uint64_t pa, uint64_t pci_addr, uint32_t size)
{
uint32_t reg;
@@ -195,11 +243,25 @@
return (0);
DELAY(5);
}
+
device_printf(sc->dev,
- "Cannot map outbound region(%d) in iATU\n", idx);
+ "Cannot map outbound region %d in legacy mode iATU\n", idx);
return (ETIMEDOUT);
}
+/* Map one outbound ATU region */
+static int
+pci_dw_map_out_atu(struct pci_dw_softc *sc, int idx, int type,
+ uint64_t pa, uint64_t pci_addr, uint32_t size)
+{
+ if (sc->iatu_ur_res)
+ return (pci_dw_map_out_atu_unroll(sc, idx, type, pa,
+ pci_addr, size));
+ else
+ return (pci_dw_map_out_atu_legacy(sc, idx, type, pa,
+ pci_addr, size));
+}
+
static int
pci_dw_setup_hw(struct pci_dw_softc *sc)
{
@@ -580,6 +642,7 @@
{
struct pci_dw_softc *sc;
int rv, rid;
+ bool unroll_mode;
sc = device_get_softc(dev);
sc->dev = dev;
@@ -660,6 +723,36 @@
if (rv != 0)
goto out;
+ unroll_mode = pci_dw_detect_atu_unroll(sc);
+ if (bootverbose)
+ device_printf(dev, "Using iATU %s mode\n",
+ unroll_mode ? "unroll" : "legacy");
+ if (unroll_mode) {
+ rid = 0;
+ rv = ofw_bus_find_string_index(sc->node, "reg-names", "atu", &rid);
+ if (rv == 0) {
+ sc->iatu_ur_res = bus_alloc_resource_any(dev,
+ SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->iatu_ur_res == NULL) {
+ device_printf(dev,
+ "Cannot allocate iATU space (rid: %d)\n",
+ rid);
+ rv = ENXIO;
+ goto out;
+ }
+ sc->iatu_ur_offset = 0;
+ sc->iatu_ur_size = rman_get_size(sc->iatu_ur_res);
+ } else if (rv == ENOENT) {
+ sc->iatu_ur_res = sc->dbi_res;
+ sc->iatu_ur_offset = DW_DEFAULT_IATU_UR_DBI_OFFSET;
+ sc->iatu_ur_size = DW_DEFAULT_IATU_UR_DBI_SIZE;
+ } else {
+ device_printf(dev, "Cannot get iATU space memory\n");
+ rv = ENXIO;
+ goto out;
+ }
+ }
+
rv = pci_dw_setup_hw(sc);
if (rv != 0)
goto out;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 27, 12:53 PM (17 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17817831
Default Alt Text
D31029.diff (5 KB)
Attached To
Mode
D31029: pci_dw: Support modern "unroll" iATU mode
Attached
Detach File
Event Timeline
Log In to Comment