OSDN Git Service

Merge remote-tracking branch 'lorenzo/pci/dwc' into next
authorBjorn Helgaas <bhelgaas@google.com>
Thu, 1 Feb 2018 17:36:07 +0000 (11:36 -0600)
committerBjorn Helgaas <helgaas@kernel.org>
Thu, 1 Feb 2018 17:36:07 +0000 (11:36 -0600)
* lorenzo/pci/dwc:
  PCI: exynos: Fix a potential init_clk_resources NULL pointer dereference
  PCI: iproc: Fix NULL pointer dereference for BCMA
  PCI: dra7xx: Iterate over INTx status bits
  PCI: dra7xx: Fix legacy INTD IRQ handling
  PCI: qcom: Account for const type of of_device_id.data
  PCI: dwc: artpec6: Fix return value check in artpec6_add_pcie_ep()
  PCI: exynos: Remove deprecated PHY initialization code
  PCI: dwc: artpec6: Add support for the ARTPEC-7 SoC
  bindings: PCI: artpec: Add support for the ARTPEC-7 SoC
  PCI: dwc: artpec6: Deassert the core before waiting for PHY
  PCI: dwc: Make cpu_addr_fixup take struct dw_pcie as argument
  PCI: dwc: artpec6: Add support for endpoint mode
  bindings: PCI: artpec: Add support for endpoint mode
  PCI: dwc: artpec6: Split artpec6_pcie_establish_link() into smaller functions
  PCI: dwc: artpec6: Use BIT and GENMASK macros
  PCI: dwc: artpec6: Remove unused defines
  PCI: dwc: dra7xx: Help compiler to remove unused code
  PCI: dwc: dra7xx: Assign pp->ops in dra7xx_add_pcie_port() rather than in probe
  PCI: dwc: dra7xx: Refactor Kconfig and Makefile handling for host/ep mode
  PCI: designware-ep: Add generic function for raising MSI irq
  PCI: designware-ep: Remove static keyword from dw_pcie_ep_reset_bar()
  PCI: designware-ep: Pre-allocate memory for MSI in dw_pcie_ep_init
  PCI: designware-ep: Read-only registers need DBI_RO_WR_EN to be writable
  PCI: designware-ep: dw_pcie_ep_set_msi() should only set MMC bits
  PCI: dwc: Use the DMA-API to get the MSI address
  pci: dwc: pci-dra7xx: Make shutdown handler static

Includes resolution to conflict between:

  4494738de0d9 ("PCI: endpoint: Add the function number as argument to EPC ops")
  6f6d7873711c ("PCI: designware-ep: Add generic function for raising MSI irq")

The resolution is due to Niklas Cassel <niklas.cassel@axis.com>:
https://lkml.kernel.org/r/20180201085608.GA22568@axis.com

1  2 
drivers/pci/dwc/Makefile
drivers/pci/dwc/pci-dra7xx.c
drivers/pci/dwc/pcie-artpec6.c
drivers/pci/dwc/pcie-designware-ep.c
drivers/pci/dwc/pcie-designware.h

Simple merge
@@@ -375,7 -371,7 +371,7 @@@ static void dra7xx_pcie_raise_msi_irq(s
        dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_MSI_XMT, reg);
  }
  
--static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep,
++static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
                                 enum pci_epc_irq_type type, u8 interrupt_num)
  {
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
@@@ -230,10 -432,78 +432,78 @@@ static int artpec6_add_pcie_port(struc
        return 0;
  }
  
- static const struct dw_pcie_ops dw_pcie_ops = {
-       .cpu_addr_fixup = artpec6_pcie_cpu_addr_fixup,
+ static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep)
+ {
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
+       enum pci_barno bar;
+       artpec6_pcie_assert_core_reset(artpec6_pcie);
+       artpec6_pcie_init_phy(artpec6_pcie);
+       artpec6_pcie_deassert_core_reset(artpec6_pcie);
+       artpec6_pcie_wait_for_phy(artpec6_pcie);
+       artpec6_pcie_set_nfts(artpec6_pcie);
+       for (bar = BAR_0; bar <= BAR_5; bar++)
+               dw_pcie_ep_reset_bar(pci, bar);
+ }
 -static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep,
++static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
+                                 enum pci_epc_irq_type type, u8 interrupt_num)
+ {
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       switch (type) {
+       case PCI_EPC_IRQ_LEGACY:
+               dev_err(pci->dev, "EP cannot trigger legacy IRQs\n");
+               return -EINVAL;
+       case PCI_EPC_IRQ_MSI:
 -              return dw_pcie_ep_raise_msi_irq(ep, interrupt_num);
++              return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
+       default:
+               dev_err(pci->dev, "UNKNOWN IRQ type\n");
+       }
+       return 0;
+ }
+ static struct dw_pcie_ep_ops pcie_ep_ops = {
+       .ep_init = artpec6_pcie_ep_init,
+       .raise_irq = artpec6_pcie_raise_irq,
  };
  
