• Home
  • Raw
  • Download

Lines Matching +full:pcie +full:- +full:ep

1 // SPDX-License-Identifier: GPL-2.0
3 // Cadence PCIe endpoint controller driver.
4 // Author: Cyrille Pitchen <cyrille.pitchen@free-electrons.com>
9 #include <linux/pci-epc.h>
13 #include "pcie-cadence.h"
22 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); in cdns_pcie_ep_write_header() local
23 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_write_header() local
25 cdns_pcie_ep_fn_writew(pcie, fn, PCI_DEVICE_ID, hdr->deviceid); in cdns_pcie_ep_write_header()
26 cdns_pcie_ep_fn_writeb(pcie, fn, PCI_REVISION_ID, hdr->revid); in cdns_pcie_ep_write_header()
27 cdns_pcie_ep_fn_writeb(pcie, fn, PCI_CLASS_PROG, hdr->progif_code); in cdns_pcie_ep_write_header()
28 cdns_pcie_ep_fn_writew(pcie, fn, PCI_CLASS_DEVICE, in cdns_pcie_ep_write_header()
29 hdr->subclass_code | hdr->baseclass_code << 8); in cdns_pcie_ep_write_header()
30 cdns_pcie_ep_fn_writeb(pcie, fn, PCI_CACHE_LINE_SIZE, in cdns_pcie_ep_write_header()
31 hdr->cache_line_size); in cdns_pcie_ep_write_header()
32 cdns_pcie_ep_fn_writew(pcie, fn, PCI_SUBSYSTEM_ID, hdr->subsys_id); in cdns_pcie_ep_write_header()
33 cdns_pcie_ep_fn_writeb(pcie, fn, PCI_INTERRUPT_PIN, hdr->interrupt_pin); in cdns_pcie_ep_write_header()
41 u32 id = CDNS_PCIE_LM_ID_VENDOR(hdr->vendorid) | in cdns_pcie_ep_write_header()
42 CDNS_PCIE_LM_ID_SUBSYS(hdr->subsys_vendor_id); in cdns_pcie_ep_write_header()
44 cdns_pcie_writel(pcie, CDNS_PCIE_LM_ID, id); in cdns_pcie_ep_write_header()
53 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); in cdns_pcie_ep_set_bar() local
54 struct cdns_pcie_epf *epf = &ep->epf[fn]; in cdns_pcie_ep_set_bar()
55 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_set_bar() local
56 dma_addr_t bar_phys = epf_bar->phys_addr; in cdns_pcie_ep_set_bar()
57 enum pci_barno bar = epf_bar->barno; in cdns_pcie_ep_set_bar()
58 int flags = epf_bar->flags; in cdns_pcie_ep_set_bar()
63 sz = max_t(size_t, epf_bar->size, CDNS_PCIE_EP_MIN_APERTURE); in cdns_pcie_ep_set_bar()
68 sz = 1ULL << fls64(sz - 1); in cdns_pcie_ep_set_bar()
69 aperture = ilog2(sz) - 7; /* 128B -> 0, 256B -> 1, 512B -> 2, ... */ in cdns_pcie_ep_set_bar()
78 return -EINVAL; in cdns_pcie_ep_set_bar()
81 epf_bar->flags |= PCI_BASE_ADDRESS_MEM_TYPE_64; in cdns_pcie_ep_set_bar()
95 cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar), in cdns_pcie_ep_set_bar()
97 cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar), in cdns_pcie_ep_set_bar()
105 b = bar - BAR_4; in cdns_pcie_ep_set_bar()
108 cfg = cdns_pcie_readl(pcie, reg); in cdns_pcie_ep_set_bar()
113 cdns_pcie_writel(pcie, reg, cfg); in cdns_pcie_ep_set_bar()
115 epf->epf_bar[bar] = epf_bar; in cdns_pcie_ep_set_bar()
123 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); in cdns_pcie_ep_clear_bar() local
124 struct cdns_pcie_epf *epf = &ep->epf[fn]; in cdns_pcie_ep_clear_bar()
125 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_clear_bar() local
126 enum pci_barno bar = epf_bar->barno; in cdns_pcie_ep_clear_bar()
134 b = bar - BAR_4; in cdns_pcie_ep_clear_bar()
138 cfg = cdns_pcie_readl(pcie, reg); in cdns_pcie_ep_clear_bar()
142 cdns_pcie_writel(pcie, reg, cfg); in cdns_pcie_ep_clear_bar()
144 cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar), 0); in cdns_pcie_ep_clear_bar()
145 cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar), 0); in cdns_pcie_ep_clear_bar()
147 epf->epf_bar[bar] = NULL; in cdns_pcie_ep_clear_bar()
153 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); in cdns_pcie_ep_map_addr() local
154 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_map_addr() local
157 r = find_first_zero_bit(&ep->ob_region_map, BITS_PER_LONG); in cdns_pcie_ep_map_addr()
158 if (r >= ep->max_regions - 1) { in cdns_pcie_ep_map_addr()
159 dev_err(&epc->dev, "no free outbound region\n"); in cdns_pcie_ep_map_addr()
160 return -EINVAL; in cdns_pcie_ep_map_addr()
163 cdns_pcie_set_outbound_region(pcie, 0, fn, r, false, addr, pci_addr, size); in cdns_pcie_ep_map_addr()
165 set_bit(r, &ep->ob_region_map); in cdns_pcie_ep_map_addr()
166 ep->ob_addr[r] = addr; in cdns_pcie_ep_map_addr()
174 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); in cdns_pcie_ep_unmap_addr() local
175 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_unmap_addr() local
178 for (r = 0; r < ep->max_regions - 1; r++) in cdns_pcie_ep_unmap_addr()
179 if (ep->ob_addr[r] == addr) in cdns_pcie_ep_unmap_addr()
182 if (r == ep->max_regions - 1) in cdns_pcie_ep_unmap_addr()
185 cdns_pcie_reset_outbound_region(pcie, r); in cdns_pcie_ep_unmap_addr()
187 ep->ob_addr[r] = 0; in cdns_pcie_ep_unmap_addr()
188 clear_bit(r, &ep->ob_region_map); in cdns_pcie_ep_unmap_addr()
193 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); in cdns_pcie_ep_set_msi() local
194 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_set_msi() local
202 flags = cdns_pcie_ep_fn_readw(pcie, fn, cap + PCI_MSI_FLAGS); in cdns_pcie_ep_set_msi()
206 cdns_pcie_ep_fn_writew(pcie, fn, cap + PCI_MSI_FLAGS, flags); in cdns_pcie_ep_set_msi()
213 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); in cdns_pcie_ep_get_msi() local
214 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_get_msi() local
219 flags = cdns_pcie_ep_fn_readw(pcie, fn, cap + PCI_MSI_FLAGS); in cdns_pcie_ep_get_msi()
221 return -EINVAL; in cdns_pcie_ep_get_msi()
234 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); in cdns_pcie_ep_get_msix() local
235 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_get_msix() local
240 val = cdns_pcie_ep_fn_readw(pcie, func_no, reg); in cdns_pcie_ep_get_msix()
242 return -EINVAL; in cdns_pcie_ep_get_msix()
252 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); in cdns_pcie_ep_set_msix() local
253 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_set_msix() local
258 val = cdns_pcie_ep_fn_readw(pcie, fn, reg); in cdns_pcie_ep_set_msix()
261 cdns_pcie_ep_fn_writew(pcie, fn, reg, val); in cdns_pcie_ep_set_msix()
266 cdns_pcie_ep_fn_writel(pcie, fn, reg, val); in cdns_pcie_ep_set_msix()
271 cdns_pcie_ep_fn_writel(pcie, fn, reg, val); in cdns_pcie_ep_set_msix()
276 static void cdns_pcie_ep_assert_intx(struct cdns_pcie_ep *ep, u8 fn, in cdns_pcie_ep_assert_intx() argument
279 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_assert_intx() local
288 if (unlikely(ep->irq_pci_addr != CDNS_PCIE_EP_IRQ_PCI_ADDR_LEGACY || in cdns_pcie_ep_assert_intx()
289 ep->irq_pci_fn != fn)) { in cdns_pcie_ep_assert_intx()
291 cdns_pcie_set_outbound_region_for_normal_msg(pcie, 0, fn, 0, in cdns_pcie_ep_assert_intx()
292 ep->irq_phys_addr); in cdns_pcie_ep_assert_intx()
293 ep->irq_pci_addr = CDNS_PCIE_EP_IRQ_PCI_ADDR_LEGACY; in cdns_pcie_ep_assert_intx()
294 ep->irq_pci_fn = fn; in cdns_pcie_ep_assert_intx()
298 ep->irq_pending |= BIT(intx); in cdns_pcie_ep_assert_intx()
301 ep->irq_pending &= ~BIT(intx); in cdns_pcie_ep_assert_intx()
305 spin_lock_irqsave(&ep->lock, flags); in cdns_pcie_ep_assert_intx()
306 status = cdns_pcie_ep_fn_readw(pcie, fn, PCI_STATUS); in cdns_pcie_ep_assert_intx()
307 if (((status & PCI_STATUS_INTERRUPT) != 0) ^ (ep->irq_pending != 0)) { in cdns_pcie_ep_assert_intx()
309 cdns_pcie_ep_fn_writew(pcie, fn, PCI_STATUS, status); in cdns_pcie_ep_assert_intx()
311 spin_unlock_irqrestore(&ep->lock, flags); in cdns_pcie_ep_assert_intx()
316 writel(0, ep->irq_cpu_addr + offset); in cdns_pcie_ep_assert_intx()
319 static int cdns_pcie_ep_send_legacy_irq(struct cdns_pcie_ep *ep, u8 fn, u8 intx) in cdns_pcie_ep_send_legacy_irq() argument
323 cmd = cdns_pcie_ep_fn_readw(&ep->pcie, fn, PCI_COMMAND); in cdns_pcie_ep_send_legacy_irq()
325 return -EINVAL; in cdns_pcie_ep_send_legacy_irq()
327 cdns_pcie_ep_assert_intx(ep, fn, intx, true); in cdns_pcie_ep_send_legacy_irq()
332 cdns_pcie_ep_assert_intx(ep, fn, intx, false); in cdns_pcie_ep_send_legacy_irq()
336 static int cdns_pcie_ep_send_msi_irq(struct cdns_pcie_ep *ep, u8 fn, in cdns_pcie_ep_send_msi_irq() argument
339 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_send_msi_irq() local
346 flags = cdns_pcie_ep_fn_readw(pcie, fn, cap + PCI_MSI_FLAGS); in cdns_pcie_ep_send_msi_irq()
348 return -EINVAL; in cdns_pcie_ep_send_msi_irq()
354 return -EINVAL; in cdns_pcie_ep_send_msi_irq()
357 data_mask = msi_count - 1; in cdns_pcie_ep_send_msi_irq()
358 data = cdns_pcie_ep_fn_readw(pcie, fn, cap + PCI_MSI_DATA_64); in cdns_pcie_ep_send_msi_irq()
359 data = (data & ~data_mask) | ((interrupt_num - 1) & data_mask); in cdns_pcie_ep_send_msi_irq()
362 pci_addr = cdns_pcie_ep_fn_readl(pcie, fn, cap + PCI_MSI_ADDRESS_HI); in cdns_pcie_ep_send_msi_irq()
364 pci_addr |= cdns_pcie_ep_fn_readl(pcie, fn, cap + PCI_MSI_ADDRESS_LO); in cdns_pcie_ep_send_msi_irq()
368 if (unlikely(ep->irq_pci_addr != (pci_addr & ~pci_addr_mask) || in cdns_pcie_ep_send_msi_irq()
369 ep->irq_pci_fn != fn)) { in cdns_pcie_ep_send_msi_irq()
371 cdns_pcie_set_outbound_region(pcie, 0, fn, 0, in cdns_pcie_ep_send_msi_irq()
373 ep->irq_phys_addr, in cdns_pcie_ep_send_msi_irq()
376 ep->irq_pci_addr = (pci_addr & ~pci_addr_mask); in cdns_pcie_ep_send_msi_irq()
377 ep->irq_pci_fn = fn; in cdns_pcie_ep_send_msi_irq()
379 writel(data, ep->irq_cpu_addr + (pci_addr & pci_addr_mask)); in cdns_pcie_ep_send_msi_irq()
384 static int cdns_pcie_ep_send_msix_irq(struct cdns_pcie_ep *ep, u8 fn, in cdns_pcie_ep_send_msix_irq() argument
389 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_send_msix_irq() local
397 /* Check whether the MSI-X feature has been enabled by the PCI host. */ in cdns_pcie_ep_send_msix_irq()
398 flags = cdns_pcie_ep_fn_readw(pcie, fn, cap + PCI_MSIX_FLAGS); in cdns_pcie_ep_send_msix_irq()
400 return -EINVAL; in cdns_pcie_ep_send_msix_irq()
403 tbl_offset = cdns_pcie_ep_fn_readl(pcie, fn, reg); in cdns_pcie_ep_send_msix_irq()
407 epf = &ep->epf[fn]; in cdns_pcie_ep_send_msix_irq()
408 msix_tbl = epf->epf_bar[bir]->addr + tbl_offset; in cdns_pcie_ep_send_msix_irq()
409 msg_addr = msix_tbl[(interrupt_num - 1)].msg_addr; in cdns_pcie_ep_send_msix_irq()
410 msg_data = msix_tbl[(interrupt_num - 1)].msg_data; in cdns_pcie_ep_send_msix_irq()
413 if (ep->irq_pci_addr != (msg_addr & ~pci_addr_mask) || in cdns_pcie_ep_send_msix_irq()
414 ep->irq_pci_fn != fn) { in cdns_pcie_ep_send_msix_irq()
416 cdns_pcie_set_outbound_region(pcie, 0, fn, 0, in cdns_pcie_ep_send_msix_irq()
418 ep->irq_phys_addr, in cdns_pcie_ep_send_msix_irq()
421 ep->irq_pci_addr = (msg_addr & ~pci_addr_mask); in cdns_pcie_ep_send_msix_irq()
422 ep->irq_pci_fn = fn; in cdns_pcie_ep_send_msix_irq()
424 writel(msg_data, ep->irq_cpu_addr + (msg_addr & pci_addr_mask)); in cdns_pcie_ep_send_msix_irq()
433 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); in cdns_pcie_ep_raise_irq() local
437 return cdns_pcie_ep_send_legacy_irq(ep, fn, 0); in cdns_pcie_ep_raise_irq()
440 return cdns_pcie_ep_send_msi_irq(ep, fn, interrupt_num); in cdns_pcie_ep_raise_irq()
443 return cdns_pcie_ep_send_msix_irq(ep, fn, interrupt_num); in cdns_pcie_ep_raise_irq()
449 return -EINVAL; in cdns_pcie_ep_raise_irq()
454 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); in cdns_pcie_ep_start() local
455 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_start() local
456 struct device *dev = pcie->dev; in cdns_pcie_ep_start()
466 list_for_each_entry(epf, &epc->pci_epf, list) in cdns_pcie_ep_start()
467 cfg |= BIT(epf->func_no); in cdns_pcie_ep_start()
468 cdns_pcie_writel(pcie, CDNS_PCIE_LM_EP_FUNC_CFG, cfg); in cdns_pcie_ep_start()
470 ret = cdns_pcie_start_link(pcie); in cdns_pcie_ep_start()
507 int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep) in cdns_pcie_ep_setup() argument
509 struct device *dev = ep->pcie.dev; in cdns_pcie_ep_setup()
511 struct device_node *np = dev->of_node; in cdns_pcie_ep_setup()
512 struct cdns_pcie *pcie = &ep->pcie; in cdns_pcie_ep_setup() local
517 pcie->is_rc = false; in cdns_pcie_ep_setup()
519 pcie->reg_base = devm_platform_ioremap_resource_byname(pdev, "reg"); in cdns_pcie_ep_setup()
520 if (IS_ERR(pcie->reg_base)) { in cdns_pcie_ep_setup()
522 return PTR_ERR(pcie->reg_base); in cdns_pcie_ep_setup()
528 return -EINVAL; in cdns_pcie_ep_setup()
530 pcie->mem_res = res; in cdns_pcie_ep_setup()
532 ret = of_property_read_u32(np, "cdns,max-outbound-regions", in cdns_pcie_ep_setup()
533 &ep->max_regions); in cdns_pcie_ep_setup()
535 dev_err(dev, "missing \"cdns,max-outbound-regions\"\n"); in cdns_pcie_ep_setup()
538 ep->ob_addr = devm_kcalloc(dev, in cdns_pcie_ep_setup()
539 ep->max_regions, sizeof(*ep->ob_addr), in cdns_pcie_ep_setup()
541 if (!ep->ob_addr) in cdns_pcie_ep_setup()
542 return -ENOMEM; in cdns_pcie_ep_setup()
545 cdns_pcie_writel(pcie, CDNS_PCIE_LM_EP_FUNC_CFG, BIT(0)); in cdns_pcie_ep_setup()
553 epc_set_drvdata(epc, ep); in cdns_pcie_ep_setup()
555 if (of_property_read_u8(np, "max-functions", &epc->max_functions) < 0) in cdns_pcie_ep_setup()
556 epc->max_functions = 1; in cdns_pcie_ep_setup()
558 ep->epf = devm_kcalloc(dev, epc->max_functions, sizeof(*ep->epf), in cdns_pcie_ep_setup()
560 if (!ep->epf) in cdns_pcie_ep_setup()
561 return -ENOMEM; in cdns_pcie_ep_setup()
563 ret = pci_epc_mem_init(epc, pcie->mem_res->start, in cdns_pcie_ep_setup()
564 resource_size(pcie->mem_res), PAGE_SIZE); in cdns_pcie_ep_setup()
570 ep->irq_cpu_addr = pci_epc_mem_alloc_addr(epc, &ep->irq_phys_addr, in cdns_pcie_ep_setup()
572 if (!ep->irq_cpu_addr) { in cdns_pcie_ep_setup()
574 ret = -ENOMEM; in cdns_pcie_ep_setup()
577 ep->irq_pci_addr = CDNS_PCIE_EP_IRQ_PCI_ADDR_NONE; in cdns_pcie_ep_setup()
579 set_bit(0, &ep->ob_region_map); in cdns_pcie_ep_setup()
581 if (ep->quirk_detect_quiet_flag) in cdns_pcie_ep_setup()
582 cdns_pcie_detect_quiet_min_delay_set(&ep->pcie); in cdns_pcie_ep_setup()
584 spin_lock_init(&ep->lock); in cdns_pcie_ep_setup()