* 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
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);
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;
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);
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)
.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;
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 {
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)
{
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 */