summaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/Kconfig27
-rw-r--r--drivers/pci/Makefile1
-rw-r--r--drivers/pci/pci-rcar-gen2.c7
-rw-r--r--drivers/pci/pci-rcar-gen3.c5
-rw-r--r--drivers/pci/pci-uclass.c10
-rw-r--r--drivers/pci/pci_mpc85xx.c11
-rw-r--r--drivers/pci/pcie_brcmstb.c387
-rw-r--r--drivers/pci/pcie_dw_amd.c250
-rw-r--r--drivers/pci/pcie_dw_mvebu.c5
-rw-r--r--drivers/pci/pcie_dw_qcom.c2
-rw-r--r--drivers/pci/pcie_imx.c4
-rw-r--r--drivers/pci/pcie_layerscape.h3
-rw-r--r--drivers/pci/pcie_layerscape_ep.c24
13 files changed, 655 insertions, 81 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 8fc57895a78..9ffccc3a80b 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -101,11 +101,11 @@ config PCI_ENHANCED_ALLOCATION
devices in place of traditional BARS for allocation of resources.
config PCI_ARID
- bool "Enable Alternate Routing-ID support for PCI"
- help
- Say Y here if you want to enable Alternate Routing-ID capability
- support on PCI devices. This helps to skip some devices in BDF
- scan that are not present.
+ bool "Enable Alternate Routing-ID support for PCI"
+ help
+ Say Y here if you want to enable Alternate Routing-ID capability
+ support on PCI devices. This helps to skip some devices in BDF
+ scan that are not present.
config PCI_SCAN_SHOW
bool "Show PCI devices during startup"
@@ -287,7 +287,7 @@ config PCI_IOMMU_EXTRA_MAPPINGS
the node describing the PCI controller.
The intent is to cover SR-IOV scenarios which need mappings for VFs
and PCI hot-plug scenarios. More documentation can be found under:
- arch/arm/cpu/armv8/fsl-layerscape/doc/README.pci_iommu_extra
+ arch/arm/cpu/armv8/fsl-layerscape/doc/README.pci_iommu_extra
config PCIE_LAYERSCAPE_EP
bool "Layerscape PCIe Endpoint mode support"
@@ -440,8 +440,8 @@ config PCIE_XILINX_NWL
bool "Xilinx NWL PCIe controller"
depends on ARCH_ZYNQMP
help
- Say 'Y' here if you want support for Xilinx / AMD NWL PCIe
- controller as Root Port.
+ Say 'Y' here if you want support for Xilinx / AMD NWL PCIe
+ controller as Root Port.
config PCIE_PLDA_COMMON
bool
@@ -456,6 +456,17 @@ config PCIE_STARFIVE_JH7110
Say Y here if you want to enable PLDA XpressRich PCIe controller
support on StarFive JH7110 SoC.
+config PCIE_DW_AMD
+ bool "AMD Versal2 DW PCIe host controller"
+ depends on ARCH_VERSAL2
+ depends on DM_GPIO
+ select PCIE_DW_COMMON
+ select SYS_PCI_64BIT
+ help
+ Say Y here to enable support for the AMD Versal Gen 2 PCIe
+ host controller. This is a DesignWare-based PCIe controller
+ used in AMD Versal Gen 2 SoCs.
+
config PCIE_DW_IMX
bool "i.MX DW PCIe controller support"
depends on ARCH_IMX8M || ARCH_IMX9
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 98f3c226f63..e6d71fd172b 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -56,4 +56,5 @@ obj-$(CONFIG_PCIE_UNIPHIER) += pcie_uniphier.o
obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
obj-$(CONFIG_PCIE_PLDA_COMMON) += pcie_plda_common.o
obj-$(CONFIG_PCIE_STARFIVE_JH7110) += pcie_starfive_jh7110.o
+obj-$(CONFIG_PCIE_DW_AMD) += pcie_dw_amd.o
obj-$(CONFIG_PCIE_DW_IMX) += pcie_dw_imx.o
diff --git a/drivers/pci/pci-rcar-gen2.c b/drivers/pci/pci-rcar-gen2.c
index 08d5c4fbb8b..53cb0916741 100644
--- a/drivers/pci/pci-rcar-gen2.c
+++ b/drivers/pci/pci-rcar-gen2.c
@@ -10,6 +10,7 @@
#include <clk.h>
#include <dm.h>
#include <errno.h>
+#include <fdtdec.h>
#include <pci.h>
#include <linux/bitops.h>
@@ -235,9 +236,9 @@ static int rcar_gen2_pci_of_to_plat(struct udevice *dev)
{
struct rcar_gen2_pci_priv *priv = dev_get_priv(dev);
- priv->cfg_base = devfdt_get_addr_index(dev, 0);
- priv->mem_base = devfdt_get_addr_index(dev, 1);
- if (!priv->cfg_base || !priv->mem_base)
+ priv->cfg_base = dev_read_addr_index(dev, 0);
+ priv->mem_base = dev_read_addr_index(dev, 1);
+ if (priv->cfg_base == FDT_ADDR_T_NONE || priv->mem_base == FDT_ADDR_T_NONE)
return -EINVAL;
return 0;
diff --git a/drivers/pci/pci-rcar-gen3.c b/drivers/pci/pci-rcar-gen3.c
index d4b4037ce19..1925d968c16 100644
--- a/drivers/pci/pci-rcar-gen3.c
+++ b/drivers/pci/pci-rcar-gen3.c
@@ -19,6 +19,7 @@
#include <clk.h>
#include <dm.h>
#include <errno.h>
+#include <fdtdec.h>
#include <pci.h>
#include <wait_bit.h>
#include <linux/bitops.h>
@@ -391,8 +392,8 @@ static int rcar_gen3_pcie_of_to_plat(struct udevice *dev)
{
struct rcar_gen3_pcie_priv *priv = dev_get_plat(dev);
- priv->regs = devfdt_get_addr_index(dev, 0);
- if (!priv->regs)
+ priv->regs = dev_read_addr_index(dev, 0);
+ if (priv->regs == FDT_ADDR_T_NONE)
return -EINVAL;
return 0;
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 83b76d01f24..4bdd1f7477f 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -927,7 +927,7 @@ int pci_bind_bus_devices(struct udevice *bus)
if (PCI_FUNC(bdf) && !found_multi)
continue;
- if (only_one_child(bus) && (PCI_MASK_BUS(bdf) > 0))
+ if (only_one_child(bus) && (PCI_DEV(bdf) > 0))
continue;
/* Check only the first access, we don't expect problems */
@@ -1126,14 +1126,14 @@ static int decode_regions(struct pci_controller *hose, ofnode parent_node,
return 0;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
- if (bd->bi_dram[i].size) {
- phys_addr_t start = bd->bi_dram[i].start;
+ if (gd->dram[i].size) {
+ phys_addr_t start = gd->dram[i].start;
if (IS_ENABLED(CONFIG_PCI_MAP_SYSTEM_MEMORY))
- start = virt_to_phys((void *)(uintptr_t)bd->bi_dram[i].start);
+ start = virt_to_phys((void *)(uintptr_t)gd->dram[i].start);
pci_set_region(hose->regions + hose->region_count++,
- start, start, bd->bi_dram[i].size,
+ start, start, gd->dram[i].size,
PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
}
}
diff --git a/drivers/pci/pci_mpc85xx.c b/drivers/pci/pci_mpc85xx.c
index c07feba7976..96550a9ff8f 100644
--- a/drivers/pci/pci_mpc85xx.c
+++ b/drivers/pci/pci_mpc85xx.c
@@ -170,13 +170,14 @@ static int mpc85xx_pci_dm_remove(struct udevice *dev)
static int mpc85xx_pci_of_to_plat(struct udevice *dev)
{
struct mpc85xx_pci_priv *priv = dev_get_priv(dev);
- fdt_addr_t addr;
+ void __iomem *addr;
- addr = devfdt_get_addr_index(dev, 0);
- if (addr == FDT_ADDR_T_NONE)
+ addr = dev_remap_addr_index(dev, 0);
+ if (!addr)
return -EINVAL;
- priv->cfg_addr = (void __iomem *)map_physmem(addr, 0, MAP_NOCACHE);
- priv->cfg_data = (void __iomem *)((ulong)priv->cfg_addr + 4);
+
+ priv->cfg_addr = addr;
+ priv->cfg_data = priv->cfg_addr + 4;
return 0;
}
diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
index f089c48f028..1b03b0a7b05 100644
--- a/drivers/pci/pcie_brcmstb.c
+++ b/drivers/pci/pcie_brcmstb.c
@@ -21,6 +21,7 @@
#include <linux/bitfield.h>
#include <linux/log2.h>
#include <linux/iopoll.h>
+#include <reset.h>
/* PCIe parameters */
#define BRCM_NUM_PCIE_OUT_WINS 4
@@ -49,6 +50,47 @@
#define SSC_STATUS_PLL_LOCK_MASK 0x800
#define SSC_STATUS_PLL_LOCK_SHIFT 11
+#define PCIE_RC_PL_PHY_CTL_15 0x184c
+#define PCIE_RC_PL_PHY_CTL_15_DIS_PLL_PD_MASK 0x400000
+#define PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK 0xff
+
+#define PCIE_MISC_UBUS_CTRL 0x40a4
+#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK BIT(13)
+#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK BIT(19)
+#define PCIE_MISC_AXI_READ_ERROR_DATA 0x4170
+#define PCIE_MISC_UBUS_TIMEOUT 0x40A8
+#define PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT 0x405c
+#define PCIE_MISC_RC_BAR4_CONFIG_LO 0x40d4
+#define PCIE_MISC_RC_BAR4_CONFIG_HI 0x40d8
+#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_HI_MASK 0xff
+#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_HI 0x4110
+#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_ENABLE 0x1
+#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_LO_MASK 0xfffff000
+#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_LO 0x410c
+
+#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP 0x40ac
+#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP 0x40b4
+#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK BIT(0)
+#define MISC_CTRL_PCIE_RCB_MPS_MODE_MASK 0x400
+
+enum {
+ RGR1_SW_INIT_1,
+ PCIE_HARD_DEBUG,
+};
+
+enum brcm_pcie_type {
+ BCM2711,
+ BCM2712
+};
+
+struct brcm_pcie;
+
+struct brcm_pcie_cfg_data {
+ const int *offsets;
+ const enum brcm_pcie_type type;
+ void (*perst_set)(struct brcm_pcie *pcie, u32 val);
+};
+
/**
* struct brcm_pcie - the PCIe controller state
* @base: Base address of memory mapped IO registers of the controller
@@ -61,6 +103,9 @@ struct brcm_pcie {
int gen;
bool ssc;
+ struct reset_ctl rescal;
+ struct reset_ctl bridge_reset;
+ const struct brcm_pcie_cfg_data *pcie_cfg;
};
/**
@@ -79,8 +124,8 @@ static int brcm_pcie_encode_ibar_size(u64 size)
if (log2_in >= 12 && log2_in <= 15)
/* Covers 4KB to 32KB (inclusive) */
return (log2_in - 12) + 0x1c;
- else if (log2_in >= 16 && log2_in <= 37)
- /* Covers 64KB to 32GB, (inclusive) */
+ else if (log2_in >= 16 && log2_in <= 36)
+ /* Covers 64KB to 64GB, (inclusive) */
return log2_in - 15;
/* Something is awry so disable */
@@ -104,6 +149,80 @@ static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
return (val & STATUS_PCIE_PORT_MASK) >> STATUS_PCIE_PORT_SHIFT;
}
+static void brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val)
+{
+ if (val)
+ setbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1],
+ RGR1_SW_INIT_1_PERST_MASK);
+ else
+ clrbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1],
+ RGR1_SW_INIT_1_PERST_MASK);
+}
+
+static void brcm_pcie_perst_set_2712(struct brcm_pcie *pcie, u32 val)
+{
+ u32 tmp;
+
+ /* Perst bit has moved and assert value is 0 */
+ tmp = readl(pcie->base + PCIE_MISC_PCIE_CTRL);
+ u32p_replace_bits(&tmp, !val, RGR1_SW_INIT_1_PERSTB_MASK);
+ writel(tmp, pcie->base + PCIE_MISC_PCIE_CTRL);
+}
+
+static int brcm_pcie_get_resets_dt(struct udevice *dev)
+{
+ struct brcm_pcie *pcie = dev_get_priv(dev);
+ int ret;
+
+ ret = reset_get_by_name(dev, "rescal", &pcie->rescal);
+ if (ret) {
+ printf("Unable to get rescal reset\n");
+ return ret;
+ }
+
+ ret = reset_get_by_name(dev, "bridge", &pcie->bridge_reset);
+ if (ret)
+ printf("Unable to get bridge reset\n");
+
+ return ret;
+}
+
+static int brcm_pcie_do_reset(struct udevice *dev)
+{
+ struct brcm_pcie *pcie = dev_get_priv(dev);
+ int ret;
+
+ ret = reset_deassert(&pcie->rescal);
+ if (ret)
+ printf("failed to deassert 'rescal'\n");
+ return ret;
+}
+
+static int brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie, u32 val)
+{
+ int ret = 0;
+
+ if (reset_valid(&pcie->bridge_reset))
+ {
+ if (val)
+ ret = reset_assert(&pcie->bridge_reset);
+ else
+ ret = reset_deassert(&pcie->bridge_reset);
+ if (ret)
+ log_err("failed to %sassert bridge reset, err=%d\n",
+ val ? "" : "de", ret);
+ return ret;
+ }
+
+ if (val)
+ setbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1],
+ RGR1_SW_INIT_1_INIT_MASK);
+ else
+ clrbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1],
+ RGR1_SW_INIT_1_INIT_MASK);
+ return 0;
+}
+
/**
* brcm_pcie_link_up() - Check whether the PCIe link is up
* @pcie: Pointer to the PCIe controller state
@@ -125,7 +244,7 @@ static int brcm_pcie_config_address(const struct udevice *dev, pci_dev_t bdf,
uint offset, void **paddress)
{
struct brcm_pcie *pcie = dev_get_priv(dev);
- unsigned int pci_bus = PCI_BUS(bdf);
+ unsigned int pci_bus = PCI_BUS(bdf) - dev_seq(dev);
unsigned int pci_dev = PCI_DEV(bdf);
unsigned int pci_func = PCI_FUNC(bdf);
int idx;
@@ -345,28 +464,150 @@ static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie,
writel(tmp, base + PCIE_MEM_WIN0_LIMIT_HI(win));
}
+static u32 brcm_bar_reg_offset(int bar)
+{
+ if (bar <= 3)
+ return PCIE_MISC_RC_BAR1_CONFIG_LO + 8 * (bar - 1);
+ else
+ return PCIE_MISC_RC_BAR4_CONFIG_LO + 8 * (bar - 4);
+}
+
+static u32 brcm_ubus_reg_offset(int bar)
+{
+ if (bar <= 3)
+ return PCIE_MISC_UBUS_BAR1_CONFIG_REMAP + 8 * (bar - 1);
+ else
+ return PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_LO + 8 * (bar - 4);
+}
+
+/*
+ * Round size up to the next power of two, as required by
+ * brcm_pcie_encode_ibar_size(). If size is already a power of two
+ * fls64(size - 1) still gives the correct result because the hardware
+ * encodes the exponent, not the raw value.
+ */
+static u64 brcm_ibar_round_size(u64 size)
+{
+ return 1ULL << fls64(size - 1);
+}
+
+static void brcm_pcie_set_inbound_windows(struct udevice *dev)
+{
+ struct brcm_pcie *pcie = dev_get_priv(dev);
+ void __iomem *base = pcie->base;
+ bool is_2712 = (pcie->pcie_cfg->type == BCM2712);
+ int i, ibar_no, ret;
+ u32 tmp;
+
+ ibar_no = 0;
+ /* pre-2712 chips leave the first entry empty */
+ if (pcie->pcie_cfg->type != BCM2712)
+ ibar_no++;
+
+ /* program inbound windows from OF property "dma-regions" */
+ for (i = 0; i < 7; i++, ibar_no++) {
+ u64 bar_cpu, bar_size, bar_pci;
+ struct pci_region region;
+ int ubus_bar_offset, rc_bar_offset;
+
+ ret = pci_get_dma_regions(dev, &region, i);
+ if (ret) /* no region #i? Then we're done. */
+ break;
+ ubus_bar_offset = brcm_ubus_reg_offset(ibar_no + 1);
+ rc_bar_offset = brcm_bar_reg_offset(ibar_no + 1);
+
+ bar_pci = region.bus_start;
+ bar_cpu = region.phys_start;
+ bar_size = region.size;
+
+ if (is_2712) {
+ /* BCM2712: BAR holds raw PCI address; UBUS remap
+ * registers supply the CPU-side translation. */
+ tmp = lower_32_bits(bar_pci);
+ u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(bar_size),
+ RC_BAR2_CONFIG_LO_SIZE_MASK);
+ writel(tmp, base + rc_bar_offset);
+ writel(upper_32_bits(bar_pci), base + rc_bar_offset + 4);
+
+ tmp = lower_32_bits(bar_cpu) &
+ PCIE_MISC_UBUS_BAR_CONFIG_REMAP_LO_MASK;
+ tmp |= PCIE_MISC_UBUS_BAR_CONFIG_REMAP_ENABLE;
+ writel(tmp, base + ubus_bar_offset);
+
+ tmp = upper_32_bits(bar_cpu) &
+ PCIE_MISC_UBUS_BAR_CONFIG_REMAP_HI_MASK;
+ writel(tmp, base + ubus_bar_offset + 4);
+ } else {
+ /* Pre-BCM2712 (e.g. BCM2711 / RPi4): the BAR config
+ * register holds the offset (bus_start - phys_start),
+ * not the raw PCI address. The size must be rounded
+ * up to the next power of two before encoding. */
+ u64 bar_offset = bar_pci - bar_cpu;
+ u64 bar_size_po2 = brcm_ibar_round_size(bar_size);
+
+ tmp = lower_32_bits(bar_offset);
+ u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(bar_size_po2),
+ RC_BAR2_CONFIG_LO_SIZE_MASK);
+ writel(tmp, base + rc_bar_offset);
+ writel(upper_32_bits(bar_offset), base + rc_bar_offset + 4);
+ /* UBUS remap registers are not used on pre-2712 hardware. */
+ }
+ }
+}
+
+static void brcm_pcie_munge_pll(struct brcm_pcie *pcie)
+{
+ u32 tmp;
+ int ret, i;
+ u8 regs[] = { 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1e };
+ u16 data[] = { 0x50b9, 0xbda1, 0x0094, 0x97b4, 0x5030, 0x5030, 0x0007 };
+
+ ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, SET_ADDR_OFFSET,
+ 0x1600);
+ for (i = 0; i < ARRAY_SIZE(regs); i++) {
+ brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp);
+ debug("PCIE MDIO pre_refclk 0x%02x = 0x%04x\n",
+ regs[i], tmp);
+ }
+ for (i = 0; i < ARRAY_SIZE(regs); i++) {
+ brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, regs[i], data[i]);
+ brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp);
+ debug("PCIE MDIO post_refclk 0x%02x = 0x%04x\n",
+ regs[i], tmp);
+ }
+
+ udelay(200);
+}
+
static int brcm_pcie_probe(struct udevice *dev)
{
struct udevice *ctlr = pci_get_controller(dev);
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
struct brcm_pcie *pcie = dev_get_priv(dev);
void __iomem *base = pcie->base;
- struct pci_region region;
bool ssc_good = false;
int num_out_wins = 0;
- u64 rc_bar2_offset, rc_bar2_size;
- unsigned int scb_size_val;
- int i, ret;
+ int i, ret = 0;
u16 nlw, cls, lnksta;
u32 tmp;
/*
+ * Ensure rescal reset for BCM2712 is really disabled.
+ */
+ if (pcie->pcie_cfg->type == BCM2712)
+ ret = brcm_pcie_do_reset(dev);
+ if (ret)
+ return ret;
+ /*
* Reset the bridge, assert the fundamental reset. Note for some SoCs,
* e.g. BCM7278, the fundamental reset should not be asserted here.
* This will need to be changed when support for other SoCs is added.
*/
- setbits_le32(base + PCIE_RGR1_SW_INIT_1,
- PCIE_RGR1_SW_INIT_1_INIT_MASK | PCIE_RGR1_SW_INIT_1_PERST_MASK);
+ ret = brcm_pcie_bridge_sw_init_set(pcie, 1);
+ if (ret)
+ return ret;
+ if (pcie->pcie_cfg->type != BCM2712)
+ pcie->pcie_cfg->perst_set(pcie, 1);
/*
* The delay is a safety precaution to preclude the reset signal
* from looking like a glitch.
@@ -374,39 +615,77 @@ static int brcm_pcie_probe(struct udevice *dev)
udelay(100);
/* Take the bridge out of reset */
- clrbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_INIT_MASK);
-
- clrbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
+ ret = brcm_pcie_bridge_sw_init_set(pcie, 0);
+ if (ret)
+ return ret;
+ clrbits_le32(base + pcie->pcie_cfg->offsets[PCIE_HARD_DEBUG],
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
/* Wait for SerDes to be stable */
udelay(100);
+ if (pcie->pcie_cfg->type == BCM2712) {
+ /* Allow a 54MHz (xosc) refclk source */
+ brcm_pcie_munge_pll(pcie);
+ /* Fix for L1SS errata */
+ tmp = readl(base + PCIE_RC_PL_PHY_CTL_15);
+ tmp &= ~PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK;
+ /* PM clock period is 18.52ns (round down) */
+ tmp |= 0x12;
+ writel(tmp, base + PCIE_RC_PL_PHY_CTL_15);
+ }
+
+ tmp = (pcie->pcie_cfg->type == BCM2712) ?
+ MISC_CTRL_MAX_BURST_SIZE_128_2712 :
+ MISC_CTRL_MAX_BURST_SIZE_128;
/* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
clrsetbits_le32(base + PCIE_MISC_MISC_CTRL,
MISC_CTRL_MAX_BURST_SIZE_MASK,
MISC_CTRL_SCB_ACCESS_EN_MASK |
MISC_CTRL_CFG_READ_UR_MODE_MASK |
- MISC_CTRL_MAX_BURST_SIZE_128);
+ MISC_CTRL_PCIE_RCB_MPS_MODE_MASK |
+ tmp);
- pci_get_dma_regions(dev, &region, 0);
- rc_bar2_offset = region.bus_start - region.phys_start;
- rc_bar2_size = 1ULL << fls64(region.size - 1);
+ tmp = readl(base + PCIE_MISC_MISC_CTRL);
+ if (pcie->pcie_cfg->type == BCM2712) {
+ /* BCM2712: fixed 32GB SCB0 window */
+ u32p_replace_bits(&tmp, 20, MISC_CTRL_SCB0_SIZE_MASK);
+ } else {
+ /* Pre-BCM2712: size SCB0 to match the actual DMA region.
+ * rc_bar2_size must be a power of two; ilog2(size) - 15
+ * gives the hardware encoding (e.g. 1GB -> 15). */
+ struct pci_region region;
+ u64 rc_bar2_size;
- tmp = lower_32_bits(rc_bar2_offset);
- u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(rc_bar2_size),
- RC_BAR2_CONFIG_LO_SIZE_MASK);
- writel(tmp, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
- writel(upper_32_bits(rc_bar2_offset),
- base + PCIE_MISC_RC_BAR2_CONFIG_HI);
+ pci_get_dma_regions(dev, &region, 0);
+ rc_bar2_size = brcm_ibar_round_size(region.size);
+ u32p_replace_bits(&tmp, rc_bar2_size ? ilog2(rc_bar2_size) - 15 : 0xf,
+ MISC_CTRL_SCB0_SIZE_MASK);
+ }
+ writel(tmp, base + PCIE_MISC_MISC_CTRL);
- scb_size_val = rc_bar2_size ?
- ilog2(rc_bar2_size) - 15 : 0xf; /* 0xf is 1GB */
+ if (pcie->pcie_cfg->type == BCM2712) {
+ /* Suppress AXI error responses and return 1s for read failures */
+ tmp = readl(base + PCIE_MISC_UBUS_CTRL);
+ u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK);
+ u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK);
+ writel(tmp, base + PCIE_MISC_UBUS_CTRL);
+ writel(0xffffffff, base + PCIE_MISC_AXI_READ_ERROR_DATA);
- tmp = readl(base + PCIE_MISC_MISC_CTRL);
- u32p_replace_bits(&tmp, scb_size_val,
- MISC_CTRL_SCB0_SIZE_MASK);
- writel(tmp, base + PCIE_MISC_MISC_CTRL);
+ /*
+ * Adjust timeouts. The UBUS timeout also affects CRS
+ * completion retries, as the request will get terminated if
+ * either timeout expires, so both have to be a large value
+ * (in clocks of 750MHz).
+ * Set UBUS timeout to 250ms, then set RC config retry timeout
+ * to be ~240ms.
+ *
+ * Setting CRSVis=1 will stop the core from blocking on a CRS
+ * response, but does require the device to be well-behaved...
+ */
+ writel(0xB2D0000, base + PCIE_MISC_UBUS_TIMEOUT);
+ writel(0xABA0000, base + PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT);
+ }
/* Disable the PCIe->GISB memory window (RC_BAR1) */
clrbits_le32(base + PCIE_MISC_RC_BAR1_CONFIG_LO,
@@ -422,12 +701,13 @@ static int brcm_pcie_probe(struct udevice *dev)
/* Clear any interrupts we find on boot */
writel(0xffffffff, base + PCIE_MSI_INTR2_CLR);
+ brcm_pcie_set_inbound_windows(dev);
+
if (pcie->gen)
brcm_pcie_set_gen(pcie, pcie->gen);
/* Unassert the fundamental reset */
- clrbits_le32(pcie->base + PCIE_RGR1_SW_INIT_1,
- PCIE_RGR1_SW_INIT_1_PERST_MASK);
+ pcie->pcie_cfg->perst_set(pcie, 0);
/*
* Wait for 100ms after PERST# deassertion; see PCIe CEM specification
@@ -514,14 +794,25 @@ static int brcm_pcie_remove(struct udevice *dev)
void __iomem *base = pcie->base;
/* Assert fundamental reset */
- setbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_PERST_MASK);
+ setbits_le32(base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1],
+ PCIE_RGR1_SW_INIT_1_PERST_MASK);
/* Turn off SerDes */
- setbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
+ setbits_le32(base + pcie->pcie_cfg->offsets[PCIE_HARD_DEBUG],
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
/* Shutdown bridge */
- setbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_INIT_MASK);
+ brcm_pcie_bridge_sw_init_set(pcie, 1);
+
+ /*
+ * For the controllers that are utilizing reset for bridge Sw init,
+ * such as BCM2712, reset should be deasserted after assertion.
+ * Leaving it in asserted state may lead to unexpected hangs in
+ * the Linux Kernel driver because it do not perform reset initialization
+ * and start accessing device memory.
+ */
+ if (pcie->pcie_cfg->type == BCM2712)
+ brcm_pcie_bridge_sw_init_set(pcie, 0);
return 0;
}
@@ -546,6 +837,11 @@ static int brcm_pcie_of_to_plat(struct udevice *dev)
else
pcie->gen = max_link_speed;
+ pcie->pcie_cfg = (const struct brcm_pcie_cfg_data *)dev_get_driver_data(dev);
+
+ if (pcie->pcie_cfg->type == BCM2712)
+ return brcm_pcie_get_resets_dt(dev);
+
return 0;
}
@@ -554,8 +850,31 @@ static const struct dm_pci_ops brcm_pcie_ops = {
.write_config = brcm_pcie_write_config,
};
+static const int pcie_offsets[] = {
+ [RGR1_SW_INIT_1] = 0x9210,
+ [PCIE_HARD_DEBUG] = 0x4204,
+};
+
+static const struct brcm_pcie_cfg_data bcm2711_cfg = {
+ .offsets = pcie_offsets,
+ .type = BCM2711,
+ .perst_set = brcm_pcie_perst_set_generic,
+};
+
+static const int pcie_offsets_bcm2712[] = {
+ [RGR1_SW_INIT_1] = 0x0,
+ [PCIE_HARD_DEBUG] = 0x4304,
+};
+
+static const struct brcm_pcie_cfg_data bcm2712_cfg = {
+ .offsets = pcie_offsets_bcm2712,
+ .type = BCM2712,
+ .perst_set = brcm_pcie_perst_set_2712,
+};
+
static const struct udevice_id brcm_pcie_ids[] = {
- { .compatible = "brcm,bcm2711-pcie" },
+ { .compatible = "brcm,bcm2711-pcie", .data = (ulong)&bcm2711_cfg },
+ { .compatible = "brcm,bcm2712-pcie", .data = (ulong)&bcm2712_cfg },
{ }
};
diff --git a/drivers/pci/pcie_dw_amd.c b/drivers/pci/pcie_dw_amd.c
new file mode 100644
index 00000000000..81c6d8f2817
--- /dev/null
+++ b/drivers/pci/pcie_dw_amd.c
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AMD Versal2 DesignWare PCIe host controller driver
+ *
+ * Copyright (C) 2025 - 2026, Advanced Micro Devices, Inc.
+ * Author: Pranav Sanwal <[email protected]>
+ */
+
+#include <dm.h>
+#include <log.h>
+#include <pci.h>
+#include <wait_bit.h>
+
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <dm/ofnode.h>
+#include <linux/delay.h>
+
+#include "pcie_dw_common.h"
+
+/*
+ * SLCR (System Level Control Register) Interrupt Register Offsets
+ * These are relative to the SLCR base address from device tree
+ */
+#define AMD_DW_TLP_IR_STATUS_MISC 0x4c0
+#define AMD_DW_TLP_IR_DISABLE_MISC 0x4cc
+
+/* Interrupt bit definitions */
+#define AMD_DW_PCIE_INTR_CMPL_TIMEOUT 15
+#define AMD_DW_PCIE_INTR_PM_PME_RCVD 24
+#define AMD_DW_PCIE_INTR_PME_TO_ACK_RCVD 25
+#define AMD_DW_PCIE_INTR_MISC_CORRECTABLE 26
+#define AMD_DW_PCIE_INTR_NONFATAL 27
+#define AMD_DW_PCIE_INTR_FATAL 28
+
+#define AMD_DW_PCIE_INTR_INTX_MASK GENMASK(23, 16)
+
+#define AMD_DW_PCIE_IMR_ALL_MASK \
+ (BIT(AMD_DW_PCIE_INTR_CMPL_TIMEOUT) | \
+ BIT(AMD_DW_PCIE_INTR_PM_PME_RCVD) | \
+ BIT(AMD_DW_PCIE_INTR_PME_TO_ACK_RCVD) | \
+ BIT(AMD_DW_PCIE_INTR_MISC_CORRECTABLE) | \
+ BIT(AMD_DW_PCIE_INTR_NONFATAL) | \
+ BIT(AMD_DW_PCIE_INTR_FATAL) | \
+ AMD_DW_PCIE_INTR_INTX_MASK)
+
+/* DW PCIe Debug Registers (in DBI space) */
+#define AMD_DW_PCIE_PORT_DEBUG1 0x72c
+#define AMD_DW_PCIE_PORT_DEBUG1_LINK_UP BIT(4)
+#define AMD_DW_PCIE_PORT_DEBUG1_LINK_IN_TRAINING BIT(29)
+#define AMD_DW_PCIE_DBI_64BIT_MEM_DECODE BIT(0)
+
+/* Link training timeout */
+#define LINK_WAIT_MSLEEP_MAX 1000
+
+/* PCIe spec timing requirements */
+#define PCIE_RESET_CONFIG_WAIT_MS 100
+#define PCIE_T_PERST_WAIT_MS 1
+
+/**
+ * struct amd_dw_pcie - AMD DesignWare PCIe controller private data
+ * @dw: DesignWare PCIe common structure
+ * @slcr_base: System Level Control Register base (for interrupts)
+ */
+struct amd_dw_pcie {
+ struct pcie_dw dw;
+ void __iomem *slcr_base;
+};
+
+static void amd_dw_pcie_init_port(struct amd_dw_pcie *pcie)
+{
+ u32 val;
+
+ if (!pcie->slcr_base)
+ return;
+
+ /* Disable all TLP interrupts */
+ writel(AMD_DW_PCIE_IMR_ALL_MASK,
+ pcie->slcr_base + AMD_DW_TLP_IR_DISABLE_MISC);
+
+ /* Clear any pending TLP interrupts */
+ val = readl(pcie->slcr_base + AMD_DW_TLP_IR_STATUS_MISC);
+ val &= AMD_DW_PCIE_IMR_ALL_MASK;
+ writel(val, pcie->slcr_base + AMD_DW_TLP_IR_STATUS_MISC);
+}
+
+static void amd_dw_pcie_start_link(struct amd_dw_pcie *pcie)
+{
+ void __iomem *reg = pcie->dw.dbi_base + AMD_DW_PCIE_PORT_DEBUG1;
+ struct udevice *dev = pcie->dw.dev;
+ struct pcie_dw *pci = &pcie->dw;
+ int ret;
+
+ ret = wait_for_bit_le32(reg, AMD_DW_PCIE_PORT_DEBUG1_LINK_UP,
+ true, LINK_WAIT_MSLEEP_MAX,
+ false);
+ if (!ret)
+ ret = wait_for_bit_le32(reg,
+ AMD_DW_PCIE_PORT_DEBUG1_LINK_IN_TRAINING,
+ false, LINK_WAIT_MSLEEP_MAX, false);
+ if (ret)
+ dev_warn(dev, "PCIE-%d: Link down\n", dev_seq(dev));
+ else
+ dev_dbg(dev, "PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n",
+ dev_seq(dev), pcie_dw_get_link_speed(pci),
+ pcie_dw_get_link_width(pci), pci->first_busno);
+}
+
+static void amd_dw_pcie_host_init(struct amd_dw_pcie *pcie)
+{
+ struct pcie_dw *pci = &pcie->dw;
+
+ /*
+ * Set 64-bit prefetchable memory decode capability. U-Boot's pci_auto.c
+ * reads this bit before assigning prefetchable BARs. If cleared, it skips
+ * PCI_PREF_BASE_UPPER32 programming, causing 64-bit BAR assignment to fail.
+ */
+ dw_pcie_dbi_write_enable(pci, true);
+ setbits_le32(pci->dbi_base + PCI_PREF_MEMORY_BASE,
+ AMD_DW_PCIE_DBI_64BIT_MEM_DECODE);
+ dw_pcie_dbi_write_enable(pci, false);
+
+ amd_dw_pcie_init_port(pcie);
+ pcie_dw_setup_host(pci);
+}
+
+static void amd_dw_pcie_request_gpio(struct udevice *dev)
+{
+ struct gpio_desc perst_gpio;
+ ofnode child_node;
+ int ret;
+
+ /*
+ * PERST# reset GPIO is optional. Child PCI endpoint nodes may carry a
+ * 'reset-gpios' property to toggle the endpoint reset signal during
+ * initialization. If absent, the endpoint is assumed to be already
+ * released from reset.
+ */
+ ofnode_for_each_subnode(child_node, dev_ofnode(dev)) {
+ ret = gpio_request_by_name_nodev(child_node, "reset-gpios", 0,
+ &perst_gpio, GPIOD_IS_OUT);
+ if (!ret) {
+ dev_dbg(dev, "Found reset-gpios in child node %s\n",
+ ofnode_get_name(child_node));
+ dm_gpio_set_value(&perst_gpio, 1);
+ mdelay(PCIE_T_PERST_WAIT_MS);
+ dm_gpio_set_value(&perst_gpio, 0);
+ mdelay(PCIE_RESET_CONFIG_WAIT_MS);
+ dm_gpio_free(dev, &perst_gpio);
+ }
+ }
+}
+
+static int amd_dw_pcie_of_to_plat(struct udevice *dev)
+{
+ struct pci_region *io_region, *mem_region, *pref_region;
+ struct amd_dw_pcie *pcie = dev_get_priv(dev);
+ struct pcie_dw *pci = &pcie->dw;
+ int ret;
+
+ pci->dev = dev;
+
+ pci->dbi_base = dev_read_addr_name_ptr(dev, "dbi");
+ if (!pci->dbi_base) {
+ dev_err(dev, "Missing 'dbi' register region\n");
+ return -EINVAL;
+ }
+
+ pci->cfg_base = dev_read_addr_size_name_ptr(dev, "config", &pci->cfg_size);
+ if (!pci->cfg_base) {
+ dev_err(dev, "Missing 'config' register region\n");
+ return -EINVAL;
+ }
+
+ pci->atu_base = dev_read_addr_name_ptr(dev, "atu");
+ if (!pci->atu_base) {
+ dev_dbg(dev, "No 'atu' region, using default offset from DBI\n");
+ pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
+ }
+
+ pcie->slcr_base = dev_read_addr_name_ptr(dev, "slcr");
+ if (!pcie->slcr_base)
+ dev_dbg(dev, "No 'slcr' region, interrupt features disabled\n");
+
+ ret = pci_get_regions(dev, &io_region, &mem_region, &pref_region);
+ if (ret < 0) {
+ dev_err(dev, "Failed to get PCI regions: %d\n", ret);
+ return ret;
+ }
+
+ if (mem_region)
+ pci->mem = *mem_region;
+
+ return 0;
+}
+
+static int amd_dw_pcie_probe(struct udevice *dev)
+{
+ struct amd_dw_pcie *pcie = dev_get_priv(dev);
+ struct pcie_dw *pci = &pcie->dw;
+
+ /* Set first bus number */
+ pci->first_busno = dev_seq(dev);
+
+ amd_dw_pcie_request_gpio(dev);
+ amd_dw_pcie_host_init(pcie);
+ amd_dw_pcie_start_link(pcie);
+
+ if (pci->mem.size) {
+ dev_dbg(dev, "Programming ATU region 0 for MEM: phys=0x%llx bus=0x%llx size=0x%llx\n",
+ (unsigned long long)pci->mem.phys_start,
+ (unsigned long long)pci->mem.bus_start,
+ (unsigned long long)pci->mem.size);
+ pcie_dw_prog_outbound_atu_unroll(pci,
+ PCIE_ATU_REGION_INDEX0,
+ PCIE_ATU_TYPE_MEM,
+ pci->mem.phys_start,
+ pci->mem.bus_start,
+ pci->mem.size);
+ } else {
+ dev_warn(dev, "No MEM region configured!\n");
+ }
+
+ dev_dbg(dev, "dbi: 0x%lx | config: 0x%lx | atu: 0x%lx | slcr: 0x%lx\n",
+ (long)pci->dbi_base, (long)pci->cfg_base,
+ (long)pci->atu_base, (long)pcie->slcr_base);
+
+ return 0;
+}
+
+static const struct dm_pci_ops amd_dw_pcie_ops = {
+ .read_config = pcie_dw_read_config,
+ .write_config = pcie_dw_write_config,
+};
+
+static const struct udevice_id amd_dw_pcie_ids[] = {
+ { .compatible = "amd,versal2-mdb-host" },
+ { }
+};
+
+U_BOOT_DRIVER(pcie_dw_amd) = {
+ .name = "pcie_dw_amd",
+ .id = UCLASS_PCI,
+ .of_match = amd_dw_pcie_ids,
+ .ops = &amd_dw_pcie_ops,
+ .of_to_plat = amd_dw_pcie_of_to_plat,
+ .probe = amd_dw_pcie_probe,
+ .priv_auto = sizeof(struct amd_dw_pcie),
+};
diff --git a/drivers/pci/pcie_dw_mvebu.c b/drivers/pci/pcie_dw_mvebu.c
index 43b919175c9..5a177478afc 100644
--- a/drivers/pci/pcie_dw_mvebu.c
+++ b/drivers/pci/pcie_dw_mvebu.c
@@ -565,13 +565,12 @@ static int pcie_dw_mvebu_of_to_plat(struct udevice *dev)
struct pcie_dw_mvebu *pcie = dev_get_priv(dev);
/* Get the controller base address */
- pcie->ctrl_base = devfdt_get_addr_index_ptr(dev, 0);
+ pcie->ctrl_base = dev_read_addr_index_ptr(dev, 0);
if (!pcie->ctrl_base)
return -EINVAL;
/* Get the config space base address and size */
- pcie->cfg_base = devfdt_get_addr_size_index_ptr(dev, 1,
- &pcie->cfg_size);
+ pcie->cfg_base = dev_read_addr_size_index_ptr(dev, 1, &pcie->cfg_size);
if (!pcie->cfg_base)
return -EINVAL;
diff --git a/drivers/pci/pcie_dw_qcom.c b/drivers/pci/pcie_dw_qcom.c
index 10c45aaba20..ce6b4d97d1d 100644
--- a/drivers/pci/pcie_dw_qcom.c
+++ b/drivers/pci/pcie_dw_qcom.c
@@ -22,7 +22,7 @@
struct qcom_pcie;
-struct qcom_pcie_ops {
+static const struct qcom_pcie_ops {
int (*config_sid)(struct qcom_pcie *priv);
};
diff --git a/drivers/pci/pcie_imx.c b/drivers/pci/pcie_imx.c
index 8d853ecf2c2..c8b8e171e39 100644
--- a/drivers/pci/pcie_imx.c
+++ b/drivers/pci/pcie_imx.c
@@ -774,8 +774,8 @@ static int imx_pcie_of_to_plat(struct udevice *dev)
{
struct imx_pcie_priv *priv = dev_get_priv(dev);
- priv->dbi_base = devfdt_get_addr_index_ptr(dev, 0);
- priv->cfg_base = devfdt_get_addr_index_ptr(dev, 1);
+ priv->dbi_base = dev_read_addr_index_ptr(dev, 0);
+ priv->cfg_base = dev_read_addr_index_ptr(dev, 1);
if (!priv->dbi_base || !priv->cfg_base)
return -EINVAL;
diff --git a/drivers/pci/pcie_layerscape.h b/drivers/pci/pcie_layerscape.h
index d5f4930e181..e6d47241e71 100644
--- a/drivers/pci/pcie_layerscape.h
+++ b/drivers/pci/pcie_layerscape.h
@@ -10,6 +10,7 @@
#include <fdtdec.h>
#include <pci.h>
+#include <linux/ioport.h>
#include <linux/sizes.h>
#include <linux/types.h>
#include <asm/arch-fsl-layerscape/svr.h>
@@ -164,7 +165,7 @@ struct ls_pcie_rc {
};
struct ls_pcie_ep {
- struct fdt_resource addr_res;
+ struct resource addr_res;
struct ls_pcie *pcie;
struct udevice *bus;
void __iomem *addr;
diff --git a/drivers/pci/pcie_layerscape_ep.c b/drivers/pci/pcie_layerscape_ep.c
index 3520488b345..b7809857565 100644
--- a/drivers/pci/pcie_layerscape_ep.c
+++ b/drivers/pci/pcie_layerscape_ep.c
@@ -7,7 +7,6 @@
#include <config.h>
#include <asm/arch/fsl_serdes.h>
#include <dm.h>
-#include <asm/global_data.h>
#include <dm/devres.h>
#include <errno.h>
#include <pci_ep.h>
@@ -16,8 +15,6 @@
#include <linux/log2.h>
#include "pcie_layerscape.h"
-DECLARE_GLOBAL_DATA_PTR;
-
static void ls_pcie_ep_enable_cfg(struct ls_pcie_ep *pcie_ep)
{
struct ls_pcie *pcie = pcie_ep->pcie;
@@ -250,17 +247,15 @@ static int ls_pcie_ep_probe(struct udevice *dev)
pcie_ep->pcie = pcie;
- pcie->dbi = devfdt_get_addr_index_ptr(dev, 0);
+ pcie->dbi = dev_read_addr_index_ptr(dev, 0);
if (!pcie->dbi)
return -EINVAL;
- pcie->ctrl = devfdt_get_addr_index_ptr(dev, 1);
+ pcie->ctrl = dev_read_addr_index_ptr(dev, 1);
if (!pcie->ctrl)
return -EINVAL;
- ret = fdt_get_named_resource(gd->fdt_blob, dev_of_offset(dev),
- "reg", "reg-names",
- "addr_space", &pcie_ep->addr_res);
+ ret = dev_read_resource_byname(dev, "addr_space", &pcie_ep->addr_res);
if (ret) {
printf("%s: resource \"addr_space\" not found\n", dev->name);
return ret;
@@ -273,8 +268,7 @@ static int ls_pcie_ep_probe(struct udevice *dev)
if (!is_serdes_configured(PCIE_SRDS_PRTCL(pcie->idx)))
return 0;
- pcie->big_endian = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
- "big-endian");
+ pcie->big_endian = dev_read_bool(dev, "big-endian");
svr = SVR_SOC_VER(get_svr());
@@ -294,13 +288,9 @@ static int ls_pcie_ep_probe(struct udevice *dev)
if (pcie->mode != PCI_HEADER_TYPE_NORMAL)
return 0;
- pcie_ep->max_functions = fdtdec_get_int(gd->fdt_blob,
- dev_of_offset(dev),
- "max-functions", 1);
- pcie_ep->num_ib_wins = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
- "num-ib-windows", 8);
- pcie_ep->num_ob_wins = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
- "num-ob-windows", 8);
+ pcie_ep->max_functions = dev_read_s32_default(dev, "max-functions", 1);
+ pcie_ep->num_ib_wins = dev_read_s32_default(dev, "num-ib-windows", 8);
+ pcie_ep->num_ob_wins = dev_read_s32_default(dev, "num-ob-windows", 8);
printf("PCIe%u: %s %s", PCIE_SRDS_PRTCL(pcie->idx), dev->name,
"Endpoint");