diff mbox

[U-Boot,06/23] pci: Set of_offset for devices not probed via DT compatible strings

Message ID 20160926182917.27531-7-paul.burton@imgtec.com
State Deferred
Delegated to: Daniel Schwierzeck
Headers show

Commit Message

Paul Burton Sept. 26, 2016, 6:29 p.m. UTC
A PCI device may be probed through standard PCI config space probing but
still be represented in a device tree. However U-Boot would not
previously set the of_offset field of the struct udevice for such PCI
devices. Fix this by searching for a DT node based upon its "reg"
property after binding a PCI device that wasn't already seen in the DT.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>

---

 drivers/pci/pci-uclass.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

Comments

Simon Glass Sept. 27, 2016, 12:35 a.m. UTC | #1
Hi Paul,

On 26 September 2016 at 12:29, Paul Burton <paul.burton@imgtec.com> wrote:
> A PCI device may be probed through standard PCI config space probing but
> still be represented in a device tree. However U-Boot would not
> previously set the of_offset field of the struct udevice for such PCI
> devices. Fix this by searching for a DT node based upon its "reg"
> property after binding a PCI device that wasn't already seen in the DT.
>
> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
>
> ---
>
>  drivers/pci/pci-uclass.c | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)

I can't see how this can happen. The PCI binding is supposed to
operate using the device tree:

/* Find this device in the device tree */
ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev);

Do you know what is going wrong?

Regards,
Simon
diff mbox

Patch

diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 3b00e6a..415c632 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -670,6 +670,33 @@  error:
 	return ret;
 }
 
+static int find_pci_of_offset(struct udevice *bus, struct udevice *dev,
+			      pci_dev_t bdf)
+{
+	struct fdt_pci_addr addr;
+	int offset, err;
+
+	if (bus->of_offset == -1)
+		return -ENOENT;
+
+	fdt_for_each_subnode(gd->fdt_blob, offset, bus->of_offset) {
+		err = fdtdec_get_pci_addr(gd->fdt_blob, offset,
+					  FDT_PCI_SPACE_CONFIG, "reg", &addr);
+		if (err == -ENOENT)
+			continue;
+		if (err)
+			return err;
+
+		if (bdf != (addr.phys_hi & 0xffff00))
+			continue;
+
+		dev->of_offset = offset;
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
 int pci_bind_bus_devices(struct udevice *bus)
 {
 	ulong vendor, device;
@@ -731,6 +758,11 @@  int pci_bind_bus_devices(struct udevice *bus)
 			}
 			ret = pci_find_and_bind_driver(bus, &find_id, bdf,
 						       &dev);
+			if (!ret) {
+				ret = find_pci_of_offset(bus, dev, bdf);
+				if (ret == -ENOENT)
+					ret = 0;
+			}
 		}
 		if (ret == -EPERM)
 			continue;