summaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
authorRichard Zhu <r65037@freescale.com>2014-09-26 16:54:02 +0800
committerJason Liu <jason.hui.liu@nxp.com>2019-02-12 10:23:11 +0800
commit35c33f3edfc174cba8ff9e1f9bca72f95f71f9a0 (patch)
tree4a4b9ccbe7918eadc4ab919d21158182b32a7b83 /drivers/pci
parent26512ed9f4b3fd32758256cddcc27301503e2296 (diff)
MLK-11484-3 PCI: designware: Refine setup_rc and add msi data restore
- move "program correct class for RC" from dw_pcie_host_init() to dw_pcie_setup_rc(). since this is RC setup, it's better to contained in dw_pcie_setup_rc function. Then, RC can be re-setup really by dw_pcie_setup_rc(). - add one store/re-store msi cfg functions. Because that pcie controller maybe powered off during system suspend, and the msi data configuration would be lost. these functions can be used to store/restore the msi data and msi_enable during the suspend/resume callback. Signed-off-by: Richard Zhu <richard.zhu@freescale.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/dwc/pcie-designware-host.c27
-rw-r--r--drivers/pci/dwc/pcie-designware.h11
2 files changed, 38 insertions, 0 deletions
diff --git a/drivers/pci/dwc/pcie-designware-host.c b/drivers/pci/dwc/pcie-designware-host.c
index 58b38c54a7cf..df18b2440102 100644
--- a/drivers/pci/dwc/pcie-designware-host.c
+++ b/drivers/pci/dwc/pcie-designware-host.c
@@ -104,6 +104,28 @@ void dw_pcie_msi_init(struct pcie_port *pp)
(u32)(msi_target >> 32 & 0xffffffff));
}
+void dw_pcie_msi_cfg_store(struct pcie_port *pp)
+{
+ int i;
+
+ for (i = 0; i < MAX_MSI_CTRLS; i++)
+ dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + i * 12, 4,
+ &pp->msi_enable[i]);
+}
+
+void dw_pcie_msi_cfg_restore(struct pcie_port *pp)
+{
+ int i;
+
+ for (i = 0; i < MAX_MSI_CTRLS; i++) {
+ dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4,
+ virt_to_phys((void *)pp->msi_data));
+ dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, 0);
+ dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + i * 12, 4,
+ pp->msi_enable[i]);
+ }
+}
+
static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
{
unsigned int res, bit, val;
@@ -619,6 +641,11 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
val |= 0x00ff0100;
dw_pcie_writel_dbi(pci, PCI_PRIMARY_BUS, val);
+ /* program correct class for RC */
+ val = dw_pcie_readl_dbi(pci, PCI_CLASS_REVISION);
+ val |= PCI_CLASS_BRIDGE_PCI << 16;
+ dw_pcie_writel_dbi(pci, val, PCI_CLASS_REVISION);
+
/* setup command register */
val = dw_pcie_readl_dbi(pci, PCI_COMMAND);
val &= 0xffff0000;
diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h
index 3551dd607b90..ce70c512809b 100644
--- a/drivers/pci/dwc/pcie-designware.h
+++ b/drivers/pci/dwc/pcie-designware.h
@@ -169,6 +169,7 @@ struct pcie_port {
int msi_irq;
struct irq_domain *irq_domain;
unsigned long msi_data;
+ unsigned int msi_enable[MAX_MSI_CTRLS];
DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
};
@@ -308,6 +309,8 @@ static inline void dw_pcie_dbi_ro_wr_dis(struct dw_pcie *pci)
#ifdef CONFIG_PCIE_DW_HOST
irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
void dw_pcie_msi_init(struct pcie_port *pp);
+void dw_pcie_msi_cfg_store(struct pcie_port *pp);
+void dw_pcie_msi_cfg_restore(struct pcie_port *pp);
void dw_pcie_setup_rc(struct pcie_port *pp);
int dw_pcie_host_init(struct pcie_port *pp);
#else
@@ -320,6 +323,14 @@ static inline void dw_pcie_msi_init(struct pcie_port *pp)
{
}
+static inline void dw_pcie_msi_cfg_store(struct pcie_port *pp)
+{
+}
+
+static inline void dw_pcie_msi_cfg_restore(struct pcie_port *pp)
+{
+}
+
static inline void dw_pcie_setup_rc(struct pcie_port *pp)
{
}