The current EPC core design relies on an EPC driver disabling all BARs by
default. An EPF driver will then enable the BARs that it wants to enabled.
This design is there because there is no epc->ops->disable_bar().
(There is a epc->ops->clear_bar(), but that is only to disable a BAR that
has been enabled using epc->ops->set_bar() first.)
By default, an EPF driver will not be able to get/enable BARs that are
marked as BAR_RESERVED or BAR_DISABLED (see pci_epc_get_next_free_bar()).
Since the current EPC code design requires an EPC driver to disable all
BARs by default, move this to DWC common code from each glue driver.
BAR_RESERVED BARs are not disabled by default because these BARs are
hardware backed, and should only be disabled explicitly by an EPF driver
if absolutely necessary for the EPF driver to function correctly.
(This is similar to how e.g. NVMe may have vendor specific BARs outside of
the mandatory BAR0 which contains the NVMe registers.)
Note that there is currently no EPC operation to disable a BAR that has not
first been programmed using pci_epc_set_bar(). If an EPF driver ever wants
to disable a BAR marked as BAR_RESERVED, a disable_bar() operation would
have to be added first.
No functional changes intended.
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Tested-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Tested-by: Koichiro Den <den@valinux.co.jp>
Reviewed-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260312130229.2282001-19-cassel@kernel.org
{
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
- enum pci_barno bar;
-
- for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
- dw_pcie_ep_reset_bar(pci, bar);
dra7xx_pcie_enable_wrapper_interrupts(dra7xx);
}
.stop_link = imx_pcie_stop_link,
};
-static void imx_pcie_ep_init(struct dw_pcie_ep *ep)
-{
- enum pci_barno bar;
- struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
-
- for (bar = BAR_0; bar <= BAR_5; bar++)
- dw_pcie_ep_reset_bar(pci, bar);
-}
-
static int imx_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
unsigned int type, u16 interrupt_num)
{
}
static const struct dw_pcie_ep_ops pcie_ep_ops = {
- .init = imx_pcie_ep_init,
.raise_irq = imx_pcie_ep_raise_irq,
.get_features = imx_pcie_ep_get_features,
};
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
struct dw_pcie_ep_func *ep_func;
- enum pci_barno bar;
ep_func = dw_pcie_ep_get_func_from_ep(ep, 0);
if (!ep_func)
return;
- for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
- dw_pcie_ep_reset_bar(pci, bar);
-
pcie->ls_epc->msi_capable = ep_func->msi_cap ? true : false;
pcie->ls_epc->msix_capable = ep_func->msix_cap ? true : false;
}
{
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
- enum pci_barno bar;
artpec6_pcie_assert_core_reset(artpec6_pcie);
artpec6_pcie_init_phy(artpec6_pcie);
artpec6_pcie_deassert_core_reset(artpec6_pcie);
artpec6_pcie_wait_for_phy(artpec6_pcie);
-
- for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
- dw_pcie_ep_reset_bar(pci, bar);
}
static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
dw_pcie_dbi_ro_wr_dis(pci);
}
+static void dw_pcie_ep_disable_bars(struct dw_pcie_ep *ep)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+ enum pci_epc_bar_type bar_type;
+ enum pci_barno bar;
+
+ for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
+ bar_type = dw_pcie_ep_get_bar_type(ep, bar);
+
+ /*
+ * Reserved BARs should not get disabled by default. All other
+ * BAR types are disabled by default.
+ *
+ * This is in line with the current EPC core design, where all
+ * BARs are disabled by default, and then the EPF driver enables
+ * the BARs it wishes to use.
+ */
+ if (bar_type != BAR_RESERVED)
+ dw_pcie_ep_reset_bar(pci, bar);
+ }
+}
+
/**
* dw_pcie_ep_init_registers - Initialize DWC EP specific registers
* @ep: DWC EP device
if (ep->ops->init)
ep->ops->init(ep);
+ dw_pcie_ep_disable_bars(ep);
+
/*
* PCIe r6.0, section 7.9.15 states that for endpoints that support
* PTM, this capability structure is required in exactly one
static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = {
};
-static void dw_plat_pcie_ep_init(struct dw_pcie_ep *ep)
-{
- struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- enum pci_barno bar;
-
- for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
- dw_pcie_ep_reset_bar(pci, bar);
-}
-
static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
unsigned int type, u16 interrupt_num)
{
}
static const struct dw_pcie_ep_ops pcie_ep_ops = {
- .init = dw_plat_pcie_ep_init,
.raise_irq = dw_plat_pcie_ep_raise_irq,
.get_features = dw_plat_pcie_get_features,
};
static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep)
{
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- enum pci_barno bar;
rockchip_pcie_enable_l0s(pci);
rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep);
-
- for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
- dw_pcie_ep_reset_bar(pci, bar);
};
static int rockchip_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
/*
* BAR4 on rk3588 exposes the ATU Port Logic Structure to the host regardless of
* iATU settings for BAR4. This means that BAR4 cannot be used by an EPF driver,
- * so mark it as RESERVED. (rockchip_pcie_ep_init() will disable all BARs by
- * default.) If the host could write to BAR4, the iATU settings (for all other
- * BARs) would be overwritten, resulting in (all other BARs) no longer working.
+ * so mark it as RESERVED.
*/
static const struct pci_epc_features rockchip_pcie_epc_features_rk3588 = {
DWC_EPC_COMMON_FEATURES,
return &qcom_pcie_epc_features;
}
-static void qcom_pcie_ep_init(struct dw_pcie_ep *ep)
-{
- struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- enum pci_barno bar;
-
- for (bar = BAR_0; bar <= BAR_5; bar++)
- dw_pcie_ep_reset_bar(pci, bar);
-}
-
static const struct dw_pcie_ep_ops pci_ep_ops = {
- .init = qcom_pcie_ep_init,
.raise_irq = qcom_pcie_ep_raise_irq,
.get_features = qcom_pcie_epc_get_features,
};
writel(PCIEDMAINTSTSEN_INIT, rcar->base + PCIEDMAINTSTSEN);
}
-static void rcar_gen4_pcie_ep_init(struct dw_pcie_ep *ep)
-{
- struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- enum pci_barno bar;
-
- for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
- dw_pcie_ep_reset_bar(pci, bar);
-}
-
static void rcar_gen4_pcie_ep_deinit(struct rcar_gen4_pcie *rcar)
{
writel(0, rcar->base + PCIEDMAINTSTSEN);
static const struct dw_pcie_ep_ops pcie_ep_ops = {
.pre_init = rcar_gen4_pcie_ep_pre_init,
- .init = rcar_gen4_pcie_ep_init,
.raise_irq = rcar_gen4_pcie_ep_raise_irq,
.get_features = rcar_gen4_pcie_ep_get_features,
.get_dbi_offset = rcar_gen4_pcie_ep_get_dbi_offset,
unsigned int perst_irq;
};
-static void stm32_pcie_ep_init(struct dw_pcie_ep *ep)
-{
- struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- enum pci_barno bar;
-
- for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
- dw_pcie_ep_reset_bar(pci, bar);
-}
-
static int stm32_pcie_start_link(struct dw_pcie *pci)
{
struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci);
}
static const struct dw_pcie_ep_ops stm32_pcie_ep_ops = {
- .init = stm32_pcie_ep_init,
.raise_irq = stm32_pcie_raise_irq,
.get_features = stm32_pcie_get_features,
};
return IRQ_HANDLED;
}
-static void tegra_pcie_ep_init(struct dw_pcie_ep *ep)
-{
- struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- enum pci_barno bar;
-
- for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
- dw_pcie_ep_reset_bar(pci, bar);
-};
-
static int tegra_pcie_ep_raise_intx_irq(struct tegra_pcie_dw *pcie, u16 irq)
{
/* Tegra194 supports only INTA */
}
static const struct dw_pcie_ep_ops pcie_ep_ops = {
- .init = tegra_pcie_ep_init,
.raise_irq = tegra_pcie_ep_raise_irq,
.get_features = tegra_pcie_ep_get_features,
};
uniphier_pcie_ltssm_enable(priv, false);
}
-static void uniphier_pcie_ep_init(struct dw_pcie_ep *ep)
-{
- struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- enum pci_barno bar;
-
- for (bar = BAR_0; bar <= BAR_5; bar++)
- dw_pcie_ep_reset_bar(pci, bar);
-}
-
static int uniphier_pcie_ep_raise_intx_irq(struct dw_pcie_ep *ep)
{
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
}
static const struct dw_pcie_ep_ops uniphier_pcie_ep_ops = {
- .init = uniphier_pcie_ep_init,
.raise_irq = uniphier_pcie_ep_raise_irq,
.get_features = uniphier_pcie_get_features,
};