diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 19daadee65f7c..9a896a6dbac5f 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -53,6 +53,7 @@ #define PARF_SLV_ADDR_SPACE_SIZE 0x16c #define PARF_MHI_CLOCK_RESET_CTRL 0x174 #define PARF_AXI_MSTR_WR_ADDR_HALT 0x178 +#define PARF_AXI_MSTR_RD_HALT_NO_WRITES 0x1a4 #define PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1a8 #define PARF_Q2A_FLUSH 0x1ac #define PARF_LTSSM 0x1b0 @@ -63,6 +64,7 @@ #define PARF_SLV_ADDR_SPACE_SIZE_V2 0x358 #define PARF_SLV_ADDR_SPACE_SIZE_V2_HI 0x35c #define PARF_NO_SNOOP_OVERRIDE 0x3d4 +#define PARF_AXI_MSTR_WR_NS_BDF_HALT 0x4a0 #define PARF_ATU_BASE_ADDR 0x634 #define PARF_ATU_BASE_ADDR_HI 0x638 #define PARF_DEVICE_TYPE 0x1000 @@ -130,6 +132,9 @@ /* PARF_AXI_MSTR_WR_ADDR_HALT register fields */ #define EN BIT(31) +/* PARF_AXI_MSTR_RD_HALT_NO_WRITES */ +#define RD_HALT_NO_WRITES_EN BIT(0) + /* PARF_LTSSM register fields */ #define LTSSM_EN BIT(8) #define PARF_LTSSM_STATE_MASK GENMASK(5, 0) @@ -138,6 +143,9 @@ #define WR_NO_SNOOP_OVERRIDE_EN BIT(1) #define RD_NO_SNOOP_OVERRIDE_EN BIT(3) +/* PARF_AXI_MSTR_WR_NS_BDF_HALT */ +#define BDF_CHANGE_HALT_EN BIT(0) + /* PARF_DEVICE_TYPE register fields */ #define DEVICE_TYPE_RC 0x4 @@ -260,12 +268,16 @@ struct qcom_pcie_ops { * @override_no_snoop: Override NO_SNOOP attribute in TLP to enable cache * snooping * @firmware_managed: Set if the Root Complex is firmware managed + * @no_l0s: Set if the Root Complex does not support L0s + * @noc_ensures_ordering: Set if the NoC preserves the ordering of inbound + * transactions from the controller. */ struct qcom_pcie_cfg { const struct qcom_pcie_ops *ops; bool override_no_snoop; bool firmware_managed; bool no_l0s; + bool noc_ensures_ordering; }; struct qcom_pcie_perst { @@ -1057,9 +1069,23 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie) pci->l1ss_support = true; - val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); - val |= EN; - writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + if (pcie->cfg->noc_ensures_ordering) { + val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + val &= ~EN; + writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + + val = readl(pcie->parf + PARF_AXI_MSTR_RD_HALT_NO_WRITES); + val &= ~RD_HALT_NO_WRITES_EN; + writel(val, pcie->parf + PARF_AXI_MSTR_RD_HALT_NO_WRITES); + + val = readl(pcie->parf + PARF_AXI_MSTR_WR_NS_BDF_HALT); + val &= ~BDF_CHANGE_HALT_EN; + writel(val, pcie->parf + PARF_AXI_MSTR_WR_NS_BDF_HALT); + } else { + val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + val |= EN; + writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + } return 0; err_disable_clocks: @@ -1571,12 +1597,14 @@ static const struct qcom_pcie_cfg cfg_1_0_0 = { static const struct qcom_pcie_cfg cfg_1_9_0 = { .ops = &ops_1_9_0, + .noc_ensures_ordering = true, }; static const struct qcom_pcie_cfg cfg_1_34_0 = { .ops = &ops_1_9_0, .override_no_snoop = true, .no_l0s = true, + .noc_ensures_ordering = true, }; static const struct qcom_pcie_cfg cfg_2_1_0 = { @@ -1598,15 +1626,18 @@ static const struct qcom_pcie_cfg cfg_2_4_0 = { static const struct qcom_pcie_cfg cfg_2_7_0 = { .ops = &ops_2_7_0, + .noc_ensures_ordering = true, }; static const struct qcom_pcie_cfg cfg_2_9_0 = { .ops = &ops_2_9_0, + .noc_ensures_ordering = true, }; static const struct qcom_pcie_cfg cfg_sc8280xp = { .ops = &ops_1_21_0, .no_l0s = true, + .noc_ensures_ordering = true, }; static const struct qcom_pcie_cfg cfg_fw_managed = {