Lines Matching +full:rk3399 +full:- +full:pcie +full:- +full:ep
1 // SPDX-License-Identifier: GPL-2.0+
3 * Rockchip AXI PCIe endpoint controller driver
7 * Author: Shawn Lin <shawn.lin@rock-chips.com>
8 * Simon Xue <xxm@rock-chips.com>
15 #include <linux/pci-epc.h>
17 #include <linux/pci-epf.h>
20 #include "pcie-rockchip.h"
23 * struct rockchip_pcie_ep - private data for PCIe endpoint controller driver
24 * @rockchip: Rockchip PCIe controller
33 * IRQ) TLP through the PCIe bus.
70 int num_pass_bits = fls64(size - 1); in rockchip_pcie_prog_ep_ob_atu()
76 addr0 = ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | in rockchip_pcie_prog_ep_ob_atu()
96 struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); in rockchip_pcie_ep_write_header() local
97 struct rockchip_pcie *rockchip = &ep->rockchip; in rockchip_pcie_ep_write_header()
102 hdr->vendorid | hdr->subsys_vendor_id << 16, in rockchip_pcie_ep_write_header()
107 reg = (reg & 0xFFFF) | (hdr->deviceid << 16); in rockchip_pcie_ep_write_header()
111 hdr->revid | in rockchip_pcie_ep_write_header()
112 hdr->progif_code << 8 | in rockchip_pcie_ep_write_header()
113 hdr->subclass_code << 16 | in rockchip_pcie_ep_write_header()
114 hdr->baseclass_code << 24, in rockchip_pcie_ep_write_header()
116 rockchip_pcie_write(rockchip, hdr->cache_line_size, in rockchip_pcie_ep_write_header()
119 rockchip_pcie_write(rockchip, hdr->subsys_id << 16, in rockchip_pcie_ep_write_header()
122 rockchip_pcie_write(rockchip, hdr->interrupt_pin << 8, in rockchip_pcie_ep_write_header()
132 struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); in rockchip_pcie_ep_set_bar() local
133 struct rockchip_pcie *rockchip = &ep->rockchip; in rockchip_pcie_ep_set_bar()
134 dma_addr_t bar_phys = epf_bar->phys_addr; in rockchip_pcie_ep_set_bar()
135 enum pci_barno bar = epf_bar->barno; in rockchip_pcie_ep_set_bar()
136 int flags = epf_bar->flags; in rockchip_pcie_ep_set_bar()
141 sz = max_t(size_t, epf_bar->size, MIN_EP_APERTURE); in rockchip_pcie_ep_set_bar()
147 sz = 1ULL << fls64(sz - 1); in rockchip_pcie_ep_set_bar()
148 aperture = ilog2(sz) - 7; /* 128B -> 0, 256B -> 1, 512B -> 2, ... */ in rockchip_pcie_ep_set_bar()
157 return -EINVAL; in rockchip_pcie_ep_set_bar()
176 b = bar - BAR_4; in rockchip_pcie_ep_set_bar()
200 struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); in rockchip_pcie_ep_clear_bar() local
201 struct rockchip_pcie *rockchip = &ep->rockchip; in rockchip_pcie_ep_clear_bar()
203 enum pci_barno bar = epf_bar->barno; in rockchip_pcie_ep_clear_bar()
210 b = bar - BAR_4; in rockchip_pcie_ep_clear_bar()
235 struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); in rockchip_pcie_ep_map_addr() local
236 struct rockchip_pcie *pcie = &ep->rockchip; in rockchip_pcie_ep_map_addr() local
239 rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, addr, pci_addr, size); in rockchip_pcie_ep_map_addr()
241 set_bit(r, &ep->ob_region_map); in rockchip_pcie_ep_map_addr()
242 ep->ob_addr[r] = addr; in rockchip_pcie_ep_map_addr()
250 struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); in rockchip_pcie_ep_unmap_addr() local
251 struct rockchip_pcie *rockchip = &ep->rockchip; in rockchip_pcie_ep_unmap_addr()
254 for (r = 0; r < ep->max_regions; r++) in rockchip_pcie_ep_unmap_addr()
255 if (ep->ob_addr[r] == addr) in rockchip_pcie_ep_unmap_addr()
258 if (r == ep->max_regions) in rockchip_pcie_ep_unmap_addr()
263 ep->ob_addr[r] = 0; in rockchip_pcie_ep_unmap_addr()
264 clear_bit(r, &ep->ob_region_map); in rockchip_pcie_ep_unmap_addr()
270 struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); in rockchip_pcie_ep_set_msi() local
271 struct rockchip_pcie *rockchip = &ep->rockchip; in rockchip_pcie_ep_set_msi()
290 struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); in rockchip_pcie_ep_get_msi() local
291 struct rockchip_pcie *rockchip = &ep->rockchip; in rockchip_pcie_ep_get_msi()
298 return -EINVAL; in rockchip_pcie_ep_get_msi()
304 static void rockchip_pcie_ep_assert_intx(struct rockchip_pcie_ep *ep, u8 fn, in rockchip_pcie_ep_assert_intx() argument
307 struct rockchip_pcie *rockchip = &ep->rockchip; in rockchip_pcie_ep_assert_intx()
312 ep->irq_pending |= BIT(intx); in rockchip_pcie_ep_assert_intx()
318 ep->irq_pending &= ~BIT(intx); in rockchip_pcie_ep_assert_intx()
326 static int rockchip_pcie_ep_send_intx_irq(struct rockchip_pcie_ep *ep, u8 fn, in rockchip_pcie_ep_send_intx_irq() argument
331 cmd = rockchip_pcie_read(&ep->rockchip, in rockchip_pcie_ep_send_intx_irq()
336 return -EINVAL; in rockchip_pcie_ep_send_intx_irq()
343 rockchip_pcie_ep_assert_intx(ep, fn, intx, true); in rockchip_pcie_ep_send_intx_irq()
345 rockchip_pcie_ep_assert_intx(ep, fn, intx, false); in rockchip_pcie_ep_send_intx_irq()
349 static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn, in rockchip_pcie_ep_send_msi_irq() argument
352 struct rockchip_pcie *rockchip = &ep->rockchip; in rockchip_pcie_ep_send_msi_irq()
359 flags = rockchip_pcie_read(&ep->rockchip, in rockchip_pcie_ep_send_msi_irq()
363 return -EINVAL; in rockchip_pcie_ep_send_msi_irq()
370 return -EINVAL; in rockchip_pcie_ep_send_msi_irq()
373 data_mask = msi_count - 1; in rockchip_pcie_ep_send_msi_irq()
378 data = (data & ~data_mask) | ((interrupt_num - 1) & data_mask); in rockchip_pcie_ep_send_msi_irq()
392 if (unlikely(ep->irq_pci_addr != (pci_addr & PCIE_ADDR_MASK) || in rockchip_pcie_ep_send_msi_irq()
393 ep->irq_pci_fn != fn)) { in rockchip_pcie_ep_send_msi_irq()
394 r = rockchip_ob_region(ep->irq_phys_addr); in rockchip_pcie_ep_send_msi_irq()
396 ep->irq_phys_addr, in rockchip_pcie_ep_send_msi_irq()
399 ep->irq_pci_addr = (pci_addr & PCIE_ADDR_MASK); in rockchip_pcie_ep_send_msi_irq()
400 ep->irq_pci_fn = fn; in rockchip_pcie_ep_send_msi_irq()
403 writew(data, ep->irq_cpu_addr + (pci_addr & ~PCIE_ADDR_MASK)); in rockchip_pcie_ep_send_msi_irq()
410 struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); in rockchip_pcie_ep_raise_irq() local
414 return rockchip_pcie_ep_send_intx_irq(ep, fn, 0); in rockchip_pcie_ep_raise_irq()
416 return rockchip_pcie_ep_send_msi_irq(ep, fn, interrupt_num); in rockchip_pcie_ep_raise_irq()
418 return -EINVAL; in rockchip_pcie_ep_raise_irq()
424 struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); in rockchip_pcie_ep_start() local
425 struct rockchip_pcie *rockchip = &ep->rockchip; in rockchip_pcie_ep_start()
430 list_for_each_entry(epf, &epc->pci_epf, list) in rockchip_pcie_ep_start()
431 cfg |= BIT(epf->func_no); in rockchip_pcie_ep_start()
465 struct rockchip_pcie_ep *ep) in rockchip_pcie_parse_ep_dt() argument
467 struct device *dev = rockchip->dev; in rockchip_pcie_parse_ep_dt()
478 err = of_property_read_u32(dev->of_node, in rockchip_pcie_parse_ep_dt()
479 "rockchip,max-outbound-regions", in rockchip_pcie_parse_ep_dt()
480 &ep->max_regions); in rockchip_pcie_parse_ep_dt()
481 if (err < 0 || ep->max_regions > MAX_REGION_LIMIT) in rockchip_pcie_parse_ep_dt()
482 ep->max_regions = MAX_REGION_LIMIT; in rockchip_pcie_parse_ep_dt()
484 ep->ob_region_map = 0; in rockchip_pcie_parse_ep_dt()
486 err = of_property_read_u8(dev->of_node, "max-functions", in rockchip_pcie_parse_ep_dt()
487 &ep->epc->max_functions); in rockchip_pcie_parse_ep_dt()
489 ep->epc->max_functions = 1; in rockchip_pcie_parse_ep_dt()
495 { .compatible = "rockchip,rk3399-pcie-ep"},
501 struct device *dev = &pdev->dev; in rockchip_pcie_ep_probe()
502 struct rockchip_pcie_ep *ep; in rockchip_pcie_ep_probe() local
510 ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); in rockchip_pcie_ep_probe()
511 if (!ep) in rockchip_pcie_ep_probe()
512 return -ENOMEM; in rockchip_pcie_ep_probe()
514 rockchip = &ep->rockchip; in rockchip_pcie_ep_probe()
515 rockchip->is_rc = false; in rockchip_pcie_ep_probe()
516 rockchip->dev = dev; in rockchip_pcie_ep_probe()
524 ep->epc = epc; in rockchip_pcie_ep_probe()
525 epc_set_drvdata(epc, ep); in rockchip_pcie_ep_probe()
527 err = rockchip_pcie_parse_ep_dt(rockchip, ep); in rockchip_pcie_ep_probe()
543 max_regions = ep->max_regions; in rockchip_pcie_ep_probe()
544 ep->ob_addr = devm_kcalloc(dev, max_regions, sizeof(*ep->ob_addr), in rockchip_pcie_ep_probe()
547 if (!ep->ob_addr) { in rockchip_pcie_ep_probe()
548 err = -ENOMEM; in rockchip_pcie_ep_probe()
555 windows = devm_kcalloc(dev, ep->max_regions, in rockchip_pcie_ep_probe()
558 err = -ENOMEM; in rockchip_pcie_ep_probe()
561 for (i = 0; i < ep->max_regions; i++) { in rockchip_pcie_ep_probe()
562 windows[i].phys_base = rockchip->mem_res->start + (SZ_1M * i); in rockchip_pcie_ep_probe()
566 err = pci_epc_multi_mem_init(epc, windows, ep->max_regions); in rockchip_pcie_ep_probe()
574 ep->irq_cpu_addr = pci_epc_mem_alloc_addr(epc, &ep->irq_phys_addr, in rockchip_pcie_ep_probe()
576 if (!ep->irq_cpu_addr) { in rockchip_pcie_ep_probe()
578 err = -ENOMEM; in rockchip_pcie_ep_probe()
582 ep->irq_pci_addr = ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR; in rockchip_pcie_ep_probe()
585 * MSI-X is not supported but the controller still advertises the MSI-X in rockchip_pcie_ep_probe()
587 * allocating MSI-X vectors which cannot be used. Avoid this by skipping in rockchip_pcie_ep_probe()
588 * the MSI-X capability entry in the PCIe capabilities linked-list: get in rockchip_pcie_ep_probe()
589 * the next pointer from the MSI-X entry and set that in the MSI in rockchip_pcie_ep_probe()
590 * capability entry (which is the previous entry). This way the MSI-X in rockchip_pcie_ep_probe()
591 * entry is skipped (left out of the linked-list) and not advertised. in rockchip_pcie_ep_probe()
624 .name = "rockchip-pcie-ep",