imx: imx8qm/qxp: check whether m4 partition booted
[oweals/u-boot.git] / drivers / pci / pci_sandbox.c
index 6de5130c2a89748a87a683c1e35614ed1b9d0aed..fa4c47659787e5b47ac20503ed8073f976a5e1f2 100644 (file)
@@ -1,28 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 2014 Google, Inc
  * Written by Simon Glass <sjg@chromium.org>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
 #include <dm.h>
 #include <fdtdec.h>
-#include <inttypes.h>
 #include <pci.h>
-#include <dm/root.h>
 
-DECLARE_GLOBAL_DATA_PTR;
+#define FDT_DEV_INFO_CELLS     4
+#define FDT_DEV_INFO_SIZE      (FDT_DEV_INFO_CELLS * sizeof(u32))
+
+#define SANDBOX_PCI_DEVFN(d, f)        ((d << 3) | f)
+
+struct sandbox_pci_priv {
+       struct {
+               u16 vendor;
+               u16 device;
+       } vendev[256];
+};
 
 static int sandbox_pci_write_config(struct udevice *bus, pci_dev_t devfn,
                                    uint offset, ulong value,
                                    enum pci_size_t size)
 {
        struct dm_pci_emul_ops *ops;
-       struct udevice *emul;
+       struct udevice *container, *emul;
        int ret;
 
-       ret = sandbox_pci_get_emul(bus, devfn, &emul);
+       ret = sandbox_pci_get_emul(bus, devfn, &container, &emul);
        if (ret)
                return ret == -ENODEV ? 0 : ret;
        ops = pci_get_emul_ops(emul);
@@ -32,19 +39,36 @@ static int sandbox_pci_write_config(struct udevice *bus, pci_dev_t devfn,
        return ops->write_config(emul, offset, value, size);
 }
 
-static int sandbox_pci_read_config(struct udevice *bus, pci_dev_t devfn,
+static int sandbox_pci_read_config(const struct udevice *bus, pci_dev_t devfn,
                                   uint offset, ulong *valuep,
                                   enum pci_size_t size)
 {
        struct dm_pci_emul_ops *ops;
-       struct udevice *emul;
+       struct udevice *container, *emul;
+       struct sandbox_pci_priv *priv = dev_get_priv(bus);
        int ret;
 
        /* Prepare the default response */
        *valuep = pci_get_ff(size);
-       ret = sandbox_pci_get_emul(bus, devfn, &emul);
-       if (ret)
-               return ret == -ENODEV ? 0 : ret;
+       ret = sandbox_pci_get_emul(bus, devfn, &container, &emul);
+       if (ret) {
+               if (!container) {
+                       u16 vendor, device;
+
+                       devfn = SANDBOX_PCI_DEVFN(PCI_DEV(devfn),
+                                                 PCI_FUNC(devfn));
+                       vendor = priv->vendev[devfn].vendor;
+                       device = priv->vendev[devfn].device;
+                       if (offset == PCI_VENDOR_ID && vendor)
+                               *valuep = vendor;
+                       else if (offset == PCI_DEVICE_ID && device)
+                               *valuep = device;
+
+                       return 0;
+               } else {
+                       return ret == -ENODEV ? 0 : ret;
+               }
+       }
        ops = pci_get_emul_ops(emul);
        if (!ops || !ops->read_config)
                return -ENOSYS;
@@ -52,10 +76,39 @@ static int sandbox_pci_read_config(struct udevice *bus, pci_dev_t devfn,
        return ops->read_config(emul, offset, valuep, size);
 }
 
-static int sandbox_pci_child_post_bind(struct udevice *dev)
+static int sandbox_pci_probe(struct udevice *dev)
 {
-       /* Attach an emulator if we can */
-       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+       struct sandbox_pci_priv *priv = dev_get_priv(dev);
+       const fdt32_t *cell;
+       u8 pdev, pfn, devfn;
+       int len;
+
+       cell = ofnode_get_property(dev_ofnode(dev), "sandbox,dev-info", &len);
+       if (!cell)
+               return 0;
+
+       if ((len % FDT_DEV_INFO_SIZE) == 0) {
+               int num = len / FDT_DEV_INFO_SIZE;
+               int i;
+
+               for (i = 0; i < num; i++) {
+                       debug("dev info #%d: %02x %02x %04x %04x\n", i,
+                             fdt32_to_cpu(cell[0]), fdt32_to_cpu(cell[1]),
+                             fdt32_to_cpu(cell[2]), fdt32_to_cpu(cell[3]));
+
+                       pdev = fdt32_to_cpu(cell[0]);
+                       pfn = fdt32_to_cpu(cell[1]);
+                       if (pdev > 31 || pfn > 7)
+                               continue;
+                       devfn = SANDBOX_PCI_DEVFN(pdev, pfn);
+                       priv->vendev[devfn].vendor = fdt32_to_cpu(cell[2]);
+                       priv->vendev[devfn].device = fdt32_to_cpu(cell[3]);
+
+                       cell += FDT_DEV_INFO_CELLS;
+               }
+       }
+
+       return 0;
 }
 
 static const struct dm_pci_ops sandbox_pci_ops = {
@@ -73,7 +126,11 @@ U_BOOT_DRIVER(pci_sandbox) = {
        .id     = UCLASS_PCI,
        .of_match = sandbox_pci_ids,
        .ops    = &sandbox_pci_ops,
-       .child_post_bind = sandbox_pci_child_post_bind,
+       .probe  = sandbox_pci_probe,
+       .priv_auto_alloc_size = sizeof(struct sandbox_pci_priv),
+
+       /* Attach an emulator if we can */
+       .child_post_bind = dm_scan_fdt_dev,
        .per_child_platdata_auto_alloc_size =
                        sizeof(struct pci_child_platdata),
 };