diff options
author | Richard Zhu <r65037@freescale.com> | 2014-09-26 16:54:02 +0800 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:23:11 +0800 |
commit | 35c33f3edfc174cba8ff9e1f9bca72f95f71f9a0 (patch) | |
tree | 4a4b9ccbe7918eadc4ab919d21158182b32a7b83 /drivers/pci | |
parent | 26512ed9f4b3fd32758256cddcc27301503e2296 (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.c | 27 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware.h | 11 |
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) { } |