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>
16 #include <linux/pci-epc.h>
20 #include "pcie-rcar.h"
24 /* Structure representing the PCIe interface */
26 struct rcar_pcie pcie; member
36 static void rcar_pcie_ep_hw_init(struct rcar_pcie *pcie) in rcar_pcie_ep_hw_init() argument
40 rcar_pci_write_reg(pcie, 0, PCIETCTLR); in rcar_pcie_ep_hw_init()
43 rcar_pci_write_reg(pcie, 0, PCIEMSR); in rcar_pcie_ep_hw_init()
46 rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP); in rcar_pcie_ep_hw_init()
47 rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS), in rcar_pcie_ep_hw_init()
49 rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f, in rcar_pcie_ep_hw_init()
53 rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0); in rcar_pcie_ep_hw_init()
55 val = rcar_pci_read_reg(pcie, EXPCAP(1)); in rcar_pcie_ep_hw_init()
58 rcar_pci_write_reg(pcie, val, EXPCAP(1)); in rcar_pcie_ep_hw_init()
60 val = rcar_pci_read_reg(pcie, EXPCAP(2)); in rcar_pcie_ep_hw_init()
65 rcar_pci_write_reg(pcie, val, EXPCAP(2)); in rcar_pcie_ep_hw_init()
68 rcar_rmw32(pcie, EXPCAP(12), PCI_EXP_LNKSTA_CLS, in rcar_pcie_ep_hw_init()
72 rcar_rmw32(pcie, TLCTLR + 1, 0x3f, 50); in rcar_pcie_ep_hw_init()
75 rcar_rmw32(pcie, RVCCAP(0), 0xfff00000, 0); in rcar_pcie_ep_hw_init()
81 static int rcar_pcie_ep_get_window(struct rcar_pcie_endpoint *ep, in rcar_pcie_ep_get_window() argument
86 for (i = 0; i < ep->num_ob_windows; i++) in rcar_pcie_ep_get_window()
87 if (ep->ob_window[i].phys_base == addr) in rcar_pcie_ep_get_window()
90 return -EINVAL; in rcar_pcie_ep_get_window()
93 static int rcar_pcie_parse_outbound_ranges(struct rcar_pcie_endpoint *ep, in rcar_pcie_parse_outbound_ranges() argument
96 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_parse_outbound_ranges() local
101 ep->num_ob_windows = 0; in rcar_pcie_parse_outbound_ranges()
108 dev_err(pcie->dev, "missing outbound window %u\n", i); in rcar_pcie_parse_outbound_ranges()
109 return -EINVAL; in rcar_pcie_parse_outbound_ranges()
111 if (!devm_request_mem_region(&pdev->dev, res->start, in rcar_pcie_parse_outbound_ranges()
114 dev_err(pcie->dev, "Cannot request memory region %s.\n", in rcar_pcie_parse_outbound_ranges()
116 return -EIO; in rcar_pcie_parse_outbound_ranges()
119 ep->ob_window[i].phys_base = res->start; in rcar_pcie_parse_outbound_ranges()
120 ep->ob_window[i].size = resource_size(res); in rcar_pcie_parse_outbound_ranges()
124 ep->ob_window[i].page_size = resource_size(res); in rcar_pcie_parse_outbound_ranges()
126 ep->num_ob_windows = i; in rcar_pcie_parse_outbound_ranges()
131 static int rcar_pcie_ep_get_pdata(struct rcar_pcie_endpoint *ep, in rcar_pcie_ep_get_pdata() argument
134 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_get_pdata() local
136 struct device *dev = pcie->dev; in rcar_pcie_ep_get_pdata()
140 err = of_address_to_resource(dev->of_node, 0, &res); in rcar_pcie_ep_get_pdata()
143 pcie->base = devm_ioremap_resource(dev, &res); in rcar_pcie_ep_get_pdata()
144 if (IS_ERR(pcie->base)) in rcar_pcie_ep_get_pdata()
145 return PTR_ERR(pcie->base); in rcar_pcie_ep_get_pdata()
147 ep->ob_window = devm_kcalloc(dev, RCAR_PCI_MAX_RESOURCES, in rcar_pcie_ep_get_pdata()
149 if (!ep->ob_window) in rcar_pcie_ep_get_pdata()
150 return -ENOMEM; in rcar_pcie_ep_get_pdata()
152 rcar_pcie_parse_outbound_ranges(ep, pdev); in rcar_pcie_ep_get_pdata()
154 err = of_property_read_u8(dev->of_node, "max-functions", in rcar_pcie_ep_get_pdata()
155 &ep->max_functions); in rcar_pcie_ep_get_pdata()
156 if (err < 0 || ep->max_functions > RCAR_EPC_MAX_FUNCTIONS) in rcar_pcie_ep_get_pdata()
157 ep->max_functions = RCAR_EPC_MAX_FUNCTIONS; in rcar_pcie_ep_get_pdata()
165 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_write_header() local
166 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_write_header() local
170 val = hdr->vendorid; in rcar_pcie_ep_write_header()
172 val = rcar_pci_read_reg(pcie, IDSETR0); in rcar_pcie_ep_write_header()
173 val |= hdr->deviceid << 16; in rcar_pcie_ep_write_header()
174 rcar_pci_write_reg(pcie, val, IDSETR0); in rcar_pcie_ep_write_header()
176 val = hdr->revid; in rcar_pcie_ep_write_header()
177 val |= hdr->progif_code << 8; in rcar_pcie_ep_write_header()
178 val |= hdr->subclass_code << 16; in rcar_pcie_ep_write_header()
179 val |= hdr->baseclass_code << 24; in rcar_pcie_ep_write_header()
180 rcar_pci_write_reg(pcie, val, IDSETR1); in rcar_pcie_ep_write_header()
183 val = hdr->subsys_vendor_id; in rcar_pcie_ep_write_header()
185 val = rcar_pci_read_reg(pcie, SUBIDSETR); in rcar_pcie_ep_write_header()
186 val |= hdr->subsys_id << 16; in rcar_pcie_ep_write_header()
187 rcar_pci_write_reg(pcie, val, SUBIDSETR); in rcar_pcie_ep_write_header()
189 if (hdr->interrupt_pin > PCI_INTERRUPT_INTA) in rcar_pcie_ep_write_header()
190 return -EINVAL; in rcar_pcie_ep_write_header()
191 val = rcar_pci_read_reg(pcie, PCICONF(15)); in rcar_pcie_ep_write_header()
192 val |= (hdr->interrupt_pin << 8); in rcar_pcie_ep_write_header()
193 rcar_pci_write_reg(pcie, val, PCICONF(15)); in rcar_pcie_ep_write_header()
201 int flags = epf_bar->flags | LAR_ENABLE | LAM_64BIT; in rcar_pcie_ep_set_bar()
202 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_set_bar() local
203 u64 size = 1ULL << fls64(epf_bar->size - 1); in rcar_pcie_ep_set_bar()
204 dma_addr_t cpu_addr = epf_bar->phys_addr; in rcar_pcie_ep_set_bar()
205 enum pci_barno bar = epf_bar->barno; in rcar_pcie_ep_set_bar()
206 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_set_bar() local
211 idx = find_first_zero_bit(ep->ib_window_map, ep->num_ib_windows); in rcar_pcie_ep_set_bar()
212 if (idx >= ep->num_ib_windows) { in rcar_pcie_ep_set_bar()
213 dev_err(pcie->dev, "no free inbound window\n"); in rcar_pcie_ep_set_bar()
214 return -EINVAL; in rcar_pcie_ep_set_bar()
220 ep->bar_to_atu[bar] = idx; in rcar_pcie_ep_set_bar()
221 /* use 64-bit BARs */ in rcar_pcie_ep_set_bar()
222 set_bit(idx, ep->ib_window_map); in rcar_pcie_ep_set_bar()
223 set_bit(idx + 1, ep->ib_window_map); in rcar_pcie_ep_set_bar()
234 mask = roundup_pow_of_two(size) - 1; in rcar_pcie_ep_set_bar()
237 rcar_pcie_set_inbound(pcie, cpu_addr, in rcar_pcie_ep_set_bar()
240 err = rcar_pcie_wait_for_phyrdy(pcie); in rcar_pcie_ep_set_bar()
242 dev_err(pcie->dev, "phy not ready\n"); in rcar_pcie_ep_set_bar()
243 return -EINVAL; in rcar_pcie_ep_set_bar()
252 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_clear_bar() local
253 enum pci_barno bar = epf_bar->barno; in rcar_pcie_ep_clear_bar()
254 u32 atu_index = ep->bar_to_atu[bar]; in rcar_pcie_ep_clear_bar()
256 rcar_pcie_set_inbound(&ep->pcie, 0x0, 0x0, 0x0, bar, false); in rcar_pcie_ep_clear_bar()
258 clear_bit(atu_index, ep->ib_window_map); in rcar_pcie_ep_clear_bar()
259 clear_bit(atu_index + 1, ep->ib_window_map); in rcar_pcie_ep_clear_bar()
265 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_set_msi() local
266 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_set_msi() local
269 flags = rcar_pci_read_reg(pcie, MSICAP(fn)); in rcar_pcie_ep_set_msi()
271 rcar_pci_write_reg(pcie, flags, MSICAP(fn)); in rcar_pcie_ep_set_msi()
278 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_get_msi() local
279 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_get_msi() local
282 flags = rcar_pci_read_reg(pcie, MSICAP(fn)); in rcar_pcie_ep_get_msi()
284 return -EINVAL; in rcar_pcie_ep_get_msi()
292 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_map_addr() local
293 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_map_addr() local
300 err = rcar_pcie_wait_for_dl(pcie); in rcar_pcie_ep_map_addr()
302 dev_err(pcie->dev, "link not up\n"); in rcar_pcie_ep_map_addr()
306 window = rcar_pcie_ep_get_window(ep, addr); in rcar_pcie_ep_map_addr()
308 dev_err(pcie->dev, "failed to get corresponding window\n"); in rcar_pcie_ep_map_addr()
309 return -EINVAL; in rcar_pcie_ep_map_addr()
315 res.end = pci_addr + size - 1; in rcar_pcie_ep_map_addr()
319 rcar_pcie_set_outbound(pcie, window, &win); in rcar_pcie_ep_map_addr()
321 ep->ob_mapped_addr[window] = addr; in rcar_pcie_ep_map_addr()
329 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_unmap_addr() local
334 for (idx = 0; idx < ep->num_ob_windows; idx++) in rcar_pcie_ep_unmap_addr()
335 if (ep->ob_mapped_addr[idx] == addr) in rcar_pcie_ep_unmap_addr()
338 if (idx >= ep->num_ob_windows) in rcar_pcie_ep_unmap_addr()
344 rcar_pcie_set_outbound(&ep->pcie, idx, &win); in rcar_pcie_ep_unmap_addr()
346 ep->ob_mapped_addr[idx] = 0; in rcar_pcie_ep_unmap_addr()
349 static int rcar_pcie_ep_assert_intx(struct rcar_pcie_endpoint *ep, in rcar_pcie_ep_assert_intx() argument
352 struct rcar_pcie *pcie = &ep->pcie; in rcar_pcie_ep_assert_intx() local
355 val = rcar_pci_read_reg(pcie, PCIEMSITXR); in rcar_pcie_ep_assert_intx()
357 dev_err(pcie->dev, "MSI is enabled, cannot assert INTx\n"); in rcar_pcie_ep_assert_intx()
358 return -EINVAL; in rcar_pcie_ep_assert_intx()
361 val = rcar_pci_read_reg(pcie, PCICONF(1)); in rcar_pcie_ep_assert_intx()
363 dev_err(pcie->dev, "INTx message transmission is disabled\n"); in rcar_pcie_ep_assert_intx()
364 return -EINVAL; in rcar_pcie_ep_assert_intx()
367 val = rcar_pci_read_reg(pcie, PCIEINTXR); in rcar_pcie_ep_assert_intx()
369 dev_err(pcie->dev, "INTx is already asserted\n"); in rcar_pcie_ep_assert_intx()
370 return -EINVAL; in rcar_pcie_ep_assert_intx()
374 rcar_pci_write_reg(pcie, val, PCIEINTXR); in rcar_pcie_ep_assert_intx()
376 val = rcar_pci_read_reg(pcie, PCIEINTXR); in rcar_pcie_ep_assert_intx()
378 rcar_pci_write_reg(pcie, val, PCIEINTXR); in rcar_pcie_ep_assert_intx()
383 static int rcar_pcie_ep_assert_msi(struct rcar_pcie *pcie, in rcar_pcie_ep_assert_msi() argument
390 val = rcar_pci_read_reg(pcie, MSICAP(fn)); in rcar_pcie_ep_assert_msi()
392 return -EINVAL; in rcar_pcie_ep_assert_msi()
399 return -EINVAL; in rcar_pcie_ep_assert_msi()
401 val = rcar_pci_read_reg(pcie, PCIEMSITXR); in rcar_pcie_ep_assert_msi()
402 rcar_pci_write_reg(pcie, val | (interrupt_num - 1), PCIEMSITXR); in rcar_pcie_ep_assert_msi()
411 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_raise_irq() local
415 return rcar_pcie_ep_assert_intx(ep, fn, 0); in rcar_pcie_ep_raise_irq()
418 return rcar_pcie_ep_assert_msi(&ep->pcie, fn, interrupt_num); in rcar_pcie_ep_raise_irq()
421 return -EINVAL; in rcar_pcie_ep_raise_irq()
427 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_start() local
429 rcar_pci_write_reg(&ep->pcie, MACCTLR_INIT_VAL, MACCTLR); in rcar_pcie_ep_start()
430 rcar_pci_write_reg(&ep->pcie, CFINIT, PCIETCTLR); in rcar_pcie_ep_start()
437 struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc); in rcar_pcie_ep_stop() local
439 rcar_pci_write_reg(&ep->pcie, 0, PCIETCTLR); in rcar_pcie_ep_stop()
446 /* use 64-bit BARs so mark BAR[1,3,5] as reserved */
475 { .compatible = "renesas,r8a774c0-pcie-ep", },
476 { .compatible = "renesas,rcar-gen3-pcie-ep" },
482 struct device *dev = &pdev->dev; in rcar_pcie_ep_probe()
483 struct rcar_pcie_endpoint *ep; in rcar_pcie_ep_probe() local
484 struct rcar_pcie *pcie; in rcar_pcie_ep_probe() local
488 ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); in rcar_pcie_ep_probe()
489 if (!ep) in rcar_pcie_ep_probe()
490 return -ENOMEM; in rcar_pcie_ep_probe()
492 pcie = &ep->pcie; in rcar_pcie_ep_probe()
493 pcie->dev = dev; in rcar_pcie_ep_probe()
502 err = rcar_pcie_ep_get_pdata(ep, pdev); in rcar_pcie_ep_probe()
508 ep->num_ib_windows = MAX_NR_INBOUND_MAPS; in rcar_pcie_ep_probe()
509 ep->ib_window_map = in rcar_pcie_ep_probe()
510 devm_kcalloc(dev, BITS_TO_LONGS(ep->num_ib_windows), in rcar_pcie_ep_probe()
512 if (!ep->ib_window_map) { in rcar_pcie_ep_probe()
513 err = -ENOMEM; in rcar_pcie_ep_probe()
518 ep->ob_mapped_addr = devm_kcalloc(dev, ep->num_ob_windows, in rcar_pcie_ep_probe()
519 sizeof(*ep->ob_mapped_addr), in rcar_pcie_ep_probe()
521 if (!ep->ob_mapped_addr) { in rcar_pcie_ep_probe()
522 err = -ENOMEM; in rcar_pcie_ep_probe()
534 epc->max_functions = ep->max_functions; in rcar_pcie_ep_probe()
535 epc_set_drvdata(epc, ep); in rcar_pcie_ep_probe()
537 rcar_pcie_ep_hw_init(pcie); in rcar_pcie_ep_probe()
539 err = pci_epc_multi_mem_init(epc, ep->ob_window, ep->num_ob_windows); in rcar_pcie_ep_probe()
558 .name = "rcar-pcie-ep",