From mboxrd@z Thu Jan 1 00:00:00 1970 From: Tim Harvey Date: Fri, 22 Feb 2019 10:03:03 -0800 Subject: [U-Boot] [RFC 06/22] dm: pci: add PCI SR-IOV EA support In-Reply-To: <20190222180319.32221-1-tharvey@gateworks.com> References: <20190222180319.32221-1-tharvey@gateworks.com> Message-ID: <20190222180319.32221-7-tharvey@gateworks.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Add Single Root I/O Virtualization (SR-IOV) and Enhanced Allocation support Signed-off-by: Tim Harvey --- 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