136d0d3b4SSimon Glass /*
236d0d3b4SSimon Glass * Copyright (c) 2014 Google, Inc
336d0d3b4SSimon Glass * Written by Simon Glass <sjg@chromium.org>
436d0d3b4SSimon Glass *
536d0d3b4SSimon Glass * SPDX-License-Identifier: GPL-2.0+
636d0d3b4SSimon Glass */
736d0d3b4SSimon Glass
836d0d3b4SSimon Glass #include <common.h>
936d0d3b4SSimon Glass #include <dm.h>
1036d0d3b4SSimon Glass #include <fdtdec.h>
11*0e00a84cSMasahiro Yamada #include <linux/libfdt.h>
1236d0d3b4SSimon Glass #include <pci.h>
1336d0d3b4SSimon Glass #include <dm/lists.h>
1436d0d3b4SSimon Glass
1536d0d3b4SSimon Glass DECLARE_GLOBAL_DATA_PTR;
1636d0d3b4SSimon Glass
1736d0d3b4SSimon Glass struct sandbox_pci_priv {
1836d0d3b4SSimon Glass int dev_count;
1936d0d3b4SSimon Glass };
2036d0d3b4SSimon Glass
sandbox_pci_get_emul(struct udevice * bus,pci_dev_t find_devfn,struct udevice ** emulp)2136d0d3b4SSimon Glass int sandbox_pci_get_emul(struct udevice *bus, pci_dev_t find_devfn,
2236d0d3b4SSimon Glass struct udevice **emulp)
2336d0d3b4SSimon Glass {
2436d0d3b4SSimon Glass struct udevice *dev;
2536d0d3b4SSimon Glass int ret;
2636d0d3b4SSimon Glass
2736d0d3b4SSimon Glass ret = pci_bus_find_devfn(bus, find_devfn, &dev);
2836d0d3b4SSimon Glass if (ret) {
2936d0d3b4SSimon Glass debug("%s: Could not find emulator for dev %x\n", __func__,
3036d0d3b4SSimon Glass find_devfn);
3136d0d3b4SSimon Glass return ret;
3236d0d3b4SSimon Glass }
3336d0d3b4SSimon Glass
3436d0d3b4SSimon Glass ret = device_find_first_child(dev, emulp);
3536d0d3b4SSimon Glass if (ret)
3636d0d3b4SSimon Glass return ret;
3736d0d3b4SSimon Glass
3836d0d3b4SSimon Glass return *emulp ? 0 : -ENODEV;
3936d0d3b4SSimon Glass }
4036d0d3b4SSimon Glass
sandbox_pci_emul_post_probe(struct udevice * dev)4136d0d3b4SSimon Glass static int sandbox_pci_emul_post_probe(struct udevice *dev)
4236d0d3b4SSimon Glass {
4336d0d3b4SSimon Glass struct sandbox_pci_priv *priv = dev->uclass->priv;
4436d0d3b4SSimon Glass
4536d0d3b4SSimon Glass priv->dev_count++;
4636d0d3b4SSimon Glass sandbox_set_enable_pci_map(true);
4736d0d3b4SSimon Glass
4836d0d3b4SSimon Glass return 0;
4936d0d3b4SSimon Glass }
5036d0d3b4SSimon Glass
sandbox_pci_emul_pre_remove(struct udevice * dev)5136d0d3b4SSimon Glass static int sandbox_pci_emul_pre_remove(struct udevice *dev)
5236d0d3b4SSimon Glass {
5336d0d3b4SSimon Glass struct sandbox_pci_priv *priv = dev->uclass->priv;
5436d0d3b4SSimon Glass
5536d0d3b4SSimon Glass priv->dev_count--;
5636d0d3b4SSimon Glass sandbox_set_enable_pci_map(priv->dev_count > 0);
5736d0d3b4SSimon Glass
5836d0d3b4SSimon Glass return 0;
5936d0d3b4SSimon Glass }
6036d0d3b4SSimon Glass
6136d0d3b4SSimon Glass UCLASS_DRIVER(pci_emul) = {
6236d0d3b4SSimon Glass .id = UCLASS_PCI_EMUL,
6336d0d3b4SSimon Glass .name = "pci_emul",
6436d0d3b4SSimon Glass .post_probe = sandbox_pci_emul_post_probe,
6536d0d3b4SSimon Glass .pre_remove = sandbox_pci_emul_pre_remove,
6636d0d3b4SSimon Glass .priv_auto_alloc_size = sizeof(struct sandbox_pci_priv),
6736d0d3b4SSimon Glass };
68