[PATCH v2 19/27] pci: PCIe driver for Marvell Armada 370/XP systems

Thomas Petazzoni thomas.petazzoni at free-electrons.com
Tue Jan 29 10:10:40 EST 2013

Dear Thierry Reding,

On Tue, 29 Jan 2013 16:02:01 +0100, Thierry Reding wrote:

> Now that I think about it, there were a few more changes needed.
> For one, the reg property of the root port nodes need to be in the
> format specified by the PCI DT binding. That is, 3 cells for the
> address and 2 cells for the size.
> So I end up with something like this:
> 	pcie-controller {
> 		...
> 		ranges = <0x00000800 0 0x80000000 0x80000000 0 0x00001000 /* port 0 registers */
> 			  0x00001000 0 0x80001000 0x80001000 0 0x00001000 /* port 1 registers */
> 			  ...>;
> 		pci at 1,0 {
> 			reg = <0x000800 0 0x80000000 0 0x1000>;
> 			...
> 		};
> 		pci at 2,0 {
> 			reg = <0x001000 0 0x80001000 0 0x1000>;
> 			...
> 		};
> 	};
> So what happens here is that for each root port (pci at 1,0 and pci at 2,0),
> the reg property is translated into the parent address space via the
> pcie-controller's ranges property. pci at 1,0 gets the memory region
> 0x80000000-0x80000fff and pci at 2,0 gets 0x80001000-0x80001fff. (These are
> actually windows through which the configuration space of the root ports
> is accessed.)
> At the same time this reg property maps both devices into the PCI
> address space at addresses 0:01.0 and 0:02.0 respectively.

This part I think I've done exactly the same thing in the Marvell PCIe
DT binding.

> The second change is that you can't rely on ARM's default implementation
> of the bus scan operation, which calls pci_scan_root_bus(), passing in a
> NULL as the struct device which acts as the bus' parent. So on Tegra I
> added a custom implementation which calls pci_create_root_bus(), passing
> in the struct device of the PCI host bridge, whose .of_node field will
> be set to the pcie-controller node above. Incidentally this also fixed
> another issue where the PCI core and ARM's pci_common_init() both
> eventually end up calling pci_bus_add_devices(). I don't remember the
> exact symptoms but I think this was causing resource conflicts during
> the second enumeration or so.
> Because a proper struct device with the correct .of_node field is passed
> into pci_create_root_bus(), the generic pcibios_get_phb_of_node() will
> know how to find it by looking at bus->bridge->parent->of_node. After
> that the generic matching code will search the bridge (pcie-controller)
> node's children and relate them to the struct pci_dev by devfn. This is
> done in pci_set_of_node() defined in drivers/pci/of.c, which calls
> of_pci_find_child_device() from drivers/of/of_pci.c.

This is quite certainly the part that I was missing. I'll try this and
let you know.

Thanks a lot for the lengthy, but very useful explanation!

Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.

More information about the linux-arm-kernel mailing list