uboot/drivers/pci/pci-emul-uclass.c
<<
>>
Prefs
   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 <log.h>
  11#include <linux/libfdt.h>
  12#include <pci.h>
  13#include <dm/lists.h>
  14
  15struct sandbox_pci_emul_priv {
  16        int dev_count;
  17};
  18
  19int sandbox_pci_get_emul(const struct udevice *bus, pci_dev_t find_devfn,
  20                         struct udevice **containerp, struct udevice **emulp)
  21{
  22        struct pci_emul_uc_priv *upriv;
  23        struct udevice *dev;
  24        int ret;
  25
  26        *containerp = NULL;
  27        ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(find_devfn), &dev);
  28        if (ret) {
  29                debug("%s: Could not find emulator for dev %x\n", __func__,
  30                      find_devfn);
  31                return ret;
  32        }
  33        *containerp = dev;
  34
  35        ret = uclass_get_device_by_phandle(UCLASS_PCI_EMUL, dev, "sandbox,emul",
  36                                           emulp);
  37        if (!ret) {
  38                upriv = dev_get_uclass_priv(*emulp);
  39
  40                upriv->client = dev;
  41        } else if (device_get_uclass_id(dev) != UCLASS_PCI_GENERIC) {
  42                /*
  43                 * See commit 4345998ae9df,
  44                 * "pci: sandbox: Support dynamically binding device driver"
  45                 */
  46                *emulp = dev;
  47        }
  48
  49        return 0;
  50}
  51
  52int sandbox_pci_get_client(struct udevice *emul, struct udevice **devp)
  53{
  54        struct pci_emul_uc_priv *upriv = dev_get_uclass_priv(emul);
  55
  56        if (!upriv->client)
  57                return -ENOENT;
  58        *devp = upriv->client;
  59
  60        return 0;
  61}
  62
  63uint sandbox_pci_read_bar(u32 barval, int type, uint size)
  64{
  65        u32 result;
  66
  67        result = barval;
  68        if (result == 0xffffffff) {
  69                if (type == PCI_BASE_ADDRESS_SPACE_IO) {
  70                        result = (~(size - 1) &
  71                                PCI_BASE_ADDRESS_IO_MASK) |
  72                                PCI_BASE_ADDRESS_SPACE_IO;
  73                } else {
  74                        result = (~(size - 1) &
  75                                PCI_BASE_ADDRESS_MEM_MASK) |
  76                                PCI_BASE_ADDRESS_MEM_TYPE_32;
  77                }
  78        }
  79
  80        return result;
  81}
  82
  83static int sandbox_pci_emul_post_probe(struct udevice *dev)
  84{
  85        struct sandbox_pci_emul_priv *priv = dev->uclass->priv;
  86
  87        priv->dev_count++;
  88        sandbox_set_enable_pci_map(true);
  89
  90        return 0;
  91}
  92
  93static int sandbox_pci_emul_pre_remove(struct udevice *dev)
  94{
  95        struct sandbox_pci_emul_priv *priv = dev->uclass->priv;
  96
  97        priv->dev_count--;
  98        sandbox_set_enable_pci_map(priv->dev_count > 0);
  99
 100        return 0;
 101}
 102
 103UCLASS_DRIVER(pci_emul) = {
 104        .id             = UCLASS_PCI_EMUL,
 105        .name           = "pci_emul",
 106        .post_probe     = sandbox_pci_emul_post_probe,
 107        .pre_remove     = sandbox_pci_emul_pre_remove,
 108        .priv_auto_alloc_size   = sizeof(struct sandbox_pci_emul_priv),
 109        .per_device_auto_alloc_size     = sizeof(struct pci_emul_uc_priv),
 110};
 111
 112/*
 113 * This uclass is a child of the pci bus. Its platdata is not defined here so
 114 * is defined by its parent, UCLASS_PCI, which uses struct pci_child_platdata.
 115 * See per_child_platdata_auto_alloc_size in UCLASS_DRIVER(pci).
 116 */
 117UCLASS_DRIVER(pci_emul_parent) = {
 118        .id             = UCLASS_PCI_EMUL_PARENT,
 119        .name           = "pci_emul_parent",
 120        .post_bind      = dm_scan_fdt_dev,
 121};
 122
 123static const struct udevice_id pci_emul_parent_ids[] = {
 124        { .compatible = "sandbox,pci-emul-parent" },
 125        { }
 126};
 127
 128U_BOOT_DRIVER(pci_emul_parent_drv) = {
 129        .name           = "pci_emul_parent_drv",
 130        .id             = UCLASS_PCI_EMUL_PARENT,
 131        .of_match       = pci_emul_parent_ids,
 132};
 133