[PATCH] of: When constructing the bus id consider assigned-addresses as well

Jason Gunthorpe jgunthorpe at obsidianresearch.com
Fri Nov 30 06:38:29 EST 2012


On Thu, Nov 29, 2012 at 04:26:48PM +0000, Grant Likely wrote:

> Hmmm. okay that makes sense, but something still isn't quite right. So
> of_translate_address should take care of drilling down through the bus
> layers, and when it gets to the PCI node it /should/ use
> of_bus_pci_translate to handle traversing down to the parent node (which
> uses the 'assigned-addresses' for the pci node.

The address translation machinery requires PCI format addresses (ie
address-cells=3) for all nodes below a PCI bus. Part of this
requirement is that 'assigned-addresses' is used for resources, *not*
'reg'.

If you attempt to stick a 'reg' in a block nested below a
'device_type="pci"' the kernel throws lots of error messsages and
generates bad address mappings.

So, we are required to use'assigned-addresses' with the 5 word format
instead of reg. This seems to be a spec requirement for everything
below a PCI bus.

We end up with a DTS where the PCI bus and everything below it must
be described in the 5 word format that looks like this:

	pex at e0000000 { // <-- This is the PCI bus/controller node
		device_type = "pci";
		ranges = <0x02000000 0x00000000 0x00000000  0xe0000000  0x0 0x8000000>;
		soc at 0 { // <-- This is the actual PCI device
			ranges = <0x02000000 0x00000000 0x00000000  0x02000000 0x00000000 0x00000000  0x0 0x8000000>;
			gpio3: gpio at 8 { // <-- This is a platform device
			        #gpio-cells = <2>;
				compatible = "linux,basic-mmio-gpio";
				gpio-controller;
				reg-names = "dat", "set", "dirin";
				assigned-addresses = <0x02000000 0x0 0x8  0x0 4>,
				                     <0x02000000 0x0 0xc  0x0 4>,
				                     <0x02000000 0x0 0x10  0x0 4>;
			};

Which (when combined with the platform_device_add change) builds up an
iomem like:

e0000000-e7ffffff : PCIe 0 MEM
  e0000000-e000ffff : 0000:00:01.0
    e0000000-e0000fff : /pex at e0000000/soc at 0/control at 0
      e0000008-e000000b : dat
        e0000008-e000000b : dat
      e000000c-e000000f : set
        e000000c-e000000f : set
      e0000010-e0000013 : dirin
        e0000010-e0000013 : dirin

(I trimmed control at 0 node from the dts fragment, see other mails on
 the overlapping regions)

And a sysfs like this:

/sys/devices/pci0000:00/0000:00:01.0/e0000000.control
/sys/devices/pci0000:00/0000:00:01.0/e0000008.gpio

Without the patch the sysfs names will not have the address (gpio.0 or
whatever it is), but all other address calculations work correctly.

> However, in your case, of_device_make_bus_id() isn't using that code
> path and you're getting a generic name instead (with no relation to the
> device address).  Correct?

Right.
 
> If that is the case, then the solution is to figure out why
> of_translate_address() doesn't currently handle your situation and
> fix

of_translate_address works perfectly - resource records are
constructed correctly, for instance. The issue is that
of_device_make_bus_id() doesn't call it:

@@ -105,6 +105,8 @@ void of_device_make_bus_id(struct device *dev)
         * For MMIO, get the physical address
         */
        reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               reg = of_get_property(node, "assigned-addresses", NULL);
        if (reg) {
                if (of_can_translate_address(node)) {
                        addr = of_translate_address(node, reg);

ie what is happening is that of_device_make_bus_id *only* calls
*_translate_address if 'reg' is a property of the node. The patch
simply extends that to call if 'reg' or 'assigned-addresses' are a
property of the node. of_device_make_bus_id doesn't do anything with
the 'reg' variable other than test it against NULL.

Jason


More information about the devicetree-discuss mailing list