With the IMX6 configured as a PCIe endpoint, I try to setup BAR0 and BAR1 as 32 bit memory BARs. The problem is that if BAR0 is configured to be a 32 bit memory BAR it seems that whatever I set in the BAR1 mask register is ignored. This is what I do in the code:
// setup BAR0 and its mask | |
RegWrite(Registers32::PCIE_EP_BAR0, 0x0); | |
RegWrite(Registers32::PCIE_EP_MASK0, 0xFFFF); |
// setup BAR1 and its mask | |
RegWrite(Registers32::PCIE_EP_BAR1, 0x0); | |
RegWrite(Registers32::PCIE_EP_MASK1, 0xFFFF); |
When the RC enumerates the endpoint and writes 0xFFFFFFFF to each BAR and then reads them back, BAR0 returns 0xFFFF0000 as expected. But BAR1 returns 0x00000000. If I change BAR0 to be a 64 bit BAR (RegWrite(Registers32::PCIE_EP_BAR0, 0x4);) but change nothing else, then BAR1 seems to work and the RC sees it request 64K of memory as expected.
I'm using a PCIe bus analyzer to verify the config reads and writes so I know it's not an issue with the RC. These are the values actually going across the wire to and from the IMX6.
Can a freescale engineer look into this please? Both the datasheet and the linux example code do not enable BAR1 as a 32 bit BAR so I'm wondering if this has ever been tested or if there is a bug in the part itself. Thanks.
Thank you. From the reference manual:
The core provides three pairs of 32-bit BARs for each implemented function. Each pair
(BARs 0 and 1, BARs 2 and 3, BARs 4 and 5) can be configured as follows:
• One 64-bit BAR: For example, BARs 0 and 1 are combined to form a single 64-bit
BAR.
• Two 32-bit BARs: For example, BARs 0 and 1 are two independent 32-bit BARs.
• One 32-bit BAR: For example, BAR 0 is a 32-bit BAR and BAR 1 is either disabled
or removed from the core altogether to reduce gate count.
So the reference manual is incorrect, the hardware is not actually capable of being configured this way?
Hello,
the information from R&D is declared as non-documented feature.
Please let me know if it helps.
Regards,
Yuri.
Hello,
From R&D:
BAR0 thru 4 are different.
BAR0+BAR1 as 64 bit addressing bar, type memory, prefetchable, mask 0xfffff, mask
writable. So Bar1 can’t be used separately.
BAR2 : 32 bit addressing , type memory, prefetchable , mask 0xfffff, mask writable
BAR3 : 32 bit addressing , type IO, mask 0xff
Have a great day,
Yuri
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Thought I would also paste the linux demo code provided by freescale as well. Based on these comments and my experience, should we assume there is indeed a hardware issue with using BAR1, BAR3, BAR4 and BAR5?
/* 32bit none-prefetchable 8M bytes memory on bar0 */ | |
writel(0x0, dbi_base + PCI_BASE_ADDRESS_0); | |
writel(SZ_8M - 1, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_0); |
/* None used bar1 */ | |
writel(0x0, dbi_base + PCI_BASE_ADDRESS_1); | |
writel(0, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_1); |
/* 4K bytes IO on bar2 */ | |
writel(0x1, dbi_base + PCI_BASE_ADDRESS_2); | |
writel(SZ_4K - 1, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_2); |
/* | |
* 32bit prefetchable 1M bytes memory on bar3 | |
* FIXME BAR MASK3 is not changable, the size | |
* is fixed to 256 bytes. | |
*/ | |
writel(0x8, dbi_base + PCI_BASE_ADDRESS_3); | |
writel(SZ_1M - 1, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_3); |
/* | |
* 64bit prefetchable 1M bytes memory on bar4-5. | |
* FIXME BAR4,5 are not enabled yet | |
*/ | |
writel(0xc, dbi_base + PCI_BASE_ADDRESS_4); | |
writel(SZ_1M - 1, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_4); | |
writel(0, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_5); |