From: Bjorn Helgaas Date: Thu, 1 Feb 2018 17:36:07 +0000 (-0600) Subject: Merge remote-tracking branch 'lorenzo/pci/dwc' into next X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=16093362d66ac205811b666ce7c38a0f34ace623;p=openwrt%2Fstaging%2Fblogic.git Merge remote-tracking branch 'lorenzo/pci/dwc' into next * 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 : https://lkml.kernel.org/r/20180201085608.GA22568@axis.com --- 16093362d66ac205811b666ce7c38a0f34ace623 diff --cc drivers/pci/dwc/pci-dra7xx.c index e77a4ceed74c,8bf7c2714db6..97611f476c7f --- a/drivers/pci/dwc/pci-dra7xx.c +++ b/drivers/pci/dwc/pci-dra7xx.c @@@ -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); diff --cc drivers/pci/dwc/pcie-artpec6.c index 6653619db6a1,b1e98205110f..7a9f4c0f1643 --- a/drivers/pci/dwc/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c @@@ -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; diff --cc drivers/pci/dwc/pcie-designware-ep.c index 7a573d8bb62d,c5aa1cac5041..52edcb19da36 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@@ -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; diff --cc drivers/pci/dwc/pcie-designware.h index e5d9d77b778e,cca5a81c1c74..eae17d96e6f7 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h @@@ -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 */