diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h index 40202988c989..34b7a56b2217 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h +++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h @@ -43,6 +43,9 @@ #define PCIE20_PARF_INT_ALL_STATUS 0x224 #define PCIE20_PARF_INT_ALL_CLEAR 0x228 #define PCIE20_PARF_INT_ALL_MASK 0x22C +#define PCIE20_PARF_INT_ALL_2_STATUS 0x500 +#define PCIE20_PARF_INT_ALL_2_CLEAR 0x504 +#define PCIE20_PARF_INT_ALL_2_MASK 0x508 #define PCIE20_PARF_CLKREQ_OVERRIDE 0x2B0 #define PCIE20_PARF_CLKREQ_IN_OVERRIDE_STS BIT(5) @@ -175,6 +178,7 @@ #define MSI_EXIT_L1SS_WAIT_MAX_COUNT 100 #define XMLH_LINK_UP 0x400 #define PARF_XMLH_LINK_UP 0x40000000 +#define CFG_BUS_MASTER_EN_DEASSERT BIT(24) #define MAX_PROP_SIZE 32 #define MAX_MSG_LEN 80 @@ -363,6 +367,7 @@ struct ep_pcie_dev_t { bool aoss_rst_clear; bool avoid_reboot_in_d3hot; bool pme_in_wake_from_d3cold; + bool bme_deassert_irq; u32 dbi_base_reg; u32 slv_space_reg; u32 phy_status_reg; diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index d20bc0b18239..7e81a80905b9 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -874,8 +874,16 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured) ep_pcie_write_mask(dev->parf + PCIE20_PARF_INT_ALL_MASK, 0, BIT(EP_PCIE_INT_EVT_L1SUB_TIMEOUT)); + if (dev->bme_deassert_irq) { + ep_pcie_write_reg(dev->parf, PCIE20_PARF_INT_ALL_2_MASK, 0); + ep_pcie_write_mask(dev->parf + PCIE20_PARF_INT_ALL_2_MASK, 0, + CFG_BUS_MASTER_EN_DEASSERT); + EP_PCIE_INFO(dev, + "PCIe V%d: PCIE20_PARF_INT_ALL_2_MASK:0x%x\n", dev->rev, + readl_relaxed(dev->parf + PCIE20_PARF_INT_ALL_2_MASK)); + } - EP_PCIE_DBG(dev, "PCIe V%d: PCIE20_PARF_INT_ALL_MASK:0x%x\n", + EP_PCIE_INFO(dev, "PCIe V%d: PCIE20_PARF_INT_ALL_MASK:0x%x\n", dev->rev, readl_relaxed(dev->parf + PCIE20_PARF_INT_ALL_MASK)); } @@ -2606,6 +2614,30 @@ static irqreturn_t ep_pcie_handle_clkreq_irq(int irq, void *data) return IRQ_HANDLED; } +/** + * ep_pcie_handle_bme_deassert_irq - Check the second status register of PCIe's + * interrupts and print error log for BME deassert IRQ. + * @dev: PCIe endpoint device structure. + * @status2: Second status register of PCIe's interrupts. + */ +static void ep_pcie_handle_bme_deassert_irq(struct ep_pcie_dev_t *dev, u32 status2) +{ + bool bme; + u32 mask2 = readl_relaxed(dev->parf + PCIE20_PARF_INT_ALL_2_MASK); + + ep_pcie_write_mask(dev->parf + PCIE20_PARF_INT_ALL_2_CLEAR, 0, status2); + + EP_PCIE_DUMP(dev, + "PCIe V%d: Global IRQ received; status2:0x%x; mask2:0x%x\n", + dev->rev, status2, mask2); + + if (status2 & CFG_BUS_MASTER_EN_DEASSERT) { + bme = readl_relaxed(dev->dm_core + PCIE20_COMMAND_STATUS) & BIT(2); + EP_PCIE_ERR(dev, "PCIe V%d: BME deassert IRQ received, BME = %d\n", + dev->rev, bme); + } +} + static irqreturn_t ep_pcie_handle_global_irq(int irq, void *data) { struct ep_pcie_dev_t *dev = data; @@ -2675,6 +2707,12 @@ static irqreturn_t ep_pcie_handle_global_irq(int irq, void *data) } } + if (dev->bme_deassert_irq) { + status = readl_relaxed(dev->parf + PCIE20_PARF_INT_ALL_2_STATUS); + if (status) + ep_pcie_handle_bme_deassert_irq(dev, status); + } + return IRQ_HANDLED; } @@ -3496,6 +3534,11 @@ static int ep_pcie_probe(struct platform_device *pdev) "PCIe V%d: PME is%s sent during wake from d3cold\n", ep_pcie_dev.rev, ep_pcie_dev.pme_in_wake_from_d3cold ? "" : " not"); + ep_pcie_dev.bme_deassert_irq = of_property_read_bool((&pdev->dev)->of_node, + "qcom,pcie-bme-deassert-irq"); + EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: BME deassert irq is%s enabled\n", + ep_pcie_dev.rev, ep_pcie_dev.bme_deassert_irq ? "" : " not"); + ret = of_property_read_u32((&pdev->dev)->of_node, "qcom,mhi-soc-reset-offset", &ep_pcie_dev.mhi_soc_reset_offset);