[U-Boot] [RFC/RESEND 06/22] dm: pci: add PCI SR-IOV EA support
Tim Harvey
tharvey at gateworks.com
Mon Mar 4 17:34:21 UTC 2019
Add Single Root I/O Virtualization (SR-IOV) and Enhanced Allocation support
Signed-off-by: Tim Harvey <tharvey at gateworks.com>
---
arch/x86/cpu/baytrail/cpu.c | 3 +-
drivers/ata/ahci.c | 8 +-
drivers/i2c/designware_i2c.c | 4 +-
drivers/i2c/intel_i2c.c | 3 +-
drivers/mmc/pci_mmc.c | 3 +-
drivers/net/e1000.c | 5 +-
drivers/net/pch_gbe.c | 3 +-
drivers/nvme/nvme.c | 3 +-
drivers/pci/pci-uclass.c | 304 +++++++++++++++++++++++++++++++++--
drivers/usb/host/ehci-pci.c | 3 +-
drivers/usb/host/xhci-pci.c | 3 +-
include/pci.h | 56 ++++++-
12 files changed, 370 insertions(+), 28 deletions(-)
diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c
index 56e98131d7..cc3eae6cb2 100644
--- a/arch/x86/cpu/baytrail/cpu.c
+++ b/arch/x86/cpu/baytrail/cpu.c
@@ -46,6 +46,7 @@ int arch_cpu_init_dm(void)
{
struct udevice *dev;
void *base;
+ size_t size;
int ret;
int i;
@@ -53,7 +54,7 @@ int arch_cpu_init_dm(void)
for (i = 0; i < 2; i++) {
ret = dm_pci_bus_find_bdf(PCI_BDF(0, 0x1e, 3 + i), &dev);
if (!ret) {
- base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+ base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, &size,
PCI_REGION_MEM);
hsuart_clock_set(base);
}
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 5fafb63aeb..d6753f140d 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -455,8 +455,9 @@ static int ahci_init_one(struct ahci_uc_priv *uc_priv, pci_dev_t dev)
uc_priv->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */
#if !defined(CONFIG_DM_SCSI)
+ size_t size;
#ifdef CONFIG_DM_PCI
- uc_priv->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5,
+ uc_priv->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5, &size,
PCI_REGION_MEM);
/* Take from kernel:
@@ -467,7 +468,7 @@ static int ahci_init_one(struct ahci_uc_priv *uc_priv, pci_dev_t dev)
if (vendor == 0x197b)
dm_pci_write_config8(dev, 0x41, 0xa1);
#else
- uc_priv->mmio_base = pci_map_bar(dev, PCI_BASE_ADDRESS_5,
+ uc_priv->mmio_base = pci_map_bar(dev, PCI_BASE_ADDRESS_5, &size,
PCI_REGION_MEM);
/* Take from kernel:
@@ -1189,8 +1190,9 @@ int ahci_probe_scsi(struct udevice *ahci_dev, ulong base)
int ahci_probe_scsi_pci(struct udevice *ahci_dev)
{
ulong base;
+ size_t size;
- base = (ulong)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_5,
+ base = (ulong)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_5, &size,
PCI_REGION_MEM);
return ahci_probe_scsi(ahci_dev, base);
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index dbc3326b5a..bd6f4416ab 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -540,8 +540,10 @@ static int designware_i2c_probe(struct udevice *bus)
if (device_is_on_pci_bus(bus)) {
#ifdef CONFIG_DM_PCI
/* Save base address from PCI BAR */
+ size_t size;
priv->regs = (struct i2c_regs *)
- dm_pci_map_bar(bus, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+ dm_pci_map_bar(bus, PCI_BASE_ADDRESS_0, &size,
+ PCI_REGION_MEM);
#ifdef CONFIG_X86
/* Use BayTrail specific timing values */
priv->scl_sda_cfg = &byt_config;
diff --git a/drivers/i2c/intel_i2c.c b/drivers/i2c/intel_i2c.c
index f5509fef16..f9de161356 100644
--- a/drivers/i2c/intel_i2c.c
+++ b/drivers/i2c/intel_i2c.c
@@ -247,10 +247,11 @@ static int intel_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
static int intel_i2c_probe(struct udevice *dev)
{
struct intel_i2c *priv = dev_get_priv(dev);
+ size_t size;
ulong base;
/* Save base address from PCI BAR */
- priv->base = (ulong)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4,
+ priv->base = (ulong)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4, &size,
PCI_REGION_IO);
base = priv->base;
diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c
index 182d41637f..84701713a7 100644
--- a/drivers/mmc/pci_mmc.c
+++ b/drivers/mmc/pci_mmc.c
@@ -28,9 +28,10 @@ static int pci_mmc_probe(struct udevice *dev)
struct pci_mmc_plat *plat = dev_get_platdata(dev);
struct pci_mmc_priv *priv = dev_get_priv(dev);
struct sdhci_host *host = &priv->host;
+ size_t size;
int ret;
- host->ioaddr = (void *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+ host->ioaddr = (void *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, &size,
PCI_REGION_MEM);
host->name = dev->name;
ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index a34f697461..fbfb9052d8 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -5501,6 +5501,9 @@ static int e1000_init_one(struct e1000_hw *hw, int cardnum, pci_dev_t devno,
#endif
{
u32 val;
+#ifdef CONFIG_DM_ETH
+ size_t size;
+#endif
/* Assign the passed-in values */
#ifdef CONFIG_DM_ETH
@@ -5551,7 +5554,7 @@ static int e1000_init_one(struct e1000_hw *hw, int cardnum, pci_dev_t devno,
hw->eeprom_semaphore_present = true;
#endif
#ifdef CONFIG_DM_ETH
- hw->hw_addr = dm_pci_map_bar(devno, PCI_BASE_ADDRESS_0,
+ hw->hw_addr = dm_pci_map_bar(devno, PCI_BASE_ADDRESS_0, &size,
PCI_REGION_MEM);
#else
hw->hw_addr = pci_map_bar(devno, PCI_BASE_ADDRESS_0,
diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c
index 2286dd07e9..3194221796 100644
--- a/drivers/net/pch_gbe.c
+++ b/drivers/net/pch_gbe.c
@@ -434,6 +434,7 @@ static int pch_gbe_probe(struct udevice *dev)
struct pch_gbe_priv *priv;
struct eth_pdata *plat = dev_get_platdata(dev);
void *iobase;
+ size_t size;
int err;
/*
@@ -445,7 +446,7 @@ static int pch_gbe_probe(struct udevice *dev)
priv->dev = dev;
- iobase = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, PCI_REGION_MEM);
+ iobase = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, &size, PCI_REGION_MEM);
plat->iobase = (ulong)iobase;
priv->mac_regs = (struct pch_gbe_regs *)iobase;
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index eb6fdeda50..49d8b12b2d 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -768,12 +768,13 @@ static int nvme_bind(struct udevice *udev)
static int nvme_probe(struct udevice *udev)
{
int ret;
+ size_t size;
struct nvme_dev *ndev = dev_get_priv(udev);
ndev->instance = trailing_strtol(udev->name);
INIT_LIST_HEAD(&ndev->namespaces);
- ndev->bar = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0,
+ ndev->bar = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, &size,
PCI_REGION_MEM);
if (readl(&ndev->bar->csts) == -1) {
ret = -ENODEV;
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index da49c96ed5..0720ffe5b4 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -599,12 +599,22 @@ int dm_pci_hose_probe_bus(struct udevice *bus)
{
int sub_bus;
int ret;
+ int ea_pos;
+ u8 reg;
debug("%s\n", __func__);
- sub_bus = pci_get_bus_max() + 1;
- debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name);
- dm_pciauto_prescan_setup_bridge(bus, sub_bus);
+ ea_pos = dm_pci_find_capability(bus, PCI_CAP_ID_EA);
+
+ if (ea_pos) {
+ dm_pci_read_config8(bus, ea_pos + sizeof(u32) + sizeof(u8), ®);
+ sub_bus = reg;
+ debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name);
+ } else {
+ sub_bus = pci_get_bus_max() + 1;
+ debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name);
+ dm_pciauto_prescan_setup_bridge(bus, sub_bus);
+ }
ret = device_probe(bus);
if (ret) {
@@ -612,13 +622,16 @@ int dm_pci_hose_probe_bus(struct udevice *bus)
ret);
return ret;
}
- if (sub_bus != bus->seq) {
- printf("%s: Internal error, bus '%s' got seq %d, expected %d\n",
- __func__, bus->name, bus->seq, sub_bus);
- return -EPIPE;
+
+ if (!ea_pos) {
+ if (sub_bus != bus->seq) {
+ printf("%s: Internal error, bus '%s' got seq %d, expected %d\n",
+ __func__, bus->name, bus->seq, sub_bus);
+ return -EPIPE;
+ }
+ sub_bus = pci_get_bus_max();
+ dm_pciauto_postscan_setup_bridge(bus, sub_bus);
}
- sub_bus = pci_get_bus_max();
- dm_pciauto_postscan_setup_bridge(bus, sub_bus);
return sub_bus;
}
@@ -828,6 +841,7 @@ int pci_bind_bus_devices(struct udevice *bus)
pplat->vendor = vendor;
pplat->device = device;
pplat->class = class;
+ pplat->is_phys = true;
}
return 0;
@@ -1326,14 +1340,258 @@ pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
return bus_addr;
}
-void *dm_pci_map_bar(struct udevice *dev, int bar, int flags)
+/* Read an Enhanced Allocation (EA) entry */
+static int dm_pci_ea_entry_read(struct udevice *dev, int offset, int *bei,
+ pci_addr_t *start, size_t *size)
{
- pci_addr_t pci_bus_addr;
+ u32 base;
+ u32 max_offset;
+ u8 prop;
+ int ent_offset = offset;
+ int ent_size;
+ u32 dw0;
+
+ dm_pci_read_config32(dev, ent_offset, &dw0);
+
+ debug("%s: %d: dw0: %lx\n", __FUNCTION__, __LINE__, (unsigned long)dw0);
+
+ ent_offset += sizeof(u32);
+
+ /* Entry size field indicates DWORDs after 1st */
+ ent_size = ((dw0 & PCI_EA_ES) + 1) * sizeof(u32);
+
+ if (!(dw0 & PCI_EA_ENABLE))
+ goto out;
+ *bei = PCI_EA_BEI(dw0);
+
+ prop = PCI_EA_PP(dw0);
+
+ debug("EA property: %x\n", prop);
+
+ /*
+ * If the Property is in the reserved range, try the Secondary
+ * Property instead.
+ */
+ if (prop > PCI_EA_P_BRIDGE_IO && prop < PCI_EA_P_MEM_RESERVED)
+ prop = PCI_EA_SP(dw0);
+ if (prop > PCI_EA_P_BRIDGE_IO)
+ goto out;
+
+ debug("EA property: %x\n", prop);
+
+ /* Read Base */
+ dm_pci_read_config32(dev, ent_offset, &base);
+ ent_offset += sizeof(u32);
+ *start = (pci_addr_t)base & PCI_EA_FIELD_MASK;
+
+ /* Read MaxOffset */
+ dm_pci_read_config32(dev, ent_offset, &max_offset);
+ ent_offset += sizeof(u32);
+
+ /* Read Base MSBs (if 64-bit entry) */
+ if (base & PCI_EA_IS_64) {
+ dm_pci_read_config32(dev, ent_offset, &base);
+ ent_offset += sizeof(u32);
+
+ *start |= (pci_addr_t)base << 32;
+ }
+
+ debug("EA (%u,%u) start = %lx\n", PCI_EA_BEI(dw0), prop, (unsigned long)*start);
+
+ *size = ((size_t)max_offset | 0x03) + 1;
+
+ /* Read MaxOffset MSBs (if 64-bit entry) */
+ if (max_offset & PCI_EA_IS_64) {
+ dm_pci_read_config32(dev, ent_offset, &max_offset);
+ ent_offset += sizeof(u32);
+
+ *size |= (size_t)max_offset << 32;
+ }
+
+ debug("EA (%u,%u) size = %lx\n", PCI_EA_BEI(dw0), prop, (unsigned long)*size);
+
+ if (*start + *size < *start) {
+ *size = 0;
+ *start = 0;
+ printf("EA Entry crosses address boundary\n");
+ goto out;
+ }
+
+ if (ent_size != ent_offset - offset) {
+ printf("EA Entry Size (%d) does not match length read (%d)\n",
+ ent_size, ent_offset - offset);
+ goto out;
+ }
+
+out:
+ return offset + ent_size;
+}
+
+/* Read an Enhanced Allocation (EA) BAR */
+int dm_pci_ea_bar_read(struct udevice *dev, int bar, pci_addr_t *start, size_t *size)
+{
+ int ea;
+ int offset;
+ u8 num_ent;
+ u8 hdr_type;
+ int i, bei = -1;
+
+ ea = dm_pci_find_capability(dev, PCI_CAP_ID_EA);
+
+ dm_pci_read_config8(dev, ea + PCI_EA_NUM_ENT, &num_ent);
+ num_ent &= PCI_EA_NUM_ENT_MASK;
+
+ offset = ea + PCI_EA_FIRST_ENT;
+
+ dm_pci_read_config8(dev, PCI_HEADER_TYPE, &hdr_type);
+
+ /* Skip DWORD 2 for type 1 functions */
+ if (hdr_type == PCI_HEADER_TYPE_BRIDGE)
+ offset += sizeof(u32);
+
+ for (i = 0; (i < num_ent) && (bar != bei); i++) {
+ offset = dm_pci_ea_entry_read(dev, offset, &bei, start, size);
+ }
+
+ return (bar == bei);
+}
+
+int dm_pci_sriov_init(struct udevice *pdev, int vf_en)
+{
+ u16 vendor, device;
+ struct udevice *bus;
+ struct udevice *dev;
+ pci_dev_t bdf;
+ u16 ctrl;
+ u16 num_vfs;
+ u16 total_vf;
+ u16 vf_offset;
+ u16 vf_stride;
+ int vf, ret;
+ int pos;
+
+ pos = dm_pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
+ if (!pos) {
+ printf("Error: SRIOV capability not found\n");
+ return -ENODEV;
+ }
+
+ dm_pci_read_config16(pdev, pos + PCI_SRIOV_CTRL, &ctrl);
+
+ dm_pci_read_config16(pdev, pos + PCI_SRIOV_TOTAL_VF, &total_vf);
+
+ if (vf_en > total_vf)
+ vf_en = total_vf;
+
+ dm_pci_write_config16(pdev, pos + PCI_SRIOV_NUM_VF, vf_en);
+
+ ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
+ dm_pci_write_config16(pdev, pos + PCI_SRIOV_CTRL, ctrl);
+
+ dm_pci_read_config16(pdev, pos + PCI_SRIOV_NUM_VF, &num_vfs);
+
+ dm_pci_read_config16(pdev, pos + PCI_SRIOV_VF_OFFSET, &vf_offset);
+ dm_pci_read_config16(pdev, pos + PCI_SRIOV_VF_STRIDE, &vf_stride);
+
+ dm_pci_read_config16(pdev, PCI_VENDOR_ID, &vendor);
+ dm_pci_read_config16(pdev, pos + PCI_SRIOV_VF_DID, &device);
+
+ bdf = dm_pci_get_bdf(pdev);
+
+ pci_get_bus(PCI_BUS(bdf), &bus);
+
+ if (!bus)
+ return -ENODEV;
+
+ bdf += PCI_BDF(0, 0, vf_offset);
+
+ for (vf = 0; vf < num_vfs; vf++) {
+ struct pci_child_platdata *pplat;
+ ulong class;
+
+ pci_bus_read_config(bus, bdf, PCI_CLASS_REVISION,
+ &class, PCI_SIZE_32);
+
+ class >>= 8;
+
+ debug("%s: bus %d/%s: found VF %x:%x\n", __func__,
+ bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf));
+
+ /* Find this device in the device tree */
+ ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev);
+
+ if (ret == -ENODEV) {
+ struct pci_device_id find_id;
+
+ memset(&find_id, 0, sizeof(find_id));
+
+ find_id.vendor = vendor;
+ find_id.device = device;
+ find_id.class = class >> 8;
+
+ ret = pci_find_and_bind_driver(bus, &find_id,
+ bdf, &dev);
+
+ if (ret)
+ return ret;
+ }
+
+ /* Update the platform data */
+ pplat = dev_get_parent_platdata(dev);
+ pplat->devfn = PCI_MASK_BUS(bdf);
+ pplat->vendor = vendor;
+ pplat->device = device;
+ pplat->class = class;
+ pplat->is_phys = false;
+ pplat->pdev = pdev;
+ pplat->vf_id = vf * vf_stride + vf_offset;
+
+ bdf += PCI_BDF(0, 0, vf_stride);
+ }
+
+ return 0;
+
+}
+
+void *dm_pci_map_bar(struct udevice *dev, int bar, size_t *size, int flags)
+{
+ int pos;
+ pci_addr_t pci_bus_start;
u32 bar_response;
+ struct pci_child_platdata *pdata = dev_get_parent_platdata(dev);
- /* read BAR address */
- dm_pci_read_config32(dev, bar, &bar_response);
- pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
+ if (!pdata->is_phys) {
+ if (bar < 9 || bar > 14)
+ return NULL;
+ dev = pdata->pdev;
+ }
+
+ pos = dm_pci_find_capability(dev, PCI_CAP_ID_EA);
+
+ if (pos) {
+ dm_pci_ea_bar_read(dev, bar, &pci_bus_start, size);
+ } else {
+ /* read BAR address */
+ if (bar >= 0 && bar <= 5) {
+ bar = PCI_BASE_ADDRESS_0 + bar * 4;
+ } else if (bar >= 9 && bar <= 14) {
+ pos = dm_pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
+ bar = pos + PCI_SRIOV_BAR + bar * 4;
+ }
+ dm_pci_read_config32(dev, bar,
+ &bar_response);
+ pci_bus_start = (pci_addr_t)(bar_response & ~0xf);
+
+ if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+ PCI_BASE_ADDRESS_MEM_TYPE_64) {
+ dm_pci_read_config32(dev, bar + 4, &bar_response);
+ }
+ pci_bus_start |= (pci_addr_t)bar_response << 32;
+ }
+
+ if (!pdata->is_phys) {
+ pci_bus_start += (pdata->vf_id - 1) * (*size);
+ }
/*
* Pass "0" as the length argument to pci_bus_to_virt. The arg
@@ -1341,7 +1599,7 @@ void *dm_pci_map_bar(struct udevice *dev, int bar, int flags)
* linear mapping. In the future, this could read the BAR size
* and pass that as the size if needed.
*/
- return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE);
+ return dm_pci_bus_to_virt(dev, pci_bus_start, flags, 0, MAP_NOCACHE);
}
int dm_pci_find_capability(struct udevice *dev, int cap)
@@ -1412,6 +1670,22 @@ int dm_pci_find_ext_capability(struct udevice *dev, int cap)
return 0;
}
+int dm_pci_sriov_get_totalvfs(struct udevice *pdev)
+{
+ u16 total_vf;
+ int pos;
+
+ pos = dm_pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
+ if (!pos) {
+ printf("Error: SRIOV capability not found\n");
+ return -ENODEV;
+ }
+
+ dm_pci_read_config16(pdev, pos + PCI_SRIOV_TOTAL_VF, &total_vf);
+
+ return total_vf;
+}
+
UCLASS_DRIVER(pci) = {
.id = UCLASS_PCI,
.name = "pci",
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 6150f3d888..db55d136b6 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -26,6 +26,7 @@ static int ehci_pci_init(struct udevice *dev, struct ehci_hccr **ret_hccr,
struct ehci_pci_priv *priv = dev_get_priv(dev);
struct ehci_hccr *hccr;
struct ehci_hcor *hcor;
+ size_t size;
int ret;
u32 cmd;
@@ -34,7 +35,7 @@ static int ehci_pci_init(struct udevice *dev, struct ehci_hccr **ret_hccr,
return ret;
hccr = (struct ehci_hccr *)dm_pci_map_bar(dev,
- PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+ PCI_BASE_ADDRESS_0, &size, PCI_REGION_MEM);
hcor = (struct ehci_hcor *)((uintptr_t) hccr +
HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index b995aef997..d42f06bc32 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -16,10 +16,11 @@ static void xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr,
{
struct xhci_hccr *hccr;
struct xhci_hcor *hcor;
+ size_t size;
u32 cmd;
hccr = (struct xhci_hccr *)dm_pci_map_bar(dev,
- PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+ PCI_BASE_ADDRESS_0, &size, PCI_REGION_MEM);
hcor = (struct xhci_hcor *)((uintptr_t) hccr +
HC_LENGTH(xhci_readl(&hccr->cr_capbase)));
diff --git a/include/pci.h b/include/pci.h
index 938a8390cb..033d5adf2a 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -411,6 +411,39 @@
#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
+/* Single Root I/O Virtualization */
+#define PCI_SRIOV_BAR 0x24 /* VF BAR0 */
+#define PCI_SRIOV_BAR 0x24 /* VF BAR0 */
+#define PCI_SRIOV_CTRL 0x08 /* SR-IOV Control */
+#define PCI_SRIOV_CTRL_VFE 0x01 /* VF Enable */
+#define PCI_SRIOV_CTRL_VFM 0x02 /* VF Migration Enable */
+#define PCI_SRIOV_CTRL_INTR 0x04 /* VF Migration Interrupt Enable */
+#define PCI_SRIOV_CTRL_MSE 0x08 /* VF Memory Space Enable */
+#define PCI_SRIOV_CTRL_ARI 0x10 /* ARI Capable Hierarchy */
+#define PCI_SRIOV_STATUS 0x0a /* SR-IOV Status */
+#define PCI_SRIOV_STATUS_VFM 0x01 /* VF Migration Status */
+#define PCI_SRIOV_INITIAL_VF 0x0c /* Initial VFs */
+#define PCI_SRIOV_TOTAL_VF 0x0e /* Total VFs */
+#define PCI_SRIOV_NUM_VF 0x10 /* Number of VFs */
+#define PCI_SRIOV_FUNC_LINK 0x12 /* Function Dependency Link */
+#define PCI_SRIOV_VF_OFFSET 0x14 /* First VF Offset */
+#define PCI_SRIOV_VF_STRIDE 0x16 /* Following VF Stride */
+#define PCI_SRIOV_VF_DID 0x1a /* VF Device ID */
+
+/* Enhanced Allocation (EA) */
+#define PCI_EA_NUM_ENT 2 /* Number of Capability Entries */
+#define PCI_EA_NUM_ENT_MASK 0x3f /* Num Entries Mask */
+#define PCI_EA_FIRST_ENT 4 /* First EA Entry in List */
+#define PCI_EA_ES 0x7 /* Entry Size */
+#define PCI_EA_BEI(x) (((x) >> 4) & 0xf) /* BAR Equivalent Indicator */
+#define PCI_EA_PP(x) (((x) >> 8) & 0xff) /* Primary Properties */
+#define PCI_EA_SP(x) (((x) >> 16) & 0xff) /* Secondary Properties */
+#define PCI_EA_P_BRIDGE_IO 0x07 /* Bridge I/O Space */
+#define PCI_EA_P_MEM_RESERVED 0xfd /* Reserved Memory */
+#define PCI_EA_ENABLE (1 << 31) /* Enable for this entry */
+#define PCI_EA_IS_64 (1 << 1) /* 64-bit field flag */
+#define PCI_EA_FIELD_MASK 0xfffffffc /* For Base & Max Offset */
+
#define PCI_MAX_PCI_DEVICES 32
#define PCI_MAX_PCI_FUNCTIONS 8
@@ -841,6 +874,9 @@ struct pci_child_platdata {
unsigned short vendor;
unsigned short device;
unsigned int class;
+ bool is_phys;
+ struct udevice *pdev;
+ int vf_id;
};
/* PCI bus operations */
@@ -1307,10 +1343,11 @@ pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t addr,
*
* @dev: Device to check
* @bar: Bar number to read (numbered from 0)
+ * @size: pointer to var to assign BAR size
* @flags: Flags for the region type (PCI_REGION_...)
* @return: pointer to the virtual address to use
*/
-void *dm_pci_map_bar(struct udevice *dev, int bar, int flags);
+void *dm_pci_map_bar(struct udevice *dev, int bar, size_t *size, int flags);
/**
* dm_pci_find_capability() - find a capability
@@ -1357,6 +1394,23 @@ int dm_pci_find_capability(struct udevice *dev, int cap);
*/
int dm_pci_find_ext_capability(struct udevice *dev, int cap);
+/**
+ * dm_pci_sriov_init() - Enable SR-IOV virtual functions
+ *
+ * @dev: PCI device
+ * @vf_en: number of virtual functions to enable
+ * @return: 0 if successful, error otherwise
+ */
+int dm_pci_sriov_init(struct udevice *dev, int vf_en);
+
+/**
+ * dm_pci_sriov_get_totalvfs() - Get number of SR-IOV virtual functions
+ *
+ * @dev: PCI device
+ * @return: number of SR-IOV virtual functions
+ */
+int dm_pci_sriov_get_totalvfs(struct udevice *pdev);
+
#define dm_pci_virt_to_bus(dev, addr, flags) \
dm_pci_phys_to_bus(dev, (virt_to_phys(addr)), (flags))
#define dm_pci_bus_to_virt(dev, addr, flags, len, map_flags) \
--
2.17.1
More information about the U-Boot
mailing list