IMX6 PCIe EP Cannot configure BAR1

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

IMX6 PCIe EP Cannot configure BAR1

1,904 Views
elijahbrown
Contributor III

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.

Labels (3)
0 Kudos
4 Replies

1,188 Views
elijahbrown
Contributor III

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?

0 Kudos

1,188 Views
Yuri
NXP Employee
NXP Employee

Hello,

the information from R&D is declared as non-documented feature.

Please let me know if it helps.

Regards,

Yuri.

0 Kudos

1,188 Views
Yuri
NXP Employee
NXP Employee

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!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,188 Views
elijahbrown
Contributor III

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);
0 Kudos