aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/sandbox/dts/test.dts2
-rw-r--r--arch/x86/cpu/baytrail/cpu.c2
-rw-r--r--drivers/ata/ahci.c9
-rw-r--r--drivers/ata/sata_sil.c6
-rw-r--r--drivers/bios_emulator/atibios.c4
-rw-r--r--drivers/gpio/octeon_gpio.c2
-rw-r--r--drivers/i2c/designware_i2c_pci.c3
-rw-r--r--drivers/i2c/intel_i2c.c2
-rw-r--r--drivers/i2c/octeon_i2c.c2
-rw-r--r--drivers/mmc/octeontx_hsmmc.c2
-rw-r--r--drivers/mmc/pci_mmc.c2
-rw-r--r--drivers/mtd/nand/raw/octeontx_bch.c6
-rw-r--r--drivers/mtd/nand/raw/octeontx_nand.c2
-rw-r--r--drivers/net/bnxt/bnxt.c9
-rw-r--r--drivers/net/e1000.c4
-rw-r--r--drivers/net/fsl_enetc.c2
-rw-r--r--drivers/net/fsl_enetc_mdio.c2
-rw-r--r--drivers/net/mscc_eswitch/felix_switch.c4
-rw-r--r--drivers/net/octeontx/bgx.c2
-rw-r--r--drivers/net/octeontx/nic_main.c2
-rw-r--r--drivers/net/octeontx/nicvf_main.c2
-rw-r--r--drivers/net/octeontx/smi.c2
-rw-r--r--drivers/net/octeontx2/cgx.c2
-rw-r--r--drivers/net/octeontx2/rvu_af.c2
-rw-r--r--drivers/net/octeontx2/rvu_pf.c3
-rw-r--r--drivers/net/pch_gbe.c2
-rw-r--r--drivers/nvme/nvme_pci.c4
-rw-r--r--drivers/pci/Kconfig7
-rw-r--r--drivers/pci/pci-uclass.c185
-rw-r--r--drivers/spi/octeon_spi.c2
-rw-r--r--drivers/usb/host/ehci-pci.c3
-rw-r--r--drivers/usb/host/ohci-pci.c2
-rw-r--r--drivers/usb/host/xhci-pci.c3
-rw-r--r--drivers/virtio/Kconfig9
-rw-r--r--drivers/virtio/Makefile3
-rw-r--r--drivers/virtio/virtio_pci_legacy.c3
-rw-r--r--drivers/virtio/virtio_pci_modern.c143
-rw-r--r--include/pci.h46
-rw-r--r--test/dm/pci.c118
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),
&reg);
@@ -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),
+ &notify_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, &notify_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);