MLK-11484-3 PCI: designware: Refine setup_rc and add msi data restore
authorRichard Zhu <r65037@freescale.com>
Fri, 26 Sep 2014 08:54:02 +0000 (16:54 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:48:33 +0000 (14:48 -0500)
- 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>
drivers/pci/host/pcie-designware.c
drivers/pci/host/pcie-designware.h

index b3a8715..b313f85 100644 (file)
@@ -296,6 +296,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;
@@ -864,6 +886,11 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
        val |= 0x00ff0100;
        dw_pcie_writel_rc(pp, PCI_PRIMARY_BUS, val);
 
+       /* program correct class for RC */
+       val = dw_pcie_readl_rc(pp, PCI_CLASS_REVISION);
+       val |= PCI_CLASS_BRIDGE_PCI << 16;
+       dw_pcie_writel_rc(pp, val, PCI_CLASS_REVISION);
+
        /* setup command register */
        val = dw_pcie_readl_rc(pp, PCI_COMMAND);
        val &= 0xffff0000;
index a567ea2..db8994f 100644 (file)
@@ -50,6 +50,7 @@ struct pcie_port {
        struct irq_domain       *irq_domain;
        unsigned long           msi_data;
        u8                      iatu_unroll_enabled;
+       unsigned int            msi_enable[MAX_MSI_CTRLS];
        DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
 };
 
@@ -79,6 +80,8 @@ int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val);
 irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
 void dw_pcie_msi_init(struct pcie_port *pp);
 int dw_pcie_wait_for_link(struct pcie_port *pp);
+void dw_pcie_msi_cfg_store(struct pcie_port *pp);
+void dw_pcie_msi_cfg_restore(struct pcie_port *pp);
 int dw_pcie_link_up(struct pcie_port *pp);
 void dw_pcie_setup_rc(struct pcie_port *pp);
 int dw_pcie_host_init(struct pcie_port *pp);