diff options
39 files changed, 401 insertions, 209 deletions
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index a8a86bc..8f93775 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -997,7 +997,7 @@ #address-cells = <3>; #size-cells = <2>; ranges = <0x02000000 0 0x30000000 0x30000000 0 0x2000 // MEM0 - 0x02000000 0 0x31000000 0x31000000 0 0x2000 // MEM1 + 0x02000000 0 0x31000000 0x3e000000 0 0x2000 // MEM1 0x01000000 0 0x40000000 0x40000000 0 0x2000>; sandbox,dev-info = <0x08 0x00 0x1234 0x5678 0x0c 0x00 0x1234 0x5678 diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c index 68bf40b..4fb6a48 100644 --- a/arch/x86/cpu/baytrail/cpu.c +++ b/arch/x86/cpu/baytrail/cpu.c @@ -56,7 +56,7 @@ static int baytrail_uart_init(void *ctx, struct event *event) 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, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); hsuart_clock_set(base); } diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 2062197..de6131f 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -416,8 +416,8 @@ static int ahci_init_one(struct ahci_uc_priv *uc_priv, struct udevice *dev) uc_priv->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ #if !defined(CONFIG_DM_SCSI) - uc_priv->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5, - PCI_REGION_MEM); + uc_priv->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); /* Take from kernel: * JMicron-specific fixup: @@ -1148,8 +1148,8 @@ int ahci_probe_scsi_pci(struct udevice *ahci_dev) ulong base; u16 vendor, device; - base = (ulong)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_5, - PCI_REGION_MEM); + base = (ulong)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_5, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); /* * Note: @@ -1164,6 +1164,7 @@ int ahci_probe_scsi_pci(struct udevice *ahci_dev) if (vendor == PCI_VENDOR_ID_CAVIUM && device == PCI_DEVICE_ID_CAVIUM_SATA) base = (uintptr_t)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_0, + 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); return ahci_probe_scsi(ahci_dev, base); } diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index b213eba..7065154 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -699,9 +699,11 @@ static int sil_pci_probe(struct udevice *dev) /* Read out all BARs */ sata_info.iobase[0] = (ulong)dm_pci_map_bar(dev, - PCI_BASE_ADDRESS_0, PCI_REGION_MEM); + PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, + PCI_REGION_MEM); sata_info.iobase[1] = (ulong)dm_pci_map_bar(dev, - PCI_BASE_ADDRESS_2, PCI_REGION_MEM); + PCI_BASE_ADDRESS_2, 0, 0, PCI_REGION_TYPE, + PCI_REGION_MEM); /* mask out the unused bits */ sata_info.iobase[0] &= 0xffffff80; diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c index 9547470..cdc5ba6 100644 --- a/drivers/bios_emulator/atibios.c +++ b/drivers/bios_emulator/atibios.c @@ -368,8 +368,8 @@ void *PCI_mapBIOSImage(struct udevice *pcidev) return NULL; } - BIOSImage = dm_pci_bus_to_virt(pcidev, BIOSImageBus, - PCI_REGION_MEM, 0, MAP_NOCACHE); + BIOSImage = dm_pci_bus_to_virt(pcidev, BIOSImageBus, 0, PCI_REGION_TYPE, + PCI_REGION_MEM, MAP_NOCACHE); /*Change the PCI BAR registers to map it onto the bus.*/ dm_pci_write_config32(pcidev, BIOSImageBAR, 0); diff --git a/drivers/gpio/octeon_gpio.c b/drivers/gpio/octeon_gpio.c index 42eae79..2b2465b 100644 --- a/drivers/gpio/octeon_gpio.c +++ b/drivers/gpio/octeon_gpio.c @@ -183,7 +183,7 @@ static int octeon_gpio_probe(struct udevice *dev) priv->data = (const struct octeon_gpio_data *)dev_get_driver_data(dev); if (priv->data->probe == PROBE_PCI) { - priv->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + priv->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); uc_priv->gpio_count = readq(priv->base + priv->data->reg_offs + GPIO_CONST) & diff --git a/drivers/i2c/designware_i2c_pci.c b/drivers/i2c/designware_i2c_pci.c index 9e38773..1572c2c 100644 --- a/drivers/i2c/designware_i2c_pci.c +++ b/drivers/i2c/designware_i2c_pci.c @@ -59,7 +59,8 @@ static int designware_i2c_pci_of_to_plat(struct udevice *dev) priv->regs = (struct i2c_regs *)dm_pci_read_bar32(dev, 0); } else { priv->regs = (struct i2c_regs *) - dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); + dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); } if (!priv->regs) return -EINVAL; diff --git a/drivers/i2c/intel_i2c.c b/drivers/i2c/intel_i2c.c index 52f7a52..dc26fa8 100644 --- a/drivers/i2c/intel_i2c.c +++ b/drivers/i2c/intel_i2c.c @@ -251,7 +251,7 @@ static int intel_i2c_probe(struct udevice *dev) 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, 0, 0, PCI_REGION_TYPE, PCI_REGION_IO); base = priv->base; diff --git a/drivers/i2c/octeon_i2c.c b/drivers/i2c/octeon_i2c.c index 50199ff..e54ef18 100644 --- a/drivers/i2c/octeon_i2c.c +++ b/drivers/i2c/octeon_i2c.c @@ -792,7 +792,7 @@ static int octeon_i2c_probe(struct udevice *dev) debug("TWSI PCI device: %x\n", bdf); - twsi->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + twsi->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); } else { twsi->base = dev_remap_addr(dev); diff --git a/drivers/mmc/octeontx_hsmmc.c b/drivers/mmc/octeontx_hsmmc.c index f0519f0..6e9acf7 100644 --- a/drivers/mmc/octeontx_hsmmc.c +++ b/drivers/mmc/octeontx_hsmmc.c @@ -3822,7 +3822,7 @@ static int octeontx_mmc_host_probe(struct udevice *dev) /* Octeon TX & TX2 use PCI based probing */ if (device_is_compatible(dev, "cavium,thunder-8890-mmc")) { - host->base_addr = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + host->base_addr = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); if (!host->base_addr) { pr_err("%s: Error: MMC base address not found\n", diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index b9ab064..cba2ea8 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -50,7 +50,7 @@ static int pci_mmc_probe(struct udevice *dev) desc = mmc_get_blk_desc(&plat->mmc); desc->removable = !(plat->cfg.host_caps & MMC_CAP_NONREMOVABLE); - host->ioaddr = (void *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + host->ioaddr = (void *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); host->name = dev->name; host->cd_gpio = priv->cd_gpio; diff --git a/drivers/mtd/nand/raw/octeontx_bch.c b/drivers/mtd/nand/raw/octeontx_bch.c index 24ffa51..c1d721c 100644 --- a/drivers/mtd/nand/raw/octeontx_bch.c +++ b/drivers/mtd/nand/raw/octeontx_bch.c @@ -176,7 +176,8 @@ static int octeontx_pci_bchpf_probe(struct udevice *dev) if (!bch) return -ENOMEM; - bch->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); + bch->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); bch->dev = dev; debug("%s: base address: %p\n", __func__, bch->reg_base); @@ -361,7 +362,8 @@ static int octeontx_pci_bchvf_probe(struct udevice *dev) vf->dev = dev; /* Map PF's configuration registers */ - vf->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); + vf->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); debug("%s: reg base: %p\n", __func__, vf->reg_base); err = octeontx_cmd_queue_initialize(dev, QID_BCH, QDEPTH - 1, 0, diff --git a/drivers/mtd/nand/raw/octeontx_nand.c b/drivers/mtd/nand/raw/octeontx_nand.c index ff363a5..b338b20 100644 --- a/drivers/mtd/nand/raw/octeontx_nand.c +++ b/drivers/mtd/nand/raw/octeontx_nand.c @@ -2098,7 +2098,7 @@ static int octeontx_pci_nand_probe(struct udevice *dev) tn->dev = dev; INIT_LIST_HEAD(&tn->chips); - tn->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); + tn->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); if (!tn->base) { ret = -EINVAL; goto release; diff --git a/drivers/net/bnxt/bnxt.c b/drivers/net/bnxt/bnxt.c index 9844e96..1c9a996 100644 --- a/drivers/net/bnxt/bnxt.c +++ b/drivers/net/bnxt/bnxt.c @@ -28,9 +28,12 @@ static void bnxt_bring_pci(struct bnxt *bp) dm_pci_read_config16(bp->pdev, PCI_SUBSYSTEM_ID, &bp->subsystem_device); dm_pci_read_config16(bp->pdev, PCI_COMMAND, &bp->cmd_reg); dm_pci_read_config8(bp->pdev, PCI_INTERRUPT_LINE, &bp->irq); - bp->bar0 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); - bp->bar1 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_2, PCI_REGION_MEM); - bp->bar2 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_4, PCI_REGION_MEM); + bp->bar0 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_0, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); + bp->bar1 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_2, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); + bp->bar2 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_4, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); cmd_reg = bp->cmd_reg | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; cmd_reg |= PCI_COMMAND_INTX_DISABLE; /* disable intr */ dm_pci_write_config16(bp->pdev, PCI_COMMAND, cmd_reg); diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 4e34248..5fe016e 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -5549,8 +5549,8 @@ 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, - PCI_REGION_MEM); + hw->hw_addr = dm_pci_map_bar(devno, PCI_BASE_ADDRESS_0, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); #else hw->hw_addr = pci_map_bar(devno, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c index 1724f94..9b97a03 100644 --- a/drivers/net/fsl_enetc.c +++ b/drivers/net/fsl_enetc.c @@ -339,7 +339,7 @@ static int enetc_probe(struct udevice *dev) } /* initialize register */ - priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0); + priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, 0); if (!priv->regs_base) { enetc_dbg(dev, "failed to map BAR0\n"); return -EINVAL; diff --git a/drivers/net/fsl_enetc_mdio.c b/drivers/net/fsl_enetc_mdio.c index 3eb6ac9..50ad76d 100644 --- a/drivers/net/fsl_enetc_mdio.c +++ b/drivers/net/fsl_enetc_mdio.c @@ -125,7 +125,7 @@ static int enetc_mdio_probe(struct udevice *dev) { struct enetc_mdio_priv *priv = dev_get_priv(dev); - priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0); + priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, 0); if (!priv->regs_base) { enetc_dbg(dev, "failed to map BAR0\n"); return -EINVAL; diff --git a/drivers/net/mscc_eswitch/felix_switch.c b/drivers/net/mscc_eswitch/felix_switch.c index 60b2e8f..709c9e3 100644 --- a/drivers/net/mscc_eswitch/felix_switch.c +++ b/drivers/net/mscc_eswitch/felix_switch.c @@ -292,13 +292,13 @@ static int felix_probe(struct udevice *dev) return -ENODEV; } - priv->imdio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0); + priv->imdio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, 0); if (!priv->imdio_base) { dev_err(dev, "failed to map BAR0\n"); return -EINVAL; } - priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4, 0); + priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4, 0, 0, PCI_REGION_TYPE, 0); if (!priv->regs_base) { dev_err(dev, "failed to map BAR4\n"); return -EINVAL; diff --git a/drivers/net/octeontx/bgx.c b/drivers/net/octeontx/bgx.c index a5c0c9f..b6592ff 100644 --- a/drivers/net/octeontx/bgx.c +++ b/drivers/net/octeontx/bgx.c @@ -1458,7 +1458,7 @@ int octeontx_bgx_probe(struct udevice *dev) int bgx_idx, node; int inc = 1; - bgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + bgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); if (!bgx->reg_base) { debug("No PCI region found\n"); diff --git a/drivers/net/octeontx/nic_main.c b/drivers/net/octeontx/nic_main.c index 0f36f25..99886e3 100644 --- a/drivers/net/octeontx/nic_main.c +++ b/drivers/net/octeontx/nic_main.c @@ -713,7 +713,7 @@ int nic_initialize(struct udevice *dev) return -ENOMEM; /* MAP PF's configuration registers */ - nic->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + nic->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); if (!nic->reg_base) { printf("Cannot map config register space, aborting\n"); diff --git a/drivers/net/octeontx/nicvf_main.c b/drivers/net/octeontx/nicvf_main.c index c30ba49..6e4d0a0 100644 --- a/drivers/net/octeontx/nicvf_main.c +++ b/drivers/net/octeontx/nicvf_main.c @@ -509,7 +509,7 @@ int nicvf_initialize(struct udevice *dev) /* Enable TSO support */ nicvf->hw_tso = true; - nicvf->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + nicvf->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); debug("nicvf->reg_base: %p\n", nicvf->reg_base); diff --git a/drivers/net/octeontx/smi.c b/drivers/net/octeontx/smi.c index d70fa82..233c26f 100644 --- a/drivers/net/octeontx/smi.c +++ b/drivers/net/octeontx/smi.c @@ -322,7 +322,7 @@ int octeontx_smi_probe(struct udevice *dev) u64 baseaddr; debug("SMI PCI device: %x\n", bdf); - if (!dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM)) { + if (!dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM)) { printf("Failed to map PCI region for bdf %x\n", bdf); return -1; } diff --git a/drivers/net/octeontx2/cgx.c b/drivers/net/octeontx2/cgx.c index d139029..c6ec320 100644 --- a/drivers/net/octeontx2/cgx.c +++ b/drivers/net/octeontx2/cgx.c @@ -253,7 +253,7 @@ int cgx_probe(struct udevice *dev) struct cgx *cgx = dev_get_priv(dev); int err; - cgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + cgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); cgx->dev = dev; cgx->cgx_id = ((u64)(cgx->reg_base) >> 24) & 0x7; diff --git a/drivers/net/octeontx2/rvu_af.c b/drivers/net/octeontx2/rvu_af.c index d2f9654..0d3a9ff 100644 --- a/drivers/net/octeontx2/rvu_af.c +++ b/drivers/net/octeontx2/rvu_af.c @@ -127,7 +127,7 @@ int rvu_af_probe(struct udevice *dev) { struct rvu_af *af_ptr = dev_get_priv(dev); - af_ptr->af_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + af_ptr->af_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); debug("%s RVU AF BAR %p\n", __func__, af_ptr->af_base); af_ptr->dev = dev; diff --git a/drivers/net/octeontx2/rvu_pf.c b/drivers/net/octeontx2/rvu_pf.c index 4b00178..5f3ea1f 100644 --- a/drivers/net/octeontx2/rvu_pf.c +++ b/drivers/net/octeontx2/rvu_pf.c @@ -58,7 +58,8 @@ int rvu_pf_probe(struct udevice *dev) debug("%s: name: %s\n", __func__, dev->name); - rvu->pf_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_2, PCI_REGION_MEM); + rvu->pf_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_2, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); rvu->pfid = dev_seq(dev) + 1; // RVU PF's start from 1; rvu->dev = dev; if (!rvu_af_dev) { diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index f189524..ad7b5b8 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -449,7 +449,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, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); plat->iobase = (ulong)iobase; priv->mac_regs = (struct pch_gbe_regs *)iobase; diff --git a/drivers/nvme/nvme_pci.c b/drivers/nvme/nvme_pci.c index 5f60fb88..36bf9c5 100644 --- a/drivers/nvme/nvme_pci.c +++ b/drivers/nvme/nvme_pci.c @@ -28,8 +28,8 @@ static int nvme_probe(struct udevice *udev) sprintf(ndev->vendor, "0x%.4x", pplat->vendor); ndev->instance = trailing_strtol(udev->name); - ndev->bar = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, - PCI_REGION_MEM); + ndev->bar = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); return nvme_init(udev); } diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 47cd074..fd22034 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -67,6 +67,13 @@ config PCI_SRIOV if available on a PCI Physical Function device and probe for applicable drivers. +config PCI_ENHANCED_ALLOCATION + bool "Enable support for Enhanced Allocation of resources" + default y + help + Enable support for Enhanced Allocation which can be used by supported + devices in place of traditional BARS for allocation of resources. + config PCI_ARID bool "Enable Alternate Routing-ID support for PCI" help diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 33dda00..970ee1a 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -645,7 +645,11 @@ int dm_pci_hose_probe_bus(struct udevice *bus) return log_msg_ret("probe", -EINVAL); } - ea_pos = dm_pci_find_capability(bus, PCI_CAP_ID_EA); + if (IS_ENABLED(CONFIG_PCI_ENHANCED_ALLOCATION)) + ea_pos = dm_pci_find_capability(bus, PCI_CAP_ID_EA); + else + ea_pos = 0; + if (ea_pos) { dm_pci_read_config8(bus, ea_pos + sizeof(u32) + sizeof(u8), ®); @@ -1013,7 +1017,22 @@ static void decode_regions(struct pci_controller *hose, ofnode parent_node, if (!IS_ENABLED(CONFIG_SYS_PCI_64BIT) && type == PCI_REGION_MEM && upper_32_bits(pci_addr)) { - debug(" - beyond the 32-bit boundary, ignoring\n"); + debug(" - pci_addr beyond the 32-bit boundary, ignoring\n"); + continue; + } + + if (!IS_ENABLED(CONFIG_PHYS_64BIT) && upper_32_bits(addr)) { + debug(" - addr beyond the 32-bit boundary, ignoring\n"); + continue; + } + + if (~((pci_addr_t)0) - pci_addr < size) { + debug(" - PCI range exceeds max address, ignoring\n"); + continue; + } + + if (~((phys_addr_t)0) - addr < size) { + debug(" - phys range exceeds max address, ignoring\n"); continue; } @@ -1375,131 +1394,84 @@ void dm_pci_write_bar32(struct udevice *dev, int barnum, u32 addr) dm_pci_write_config32(dev, bar, addr); } -static int _dm_pci_bus_to_phys(struct udevice *ctlr, - pci_addr_t bus_addr, unsigned long flags, - unsigned long skip_mask, phys_addr_t *pa) +phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr, + size_t len, unsigned long mask, + unsigned long flags) { - struct pci_controller *hose = dev_get_uclass_priv(ctlr); + struct udevice *ctlr; + struct pci_controller *hose; struct pci_region *res; + pci_addr_t offset; int i; - if (hose->region_count == 0) { - *pa = bus_addr; - return 0; - } + /* The root controller has the region information */ + ctlr = pci_get_controller(dev); + hose = dev_get_uclass_priv(ctlr); + + if (hose->region_count == 0) + return bus_addr; for (i = 0; i < hose->region_count; i++) { res = &hose->regions[i]; - if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) + if ((res->flags & mask) != flags) continue; - if (res->flags & skip_mask) + if (bus_addr < res->bus_start) continue; - if (bus_addr >= res->bus_start && - (bus_addr - res->bus_start) < res->size) { - *pa = (bus_addr - res->bus_start + res->phys_start); - return 0; - } - } - - return 1; -} - -phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr, - unsigned long flags) -{ - phys_addr_t phys_addr = 0; - struct udevice *ctlr; - int ret; + offset = bus_addr - res->bus_start; + if (offset >= res->size) + continue; - /* The root controller has the region information */ - ctlr = pci_get_controller(dev); + if (len > res->size - offset) + continue; - /* - * if PCI_REGION_MEM is set we do a two pass search with preference - * on matches that don't have PCI_REGION_SYS_MEMORY set - */ - if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) { - ret = _dm_pci_bus_to_phys(ctlr, bus_addr, - flags, PCI_REGION_SYS_MEMORY, - &phys_addr); - if (!ret) - return phys_addr; + return res->phys_start + offset; } - ret = _dm_pci_bus_to_phys(ctlr, bus_addr, flags, 0, &phys_addr); - - if (ret) - puts("pci_hose_bus_to_phys: invalid physical address\n"); - - return phys_addr; + puts("pci_hose_bus_to_phys: invalid physical address\n"); + return 0; } -static int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, - unsigned long flags, unsigned long skip_mask, - pci_addr_t *ba) +pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, + size_t len, unsigned long mask, + unsigned long flags) { - struct pci_region *res; struct udevice *ctlr; - pci_addr_t bus_addr; - int i; struct pci_controller *hose; + struct pci_region *res; + phys_addr_t offset; + int i; /* The root controller has the region information */ ctlr = pci_get_controller(dev); hose = dev_get_uclass_priv(ctlr); - if (hose->region_count == 0) { - *ba = phys_addr; - return 0; - } + if (hose->region_count == 0) + return phys_addr; for (i = 0; i < hose->region_count; i++) { res = &hose->regions[i]; - if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) + if ((res->flags & mask) != flags) continue; - if (res->flags & skip_mask) + if (phys_addr < res->phys_start) continue; - bus_addr = phys_addr - res->phys_start + res->bus_start; - - if (bus_addr >= res->bus_start && - (bus_addr - res->bus_start) < res->size) { - *ba = bus_addr; - return 0; - } - } - - return 1; -} + offset = phys_addr - res->phys_start; + if (offset >= res->size) + continue; -pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, - unsigned long flags) -{ - pci_addr_t bus_addr = 0; - int ret; + if (len > res->size - offset) + continue; - /* - * if PCI_REGION_MEM is set we do a two pass search with preference - * on matches that don't have PCI_REGION_SYS_MEMORY set - */ - if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) { - ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, - PCI_REGION_SYS_MEMORY, &bus_addr); - if (!ret) - return bus_addr; + return res->bus_start + offset; } - ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 0, &bus_addr); - - if (ret) - puts("pci_hose_phys_to_bus: invalid physical address\n"); - - return bus_addr; + puts("pci_hose_phys_to_bus: invalid physical address\n"); + return 0; } static phys_addr_t dm_pci_map_ea_virt(struct udevice *dev, int ea_off, @@ -1533,8 +1505,9 @@ static phys_addr_t dm_pci_map_ea_virt(struct udevice *dev, int ea_off, return addr; } -static void *dm_pci_map_ea_bar(struct udevice *dev, int bar, int flags, - int ea_off, struct pci_child_plat *pdata) +static void *dm_pci_map_ea_bar(struct udevice *dev, int bar, size_t offset, + size_t len, int ea_off, + struct pci_child_plat *pdata) { int ea_cnt, i, entry_size; int bar_id = (bar - PCI_BASE_ADDRESS_0) >> 2; @@ -1576,14 +1549,18 @@ static void *dm_pci_map_ea_bar(struct udevice *dev, int bar, int flags, if (IS_ENABLED(CONFIG_PCI_SRIOV)) addr += dm_pci_map_ea_virt(dev, ea_off, pdata); + if (~((phys_addr_t)0) - addr < offset) + return NULL; + /* size ignored for now */ - return map_physmem(addr, 0, flags); + return map_physmem(addr + offset, len, MAP_NOCACHE); } return 0; } -void *dm_pci_map_bar(struct udevice *dev, int bar, int flags) +void *dm_pci_map_bar(struct udevice *dev, int bar, size_t offset, size_t len, + unsigned long mask, unsigned long flags) { struct pci_child_plat *pdata = dev_get_parent_plat(dev); struct udevice *udev = dev; @@ -1606,21 +1583,29 @@ void *dm_pci_map_bar(struct udevice *dev, int bar, int flags) * Incase of virtual functions, pdata will help read VF BEI * and EA entry size. */ - ea_off = dm_pci_find_capability(udev, PCI_CAP_ID_EA); + if (IS_ENABLED(CONFIG_PCI_ENHANCED_ALLOCATION)) + ea_off = dm_pci_find_capability(udev, PCI_CAP_ID_EA); + else + ea_off = 0; + if (ea_off) - return dm_pci_map_ea_bar(udev, bar, flags, ea_off, pdata); + return dm_pci_map_ea_bar(udev, bar, offset, len, ea_off, pdata); /* read BAR address */ dm_pci_read_config32(udev, bar, &bar_response); pci_bus_addr = (pci_addr_t)(bar_response & ~0xf); + if (~((pci_addr_t)0) - pci_bus_addr < offset) + return NULL; + /* - * Pass "0" as the length argument to pci_bus_to_virt. The arg - * isn't actually used on any platform because U-Boot assumes a static - * linear mapping. In the future, this could read the BAR size - * and pass that as the size if needed. + * Forward the length argument to dm_pci_bus_to_virt. The length will + * be used to check that the entire address range has been declared as + * a PCI range, but a better check would be to probe for the size of + * the bar and prevent overflow more locally. */ - return dm_pci_bus_to_virt(udev, pci_bus_addr, flags, 0, MAP_NOCACHE); + return dm_pci_bus_to_virt(udev, pci_bus_addr + offset, len, mask, flags, + MAP_NOCACHE); } static int _dm_pci_find_next_capability(struct udevice *dev, u8 pos, int cap) diff --git a/drivers/spi/octeon_spi.c b/drivers/spi/octeon_spi.c index fcabc11..c2a7ee23 100644 --- a/drivers/spi/octeon_spi.c +++ b/drivers/spi/octeon_spi.c @@ -568,7 +568,7 @@ static int octeon_spi_probe(struct udevice *dev) pci_dev_t bdf = dm_pci_get_bdf(dev); debug("SPI PCI device: %x\n", bdf); - priv->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + priv->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); /* Add base offset */ priv->base += 0x1000; diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 4f711de..1ab3061 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -36,7 +36,8 @@ 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, 0, 0, PCI_REGION_TYPE, + PCI_REGION_MEM); hcor = (struct ehci_hcor *)((uintptr_t) hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 6ddc9da..f061aec 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -18,7 +18,7 @@ static int ohci_pci_probe(struct udevice *dev) { struct ohci_regs *regs; - regs = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); + regs = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); return ohci_register(dev, regs); } diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 630bc20..11f1c02 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -27,7 +27,8 @@ static int xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr, u32 cmd; hccr = (struct xhci_hccr *)dm_pci_map_bar(dev, - PCI_BASE_ADDRESS_0, PCI_REGION_MEM); + PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, + PCI_REGION_MEM); if (!hccr) { printf("xhci-pci init cannot map PCI mem bar\n"); return -EIO; diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index 863c3fb..586263e 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -37,6 +37,15 @@ config VIRTIO_PCI This driver provides support for virtio based paravirtual device drivers over PCI. +config VIRTIO_PCI_LEGACY + bool "PCI driver for legacy virtio devices" + depends on PCI + select VIRTIO + default VIRTIO_PCI + help + This driver provides support for legacy virtio based paravirtual + device drivers over PCI. + config VIRTIO_SANDBOX bool "Sandbox driver for virtio devices" depends on SANDBOX diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile index dc88809..4c63a6c 100644 --- a/drivers/virtio/Makefile +++ b/drivers/virtio/Makefile @@ -5,7 +5,8 @@ obj-y += virtio-uclass.o virtio_ring.o obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o -obj-$(CONFIG_VIRTIO_PCI) += virtio_pci_legacy.o virtio_pci_modern.o +obj-$(CONFIG_VIRTIO_PCI) += virtio_pci_modern.o +obj-$(CONFIG_VIRTIO_PCI_LEGACY) += virtio_pci_legacy.o obj-$(CONFIG_VIRTIO_SANDBOX) += virtio_sandbox.o obj-$(CONFIG_VIRTIO_NET) += virtio_net.o obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c index 03fa5cb..cf5dfb1 100644 --- a/drivers/virtio/virtio_pci_legacy.c +++ b/drivers/virtio/virtio_pci_legacy.c @@ -319,7 +319,8 @@ static int virtio_pci_probe(struct udevice *udev) uc_priv->device = subdevice; uc_priv->vendor = subvendor; - priv->ioaddr = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, PCI_REGION_IO); + priv->ioaddr = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, 0, 0, + PCI_REGION_TYPE, PCI_REGION_IO); if (!priv->ioaddr) return -ENXIO; debug("(%s): virtio legacy device reg base %04lx\n", diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index fd8a1f3..880a12c 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -94,6 +94,7 @@ * * @common: pci transport device common register block base * @notify_base: pci transport device notify register block base + * @notify_len: pci transport device notify register block length * @device: pci transport device device-specific register block base * @device_len: pci transport device device-specific register block length * @notify_offset_multiplier: multiply queue_notify_off by this value @@ -101,6 +102,7 @@ struct virtio_pci_priv { struct virtio_pci_common_cfg __iomem *common; void __iomem *notify_base; + u32 notify_len; void __iomem *device; u32 device_len; u32 notify_offset_multiplier; @@ -114,7 +116,11 @@ static int virtio_pci_get_config(struct udevice *udev, unsigned int offset, __le16 w; __le32 l; - WARN_ON(offset + len > priv->device_len); + if (!priv->device) + return -ENOSYS; + + if (offset + len > priv->device_len) + return -EINVAL; switch (len) { case 1: @@ -136,7 +142,7 @@ static int virtio_pci_get_config(struct udevice *udev, unsigned int offset, memcpy(buf + sizeof(l), &l, sizeof(l)); break; default: - WARN_ON(true); + return -EINVAL; } return 0; @@ -150,7 +156,11 @@ static int virtio_pci_set_config(struct udevice *udev, unsigned int offset, __le16 w; __le32 l; - WARN_ON(offset + len > priv->device_len); + if (!priv->device) + return -ENOSYS; + + if (offset + len > priv->device_len) + return -EINVAL; switch (len) { case 1: @@ -172,7 +182,7 @@ static int virtio_pci_set_config(struct udevice *udev, unsigned int offset, iowrite32(le32_to_cpu(l), priv->device + offset + sizeof(l)); break; default: - WARN_ON(true); + return -EINVAL; } return 0; @@ -365,11 +375,19 @@ static int virtio_pci_notify(struct udevice *udev, struct virtqueue *vq) off = ioread16(&priv->common->queue_notify_off); /* + * Check the effective offset is in bounds and leaves space for the + * notification, which is just a single 16-bit value since + * VIRTIO_F_NOTIFICATION_DATA isn't negotiated by the drivers. + */ + off *= priv->notify_offset_multiplier; + if (off > priv->notify_len - sizeof(u16)) + return -EIO; + + /* * We write the queue's selector into the notification register * to signal the other end */ - iowrite16(vq->index, - priv->notify_base + off * priv->notify_offset_multiplier); + iowrite16(vq->index, priv->notify_base + off); return 0; } @@ -379,28 +397,51 @@ static int virtio_pci_notify(struct udevice *udev, struct virtqueue *vq) * * @udev: the transport device * @cfg_type: the VIRTIO_PCI_CAP_* value we seek + * @cap_size: expected size of the capability + * @cap: capability read from the config space * * Return: offset of the configuration structure */ -static int virtio_pci_find_capability(struct udevice *udev, u8 cfg_type) +static int virtio_pci_find_capability(struct udevice *udev, u8 cfg_type, + size_t cap_size, + struct virtio_pci_cap *cap) { int pos; int offset; - u8 type, bar; + + assert(cap_size >= sizeof(struct virtio_pci_cap)); + assert(cap_size <= PCI_CFG_SPACE_SIZE); + + if (!cap) + return 0; for (pos = dm_pci_find_capability(udev, PCI_CAP_ID_VNDR); pos > 0; pos = dm_pci_find_next_capability(udev, pos, PCI_CAP_ID_VNDR)) { + /* Ensure the capability is within bounds */ + if (PCI_CFG_SPACE_SIZE - cap_size < pos) + return 0; + + offset = pos + offsetof(struct virtio_pci_cap, cap_vndr); + dm_pci_read_config8(udev, offset, &cap->cap_vndr); + offset = pos + offsetof(struct virtio_pci_cap, cap_next); + dm_pci_read_config8(udev, offset, &cap->cap_next); + offset = pos + offsetof(struct virtio_pci_cap, cap_len); + dm_pci_read_config8(udev, offset, &cap->cap_len); offset = pos + offsetof(struct virtio_pci_cap, cfg_type); - dm_pci_read_config8(udev, offset, &type); + dm_pci_read_config8(udev, offset, &cap->cfg_type); offset = pos + offsetof(struct virtio_pci_cap, bar); - dm_pci_read_config8(udev, offset, &bar); + dm_pci_read_config8(udev, offset, &cap->bar); + offset = pos + offsetof(struct virtio_pci_cap, offset); + dm_pci_read_config32(udev, offset, &cap->offset); + offset = pos + offsetof(struct virtio_pci_cap, length); + dm_pci_read_config32(udev, offset, &cap->length); /* Ignore structures with reserved BAR values */ - if (bar > 0x5) + if (cap->bar > 0x5) continue; - if (type == cfg_type) + if (cap->cfg_type == cfg_type) return pos; } @@ -411,35 +452,24 @@ static int virtio_pci_find_capability(struct udevice *udev, u8 cfg_type) * virtio_pci_map_capability - map base address of the capability * * @udev: the transport device - * @off: offset of the configuration structure + * @cap: capability to map * * Return: base address of the capability */ -static void __iomem *virtio_pci_map_capability(struct udevice *udev, int off) +static void __iomem *virtio_pci_map_capability(struct udevice *udev, + const struct virtio_pci_cap *cap) { - u8 bar; - u32 offset; - ulong base; - void __iomem *p; - - if (!off) - return NULL; - - offset = off + offsetof(struct virtio_pci_cap, bar); - dm_pci_read_config8(udev, offset, &bar); - offset = off + offsetof(struct virtio_pci_cap, offset); - dm_pci_read_config32(udev, offset, &offset); - /* - * TODO: adding 64-bit BAR support - * - * Per spec, the BAR is permitted to be either 32-bit or 64-bit. - * For simplicity, only read the BAR address as 32-bit. + * Find the corresponding memory region that isn't system memory but is + * writable. */ - base = dm_pci_read_bar32(udev, bar); - p = (void __iomem *)base + offset; + unsigned long mask = + PCI_REGION_TYPE | PCI_REGION_SYS_MEMORY | PCI_REGION_RO; + unsigned long flags = PCI_REGION_MEM; + u8 *p = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0 + cap->bar, cap->offset, + cap->length, mask, flags); - return p; + return (void __iomem *)p; } static int virtio_pci_bind(struct udevice *udev) @@ -462,6 +492,7 @@ static int virtio_pci_probe(struct udevice *udev) u16 subvendor; u8 revision; int common, notify, device; + struct virtio_pci_cap common_cap, notify_cap, device_cap; int offset; /* We only own devices >= 0x1040 and <= 0x107f: leave the rest. */ @@ -477,34 +508,60 @@ static int virtio_pci_probe(struct udevice *udev) uc_priv->vendor = subvendor; /* Check for a common config: if not, use legacy mode (bar 0) */ - common = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_COMMON_CFG); + common = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_COMMON_CFG, + sizeof(struct virtio_pci_cap), + &common_cap); if (!common) { printf("(%s): leaving for legacy driver\n", udev->name); return -ENODEV; } + if (common_cap.length < sizeof(struct virtio_pci_common_cfg)) { + printf("(%s): virtio common config too small\n", udev->name); + return -EINVAL; + } + /* If common is there, notify should be too */ - notify = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_NOTIFY_CFG); + notify = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_NOTIFY_CFG, + sizeof(struct virtio_pci_notify_cap), + ¬ify_cap); if (!notify) { printf("(%s): missing capabilities %i/%i\n", udev->name, common, notify); return -EINVAL; } + /* Map configuration structures */ + priv->common = virtio_pci_map_capability(udev, &common_cap); + if (!priv->common) { + printf("(%s): could not map common config\n", udev->name); + return -EINVAL; + } + + priv->notify_len = notify_cap.length; + priv->notify_base = virtio_pci_map_capability(udev, ¬ify_cap); + if (!priv->notify_base) { + printf("(%s): could not map notify config\n", udev->name); + return -EINVAL; + } + /* * Device capability is only mandatory for devices that have * device-specific configuration. */ - device = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_DEVICE_CFG); + device = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_DEVICE_CFG, + sizeof(struct virtio_pci_cap), + &device_cap); if (device) { - offset = notify + offsetof(struct virtio_pci_cap, length); - dm_pci_read_config32(udev, offset, &priv->device_len); + priv->device_len = device_cap.length; + priv->device = virtio_pci_map_capability(udev, &device_cap); + if (!priv->device) { + printf("(%s): could not map device config\n", + udev->name); + return -EINVAL; + } } - /* Map configuration structures */ - priv->common = virtio_pci_map_capability(udev, common); - priv->notify_base = virtio_pci_map_capability(udev, notify); - priv->device = virtio_pci_map_capability(udev, device); debug("(%p): common @ %p, notify base @ %p, device @ %p\n", udev, priv->common, priv->notify_base, priv->device); diff --git a/include/pci.h b/include/pci.h index 5dbdcb0..d7ed35d 100644 --- a/include/pci.h +++ b/include/pci.h @@ -1313,26 +1313,30 @@ void dm_pci_write_bar32(struct udevice *dev, int barnum, u32 addr); u32 dm_pci_read_bar32(const struct udevice *dev, int barnum); /** - * dm_pci_bus_to_phys() - convert a PCI bus address to a physical address + * dm_pci_bus_to_phys() - convert a PCI bus address range to a physical address * * @dev: Device containing the PCI address * @addr: PCI address to convert + * @len: Length of the address range + * @mask: Mask to match flags for the region type * @flags: Flags for the region type (PCI_REGION_...) * Return: physical address corresponding to that PCI bus address */ -phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t addr, - unsigned long flags); +phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t addr, size_t len, + unsigned long mask, unsigned long flags); /** * dm_pci_phys_to_bus() - convert a physical address to a PCI bus address * * @dev: Device containing the bus address * @addr: Physical address to convert + * @len: Length of the address range + * @mask: Mask to match flags for the region type * @flags: Flags for the region type (PCI_REGION_...) * Return: PCI bus address corresponding to that physical address */ -pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t addr, - unsigned long flags); +pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t addr, size_t len, + unsigned long mask, unsigned long flags); /** * dm_pci_map_bar() - get a virtual address associated with a BAR region @@ -1346,10 +1350,14 @@ pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t addr, * * @dev: Device to check * @bar: Bar register offset (PCI_BASE_ADDRESS_...) + * @offset: Offset from the base to map + * @len: Length to map + * @mask: Mask to match flags for the region type * @flags: Flags for the region type (PCI_REGION_...) * @return: pointer to the virtual address to use or 0 on error */ -void *dm_pci_map_bar(struct udevice *dev, int bar, int flags); +void *dm_pci_map_bar(struct udevice *dev, int bar, size_t offset, size_t len, + unsigned long mask, unsigned long flags); /** * dm_pci_find_next_capability() - find a capability starting from an offset @@ -1453,28 +1461,34 @@ int dm_pci_find_ext_capability(struct udevice *dev, int cap); int dm_pci_flr(struct udevice *dev); #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) \ - map_physmem(dm_pci_bus_to_phys(dev, (addr), (flags)), \ - (len), (map_flags)) + dm_pci_phys_to_bus(dev, (virt_to_phys(addr)), 0, PCI_REGION_TYPE, (flags)) +#define dm_pci_bus_to_virt(dev, addr, len, mask, flags, map_flags) \ +({ \ + size_t _len = (len); \ + phys_addr_t phys_addr = dm_pci_bus_to_phys((dev), (addr), _len, \ + (mask), (flags)); \ + map_physmem(phys_addr, _len, (map_flags)); \ +}) #define dm_pci_phys_to_mem(dev, addr) \ - dm_pci_phys_to_bus((dev), (addr), PCI_REGION_MEM) + dm_pci_phys_to_bus((dev), (addr), 0, PCI_REGION_TYPE, PCI_REGION_MEM) #define dm_pci_mem_to_phys(dev, addr) \ - dm_pci_bus_to_phys((dev), (addr), PCI_REGION_MEM) + dm_pci_bus_to_phys((dev), (addr), 0, PCI_REGION_TYPE, PCI_REGION_MEM) #define dm_pci_phys_to_io(dev, addr) \ - dm_pci_phys_to_bus((dev), (addr), PCI_REGION_IO) + dm_pci_phys_to_bus((dev), (addr), 0, PCI_REGION_TYPE, PCI_REGION_IO) #define dm_pci_io_to_phys(dev, addr) \ - dm_pci_bus_to_phys((dev), (addr), PCI_REGION_IO) + dm_pci_bus_to_phys((dev), (addr), 0, PCI_REGION_TYPE, PCI_REGION_IO) #define dm_pci_virt_to_mem(dev, addr) \ dm_pci_virt_to_bus((dev), (addr), PCI_REGION_MEM) #define dm_pci_mem_to_virt(dev, addr, len, map_flags) \ - dm_pci_bus_to_virt((dev), (addr), PCI_REGION_MEM, (len), (map_flags)) + dm_pci_bus_to_virt((dev), (addr), (len), PCI_REGION_TYPE, \ + PCI_REGION_MEM, (map_flags)) #define dm_pci_virt_to_io(dev, addr) \ dm_pci_virt_to_bus((dev), (addr), PCI_REGION_IO) #define dm_pci_io_to_virt(dev, addr, len, map_flags) \ - dm_pci_bus_to_virt((dev), (addr), PCI_REGION_IO, (len), (map_flags)) + dm_pci_bus_to_virt((dev), (addr), (len), PCI_REGION_TYPE, \ + PCI_REGION_IO, (map_flags)) /** * dm_pci_find_device() - find a device by vendor/device ID diff --git a/test/dm/pci.c b/test/dm/pci.c index 00e4440..70a736c 100644 --- a/test/dm/pci.c +++ b/test/dm/pci.c @@ -268,27 +268,27 @@ static int dm_test_pci_ea(struct unit_test_state *uts) ut_asserteq(PCI_CAP_ID_EA_OFFSET, cap); /* test swap case in BAR 1 */ - bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_0, 0); + bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, 0); ut_assertnonnull(bar); *(int *)bar = 2; /* swap upper/lower */ - bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_1, 0); + bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_1, 0, 0, PCI_REGION_TYPE, 0); ut_assertnonnull(bar); strcpy(bar, "ea TEST"); unmap_sysmem(bar); - bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_1, 0); + bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_1, 0, 0, PCI_REGION_TYPE, 0); ut_assertnonnull(bar); ut_asserteq_str("EA test", bar); /* test magic values in BARs2, 4; BAR 3 is n/a */ - bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_2, 0); + bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_2, 0, 0, PCI_REGION_TYPE, 0); ut_assertnonnull(bar); ut_asserteq(PCI_EA_BAR2_MAGIC, *(u32 *)bar); - bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_3, 0); + bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_3, 0, 0, PCI_REGION_TYPE, 0); ut_assertnull(bar); - bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_4, 0); + bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_4, 0, 0, PCI_REGION_TYPE, 0); ut_assertnonnull(bar); ut_asserteq(PCI_EA_BAR4_MAGIC, *(u32 *)bar); @@ -376,3 +376,109 @@ static int dm_test_pci_region_multi(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_pci_region_multi, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* + * Test the translation of PCI bus addresses to physical addresses using the + * ranges from bus#1. + */ +static int dm_test_pci_bus_to_phys(struct unit_test_state *uts) +{ + unsigned long mask = PCI_REGION_TYPE; + unsigned long flags = PCI_REGION_MEM; + struct udevice *dev; + phys_addr_t phys_addr; + + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x08, 0), &dev)); + + /* Before any of the ranges. */ + phys_addr = dm_pci_bus_to_phys(dev, 0x20000000, 0x400, mask, flags); + ut_asserteq(0, phys_addr); + + /* Identity range: whole, start, mid, end */ + phys_addr = dm_pci_bus_to_phys(dev, 0x2ffff000, 0x2000, mask, flags); + ut_asserteq(0, phys_addr); + phys_addr = dm_pci_bus_to_phys(dev, 0x30000000, 0x2000, mask, flags); + ut_asserteq(0x30000000, phys_addr); + phys_addr = dm_pci_bus_to_phys(dev, 0x30000000, 0x1000, mask, flags); + ut_asserteq(0x30000000, phys_addr); + phys_addr = dm_pci_bus_to_phys(dev, 0x30000abc, 0x12, mask, flags); + ut_asserteq(0x30000abc, phys_addr); + phys_addr = dm_pci_bus_to_phys(dev, 0x30000800, 0x1800, mask, flags); + ut_asserteq(0x30000800, phys_addr); + phys_addr = dm_pci_bus_to_phys(dev, 0x30008000, 0x1801, mask, flags); + ut_asserteq(0, phys_addr); + + /* Translated range: whole, start, mid, end */ + phys_addr = dm_pci_bus_to_phys(dev, 0x30fff000, 0x2000, mask, flags); + ut_asserteq(0, phys_addr); + phys_addr = dm_pci_bus_to_phys(dev, 0x31000000, 0x2000, mask, flags); + ut_asserteq(0x3e000000, phys_addr); + phys_addr = dm_pci_bus_to_phys(dev, 0x31000000, 0x1000, mask, flags); + ut_asserteq(0x3e000000, phys_addr); + phys_addr = dm_pci_bus_to_phys(dev, 0x31000abc, 0x12, mask, flags); + ut_asserteq(0x3e000abc, phys_addr); + phys_addr = dm_pci_bus_to_phys(dev, 0x31000800, 0x1800, mask, flags); + ut_asserteq(0x3e000800, phys_addr); + phys_addr = dm_pci_bus_to_phys(dev, 0x31008000, 0x1801, mask, flags); + ut_asserteq(0, phys_addr); + + /* Beyond all of the ranges. */ + phys_addr = dm_pci_bus_to_phys(dev, 0x32000000, 0x400, mask, flags); + ut_asserteq(0, phys_addr); + + return 0; +} +DM_TEST(dm_test_pci_bus_to_phys, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* + * Test the translation of physical addresses to PCI bus addresses using the + * ranges from bus#1. + */ +static int dm_test_pci_phys_to_bus(struct unit_test_state *uts) +{ + unsigned long mask = PCI_REGION_TYPE; + unsigned long flags = PCI_REGION_MEM; + struct udevice *dev; + pci_addr_t pci_addr; + + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x08, 0), &dev)); + + /* Before any of the ranges. */ + pci_addr = dm_pci_phys_to_bus(dev, 0x20000000, 0x400, mask, flags); + ut_asserteq(0, pci_addr); + + /* Identity range: partial overlap, whole, start, mid, end */ + pci_addr = dm_pci_phys_to_bus(dev, 0x2ffff000, 0x2000, mask, flags); + ut_asserteq(0, pci_addr); + pci_addr = dm_pci_phys_to_bus(dev, 0x30000000, 0x2000, mask, flags); + ut_asserteq(0x30000000, pci_addr); + pci_addr = dm_pci_phys_to_bus(dev, 0x30000000, 0x1000, mask, flags); + ut_asserteq(0x30000000, pci_addr); + pci_addr = dm_pci_phys_to_bus(dev, 0x30000abc, 0x12, mask, flags); + ut_asserteq(0x30000abc, pci_addr); + pci_addr = dm_pci_phys_to_bus(dev, 0x30000800, 0x1800, mask, flags); + ut_asserteq(0x30000800, pci_addr); + pci_addr = dm_pci_phys_to_bus(dev, 0x30008000, 0x1801, mask, flags); + ut_asserteq(0, pci_addr); + + /* Translated range: partial overlap, whole, start, mid, end */ + pci_addr = dm_pci_phys_to_bus(dev, 0x3dfff000, 0x2000, mask, flags); + ut_asserteq(0, pci_addr); + pci_addr = dm_pci_phys_to_bus(dev, 0x3e000000, 0x2000, mask, flags); + ut_asserteq(0x31000000, pci_addr); + pci_addr = dm_pci_phys_to_bus(dev, 0x3e000000, 0x1000, mask, flags); + ut_asserteq(0x31000000, pci_addr); + pci_addr = dm_pci_phys_to_bus(dev, 0x3e000abc, 0x12, mask, flags); + ut_asserteq(0x31000abc, pci_addr); + pci_addr = dm_pci_phys_to_bus(dev, 0x3e000800, 0x1800, mask, flags); + ut_asserteq(0x31000800, pci_addr); + pci_addr = dm_pci_phys_to_bus(dev, 0x3e008000, 0x1801, mask, flags); + ut_asserteq(0, pci_addr); + + /* Beyond all of the ranges. */ + pci_addr = dm_pci_phys_to_bus(dev, 0x3f000000, 0x400, mask, flags); + ut_asserteq(0, pci_addr); + + return 0; +} +DM_TEST(dm_test_pci_phys_to_bus, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |