This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

PCI BAR setup

Other Parts Discussed in Thread: AM3874

DM814x processor on a custom (non-EVM) board, booting from NOR flash, and operating as a PCIe EP (behind a PLX8112 PCIe-PCI bridge) with an x86 host.  Basic PCI operations all seem to be OK (memory-mapped reads and writes, EDMA out to host-based buffers).

We currently configure for EP mode in U-Boot, and are only using BAR0 and BAR1.  I'm trying to disable the other unused BARs by setting the BAR masks and attributes to 0:

static void pcie_setup_ep()
{
/* Set "Application Request Retry Enable" while we configure EP.
* (CMD_STATUS) */
__raw_writel(__raw_readl(0x51000004) | (1 << 4), 0x51000004);

/* Set vendor & device ID. (VENDOR_DEVICE_ID) */
__raw_writel(0x104C | (0xB801 << 16), 0x51001000);

/* Enable device for memory accesses. (STATUS_COMMAND) */
__raw_writel(__raw_readl(0x51001004) | (1 << 1), 0x51001004);

/* Set CLASSCODE. (CLASSCODE_REVID) */
__raw_writel(0x04000001, 0x51001008);

/* Enable DBI_CS2 - allows BAR mask setup. (CMD_STATUS) */
__raw_writel(__raw_readl(0x51000004) | (1 << 5), 0x51000004);
while((__raw_readl(0x51000004) & (1 << 5)) == 0);

/* Set BAR masks prior to enumeration by RC. */
__raw_writel(0x00000FFF, 0x51001010); /* BAR0: 4 KiB */
__raw_writel(0x007FFFFF, 0x51001014); /* BAR1: 8 MiB */
__raw_writel(0x00000000, 0x51001018); /* BAR2: disabled */
__raw_writel(0x00000000, 0x5100101C); /* BAR3: disabled */
__raw_writel(0x00000000, 0x51001020); /* BAR4: disabled */
__raw_writel(0x00000000, 0x51001024); /* BAR5: disabled */

/* Disable DBI_CS2. (CMD_STATUS) */
__raw_writel(__raw_readl(0x51000004) & ~(1 << 5), 0x51000004);

/* Set BAR access type and attributes after DBI_CS2 disable. */
__raw_writel(0x00000000, 0x51001010); /* BAR0: 32-bit, !pre-fetch */
__raw_writel(0x00000000, 0x51001014); /* BAR1: 32-bit, !pre-fetch */
__raw_writel(0x00000000, 0x51001018); /* BAR2: disabled */
__raw_writel(0x00000000, 0x5100101C); /* BAR3: disabled */
__raw_writel(0x00000000, 0x51001020); /* BAR4: disabled */
__raw_writel(0x00000000, 0x51001024); /* BAR5: disabled */

/* Enable [in/out]-bound address translation. (CMD_STATUS) */
__raw_writel(__raw_readl(0x51000004) | (3 << 1), 0x51000004);

/* Disable legacy and set-up MSI interrupts. */
__raw_writel(0x00000000, 0x5100018C);
__raw_writel(__raw_readl(0x51001004) | (1 << 10), 0x51001004);
__raw_writel(__raw_readl(0x51001050) | (1 << 16), 0x51001050);
__raw_writel(0xFFFFFFFF, 0x51000108);

/* Set x1 mode: LINK_CAP, PL_GEN2 & PL_LINK_CTRL */
__raw_writel((__raw_readl(0x5100107C) & ~(0x3F << 4)) | (1 << 4), 0x5100107C);
__raw_writel((__raw_readl(0x5100180C) & ~(0xFF << 8)) | (1 << 8), 0x5100180C);
__raw_writel((__raw_readl(0x51001710) & ~(0x3F << 16)) | (1 << 16), 0x5100180C);
}

After the above runs, however, I see that I have BAR2 and BAR4 flagged as pre-fetchable in a register dump (still the default register value?), and the OS reports similarly (note that this is just following U-Boot initialization, no other kernel and/or PCI EP driver is loaded on the DM814x for purposes of this test).

#md.l 51001000 40
51001000: b801104c 00100007 04000001 00000004 L...............
51001010: cffff000 cf000000 00000008 00000000 ................
51001020: 00000008 00000000 00000000 00010000 ................
51001030: 00000000 00000040 00000000 0000010b ....@...........
51001040: 00035001 00000000 00000000 00000000 .P..............
51001050: 00807005 00000000 00000000 00000000 .p..............
51001060: 00000000 00000000 00000000 00000000 ................
51001070: 00020010 00648701 00092810 00035412 ......d..(...T..
51001080: 10110000 00000000 00000000 00000000 ................
51001090: 00000000 0000001f 00000000 00000006 ................
510010a0: 00010002 00000000 00000000 00000000 ................
510010b0: 00000000 00000000 00000000 00000000 ................
510010c0: 00000000 00000000 00000000 00000000 ................
510010d0: 00000000 00000000 00000000 00000000 ................
510010e0: 00000000 00000000 00000000 00000000 ................
510010f0: 00000000 00000000 00000000 00000000 ................

$ sudo lspci -v -s 03:00.0
03:00.0 Multimedia video controller: Texas Instruments Device b801 (rev 01)
Flags: bus master, fast devsel, latency 0, IRQ 11
Memory at cffff000 (32-bit, non-prefetchable) [size=4K]
Memory at cf000000 (32-bit, non-prefetchable) [size=8M]
Memory at <unassigned> (32-bit, prefetchable)
Memory at <unassigned> (32-bit, prefetchable)
Capabilities: [40] Power Management version 3
Capabilities: [50] Message Signalled Interrupts: Mask- 64bit- Queue=0/0 Enable-
Capabilities: [70] Express Endpoint, MSI 00

Is there something I'm missing in the above setup logic which will allow these unused BARs to be properly disabled?

Thanks.

-Cory