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

1 // SPDX-License-Identifier: GPL-2.0
3 * PCIe endpoint driver for Renesas R-Car SoCs
6 * Author: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
13 #include <linux/pci-epc.h>
17 #include "pcie-rcar.h"
21 /* Structure representing the PCIe interface */
23 struct rcar_pcie pcie; member
33 static void rcar_pcie_ep_hw_init(struct rcar_pcie *pcie) in rcar_pcie_ep_hw_init() argument
37 rcar_pci_write_reg(pcie, 0, PCIETCTLR); in rcar_pcie_ep_hw_init()
40 rcar_pci_write_reg(pcie, 0, PCIEMSR); in rcar_pcie_ep_hw_init()
43 rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP); in rcar_pcie_ep_hw_init()
44 rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS), in rcar_pcie_ep_hw_init()
46 rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f, in rcar_pcie_ep_hw_init()
50 rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0); in rcar_pcie_ep_hw_init()
52 val = rcar_pci_read_reg(pcie, EXPCAP(1)); in rcar_pcie_ep_hw_init()
55 rcar_pci_write_reg(pcie, val, EXPCAP(1)); in rcar_pcie_ep_hw_init()
57 val = rcar_pci_read_reg(pcie, EXPCAP(2)); in rcar_pcie_ep_hw_init()
62 rcar_pci_write_reg(pcie, val, EXPCAP(2)); in rcar_pcie_ep_hw_init()
65 rcar_rmw32(pcie, EXPCAP(12), PCI_EXP_LNKSTA_CLS, in rcar_pcie_ep_hw_init()
69 rcar_rmw32(pcie, TLCTLR + 1, 0x3f, 50); in rcar_pcie_ep_hw_init()
72 rcar_rmw32(pcie, RVCCAP(0), 0xfff00000, 0); in rcar_pcie_ep_hw_init()
78 static int rcar_pcie_ep_get_window(struct rcar_pcie_endpoint *ep, in rcar_pcie_ep_get_window() argument
83 for (i = 0; i < ep->num_ob_windows; i++) in rcar_pcie_ep_get_window()
84 if (ep->ob_window[i].phys_base == addr) in rcar_pcie_ep_get_window()
87 return -EINVAL; in rcar_pcie_ep_get_window()
90 static int rcar_pcie_parse_outbound_ranges(struct rcar_pcie_endpoint *ep, in rcar_pcie_parse_outbound_ranges() argument
93 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_parse_outbound_ranges() local
98 ep->num_ob_windows = 0; in rcar_pcie_parse_outbound_ranges()
105 dev_err(pcie->dev, "missing outbound window %u\n", i); in rcar_pcie_parse_outbound_ranges()
106 return -EINVAL; in rcar_pcie_parse_outbound_ranges()
108 if (!devm_request_mem_region(&pdev->dev, res->start, in rcar_pcie_parse_outbound_ranges()
111 dev_err(pcie->dev, "Cannot request memory region %s.\n", in rcar_pcie_parse_outbound_ranges()
113 return -EIO; in rcar_pcie_parse_outbound_ranges()
116 ep->ob_window[i].phys_base = res->start; in rcar_pcie_parse_outbound_ranges()
117 ep->ob_window[i].size = resource_size(res); in rcar_pcie_parse_outbound_ranges()
121 ep->ob_window[i].page_size = resource_size(res); in rcar_pcie_parse_outbound_ranges()
123 ep->num_ob_windows = i; in rcar_pcie_parse_outbound_ranges()
128 static int rcar_pcie_ep_get_pdata(struct rcar_pcie_endpoint *ep, in rcar_pcie_ep_get_pdata() argument
131 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_get_pdata() local
133 struct device *dev = pcie->dev; in rcar_pcie_ep_get_pdata()
137 err = of_address_to_resource(dev->of_node, 0, &res); in rcar_pcie_ep_get_pdata()
140 pcie->base = devm_ioremap_resource(dev, &res); in rcar_pcie_ep_get_pdata()
141 if (IS_ERR(pcie->base)) in rcar_pcie_ep_get_pdata()
142 return PTR_ERR(pcie->base); in rcar_pcie_ep_get_pdata()
144 ep->ob_window = devm_kcalloc(dev, RCAR_PCI_MAX_RESOURCES, in rcar_pcie_ep_get_pdata()
146 if (!ep->ob_window) in rcar_pcie_ep_get_pdata()
147 return -ENOMEM; in rcar_pcie_ep_get_pdata()
149 rcar_pcie_parse_outbound_ranges(ep, pdev); in rcar_pcie_ep_get_pdata()
151 err = of_property_read_u8(dev->of_node, "max-functions", in rcar_pcie_ep_get_pdata()
152 &ep->max_functions); in rcar_pcie_ep_get_pdata()
153 if (err < 0 || ep->max_functions > RCAR_EPC_MAX_FUNCTIONS) in rcar_pcie_ep_get_pdata()
154 ep->max_functions = RCAR_EPC_MAX_FUNCTIONS; in rcar_pcie_ep_get_pdata()
162 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_write_header() local
163 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_write_header() local
167 val = hdr->vendorid; in rcar_pcie_ep_write_header()
169 val = rcar_pci_read_reg(pcie, IDSETR0); in rcar_pcie_ep_write_header()
170 val |= hdr->deviceid << 16; in rcar_pcie_ep_write_header()
171 rcar_pci_write_reg(pcie, val, IDSETR0); in rcar_pcie_ep_write_header()
173 val = hdr->revid; in rcar_pcie_ep_write_header()
174 val |= hdr->progif_code << 8; in rcar_pcie_ep_write_header()
175 val |= hdr->subclass_code << 16; in rcar_pcie_ep_write_header()
176 val |= hdr->baseclass_code << 24; in rcar_pcie_ep_write_header()
177 rcar_pci_write_reg(pcie, val, IDSETR1); in rcar_pcie_ep_write_header()
180 val = hdr->subsys_vendor_id; in rcar_pcie_ep_write_header()
182 val = rcar_pci_read_reg(pcie, SUBIDSETR); in rcar_pcie_ep_write_header()
183 val |= hdr->subsys_id << 16; in rcar_pcie_ep_write_header()
184 rcar_pci_write_reg(pcie, val, SUBIDSETR); in rcar_pcie_ep_write_header()
186 if (hdr->interrupt_pin > PCI_INTERRUPT_INTA) in rcar_pcie_ep_write_header()
187 return -EINVAL; in rcar_pcie_ep_write_header()
188 val = rcar_pci_read_reg(pcie, PCICONF(15)); in rcar_pcie_ep_write_header()
189 val |= (hdr->interrupt_pin << 8); in rcar_pcie_ep_write_header()
190 rcar_pci_write_reg(pcie, val, PCICONF(15)); in rcar_pcie_ep_write_header()
198 int flags = epf_bar->flags | LAR_ENABLE | LAM_64BIT; in rcar_pcie_ep_set_bar()
199 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_set_bar() local
200 u64 size = 1ULL << fls64(epf_bar->size - 1); in rcar_pcie_ep_set_bar()
201 dma_addr_t cpu_addr = epf_bar->phys_addr; in rcar_pcie_ep_set_bar()
202 enum pci_barno bar = epf_bar->barno; in rcar_pcie_ep_set_bar()
203 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_set_bar() local
208 idx = find_first_zero_bit(ep->ib_window_map, ep->num_ib_windows); in rcar_pcie_ep_set_bar()
209 if (idx >= ep->num_ib_windows) { in rcar_pcie_ep_set_bar()
210 dev_err(pcie->dev, "no free inbound window\n"); in rcar_pcie_ep_set_bar()
211 return -EINVAL; in rcar_pcie_ep_set_bar()
217 ep->bar_to_atu[bar] = idx; in rcar_pcie_ep_set_bar()
218 /* use 64-bit BARs */ in rcar_pcie_ep_set_bar()
219 set_bit(idx, ep->ib_window_map); in rcar_pcie_ep_set_bar()
220 set_bit(idx + 1, ep->ib_window_map); in rcar_pcie_ep_set_bar()
231 mask = roundup_pow_of_two(size) - 1; in rcar_pcie_ep_set_bar()
234 rcar_pcie_set_inbound(pcie, cpu_addr, in rcar_pcie_ep_set_bar()
237 err = rcar_pcie_wait_for_phyrdy(pcie); in rcar_pcie_ep_set_bar()
239 dev_err(pcie->dev, "phy not ready\n"); in rcar_pcie_ep_set_bar()
240 return -EINVAL; in rcar_pcie_ep_set_bar()
249 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_clear_bar() local
250 enum pci_barno bar = epf_bar->barno; in rcar_pcie_ep_clear_bar()
251 u32 atu_index = ep->bar_to_atu[bar]; in rcar_pcie_ep_clear_bar()
253 rcar_pcie_set_inbound(&ep->pcie, 0x0, 0x0, 0x0, bar, false); in rcar_pcie_ep_clear_bar()
255 clear_bit(atu_index, ep->ib_window_map); in rcar_pcie_ep_clear_bar()
256 clear_bit(atu_index + 1, ep->ib_window_map); in rcar_pcie_ep_clear_bar()
262 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_set_msi() local
263 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_set_msi() local
266 flags = rcar_pci_read_reg(pcie, MSICAP(fn)); in rcar_pcie_ep_set_msi()
268 rcar_pci_write_reg(pcie, flags, MSICAP(fn)); in rcar_pcie_ep_set_msi()
275 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_get_msi() local
276 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_get_msi() local
279 flags = rcar_pci_read_reg(pcie, MSICAP(fn)); in rcar_pcie_ep_get_msi()
281 return -EINVAL; in rcar_pcie_ep_get_msi()
289 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_map_addr() local
290 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_map_addr() local
297 err = rcar_pcie_wait_for_dl(pcie); in rcar_pcie_ep_map_addr()
299 dev_err(pcie->dev, "link not up\n"); in rcar_pcie_ep_map_addr()
303 window = rcar_pcie_ep_get_window(ep, addr); in rcar_pcie_ep_map_addr()
305 dev_err(pcie->dev, "failed to get corresponding window\n"); in rcar_pcie_ep_map_addr()
306 return -EINVAL; in rcar_pcie_ep_map_addr()
312 res.end = pci_addr + size - 1; in rcar_pcie_ep_map_addr()
316 rcar_pcie_set_outbound(pcie, window, &win); in rcar_pcie_ep_map_addr()
318 ep->ob_mapped_addr[window] = addr; in rcar_pcie_ep_map_addr()
326 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_unmap_addr() local
331 for (idx = 0; idx < ep->num_ob_windows; idx++) in rcar_pcie_ep_unmap_addr()
332 if (ep->ob_mapped_addr[idx] == addr) in rcar_pcie_ep_unmap_addr()
335 if (idx >= ep->num_ob_windows) in rcar_pcie_ep_unmap_addr()
341 rcar_pcie_set_outbound(&ep->pcie, idx, &win); in rcar_pcie_ep_unmap_addr()
343 ep->ob_mapped_addr[idx] = 0; in rcar_pcie_ep_unmap_addr()
346 static int rcar_pcie_ep_assert_intx(struct rcar_pcie_endpoint *ep, in rcar_pcie_ep_assert_intx() argument
349 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_assert_intx() local
352 val = rcar_pci_read_reg(pcie, PCIEMSITXR); in rcar_pcie_ep_assert_intx()
354 dev_err(pcie->dev, "MSI is enabled, cannot assert INTx\n"); in rcar_pcie_ep_assert_intx()
355 return -EINVAL; in rcar_pcie_ep_assert_intx()
358 val = rcar_pci_read_reg(pcie, PCICONF(1)); in rcar_pcie_ep_assert_intx()
360 dev_err(pcie->dev, "INTx message transmission is disabled\n"); in rcar_pcie_ep_assert_intx()
361 return -EINVAL; in rcar_pcie_ep_assert_intx()
364 val = rcar_pci_read_reg(pcie, PCIEINTXR); in rcar_pcie_ep_assert_intx()
366 dev_err(pcie->dev, "INTx is already asserted\n"); in rcar_pcie_ep_assert_intx()
367 return -EINVAL; in rcar_pcie_ep_assert_intx()
371 rcar_pci_write_reg(pcie, val, PCIEINTXR); in rcar_pcie_ep_assert_intx()
373 val = rcar_pci_read_reg(pcie, PCIEINTXR); in rcar_pcie_ep_assert_intx()
375 rcar_pci_write_reg(pcie, val, PCIEINTXR); in rcar_pcie_ep_assert_intx()
380 static int rcar_pcie_ep_assert_msi(struct rcar_pcie *pcie, in rcar_pcie_ep_assert_msi() argument
387 val = rcar_pci_read_reg(pcie, MSICAP(fn)); in rcar_pcie_ep_assert_msi()
389 return -EINVAL; in rcar_pcie_ep_assert_msi()
396 return -EINVAL; in rcar_pcie_ep_assert_msi()
398 val = rcar_pci_read_reg(pcie, PCIEMSITXR); in rcar_pcie_ep_assert_msi()
399 rcar_pci_write_reg(pcie, val | (interrupt_num - 1), PCIEMSITXR); in rcar_pcie_ep_assert_msi()
408 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_raise_irq() local
412 return rcar_pcie_ep_assert_intx(ep, fn, 0); in rcar_pcie_ep_raise_irq()
415 return rcar_pcie_ep_assert_msi(&ep->pcie, fn, interrupt_num); in rcar_pcie_ep_raise_irq()
418 return -EINVAL; in rcar_pcie_ep_raise_irq()
424 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_start() local
426 rcar_pci_write_reg(&ep->pcie, MACCTLR_INIT_VAL, MACCTLR); in rcar_pcie_ep_start()
427 rcar_pci_write_reg(&ep->pcie, CFINIT, PCIETCTLR); in rcar_pcie_ep_start()
434 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_stop() local
436 rcar_pci_write_reg(&ep->pcie, 0, PCIETCTLR); in rcar_pcie_ep_stop()
443 /* use 64-bit BARs so mark BAR[1,3,5] as reserved */
472 { .compatible = "renesas,r8a774c0-pcie-ep", },
473 { .compatible = "renesas,rcar-gen3-pcie-ep" },
479 struct device *dev = &pdev->dev; in rcar_pcie_ep_probe()
480 struct rcar_pcie_endpoint *ep; in rcar_pcie_ep_probe() local
481 struct rcar_pcie *pcie; in rcar_pcie_ep_probe() local
485 ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); in rcar_pcie_ep_probe()
486 if (!ep) in rcar_pcie_ep_probe()
487 return -ENOMEM; in rcar_pcie_ep_probe()
489 pcie = &ep->pcie; in rcar_pcie_ep_probe()
490 pcie->dev = dev; in rcar_pcie_ep_probe()
499 err = rcar_pcie_ep_get_pdata(ep, pdev); in rcar_pcie_ep_probe()
505 ep->num_ib_windows = MAX_NR_INBOUND_MAPS; in rcar_pcie_ep_probe()
506 ep->ib_window_map = in rcar_pcie_ep_probe()
507 devm_kcalloc(dev, BITS_TO_LONGS(ep->num_ib_windows), in rcar_pcie_ep_probe()
509 if (!ep->ib_window_map) { in rcar_pcie_ep_probe()
510 err = -ENOMEM; in rcar_pcie_ep_probe()
515 ep->ob_mapped_addr = devm_kcalloc(dev, ep->num_ob_windows, in rcar_pcie_ep_probe()
516 sizeof(*ep->ob_mapped_addr), in rcar_pcie_ep_probe()
518 if (!ep->ob_mapped_addr) { in rcar_pcie_ep_probe()
519 err = -ENOMEM; in rcar_pcie_ep_probe()
531 epc->max_functions = ep->max_functions; in rcar_pcie_ep_probe()
532 epc_set_drvdata(epc, ep); in rcar_pcie_ep_probe()
534 rcar_pcie_ep_hw_init(pcie); in rcar_pcie_ep_probe()
536 err = pci_epc_multi_mem_init(epc, ep->ob_window, ep->num_ob_windows); in rcar_pcie_ep_probe()
555 .name = "rcar-pcie-ep",