return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
 }
 
+static u8 mvebu_pcie_get_local_bus_nr(struct mvebu_pcie_port *port)
+{
+       return (mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_BUS) >> 8;
+}
+
 static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr)
 {
        u32 stat;
                *value = mvebu_readl(port, PCIE_CMD_OFF);
                break;
 
+       case PCI_PRIMARY_BUS: {
+               /*
+                * From the whole 32bit register we support reading from HW only
+                * secondary bus number which is mvebu local bus number.
+                * Other bits are retrieved only from emulated config buffer.
+                */
+               __le32 *cfgspace = (__le32 *)&bridge->conf;
+               u32 val = le32_to_cpu(cfgspace[PCI_PRIMARY_BUS / 4]);
+               val &= ~0xff00;
+               val |= mvebu_pcie_get_local_bus_nr(port) << 8;
+               *value = val;
+               break;
+       }
+
        default:
                return PCI_BRIDGE_EMUL_NOT_HANDLED;
        }
                break;
 
        case PCI_PRIMARY_BUS:
-               mvebu_pcie_set_local_bus_nr(port, conf->secondary_bus);
+               if (mask & 0xff00)
+                       mvebu_pcie_set_local_bus_nr(port, conf->secondary_bus);
                break;
 
        default:
                        continue;
                }
 
+               /*
+                * PCIe topology exported by mvebu hw is quite complicated. In
+                * reality has something like N fully independent host bridges
+                * where each host bridge has one PCIe Root Port (which acts as
+                * PCI Bridge device). Each host bridge has its own independent
+                * internal registers, independent access to PCI config space,
+                * independent interrupt lines, independent window and memory
+                * access configuration. But additionally there is some kind of
+                * peer-to-peer support between PCIe devices behind different
+                * host bridges limited just to forwarding of memory and I/O
+                * transactions (forwarding of error messages and config cycles
+                * is not supported). So we could say there are N independent
+                * PCIe Root Complexes.
+                *
+                * For this kind of setup DT should have been structured into
+                * N independent PCIe controllers / host bridges. But instead
+                * structure in past was defined to put PCIe Root Ports of all
+                * host bridges into one bus zero, like in classic multi-port
+                * Root Complex setup with just one host bridge.
+                *
+                * This means that pci-mvebu.c driver provides "virtual" bus 0
+                * on which registers all PCIe Root Ports (PCI Bridge devices)
+                * specified in DT by their BDF addresses and virtually routes
+                * PCI config access of each PCI bridge device to specific PCIe
+                * host bridge.
+                *
+                * Normally PCI Bridge should choose between Type 0 and Type 1
+                * config requests based on primary and secondary bus numbers
+                * configured on the bridge itself. But because mvebu PCI Bridge
+                * does not have registers for primary and secondary bus numbers
+                * in its config space, it determinates type of config requests
+                * via its own custom way.
+                *
+                * There are two options how mvebu determinate type of config
+                * request.
+                *
+                * 1. If Secondary Bus Number Enable bit is not set or is not
+                * available (applies for pre-XP PCIe controllers) then Type 0
+                * is used if target bus number equals Local Bus Number (bits
+                * [15:8] in register 0x1a04) and target device number differs
+                * from Local Device Number (bits [20:16] in register 0x1a04).
+                * Type 1 is used if target bus number differs from Local Bus
+                * Number. And when target bus number equals Local Bus Number
+                * and target device equals Local Device Number then request is
+                * routed to Local PCI Bridge (PCIe Root Port).
+                *
+                * 2. If Secondary Bus Number Enable bit is set (bit 7 in
+                * register 0x1a2c) then mvebu hw determinate type of config
+                * request like compliant PCI Bridge based on primary bus number
+                * which is configured via Local Bus Number (bits [15:8] in
+                * register 0x1a04) and secondary bus number which is configured
+                * via Secondary Bus Number (bits [7:0] in register 0x1a2c).
+                * Local PCI Bridge (PCIe Root Port) is available on primary bus
+                * as device with Local Device Number (bits [20:16] in register
+                * 0x1a04).
+                *
+                * Secondary Bus Number Enable bit is disabled by default and
+                * option 2. is not available on pre-XP PCIe controllers. Hence
+                * this driver always use option 1.
+                *
+                * Basically it means that primary and secondary buses shares
+                * one virtual number configured via Local Bus Number bits and
+                * Local Device Number bits determinates if accessing primary
+                * or secondary bus. Set Local Device Number to 1 and redirect
+                * all writes of PCI Bridge Secondary Bus Number register to
+                * Local Bus Number (bits [15:8] in register 0x1a04).
+                *
+                * So when accessing devices on buses behind secondary bus
+                * number it would work correctly. And also when accessing
+                * device 0 at secondary bus number via config space would be
+                * correctly routed to secondary bus. Due to issues described
+                * in mvebu_pcie_setup_hw(), PCI Bridges at primary bus (zero)
+                * are not accessed directly via PCI config space but rarher
+                * indirectly via kernel emulated PCI bridge driver.
+                */
                mvebu_pcie_setup_hw(port);
-               mvebu_pcie_set_local_dev_nr(port, 1);
+               mvebu_pcie_set_local_dev_nr(port, 0);
        }
 
        pcie->nports = i;