1 /*
2  * Copyright (c) 2019 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_
8 #define ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_
9 
10 /**
11  * @brief PCIe Host Interface
12  * @defgroup pcie_host_interface PCIe Host Interface
13  * @ingroup io_interfaces
14  * @{
15  */
16 
17 #include <stddef.h>
18 #include <zephyr/devicetree.h>
19 #include <zephyr/dt-bindings/pcie/pcie.h>
20 #include <zephyr/types.h>
21 #include <zephyr/kernel.h>
22 #include <zephyr/sys/iterable_sections.h>
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 /**
29  * @typedef pcie_bdf_t
30  * @brief A unique PCI(e) endpoint (bus, device, function).
31  *
32  * A PCI(e) endpoint is uniquely identified topologically using a
33  * (bus, device, function) tuple. The internal structure is documented
34  * in include/dt-bindings/pcie/pcie.h: see PCIE_BDF() and friends, since
35  * these tuples are referenced from devicetree.
36  */
37 typedef uint32_t pcie_bdf_t;
38 
39 /**
40  * @typedef pcie_id_t
41  * @brief A unique PCI(e) identifier (vendor ID, device ID).
42  *
43  * The PCIE_CONF_ID register for each endpoint is a (vendor ID, device ID)
44  * pair, which is meant to tell the system what the PCI(e) endpoint is. Again,
45  * look to PCIE_ID_* macros in include/dt-bindings/pcie/pcie.h for more.
46  */
47 typedef uint32_t pcie_id_t;
48 
49 /* Helper macro to exclude invalid PCIe identifiers. We should really only
50  * need to look for PCIE_ID_NONE, but because of some broken PCI host controllers
51  * we have try cases where both VID & DID are zero or just one of them is
52  * zero (0x0000) and the other is all ones (0xFFFF).
53  */
54 #define PCIE_ID_IS_VALID(id) ((id != PCIE_ID_NONE) && \
55 			      (id != PCIE_ID(0x0000, 0x0000)) && \
56 			      (id != PCIE_ID(0xFFFF, 0x0000)) && \
57 			      (id != PCIE_ID(0x0000, 0xFFFF)))
58 
59 struct pcie_dev {
60 	pcie_bdf_t bdf;
61 	pcie_id_t  id;
62 	uint32_t   class_rev;
63 	uint32_t   class_rev_mask;
64 };
65 
66 #define Z_DEVICE_PCIE_NAME(node_id) _CONCAT(pcie_dev_, DT_DEP_ORD(node_id))
67 
68 /**
69  * @brief Get the PCIe Vendor and Device ID for a node
70  *
71  * @param node_id DTS node identifier
72  * @return The VID/DID combination as pcie_id_t
73  */
74 #define PCIE_DT_ID(node_id) PCIE_ID(DT_PROP_OR(node_id, vendor_id, 0xffff), \
75 				    DT_PROP_OR(node_id, device_id, 0xffff))
76 
77 /**
78  * @brief Get the PCIe Vendor and Device ID for a node
79  *
80  * This is equivalent to
81  * <tt>PCIE_DT_ID(DT_DRV_INST(inst))</tt>
82  *
83  * @param inst Devicetree instance number
84  * @return The VID/DID combination as pcie_id_t
85  */
86 #define PCIE_DT_INST_ID(inst) PCIE_DT_ID(DT_DRV_INST(inst))
87 
88 /**
89  * @brief Declare a PCIe context variable for a DTS node
90  *
91  * Declares a PCIe context for a DTS node. This must be done before
92  * using the DEVICE_PCIE_INIT() macro for the same node.
93  *
94  * @param node_id DTS node identifier
95  */
96 #define DEVICE_PCIE_DECLARE(node_id)                                        \
97 	STRUCT_SECTION_ITERABLE(pcie_dev, Z_DEVICE_PCIE_NAME(node_id)) = {  \
98 		.bdf = PCIE_BDF_NONE,                                       \
99 		.id = PCIE_DT_ID(node_id),                                  \
100 		.class_rev = DT_PROP_OR(node_id, class_rev, 0),             \
101 		.class_rev_mask = DT_PROP_OR(node_id, class_rev_mask, 0),   \
102 	}
103 
104 /**
105  * @brief Declare a PCIe context variable for a DTS node
106  *
107  * This is equivalent to
108  * <tt>DEVICE_PCIE_DECLARE(DT_DRV_INST(inst))</tt>
109  *
110  * @param inst Devicetree instance number
111  */
112 #define DEVICE_PCIE_INST_DECLARE(inst) DEVICE_PCIE_DECLARE(DT_DRV_INST(inst))
113 
114 /**
115  * @brief Initialize a named struct member to point at a PCIe context
116  *
117  * Initialize PCIe-related information within a specific instance of
118  * a device config struct, using information from DTS. Using the macro
119  * requires having first created PCIe context struct using the
120  * DEVICE_PCIE_DECLARE() macro.
121  *
122  * Example for an instance of a driver belonging to the "foo" subsystem
123  *
124  * struct foo_config {
125  *	struct pcie_dev *pcie;
126  *	...
127  *};
128  *
129  * DEVICE_PCIE_ID_DECLARE(DT_DRV_INST(...));
130  * struct foo_config my_config = {
131 	DEVICE_PCIE_INIT(pcie, DT_DRV_INST(...)),
132  *	...
133  * };
134  *
135  * @param node_id DTS node identifier
136  * @param name Member name within config for the MMIO region
137  */
138 #define DEVICE_PCIE_INIT(node_id, name) .name = &Z_DEVICE_PCIE_NAME(node_id)
139 
140 /**
141  * @brief Initialize a named struct member to point at a PCIe context
142  *
143  * This is equivalent to
144  * <tt>DEVICE_PCIE_INIT(DT_DRV_INST(inst), name)</tt>
145  *
146  * @param inst Devicetree instance number
147  * @param name Name of the struct member (of type struct pcie_dev *)
148  */
149 #define DEVICE_PCIE_INST_INIT(inst, name) \
150 	DEVICE_PCIE_INIT(DT_DRV_INST(inst), name)
151 
152 struct pcie_bar {
153 	uintptr_t phys_addr;
154 	size_t size;
155 };
156 
157 /*
158  * These functions are arch-, board-, or SoC-specific.
159  */
160 
161 /**
162  * @brief Read a 32-bit word from an endpoint's configuration space.
163  *
164  * This function is exported by the arch/SoC/board code.
165  *
166  * @param bdf PCI(e) endpoint
167  * @param reg the configuration word index (not address)
168  * @return the word read (0xFFFFFFFFU if nonexistent endpoint or word)
169  */
170 extern uint32_t pcie_conf_read(pcie_bdf_t bdf, unsigned int reg);
171 
172 /**
173  * @brief Write a 32-bit word to an endpoint's configuration space.
174  *
175  * This function is exported by the arch/SoC/board code.
176  *
177  * @param bdf PCI(e) endpoint
178  * @param reg the configuration word index (not address)
179  * @param data the value to write
180  */
181 extern void pcie_conf_write(pcie_bdf_t bdf, unsigned int reg, uint32_t data);
182 
183 /** Callback type used for scanning for PCI endpoints
184  *
185  * @param bdf      BDF value for a found endpoint.
186  * @param id       Vendor & Device ID for the found endpoint.
187  * @param cb_data  Custom, use case specific data.
188  *
189  * @return true to continue scanning, false to stop scanning.
190  */
191 typedef bool (*pcie_scan_cb_t)(pcie_bdf_t bdf, pcie_id_t id, void *cb_data);
192 
193 enum {
194 	/** Scan all available PCI host controllers and sub-busses */
195 	PCIE_SCAN_RECURSIVE = BIT(0),
196 	/** Do the callback for all endpoint types, including bridges */
197 	PCIE_SCAN_CB_ALL = BIT(1),
198 };
199 
200 /** Options for performing a scan for PCI devices */
201 struct pcie_scan_opt {
202 	/** Initial bus number to scan */
203 	uint8_t bus;
204 
205 	/** Function to call for each found endpoint */
206 	pcie_scan_cb_t cb;
207 
208 	/** Custom data to pass to the scan callback */
209 	void *cb_data;
210 
211 	/** Scan flags */
212 	uint32_t flags;
213 };
214 
215 /** Scan for PCIe devices.
216  *
217  * Scan the PCI bus (or buses) for available endpoints.
218  *
219  * @param opt Options determining how to perform the scan.
220  * @return 0 on success, negative POSIX error number on failure.
221  */
222 int pcie_scan(const struct pcie_scan_opt *opt);
223 
224 /**
225  * @brief Get the MBAR at a specific BAR index
226  * @param bdf the PCI(e) endpoint
227  * @param bar_index 0-based BAR index
228  * @param mbar Pointer to struct pcie_bar
229  * @return true if the mbar was found and is valid, false otherwise
230  */
231 extern bool pcie_get_mbar(pcie_bdf_t bdf,
232 			  unsigned int bar_index,
233 			  struct pcie_bar *mbar);
234 
235 /**
236  * @brief Probe the nth MMIO address assigned to an endpoint.
237  * @param bdf the PCI(e) endpoint
238  * @param index (0-based) index
239  * @param mbar Pointer to struct pcie_bar
240  * @return true if the mbar was found and is valid, false otherwise
241  *
242  * A PCI(e) endpoint has 0 or more memory-mapped regions. This function
243  * allows the caller to enumerate them by calling with index=0..n.
244  * Value of n has to be below 6, as there is a maximum of 6 BARs. The indices
245  * are order-preserving with respect to the endpoint BARs: e.g., index 0
246  * will return the lowest-numbered memory BAR on the endpoint.
247  */
248 extern bool pcie_probe_mbar(pcie_bdf_t bdf,
249 			    unsigned int index,
250 			    struct pcie_bar *mbar);
251 
252 /**
253  * @brief Get the I/O BAR at a specific BAR index
254  * @param bdf the PCI(e) endpoint
255  * @param bar_index 0-based BAR index
256  * @param iobar Pointer to struct pcie_bar
257  * @return true if the I/O BAR was found and is valid, false otherwise
258  */
259 extern bool pcie_get_iobar(pcie_bdf_t bdf,
260 			   unsigned int bar_index,
261 			   struct pcie_bar *iobar);
262 
263 /**
264  * @brief Probe the nth I/O BAR address assigned to an endpoint.
265  * @param bdf the PCI(e) endpoint
266  * @param index (0-based) index
267  * @param iobar Pointer to struct pcie_bar
268  * @return true if the I/O BAR was found and is valid, false otherwise
269  *
270  * A PCI(e) endpoint has 0 or more I/O regions. This function
271  * allows the caller to enumerate them by calling with index=0..n.
272  * Value of n has to be below 6, as there is a maximum of 6 BARs. The indices
273  * are order-preserving with respect to the endpoint BARs: e.g., index 0
274  * will return the lowest-numbered I/O BAR on the endpoint.
275  */
276 extern bool pcie_probe_iobar(pcie_bdf_t bdf,
277 			     unsigned int index,
278 			     struct pcie_bar *iobar);
279 
280 /**
281  * @brief Set or reset bits in the endpoint command/status register.
282  *
283  * @param bdf the PCI(e) endpoint
284  * @param bits the powerset of bits of interest
285  * @param on use true to set bits, false to reset them
286  */
287 extern void pcie_set_cmd(pcie_bdf_t bdf, uint32_t bits, bool on);
288 
289 #ifndef CONFIG_PCIE_CONTROLLER
290 /**
291  * @brief Allocate an IRQ for an endpoint.
292  *
293  * This function first checks the IRQ register and if it contains a valid
294  * value this is returned. If the register does not contain a valid value
295  * allocation of a new one is attempted.
296  * Such function is only exposed if CONFIG_PCIE_CONTROLLER is unset.
297  * It is thus available where architecture tied dynamic IRQ allocation for
298  * PCIe device makes sense.
299  *
300  * @param bdf the PCI(e) endpoint
301  * @return the IRQ number, or PCIE_CONF_INTR_IRQ_NONE if allocation failed.
302  */
303 extern unsigned int pcie_alloc_irq(pcie_bdf_t bdf);
304 #endif /* CONFIG_PCIE_CONTROLLER */
305 
306 /**
307  * @brief Return the IRQ assigned by the firmware/board to an endpoint.
308  *
309  * @param bdf the PCI(e) endpoint
310  * @return the IRQ number, or PCIE_CONF_INTR_IRQ_NONE if unknown.
311  */
312 extern unsigned int pcie_get_irq(pcie_bdf_t bdf);
313 
314 /**
315  * @brief Enable the PCI(e) endpoint to generate the specified IRQ.
316  *
317  * @param bdf the PCI(e) endpoint
318  * @param irq the IRQ to generate
319  *
320  * If MSI is enabled and the endpoint supports it, the endpoint will
321  * be configured to generate the specified IRQ via MSI. Otherwise, it
322  * is assumed that the IRQ has been routed by the boot firmware
323  * to the specified IRQ, and the IRQ is enabled (at the I/O APIC, or
324  * wherever appropriate).
325  */
326 extern void pcie_irq_enable(pcie_bdf_t bdf, unsigned int irq);
327 
328 /**
329  * @brief Find a PCI(e) capability in an endpoint's configuration space.
330  *
331  * @param bdf the PCI endpoint to examine
332  * @param cap_id the capability ID of interest
333  * @return the index of the configuration word, or 0 if no capability.
334  */
335 extern uint32_t pcie_get_cap(pcie_bdf_t bdf, uint32_t cap_id);
336 
337 /**
338  * @brief Find an Extended PCI(e) capability in an endpoint's configuration space.
339  *
340  * @param bdf the PCI endpoint to examine
341  * @param cap_id the capability ID of interest
342  * @return the index of the configuration word, or 0 if no capability.
343  */
344 extern uint32_t pcie_get_ext_cap(pcie_bdf_t bdf, uint32_t cap_id);
345 
346 /**
347  * @brief Dynamically connect a PCIe endpoint IRQ to an ISR handler
348  *
349  * @param bdf the PCI endpoint to examine
350  * @param irq the IRQ to connect (see pcie_alloc_irq())
351  * @param priority priority of the IRQ
352  * @param routine the ISR handler to connect to the IRQ
353  * @param parameter the parameter to provide to the handler
354  * @param flags IRQ connection flags
355  * @return true if connected, false otherwise
356  */
357 extern bool pcie_connect_dynamic_irq(pcie_bdf_t bdf,
358 				     unsigned int irq,
359 				     unsigned int priority,
360 				     void (*routine)(const void *parameter),
361 				     const void *parameter,
362 				     uint32_t flags);
363 
364 /**
365  * @brief Get the BDF for a given PCI host controller
366  *
367  * This macro is useful when the PCI host controller behind PCIE_BDF(0, 0, 0)
368  * indicates a multifunction device. In such a case each function of this
369  * endpoint is a potential host controller itself.
370  *
371  * @param n Bus number
372  * @return BDF value of the given host controller
373  */
374 #define PCIE_HOST_CONTROLLER(n) PCIE_BDF(0, 0, n)
375 
376 /*
377  * Configuration word 13 contains the head of the capabilities list.
378  */
379 
380 #define PCIE_CONF_CAPPTR	13U	/* capabilities pointer */
381 #define PCIE_CONF_CAPPTR_FIRST(w)	(((w) >> 2) & 0x3FU)
382 
383 /*
384  * The first word of every capability contains a capability identifier,
385  * and a link to the next capability (or 0) in configuration space.
386  */
387 
388 #define PCIE_CONF_CAP_ID(w)		((w) & 0xFFU)
389 #define PCIE_CONF_CAP_NEXT(w)		(((w) >> 10) & 0x3FU)
390 
391 /*
392  * The extended PCI Express capabilities lie at the end of the PCI configuration space
393  */
394 
395 #define PCIE_CONF_EXT_CAPPTR	64U
396 
397 /*
398  * The first word of every capability contains an extended capability identifier,
399  * and a link to the next capability (or 0) in the extended configuration space.
400  */
401 
402 #define PCIE_CONF_EXT_CAP_ID(w)		((w) & 0xFFFFU)
403 #define PCIE_CONF_EXT_CAP_VER(w)	(((w) >> 16) & 0xFU)
404 #define PCIE_CONF_EXT_CAP_NEXT(w)	(((w) >> 20) & 0xFFFU)
405 
406 /*
407  * Configuration word 0 aligns directly with pcie_id_t.
408  */
409 
410 #define PCIE_CONF_ID		0U
411 
412 /*
413  * Configuration word 1 contains command and status bits.
414  */
415 
416 #define PCIE_CONF_CMDSTAT	1U	/* command/status register */
417 
418 #define PCIE_CONF_CMDSTAT_IO		0x00000001U  /* I/O access enable */
419 #define PCIE_CONF_CMDSTAT_MEM		0x00000002U  /* mem access enable */
420 #define PCIE_CONF_CMDSTAT_MASTER	0x00000004U  /* bus master enable */
421 #define PCIE_CONF_CMDSTAT_INTERRUPT	0x00080000U  /* interrupt status */
422 #define PCIE_CONF_CMDSTAT_CAPS		0x00100000U  /* capabilities list */
423 
424 /*
425  * Configuration word 2 has additional function identification that
426  * we only care about for debug output (PCIe shell commands).
427  */
428 
429 #define PCIE_CONF_CLASSREV	2U	/* class/revision register */
430 
431 #define PCIE_CONF_CLASSREV_CLASS(w)	(((w) >> 24) & 0xFFU)
432 #define PCIE_CONF_CLASSREV_SUBCLASS(w)  (((w) >> 16) & 0xFFU)
433 #define PCIE_CONF_CLASSREV_PROGIF(w)	(((w) >> 8) & 0xFFU)
434 #define PCIE_CONF_CLASSREV_REV(w)	((w) & 0xFFU)
435 
436 /*
437  * The only part of configuration word 3 that is of interest to us is
438  * the header type, as we use it to distinguish functional endpoints
439  * from bridges (which are, for our purposes, transparent).
440  */
441 
442 #define PCIE_CONF_TYPE		3U
443 
444 #define PCIE_CONF_MULTIFUNCTION(w)	(((w) & 0x00800000U) != 0U)
445 #define PCIE_CONF_TYPE_BRIDGE(w)	(((w) & 0x007F0000U) != 0U)
446 #define PCIE_CONF_TYPE_GET(w)		(((w) >> 16) & 0x7F)
447 
448 #define PCIE_CONF_TYPE_STANDARD         0x0U
449 #define PCIE_CONF_TYPE_PCI_BRIDGE       0x1U
450 #define PCIE_CONF_TYPE_CARDBUS_BRIDGE   0x2U
451 
452 /*
453  * Words 4-9 are BARs are I/O or memory decoders. Memory decoders may
454  * be 64-bit decoders, in which case the next configuration word holds
455  * the high-order bits (and is, thus, not a BAR itself).
456  */
457 
458 #define PCIE_CONF_BAR0		4U
459 #define PCIE_CONF_BAR1		5U
460 #define PCIE_CONF_BAR2		6U
461 #define PCIE_CONF_BAR3		7U
462 #define PCIE_CONF_BAR4		8U
463 #define PCIE_CONF_BAR5		9U
464 
465 #define PCIE_CONF_BAR_IO(w)		(((w) & 0x00000001U) == 0x00000001U)
466 #define PCIE_CONF_BAR_MEM(w)		(((w) & 0x00000001U) != 0x00000001U)
467 #define PCIE_CONF_BAR_64(w)		(((w) & 0x00000006U) == 0x00000004U)
468 #define PCIE_CONF_BAR_ADDR(w)		((w) & ~0xfUL)
469 #define PCIE_CONF_BAR_IO_ADDR(w)	((w) & ~0x3UL)
470 #define PCIE_CONF_BAR_FLAGS(w)		((w) & 0xfUL)
471 #define PCIE_CONF_BAR_NONE		0U
472 
473 #define PCIE_CONF_BAR_INVAL		0xFFFFFFF0U
474 #define PCIE_CONF_BAR_INVAL64		0xFFFFFFFFFFFFFFF0UL
475 
476 #define PCIE_CONF_BAR_INVAL_FLAGS(w)			\
477 	((((w) & 0x00000006U) == 0x00000006U) ||	\
478 	 (((w) & 0x00000006U) == 0x00000002U))
479 
480 /*
481  * Type 1 Header has files related to bus management
482  */
483 #define PCIE_BUS_NUMBER         6U
484 
485 #define PCIE_BUS_PRIMARY_NUMBER(w)      ((w) & 0xffUL)
486 #define PCIE_BUS_SECONDARY_NUMBER(w)    (((w) >> 8) & 0xffUL)
487 #define PCIE_BUS_SUBORDINATE_NUMBER(w)  (((w) >> 16) & 0xffUL)
488 #define PCIE_SECONDARY_LATENCY_TIMER(w) (((w) >> 24) & 0xffUL)
489 
490 #define PCIE_BUS_NUMBER_VAL(prim, sec, sub, lat) \
491 	(((prim) & 0xffUL) |			 \
492 	 (((sec) & 0xffUL) << 8) |		 \
493 	 (((sub) & 0xffUL) << 16) |		 \
494 	 (((lat) & 0xffUL) << 24))
495 
496 /*
497  * Type 1 words 7 to 12 setups Bridge Memory base and limits
498  */
499 #define PCIE_IO_SEC_STATUS      7U
500 
501 #define PCIE_IO_BASE(w)         ((w) & 0xffUL)
502 #define PCIE_IO_LIMIT(w)        (((w) >> 8) & 0xffUL)
503 #define PCIE_SEC_STATUS(w)      (((w) >> 16) & 0xffffUL)
504 
505 #define PCIE_IO_SEC_STATUS_VAL(iob, iol, sec_status) \
506 	(((iob) & 0xffUL) |			     \
507 	 (((iol) & 0xffUL) << 8) |		     \
508 	 (((sec_status) & 0xffffUL) << 16))
509 
510 #define PCIE_MEM_BASE_LIMIT     8U
511 
512 #define PCIE_MEM_BASE(w)        ((w) & 0xffffUL)
513 #define PCIE_MEM_LIMIT(w)       (((w) >> 16) & 0xffffUL)
514 
515 #define PCIE_MEM_BASE_LIMIT_VAL(memb, meml) \
516 	(((memb) & 0xffffUL) |		    \
517 	 (((meml) & 0xffffUL) << 16))
518 
519 #define PCIE_PREFETCH_BASE_LIMIT        9U
520 
521 #define PCIE_PREFETCH_BASE(w)   ((w) & 0xffffUL)
522 #define PCIE_PREFETCH_LIMIT(w)  (((w) >> 16) & 0xffffUL)
523 
524 #define PCIE_PREFETCH_BASE_LIMIT_VAL(pmemb, pmeml) \
525 	(((pmemb) & 0xffffUL) |			   \
526 	 (((pmeml) & 0xffffUL) << 16))
527 
528 #define PCIE_PREFETCH_BASE_UPPER        10U
529 
530 #define PCIE_PREFETCH_LIMIT_UPPER       11U
531 
532 #define PCIE_IO_BASE_LIMIT_UPPER        12U
533 
534 #define PCIE_IO_BASE_UPPER(w)   ((w) & 0xffffUL)
535 #define PCIE_IO_LIMIT_UPPER(w)  (((w) >> 16) & 0xffffUL)
536 
537 #define PCIE_IO_BASE_LIMIT_UPPER_VAL(iobu, iolu) \
538 	(((iobu) & 0xffffUL) |			 \
539 	 (((iolu) & 0xffffUL) << 16))
540 
541 /*
542  * Word 15 contains information related to interrupts.
543  *
544  * We're only interested in the low byte, which is [supposed to be] set by
545  * the firmware to indicate which wire IRQ the device interrupt is routed to.
546  */
547 
548 #define PCIE_CONF_INTR		15U
549 
550 #define PCIE_CONF_INTR_IRQ(w)	((w) & 0xFFU)
551 #define PCIE_CONF_INTR_IRQ_NONE	0xFFU  /* no interrupt routed */
552 
553 #define PCIE_MAX_BUS  (0xFFFFFFFFU & PCIE_BDF_BUS_MASK)
554 #define PCIE_MAX_DEV  (0xFFFFFFFFU & PCIE_BDF_DEV_MASK)
555 #define PCIE_MAX_FUNC (0xFFFFFFFFU & PCIE_BDF_FUNC_MASK)
556 
557 /**
558  * @brief Initialize an interrupt handler for a PCIe endpoint IRQ
559  *
560  * This routine is only meant to be used by drivers using PCIe bus and having
561  * fixed or MSI based IRQ (so no runtime detection of the IRQ). In case
562  * of runtime detection see pcie_connect_dynamic_irq()
563  *
564  * @param bdf_p PCIe endpoint BDF
565  * @param irq_p IRQ line number.
566  * @param priority_p Interrupt priority.
567  * @param isr_p Address of interrupt service routine.
568  * @param isr_param_p Parameter passed to interrupt service routine.
569  * @param flags_p Architecture-specific IRQ configuration flags..
570  */
571 #define PCIE_IRQ_CONNECT(bdf_p, irq_p, priority_p,			\
572 			 isr_p, isr_param_p, flags_p)			\
573 	ARCH_PCIE_IRQ_CONNECT(bdf_p, irq_p, priority_p,			\
574 			      isr_p, isr_param_p, flags_p)
575 
576 #ifdef __cplusplus
577 }
578 #endif
579 
580 /**
581  * @}
582  */
583 
584 #endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_ */
585