Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2019 Ramon Fried <ramon.fried@gmail.com> */ #include <dm.h> #include <errno.h> #include <pci.h> #include <pci_ep.h> #include <asm/test.h> /** * struct sandbox_pci_ep_priv - private data for driver * @hdr: Stores the EP device header * @msix: required MSIx count; * @msi: required MSI count; */ struct sandbox_pci_ep_priv { struct pci_ep_header hdr; struct pci_bar bars[6]; int msix; int msi; int irq_count; }; /* Method exported for testing purposes */ int sandbox_get_pci_ep_irq_count(struct udevice *dev) { struct sandbox_pci_ep_priv *priv = dev_get_priv(dev); return priv->irq_count; } static const struct udevice_id sandbox_pci_ep_ids[] = { { .compatible = "sandbox,pci_ep" }, { } }; static int sandbox_write_header(struct udevice *dev, uint fn, struct pci_ep_header *hdr) { struct sandbox_pci_ep_priv *priv = dev_get_priv(dev); if (fn > 0) return -ENODEV; memcpy(&priv->hdr, hdr, sizeof(*hdr)); return 0; } static int sandbox_read_header(struct udevice *dev, uint fn, struct pci_ep_header *hdr) { struct sandbox_pci_ep_priv *priv = dev_get_priv(dev); if (fn > 0) return -ENODEV; memcpy(hdr, &priv->hdr, sizeof(*hdr)); return 0; } static int sandbox_set_bar(struct udevice *dev, uint fn, struct pci_bar *ep_bar) { struct sandbox_pci_ep_priv *priv = dev_get_priv(dev); int bar_idx; if (fn > 0) return -ENODEV; bar_idx = ep_bar->barno; memcpy(&priv->bars[bar_idx], ep_bar, sizeof(*ep_bar)); return 0; } static int sandbox_read_bar(struct udevice *dev, uint fn, struct pci_bar *ep_bar, enum pci_barno barno) { struct sandbox_pci_ep_priv *priv = dev_get_priv(dev); if (fn > 0) return -ENODEV; memcpy(ep_bar, &priv->bars[barno], sizeof(*ep_bar)); return 0; } static int sandbox_set_msi(struct udevice *dev, uint fn, uint interrupts) { struct sandbox_pci_ep_priv *priv = dev_get_priv(dev); if (fn > 0) return -ENODEV; priv->msi = interrupts; return 0; } static int sandbox_get_msi(struct udevice *dev, uint fn) { struct sandbox_pci_ep_priv *priv = dev_get_priv(dev); if (fn > 0) return -ENODEV; return priv->msi; } static int sandbox_set_msix(struct udevice *dev, uint fn, uint interrupts) { struct sandbox_pci_ep_priv *priv = dev_get_priv(dev); if (fn > 0) return -ENODEV; priv->msix = interrupts; return 0; } static int sandbox_get_msix(struct udevice *dev, uint fn) { struct sandbox_pci_ep_priv *priv = dev_get_priv(dev); if (fn > 0) return -ENODEV; return priv->msix; } static int sandbox_raise_irq(struct udevice *dev, uint fn, enum pci_ep_irq_type type, uint interrupt_num) { struct sandbox_pci_ep_priv *priv = dev_get_priv(dev); if (fn > 0) return -ENODEV; priv->irq_count++; return 0; } static int sandbox_pci_ep_probe(struct udevice *dev) { struct sandbox_pci_ep_priv *priv = dev_get_priv(dev); memset(priv, 0, sizeof(*priv)); return 0; } static struct pci_ep_ops sandbox_pci_ep_ops = { .write_header = sandbox_write_header, .read_header = sandbox_read_header, .set_bar = sandbox_set_bar, .read_bar = sandbox_read_bar, .set_msi = sandbox_set_msi, .get_msi = sandbox_get_msi, .set_msix = sandbox_set_msix, .get_msix = sandbox_get_msix, .raise_irq = sandbox_raise_irq, }; U_BOOT_DRIVER(pci_ep_sandbox) = { .name = "pci_ep_sandbox", .id = UCLASS_PCI_EP, .of_match = sandbox_pci_ep_ids, .probe = sandbox_pci_ep_probe, .ops = &sandbox_pci_ep_ops, .priv_auto = sizeof(struct sandbox_pci_ep_priv), }; |