Coverage Report

Created: 2026-03-11 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/u-boot/drivers/pci/pci_sandbox.c
Line
Count
Source
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 <dm.h>
8
#include <fdtdec.h>
9
#include <log.h>
10
#include <pci.h>
11
12
0
#define FDT_DEV_INFO_CELLS  4
13
0
#define FDT_DEV_INFO_SIZE (FDT_DEV_INFO_CELLS * sizeof(u32))
14
15
0
#define SANDBOX_PCI_DEVFN(d, f) ((d << 3) | f)
16
17
struct sandbox_pci_priv {
18
  struct {
19
    u16 vendor;
20
    u16 device;
21
  } vendev[256];
22
};
23
24
static int sandbox_pci_write_config(struct udevice *bus, pci_dev_t devfn,
25
            uint offset, ulong value,
26
            enum pci_size_t size)
27
0
{
28
0
  struct dm_pci_emul_ops *ops;
29
0
  struct udevice *container, *emul;
30
0
  int ret;
31
32
0
  ret = sandbox_pci_get_emul(bus, devfn, &container, &emul);
33
0
  if (ret)
34
0
    return ret == -ENODEV ? 0 : ret;
35
0
  ops = pci_get_emul_ops(emul);
36
0
  if (!ops || !ops->write_config)
37
0
    return -ENOSYS;
38
39
0
  return ops->write_config(emul, offset, value, size);
40
0
}
41
42
static int sandbox_pci_read_config(const struct udevice *bus, pci_dev_t devfn,
43
           uint offset, ulong *valuep,
44
           enum pci_size_t size)
45
0
{
46
0
  struct dm_pci_emul_ops *ops;
47
0
  struct udevice *container, *emul;
48
0
  struct sandbox_pci_priv *priv = dev_get_priv(bus);
49
0
  int ret;
50
51
  /* Prepare the default response */
52
0
  *valuep = pci_get_ff(size);
53
0
  ret = sandbox_pci_get_emul(bus, devfn, &container, &emul);
54
0
  if (ret) {
55
0
    if (!container) {
56
0
      u16 vendor, device;
57
58
0
      devfn = SANDBOX_PCI_DEVFN(PCI_DEV(devfn),
59
0
              PCI_FUNC(devfn));
60
0
      vendor = priv->vendev[devfn].vendor;
61
0
      device = priv->vendev[devfn].device;
62
0
      if (offset == PCI_VENDOR_ID && vendor)
63
0
        *valuep = vendor;
64
0
      else if (offset == PCI_DEVICE_ID && device)
65
0
        *valuep = device;
66
67
0
      return 0;
68
0
    } else {
69
0
      return ret == -ENODEV ? 0 : ret;
70
0
    }
71
0
  }
72
0
  ops = pci_get_emul_ops(emul);
73
0
  if (!ops || !ops->read_config)
74
0
    return -ENOSYS;
75
76
0
  return ops->read_config(emul, offset, valuep, size);
77
0
}
78
79
static int sandbox_pci_probe(struct udevice *dev)
80
0
{
81
0
  struct sandbox_pci_priv *priv = dev_get_priv(dev);
82
0
  const fdt32_t *cell;
83
0
  u8 pdev, pfn, devfn;
84
0
  int len;
85
86
0
  cell = ofnode_get_property(dev_ofnode(dev), "sandbox,dev-info", &len);
87
0
  if (!cell)
88
0
    return 0;
89
90
0
  if ((len % FDT_DEV_INFO_SIZE) == 0) {
91
0
    int num = len / FDT_DEV_INFO_SIZE;
92
0
    int i;
93
94
0
    for (i = 0; i < num; i++) {
95
0
      debug("dev info #%d: %02x %02x %04x %04x\n", i,
96
0
            fdt32_to_cpu(cell[0]), fdt32_to_cpu(cell[1]),
97
0
            fdt32_to_cpu(cell[2]), fdt32_to_cpu(cell[3]));
98
99
0
      pdev = fdt32_to_cpu(cell[0]);
100
0
      pfn = fdt32_to_cpu(cell[1]);
101
0
      if (pdev > 31 || pfn > 7)
102
0
        continue;
103
0
      devfn = SANDBOX_PCI_DEVFN(pdev, pfn);
104
0
      priv->vendev[devfn].vendor = fdt32_to_cpu(cell[2]);
105
0
      priv->vendev[devfn].device = fdt32_to_cpu(cell[3]);
106
107
0
      cell += FDT_DEV_INFO_CELLS;
108
0
    }
109
0
  }
110
111
0
  return 0;
112
0
}
113
114
static const struct dm_pci_ops sandbox_pci_ops = {
115
  .read_config = sandbox_pci_read_config,
116
  .write_config = sandbox_pci_write_config,
117
};
118
119
static const struct udevice_id sandbox_pci_ids[] = {
120
  { .compatible = "sandbox,pci" },
121
  { }
122
};
123
124
U_BOOT_DRIVER(pci_sandbox) = {
125
  .name = "pci_sandbox",
126
  .id = UCLASS_PCI,
127
  .of_match = sandbox_pci_ids,
128
  .ops  = &sandbox_pci_ops,
129
  .probe  = sandbox_pci_probe,
130
  .priv_auto  = sizeof(struct sandbox_pci_priv),
131
132
  /* Attach an emulator if we can */
133
  .child_post_bind = dm_scan_fdt_dev,
134
  .per_child_plat_auto  = sizeof(struct pci_child_plat),
135
};