From 5e6eb6667408eb397dd8a8235740434902f33d68 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. Change-Id: Ie5b5a0b7f6ab03961658b4217c9db2cada0edb93 Signed-off-by: Shawn Lin Signed-off-by: Simon Xue --- 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 1d637dd53072..356fc72840c1 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -85,6 +85,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 @@ -690,6 +691,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); @@ -1256,6 +1260,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); @@ -1277,6 +1282,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; }