On Sunday 26 September 2021 00:54:42 Marek Behún wrote:
> @@ -355,20 +369,55 @@ static int pcie_advk_read_config(const struct udevice 
> *bus, pci_dev_t bdf,
>                                enum pci_size_t size)
>  {
>       struct pcie_advk *pcie = dev_get_priv(bus);
> +     int busno = PCI_BUS(bdf) - dev_seq(bus);
>       int retry_count;
>       bool allow_crs;
> +     ulong data;
>       uint reg;
>       int ret;
>  
>       dev_dbg(pcie->dev, "PCIE CFG read:  (b,d,f)=(%2d,%2d,%2d) ",
>               PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
>  
> -     if (!pcie_advk_addr_valid(bdf, pcie->first_busno)) {
> +     if (!pcie_advk_addr_valid(pcie, busno, PCI_DEV(bdf), PCI_FUNC(bdf))) {
>               dev_dbg(pcie->dev, "- out of range\n");
>               *valuep = pci_get_ff(size);
>               return 0;
>       }
>  
> +     /*
> +      * The configuration space of the PCI Bridge on primary (local) bus is
> +      * not accessible via PIO transfers like all other PCIe devices. PCI
> +      * Bridge config registers are available directly in Aardvark memory
> +      * space starting at offset zero. Moreover PCI Bridge registers in the
> +      * range 0x10 - 0x34 are not available and register 0x38 (Expansion ROM
> +      * Base Address) is at offset 0x30.
> +      * We therefore read configuration space content of the primary PCI
> +      * Bridge from our virtual cache.
> +      */
> +     if (busno == pcie->first_busno) {
> +             if (offset >= 0x10 && offset < 0x34)
> +                     data = pcie->cfgcache[(offset - 0x10) / 4];
> +             else if ((offset & ~3) == PCI_ROM_ADDRESS1)
> +                     data = advk_readl(pcie, PCIE_CORE_EXP_ROM_BAR_REG);
> +             else
> +                     data = advk_readl(pcie, offset & ~3);
> +
> +             if ((offset & ~3) == (PCI_HEADER_TYPE & ~3)) {
> +                     /*
> +                      * Change Header Type of PCI Bridge device to Type 1
> +                      * (0x01, used by PCI Bridges) because hardwired value
> +                      * is Type 0 (0x00, used by Endpoint devices).
> +                      */
> +                     data &= ~0x00ff0000;
                                     ^^
There is a small mistake. Header Type is 7-bit value. Upper 8th bit
indicates if device is multifunction. So correct mask should be:

                        data &= ~0x007f0000;

> +                     data |= PCI_HEADER_TYPE_BRIDGE << 16;
> +             }
> +
> +             *valuep = pci_conv_32_to_size(data, offset, size);
> +
> +             return 0;
> +     }
> +
>       /*
>        * Returning fabricated CRS value (0xFFFF0001) by PCIe Root Complex to
>        * OS is allowed only for 4-byte PCI_VENDOR_ID config read request and

Reply via email to