From f0d532ee6659ed922e25eb721cb976fd264e072f Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Wed, 2 Jun 2021 17:55:07 +0800 Subject: [PATCH] PCI: rockchip: dw: Restore DBI COMMAND register It isn't sticky when link goes down for whatever reason. If devices want to reset the modules by puting link into D3 state or whatever, we should restore it the. Otherwise devices cannot access RC's resource even if the link is recovered. Signed-off-by: Shawn Lin Change-Id: Ie5b5a0b7f6ab03961658b4217c9db2cada0edb93 --- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index fdc3597ed6d5..caf41cce1b45 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -84,6 +84,7 @@ struct reset_bulk_data { #define PCIE_CAP_LINK_CONTROL2_LINK_STATUS 0xa0 #define PCIE_CLIENT_INTR_STATUS_LEGACY 0x08 +#define PCIE_CLIENT_INTR_STATUS_MISC 0x10 #define PCIE_CLIENT_INTR_MASK_LEGACY 0x1c #define UNMASK_ALL_LEGACY_INT 0xffff0000 #define PCIE_CLIENT_INTR_MASK 0x24 @@ -447,6 +448,9 @@ static int rk_pcie_establish_link(struct dw_pcie *pci) rk_pcie_link_status_clear(rk_pcie); rk_pcie_enable_debug(rk_pcie); + /* Enable client reset or link down interrupt */ + rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0x40000); + /* Enable LTSSM */ rk_pcie_enable_ltssm(rk_pcie); @@ -997,6 +1001,7 @@ static irqreturn_t rk_pcie_sys_irq_handler(int irq, void *arg) u32 chn = 0; union int_status status; union int_clear clears; + u32 reg, val; status.asdword = dw_pcie_readl_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS); @@ -1018,6 +1023,18 @@ static irqreturn_t rk_pcie_sys_irq_handler(int irq, void *arg) PCIE_DMA_WR_INT_CLEAR, clears.asdword); } + reg = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MISC); + if (reg & BIT(2)) { + /* Setup command register */ + val = dw_pcie_readl_dbi(rk_pcie->pci, PCI_COMMAND); + val &= 0xffff0000; + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_SERR; + dw_pcie_writel_dbi(rk_pcie->pci, PCI_COMMAND, val); + } + + rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MISC, reg); + return IRQ_HANDLED; }