+ static int artpec6_add_pcie_ep(struct artpec6_pcie *artpec6_pcie,
+                              struct platform_device *pdev)
+ {
+       int ret;
+       struct dw_pcie_ep *ep;
+       struct resource *res;
+       struct device *dev = &pdev->dev;
+       struct dw_pcie *pci = artpec6_pcie->pci;
+       ep = &pci->ep;
+       ep->ops = &pcie_ep_ops;
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi2");
+       pci->dbi_base2 = devm_ioremap(dev, res->start, resource_size(res));
+       if (!pci->dbi_base2)
+               return -ENOMEM;
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
+       if (!res)
+               return -EINVAL;
+       ep->phys_base = res->start;
+       ep->addr_size = resource_size(res);
+       ret = dw_pcie_ep_init(ep);
+       if (ret) {
+               dev_err(dev, "failed to initialize endpoint\n");
+               return ret;
+       }
+       return 0;
+ }
  static int artpec6_pcie_probe(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
@@@ -35,11 -35,13 +35,13 @@@ void dw_pcie_ep_reset_bar(struct dw_pci
        u32 reg;
  
        reg = PCI_BASE_ADDRESS_0 + (4 * bar);
+       dw_pcie_dbi_ro_wr_en(pci);
        dw_pcie_writel_dbi2(pci, reg, 0x0);
        dw_pcie_writel_dbi(pci, reg, 0x0);
+       dw_pcie_dbi_ro_wr_dis(pci);
  }
  
 -static int dw_pcie_ep_write_header(struct pci_epc *epc,
 +static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,
                                   struct pci_epf_header *hdr)
  {
        struct dw_pcie_ep *ep = epc_get_drvdata(epc);
@@@ -238,7 -244,7 +248,7 @@@ static int dw_pcie_ep_raise_irq(struct 
        if (!ep->ops->raise_irq)
                return -EINVAL;
  
--      return ep->ops->raise_irq(ep, type, interrupt_num);
++      return ep->ops->raise_irq(ep, func_no, type, interrupt_num);
  }
  
  static void dw_pcie_ep_stop(struct pci_epc *epc)
@@@ -276,6 -282,41 +286,41 @@@ static const struct pci_epc_ops epc_op
        .stop                   = dw_pcie_ep_stop,
  };
  
 -int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep,
++int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
+                            u8 interrupt_num)
+ {
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       struct pci_epc *epc = ep->epc;
+       u16 msg_ctrl, msg_data;
+       u32 msg_addr_lower, msg_addr_upper;
+       u64 msg_addr;
+       bool has_upper;
+       int ret;
+       /* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */
+       msg_ctrl = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL);
+       has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT);
+       msg_addr_lower = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_L32);
+       if (has_upper) {
+               msg_addr_upper = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_U32);
+               msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_64);
+       } else {
+               msg_addr_upper = 0;
+               msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_32);
+       }
+       msg_addr = ((u64) msg_addr_upper) << 32 | msg_addr_lower;
 -      ret = dw_pcie_ep_map_addr(epc, ep->msi_mem_phys, msg_addr,
++      ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr,
+                                 epc->mem->page_size);
+       if (ret)
+               return ret;
+       writel(msg_data | (interrupt_num - 1), ep->msi_mem);
 -      dw_pcie_ep_unmap_addr(epc, ep->msi_mem_phys);
++      dw_pcie_ep_unmap_addr(epc, func_no, ep->msi_mem_phys);
+       return 0;
+ }
  void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
  {
        struct pci_epc *epc = ep->epc;
@@@ -180,8 -184,8 +184,8 @@@ enum dw_pcie_as_type 
  
  struct dw_pcie_ep_ops {
        void    (*ep_init)(struct dw_pcie_ep *ep);
--      int     (*raise_irq)(struct dw_pcie_ep *ep, enum pci_epc_irq_type type,
--                           u8 interrupt_num);
++      int     (*raise_irq)(struct dw_pcie_ep *ep, u8 func_no,
++                           enum pci_epc_irq_type type, u8 interrupt_num);
  };
  
  struct dw_pcie_ep {
@@@ -334,6 -340,8 +340,9 @@@ static inline int dw_pcie_host_init(str
  void dw_pcie_ep_linkup(struct dw_pcie_ep *ep);
  int dw_pcie_ep_init(struct dw_pcie_ep *ep);
  void dw_pcie_ep_exit(struct dw_pcie_ep *ep);
 -int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 interrupt_num);
++int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
++                           u8 interrupt_num);
+ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar);
  #else
  static inline void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)
  {
@@@ -347,5 -355,15 +356,15 @@@ static inline int dw_pcie_ep_init(struc
  static inline void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
  {
  }
 -static inline int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep,
++static inline int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
+                                          u8 interrupt_num)
+ {
+       return 0;
+ }
+ static inline void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
+ {
+ }
  #endif
  #endif /* _PCIE_DESIGNWARE_H */