summaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/Kconfig10
-rw-r--r--drivers/pci/pci_auto.c16
-rw-r--r--drivers/pci/pcie_xilinx.c53
3 files changed, 58 insertions, 21 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 4f876d39875..409049137cc 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -67,6 +67,7 @@ config PCI_CONFIG_HOST_BRIDGE
config PCI_MAP_SYSTEM_MEMORY
bool "Map local system memory from a virtual base address"
depends on MIPS
+ default y if !ARCH_MAP_SYSMEM
help
Say Y if base address of system memory is being used as a virtual address
instead of a physical address (e.g. on MIPS). The PCI core will then remap
@@ -75,6 +76,15 @@ config PCI_MAP_SYSTEM_MEMORY
This should only be required on MIPS where CFG_SYS_SDRAM_BASE is still
being used as virtual address.
+config PCI_BRIDGE_MEM_ALIGNMENT
+ hex "Alignment boundary of PCI memory resource allocation"
+ default 0x10000 if TARGET_BOSTON
+ default 0x100000
+ help
+ Specify a boundary for alignment of PCI memory resource allocation,
+ this is normally 0x100000 (1MB) but can be reduced to accommodate
+ hardware with tight bridge range if hardware allows.
+
config PCI_SRIOV
bool "Enable Single Root I/O Virtualization support for PCI"
help
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
index e68e31a8227..4a1c782be36 100644
--- a/drivers/pci/pci_auto.c
+++ b/drivers/pci/pci_auto.c
@@ -373,8 +373,8 @@ void dm_pciauto_prescan_setup_bridge(struct udevice *dev, int sub_bus)
dm_pci_write_config8(dev, PCI_SUBORDINATE_BUS, 0xff);
if (pci_mem) {
- /* Round memory allocator to 1MB boundary */
- pciauto_region_align(pci_mem, 0x100000);
+ /* Round memory allocator */
+ pciauto_region_align(pci_mem, CONFIG_PCI_BRIDGE_MEM_ALIGNMENT);
/*
* Set up memory and I/O filter limits, assume 32-bit
@@ -388,8 +388,8 @@ void dm_pciauto_prescan_setup_bridge(struct udevice *dev, int sub_bus)
}
if (pci_prefetch) {
- /* Round memory allocator to 1MB boundary */
- pciauto_region_align(pci_prefetch, 0x100000);
+ /* Round memory allocator */
+ pciauto_region_align(pci_prefetch, CONFIG_PCI_BRIDGE_MEM_ALIGNMENT);
/*
* Set up memory and I/O filter limits, assume 32-bit
@@ -466,8 +466,8 @@ void dm_pciauto_postscan_setup_bridge(struct udevice *dev, int sub_bus)
dm_pci_write_config8(dev, PCI_SUBORDINATE_BUS, sub_bus - dev_seq(ctlr));
if (pci_mem) {
- /* Round memory allocator to 1MB boundary */
- pciauto_region_align(pci_mem, 0x100000);
+ /* Round memory allocator */
+ pciauto_region_align(pci_mem, CONFIG_PCI_BRIDGE_MEM_ALIGNMENT);
dm_pci_write_config16(dev, PCI_MEMORY_LIMIT,
((pci_mem->bus_lower - 1) >> 16) &
@@ -481,8 +481,8 @@ void dm_pciauto_postscan_setup_bridge(struct udevice *dev, int sub_bus)
&prefechable_64);
prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK;
- /* Round memory allocator to 1MB boundary */
- pciauto_region_align(pci_prefetch, 0x100000);
+ /* Round memory allocator */
+ pciauto_region_align(pci_prefetch, CONFIG_PCI_BRIDGE_MEM_ALIGNMENT);
dm_pci_write_config16(dev, PCI_PREF_MEMORY_LIMIT,
(((pci_prefetch->bus_lower - 1) >> 16) &
diff --git a/drivers/pci/pcie_xilinx.c b/drivers/pci/pcie_xilinx.c
index a674ab04bee..63058e8e7c5 100644
--- a/drivers/pci/pcie_xilinx.c
+++ b/drivers/pci/pcie_xilinx.c
@@ -18,14 +18,19 @@
*/
struct xilinx_pcie {
void *cfg_base;
+ pci_size_t size;
+ int first_busno;
};
/* Register definitions */
-#define XILINX_PCIE_REG_PSCR 0x144
-#define XILINX_PCIE_REG_PSCR_LNKUP BIT(11)
-#define XILINX_PCIE_REG_RPSC 0x148
-#define XILINX_PCIE_REG_RPSC_BEN BIT(0)
-
+#define XILINX_PCIE_REG_BRIDGE_INFO 0x130
+#define XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_SHIFT 16
+#define XILINX_PCIE_REG_BRIDGE_INFO_ECAMSZ_MASK (0x7 << 16)
+#define XILINX_PCIE_REG_INT_MASK 0x13c
+#define XILINX_PCIE_REG_PSCR 0x144
+#define XILINX_PCIE_REG_PSCR_LNKUP BIT(11)
+#define XILINX_PCIE_REG_RPSC 0x148
+#define XILINX_PCIE_REG_RPSC_BEN BIT(0)
/**
* pcie_xilinx_link_up() - Check whether the PCIe link is up
* @pcie: Pointer to the PCI controller state
@@ -61,14 +66,18 @@ static int pcie_xilinx_config_address(const struct udevice *udev, pci_dev_t bdf,
uint offset, void **paddress)
{
struct xilinx_pcie *pcie = dev_get_priv(udev);
- unsigned int bus = PCI_BUS(bdf);
+ unsigned int bus = PCI_BUS(bdf) - pcie->first_busno;
unsigned int dev = PCI_DEV(bdf);
unsigned int func = PCI_FUNC(bdf);
+ int num_buses = DIV_ROUND_UP(pcie->size, 1 << 16);
void *addr;
if ((bus > 0) && !pcie_xilinx_link_up(pcie))
return -ENODEV;
+ if (bus > num_buses)
+ return -ENODEV;
+
/*
* Busses 0 (host-PCIe bridge) & 1 (its immediate child) are
* limited to a single device each.
@@ -142,20 +151,37 @@ static int pcie_xilinx_of_to_plat(struct udevice *dev)
struct xilinx_pcie *pcie = dev_get_priv(dev);
fdt_addr_t addr;
fdt_size_t size;
- u32 rpsc;
addr = dev_read_addr_size(dev, &size);
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
- pcie->cfg_base = devm_ioremap(dev, addr, size);
- if (IS_ERR(pcie->cfg_base))
- return PTR_ERR(pcie->cfg_base);
+ pcie->cfg_base = map_physmem(addr, size, MAP_NOCACHE);
+ if (!pcie->cfg_base)
+ return -ENOMEM;
+ pcie->size = size;
+ return 0;
+}
- /* Enable the Bridge enable bit */
- rpsc = __raw_readl(pcie->cfg_base + XILINX_PCIE_REG_RPSC);
+static int pci_xilinx_probe(struct udevice *dev)
+{
+ struct xilinx_pcie *pcie = dev_get_priv(dev);
+ u32 rpsc;
+ int num_buses = DIV_ROUND_UP(pcie->size, 1 << 16);
+
+ pcie->first_busno = dev_seq(dev);
+
+ /* Disable all interrupts */
+ writel(0, pcie->cfg_base + XILINX_PCIE_REG_INT_MASK);
+
+ /* Enable the bridge */
+ rpsc = readl(pcie->cfg_base + XILINX_PCIE_REG_RPSC);
rpsc |= XILINX_PCIE_REG_RPSC_BEN;
- __raw_writel(rpsc, pcie->cfg_base + XILINX_PCIE_REG_RPSC);
+ writel(rpsc, pcie->cfg_base + XILINX_PCIE_REG_RPSC);
+
+ /* Enable access to all possible subordinate buses */
+ writel((0 << 0) | (1 << 8) | (num_buses << 16),
+ pcie->cfg_base + PCI_PRIMARY_BUS);
return 0;
}
@@ -176,5 +202,6 @@ U_BOOT_DRIVER(pcie_xilinx) = {
.of_match = pcie_xilinx_ids,
.ops = &pcie_xilinx_ops,
.of_to_plat = pcie_xilinx_of_to_plat,
+ .probe = pci_xilinx_probe,
.priv_auto = sizeof(struct xilinx_pcie),
};