pci: sandbox: Move the emulators into their own node
[oweals/u-boot.git] / drivers / pci / pci-emul-uclass.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2014 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <fdtdec.h>
10 #include <linux/libfdt.h>
11 #include <pci.h>
12 #include <dm/lists.h>
13 #include <dm/uclass-internal.h>
14
15 struct sandbox_pci_emul_priv {
16         int dev_count;
17 };
18
19 int sandbox_pci_get_emul(struct udevice *bus, pci_dev_t find_devfn,
20                          struct udevice **containerp, struct udevice **emulp)
21 {
22         struct udevice *dev;
23         int ret;
24
25         *containerp = NULL;
26         ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(find_devfn), &dev);
27         if (ret) {
28                 debug("%s: Could not find emulator for dev %x\n", __func__,
29                       find_devfn);
30                 return ret;
31         }
32         *containerp = dev;
33
34         /*
35          * See commit 4345998ae9df,
36          * "pci: sandbox: Support dynamically binding device driver"
37          */
38         ret = uclass_find_device_by_phandle(UCLASS_PCI_EMUL, dev,
39                                             "sandbox,emul", emulp);
40         if (ret && device_get_uclass_id(dev) != UCLASS_PCI_GENERIC)
41                 *emulp = dev;
42
43         return *emulp ? 0 : -ENODEV;
44 }
45
46 static int sandbox_pci_emul_post_probe(struct udevice *dev)
47 {
48         struct sandbox_pci_emul_priv *priv = dev->uclass->priv;
49
50         priv->dev_count++;
51         sandbox_set_enable_pci_map(true);
52
53         return 0;
54 }
55
56 static int sandbox_pci_emul_pre_remove(struct udevice *dev)
57 {
58         struct sandbox_pci_emul_priv *priv = dev->uclass->priv;
59
60         priv->dev_count--;
61         sandbox_set_enable_pci_map(priv->dev_count > 0);
62
63         return 0;
64 }
65
66 UCLASS_DRIVER(pci_emul) = {
67         .id             = UCLASS_PCI_EMUL,
68         .name           = "pci_emul",
69         .post_probe     = sandbox_pci_emul_post_probe,
70         .pre_remove     = sandbox_pci_emul_pre_remove,
71         .priv_auto_alloc_size   = sizeof(struct sandbox_pci_emul_priv),
72 };
73
74 /*
75  * This uclass is a child of the pci bus. Its platdata is not defined here so
76  * is defined by its parent, UCLASS_PCI, which uses struct pci_child_platdata.
77  * See per_child_platdata_auto_alloc_size in UCLASS_DRIVER(pci).
78  */
79 UCLASS_DRIVER(pci_emul_parent) = {
80         .id             = UCLASS_PCI_EMUL_PARENT,
81         .name           = "pci_emul_parent",
82         .post_bind      = dm_scan_fdt_dev,
83 };
84
85 static const struct udevice_id pci_emul_parent_ids[] = {
86         { .compatible = "sandbox,pci-emul-parent" },
87         { }
88 };
89
90 U_BOOT_DRIVER(pci_emul_parent_drv) = {
91         .name           = "pci_emul_parent_drv",
92         .id             = UCLASS_PCI_EMUL_PARENT,
93         .of_match       = pci_emul_parent_ids,
94 };