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.

AM5749: PCIe endpoint BAR4 containing bad value

Part Number: AM5749

I have an AM5749 on a custom board (SOM + custom board) that is plugging into a host PC as root complex with the device in endpoint mode.

I have a Linux endpoint driver that is able to establish the link and configure the first four bars (BAR0 through BAR3) and I am not attempting to use BAR4 or BAR5.  Yet the value for BAR4 as seen from the host is 0x0000008 which apparently means prefetchable but otherwise unassigned.  Using "lspci" from the Linux host reports "Region 4: Memory at <unassigned> (32-bit, prefetchable)".  Using EFI shell from BIOS reports the value 0x00000008.

This is not a major issue when the host PC is Linux, but for a Windows host I believe this is causing some heartburn.  I think it can be overcome and I am exploring that option but I would prefer to fix it on the endpoint side if possible.

My first question is, is this normal?

I am not an expert when it comes to the software stack, but I had tried pci_epc_clear_bar on BAR4 and BAR5 within the EPF bind operation and it had no effect. 

Where should I be looking to either avoid assigning the incorrect value, or try to overwrite the incorrect value with all zeroes?

  • Jamie, 

    Since BAR4 and BAR5 is unused, you can disable them from the EP device software, via the DIF interface. Refer to 

         24.9.4.9.3 Base Address Registers (BAR) Initialization

    of the TRM for some background. Register you will need to write is:

    PCIECTRL_EP_DBICS2_BAR4_MASK, and need to enable DBICS2 interface to write this register. 

    please reply back if further clarification is needed. 

    jian

  • Believe it or not, this has been immensely helpful.  I was looking in this direction but with low confidence, and this allowed me to focus my attention without worrying that I was in the wrong area.

    On BAR4 it appears that I can't set the MASK to zero without the BAR changing from 0 to 8.  This is true for BAR0 and BAR2 and BAR4 but not for BAR1, BAR3, or BAR5.  Strange.  I have tried multiple different sequences and none seem to allow me to have mask and BAR equal to zero.

    I am conducting these experiments within the u-boot secondary bootloader.  Within the Linux driver it is not as direct and so much less clear what function is having what effect.

    I tried this sequence on all six bars:

    1. Print out the initial BAR and MASK value
    2. Assign BAR = 0x00F00000
    3. Assign MASK = 0x00001FFF
    4. Print out BAR  (point 1)  (always 0x00F00000)
    5. Assign MASK = 0
    6. Print out BAR (point 2)  (sometimes 0, sometimes 8)
    7. Assign BAR = 0
    8. Print out BAR (point 3)  (no effect, either 0 or 8 unchanged from 6 above)
    9. Assign MASK = 0x00001FFF
    10. Print out BAR (point 4)  (always 8)
    11. Assign BAR = 0x00F00000
    12. Print out BAR (point 5)  (always 0x00F00000)

    I suppose it makes sense that if the BAR is 0 and the MASK changes from 0 to 1FFF (enable changes from 0 to 1) that the BAR would be initialized to some standard value.  What I don't understand is why it seems impossible to have MASK = 0 and BAR = 0 for BAR0, BAR2, and BAR4.  Or at least I have not found a sequence that can achieve it.

    I think I have a workaround, since I am only using BAR0, BAR1, and BAR2, I can assign an extra nonempty BAR to BAR4 which should stop the Windows RC from complaining.  I gather from the YouTube video on the Sitara PCIe EP mode that four BARs are permitted.  I don't fully understand the "inbound window" limitation but it sounds like I don't need to.  I will try a small region for BAR4.

    Below is a code fragment from the test program that checks all 6 BARs (runs as part of u-boot), and below that is the output that I captured from the UART/serial.

    I'll post back if my workaround is successful, or if it isn't I assume I'll have something more specific to ask.

    Thanks again,

    -Jamie


    printf("pre PCIECTRL_EP_DBICS_BAR0 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR0));
    printf("pre PCIECTRL_EP_DBICS2_BAR0_MASK = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS2_BAR0_MASK));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR0, 0x00F00000);
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR0_MASK, 0x00001FFF);
    printf("point 1 PCIECTRL_EP_DBICS_BAR0 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR0));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR0_MASK, 0x00000000);
    printf("point 2 PCIECTRL_EP_DBICS_BAR0 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR0));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR0, 0x00000000);
    printf("point 3 PCIECTRL_EP_DBICS_BAR0 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR0));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR0_MASK, 0x00001FFF);
    printf("point 4 PCIECTRL_EP_DBICS_BAR0 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR0));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR0, 0x00F00000);
    printf("point 5 PCIECTRL_EP_DBICS_BAR0 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR0));

    printf("pre PCIECTRL_EP_DBICS_BAR1 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR1));
    printf("pre PCIECTRL_EP_DBICS2_BAR1_MASK = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS2_BAR1_MASK));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR1, 0x00F00000);
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR1_MASK, 0x00001FFF);
    printf("point 1 PCIECTRL_EP_DBICS_BAR1 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR1));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR1_MASK, 0x00000000);
    printf("point 2 PCIECTRL_EP_DBICS_BAR1 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR1));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR1, 0x00000000);
    printf("point 3 PCIECTRL_EP_DBICS_BAR1 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR1));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR1_MASK, 0x00001FFF);
    printf("point 4 PCIECTRL_EP_DBICS_BAR1 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR1));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR1, 0x00F00000);
    printf("point 5 PCIECTRL_EP_DBICS_BAR1 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR1));

    printf("pre PCIECTRL_EP_DBICS_BAR2 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR2));
    printf("pre PCIECTRL_EP_DBICS2_BAR2_MASK = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS2_BAR2_MASK));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR2, 0x00F00000);
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR2_MASK, 0x00001FFF);
    printf("point 1 PCIECTRL_EP_DBICS_BAR2 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR2));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR2_MASK, 0x00000000);
    printf("point 2 PCIECTRL_EP_DBICS_BAR2 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR2));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR2, 0x00000000);
    printf("point 3 PCIECTRL_EP_DBICS_BAR2 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR2));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR2_MASK, 0x00001FFF);
    printf("point 4 PCIECTRL_EP_DBICS_BAR2 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR2));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR2, 0x00F00000);
    printf("point 5 PCIECTRL_EP_DBICS_BAR2 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR2));

    printf("pre PCIECTRL_EP_DBICS_BAR3 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR3));
    printf("pre PCIECTRL_EP_DBICS2_BAR3_MASK = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS2_BAR3_MASK));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR3, 0x00F00000);
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR3_MASK, 0x00001FFF);
    printf("point 1 PCIECTRL_EP_DBICS_BAR3 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR3));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR3_MASK, 0x00000000);
    printf("point 2 PCIECTRL_EP_DBICS_BAR3 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR3));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR3, 0x00000000);
    printf("point 3 PCIECTRL_EP_DBICS_BAR3 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR3));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR3_MASK, 0x00001FFF);
    printf("point 4 PCIECTRL_EP_DBICS_BAR3 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR3));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR3, 0x00F00000);
    printf("point 5 PCIECTRL_EP_DBICS_BAR3 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR3));

    printf("pre PCIECTRL_EP_DBICS_BAR4 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR4));
    printf("pre PCIECTRL_EP_DBICS2_BAR4_MASK = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS2_BAR4_MASK));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR4, 0x00F00000);
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR4_MASK, 0x00001FFF);
    printf("point 1 PCIECTRL_EP_DBICS_BAR4 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR4));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR4_MASK, 0x00000000);
    printf("point 2 PCIECTRL_EP_DBICS_BAR4 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR4));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR4, 0x00000000);
    printf("point 3 PCIECTRL_EP_DBICS_BAR4 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR4));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR4_MASK, 0x00001FFF);
    printf("point 4 PCIECTRL_EP_DBICS_BAR4 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR4));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR4, 0x00F00000);
    printf("point 5 PCIECTRL_EP_DBICS_BAR4 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR4));

    printf("pre PCIECTRL_EP_DBICS_BAR5 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR5));
    printf("pre PCIECTRL_EP_DBICS2_BAR5_MASK = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS2_BAR5_MASK));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR5, 0x00F00000);
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR5_MASK, 0x00001FFF);
    printf("point 1 PCIECTRL_EP_DBICS_BAR5 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR5));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR5_MASK, 0x00000000);
    printf("point 2 PCIECTRL_EP_DBICS_BAR5 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR5));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR5, 0x00000000);
    printf("point 3 PCIECTRL_EP_DBICS_BAR5 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR5));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS2_BAR5_MASK, 0x00001FFF);
    printf("point 4 PCIECTRL_EP_DBICS_BAR5 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR5));
    HW_WR_REG32(baseAddr + PCIECTRL_EP_DBICS_BAR5, 0x00F00000);
    printf("point 5 PCIECTRL_EP_DBICS_BAR5 = 0x%X\n", HW_RD_REG32(PCIECTRL_EP_DBICS_BASE + PCIECTRL_EP_DBICS_BAR5));

     


    pre PCIECTRL_EP_DBICS_BAR0 = 0x8
    pre PCIECTRL_EP_DBICS2_BAR0_MASK = 0x8
    WRITE addr: 0x51000010 value: 0x00f00000
    WRITE addr: 0x51001010 value: 0x00001fff
    point 1 PCIECTRL_EP_DBICS_BAR0 = 0xF00000
    WRITE addr: 0x51001010 value: 0x00000000
    point 2 PCIECTRL_EP_DBICS_BAR0 = 0x8
    WRITE addr: 0x51000010 value: 0x00000000
    point 3 PCIECTRL_EP_DBICS_BAR0 = 0x8
    WRITE addr: 0x51001010 value: 0x00001fff
    point 4 PCIECTRL_EP_DBICS_BAR0 = 0x8
    WRITE addr: 0x51000010 value: 0x00f00000
    point 5 PCIECTRL_EP_DBICS_BAR0 = 0xF00000

    pre PCIECTRL_EP_DBICS_BAR1 = 0x8
    pre PCIECTRL_EP_DBICS2_BAR1_MASK = 0x8
    WRITE addr: 0x51000014 value: 0x00f00000
    WRITE addr: 0x51001014 value: 0x00001fff
    point 1 PCIECTRL_EP_DBICS_BAR1 = 0xF00000
    WRITE addr: 0x51001014 value: 0x00000000
    point 2 PCIECTRL_EP_DBICS_BAR1 = 0x0
    WRITE addr: 0x51000014 value: 0x00000000
    point 3 PCIECTRL_EP_DBICS_BAR1 = 0x0
    WRITE addr: 0x51001014 value: 0x00001fff
    point 4 PCIECTRL_EP_DBICS_BAR1 = 0x8
    WRITE addr: 0x51000014 value: 0x00f00000
    point 5 PCIECTRL_EP_DBICS_BAR1 = 0xF00000

    pre PCIECTRL_EP_DBICS_BAR2 = 0x8
    pre PCIECTRL_EP_DBICS2_BAR2_MASK = 0x8
    WRITE addr: 0x51000018 value: 0x00f00000
    WRITE addr: 0x51001018 value: 0x00001fff
    point 1 PCIECTRL_EP_DBICS_BAR2 = 0xF00000
    WRITE addr: 0x51001018 value: 0x00000000
    point 2 PCIECTRL_EP_DBICS_BAR2 = 0x8
    WRITE addr: 0x51000018 value: 0x00000000
    point 3 PCIECTRL_EP_DBICS_BAR2 = 0x8
    WRITE addr: 0x51001018 value: 0x00001fff
    point 4 PCIECTRL_EP_DBICS_BAR2 = 0x8
    WRITE addr: 0x51000018 value: 0x00f00000
    point 5 PCIECTRL_EP_DBICS_BAR2 = 0xF00000

    pre PCIECTRL_EP_DBICS_BAR3 = 0x8
    pre PCIECTRL_EP_DBICS2_BAR3_MASK = 0x8
    WRITE addr: 0x5100001c value: 0x00f00000
    WRITE addr: 0x5100101c value: 0x00001fff
    point 1 PCIECTRL_EP_DBICS_BAR3 = 0xF00000
    WRITE addr: 0x5100101c value: 0x00000000
    point 2 PCIECTRL_EP_DBICS_BAR3 = 0x0
    WRITE addr: 0x5100001c value: 0x00000000
    point 3 PCIECTRL_EP_DBICS_BAR3 = 0x0
    WRITE addr: 0x5100101c value: 0x00001fff
    point 4 PCIECTRL_EP_DBICS_BAR3 = 0x8
    WRITE addr: 0x5100001c value: 0x00f00000
    point 5 PCIECTRL_EP_DBICS_BAR3 = 0xF00000

    pre PCIECTRL_EP_DBICS_BAR4 = 0x8
    pre PCIECTRL_EP_DBICS2_BAR4_MASK = 0x8
    WRITE addr: 0x51000020 value: 0x00f00000
    WRITE addr: 0x51001020 value: 0x00001fff
    point 1 PCIECTRL_EP_DBICS_BAR4 = 0xF00000
    WRITE addr: 0x51001020 value: 0x00000000
    point 2 PCIECTRL_EP_DBICS_BAR4 = 0x8
    WRITE addr: 0x51000020 value: 0x00000000
    point 3 PCIECTRL_EP_DBICS_BAR4 = 0x8
    WRITE addr: 0x51001020 value: 0x00001fff
    point 4 PCIECTRL_EP_DBICS_BAR4 = 0x8
    WRITE addr: 0x51000020 value: 0x00f00000
    point 5 PCIECTRL_EP_DBICS_BAR4 = 0xF00000

    pre PCIECTRL_EP_DBICS_BAR5 = 0x8
    pre PCIECTRL_EP_DBICS2_BAR5_MASK = 0x8
    WRITE addr: 0x51000024 value: 0x00f00000
    WRITE addr: 0x51001024 value: 0x00001fff
    point 1 PCIECTRL_EP_DBICS_BAR5 = 0xF00000
    WRITE addr: 0x51001024 value: 0x00000000
    point 2 PCIECTRL_EP_DBICS_BAR5 = 0x0
    WRITE addr: 0x51000024 value: 0x00000000
    point 3 PCIECTRL_EP_DBICS_BAR5 = 0x0
    WRITE addr: 0x51001024 value: 0x00001fff
    point 4 PCIECTRL_EP_DBICS_BAR5 = 0x8
    WRITE addr: 0x51000024 value: 0x00f00000
    point 5 PCIECTRL_EP_DBICS_BAR5 = 0xF00000

     

  • I can confirm that by allocating a small (1024 byte) BAR to BAR4, I can avoid the issue with the BAR value of 0x00000008, and Windows is much happier.

    No workarounds are needed within Windows to try to modify the resource list (which is a good thing because the Windows driver workaround didn't seem to be working.)

    It is still a puzzle as to why it was impossible to give BAR4 a value of 0.  But anyway my problem is solved.

    Thank you.