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 #include <stddef.h>
11 #include <dt-bindings/pcie/pcie.h>
12 #include <zephyr/types.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /**
19  * @typedef pcie_bdf_t
20  * @brief A unique PCI(e) endpoint (bus, device, function).
21  *
22  * A PCI(e) endpoint is uniquely identified topologically using a
23  * (bus, device, function) tuple. The internal structure is documented
24  * in include/dt-bindings/pcie/pcie.h: see PCIE_BDF() and friends, since
25  * these tuples are referenced from devicetree.
26  */
27 typedef uint32_t pcie_bdf_t;
28 
29 /**
30  * @typedef pcie_id_t
31  * @brief A unique PCI(e) identifier (vendor ID, device ID).
32  *
33  * The PCIE_CONF_ID register for each endpoint is a (vendor ID, device ID)
34  * pair, which is meant to tell the system what the PCI(e) endpoint is. Again,
35  * look to PCIE_ID_* macros in include/dt-bindings/pcie/pcie.h for more.
36  */
37 typedef uint32_t pcie_id_t;
38 
39 struct pcie_mbar {
40 	uintptr_t phys_addr;
41 	size_t size;
42 };
43 
44 /*
45  * These functions are arch-, board-, or SoC-specific.
46  */
47 
48 /**
49  * @brief Look up the BDF based on PCI(e) vendor & device ID
50  *
51  * This function is used to look up the BDF for a device given its
52  * vendor and device ID.
53  *
54  * @param id PCI(e) vendor & device ID encoded using PCIE_ID()
55  * @return The BDF for the device, or PCIE_BDF_NONE if it was not found
56  */
57 extern pcie_bdf_t pcie_bdf_lookup(pcie_id_t id);
58 
59 /**
60  * @brief Read a 32-bit word from an endpoint's configuration space.
61  *
62  * This function is exported by the arch/SoC/board code.
63  *
64  * @param bdf PCI(e) endpoint
65  * @param reg the configuration word index (not address)
66  * @return the word read (0xFFFFFFFFU if nonexistent endpoint or word)
67  */
68 extern uint32_t pcie_conf_read(pcie_bdf_t bdf, unsigned int reg);
69 
70 /**
71  * @brief Write a 32-bit word to an endpoint's configuration space.
72  *
73  * This function is exported by the arch/SoC/board code.
74  *
75  * @param bdf PCI(e) endpoint
76  * @param reg the configuration word index (not address)
77  * @param data the value to write
78  */
79 extern void pcie_conf_write(pcie_bdf_t bdf, unsigned int reg, uint32_t data);
80 
81 /**
82  * @brief Probe for the presence of a PCI(e) endpoint.
83  *
84  * @param bdf the endpoint to probe
85  * @param id the endpoint ID to expect, or PCIE_ID_NONE for "any device"
86  * @return true if the device is present, false otherwise
87  */
88 extern bool pcie_probe(pcie_bdf_t bdf, pcie_id_t id);
89 
90 /**
91  * @brief Get the MBAR at a specific BAR index
92  * @param bdf the PCI(e) endpoint
93  * @param bar_index 0-based BAR index
94  * @param mbar Pointer to struct pcie_mbar
95  * @return true if the mbar was found and is valid, false otherwise
96  */
97 extern bool pcie_get_mbar(pcie_bdf_t bdf,
98 			  unsigned int bar_index,
99 			  struct pcie_mbar *mbar);
100 
101 /**
102  * @brief Probe the nth MMIO address assigned to an endpoint.
103  * @param bdf the PCI(e) endpoint
104  * @param index (0-based) index
105  * @param mbar Pointer to struct pcie_mbar
106  * @return true if the mbar was found and is valid, false otherwise
107  *
108  * A PCI(e) endpoint has 0 or more memory-mapped regions. This function
109  * allows the caller to enumerate them by calling with index=0..n.
110  * Value of n has to be below 6, as there is a maximum of 6 BARs. The indices
111  * are order-preserving with respect to the endpoint BARs: e.g., index 0
112  * will return the lowest-numbered memory BAR on the endpoint.
113  */
114 extern bool pcie_probe_mbar(pcie_bdf_t bdf,
115 			    unsigned int index,
116 			    struct pcie_mbar *mbar);
117 
118 /**
119  * @brief Set or reset bits in the endpoint command/status register.
120  *
121  * @param bdf the PCI(e) endpoint
122  * @param bits the powerset of bits of interest
123  * @param on use true to set bits, false to reset them
124  */
125 extern void pcie_set_cmd(pcie_bdf_t bdf, uint32_t bits, bool on);
126 
127 /**
128  * @brief Allocate an IRQ for an endpoint.
129  *
130  * This function first checks the IRQ register and if it contains a valid
131  * value this is returned. If the register does not contain a valid value
132  * allocation of a new one is attempted.
133  *
134  * @param bdf the PCI(e) endpoint
135  * @return the IRQ number, or PCIE_CONF_INTR_IRQ_NONE if allocation failed.
136  */
137 extern unsigned int pcie_alloc_irq(pcie_bdf_t bdf);
138 
139 /**
140  * @brief Return the IRQ assigned by the firmware/board to an endpoint.
141  *
142  * @param bdf the PCI(e) endpoint
143  * @return the IRQ number, or PCIE_CONF_INTR_IRQ_NONE if unknown.
144  */
145 extern unsigned int pcie_get_irq(pcie_bdf_t bdf);
146 
147 /**
148  * @brief Enable the PCI(e) endpoint to generate the specified IRQ.
149  *
150  * @param bdf the PCI(e) endpoint
151  * @param irq the IRQ to generate
152  *
153  * If MSI is enabled and the endpoint supports it, the endpoint will
154  * be configured to generate the specified IRQ via MSI. Otherwise, it
155  * is assumed that the IRQ has been routed by the boot firmware
156  * to the specified IRQ, and the IRQ is enabled (at the I/O APIC, or
157  * wherever appropriate).
158  */
159 extern void pcie_irq_enable(pcie_bdf_t bdf, unsigned int irq);
160 
161 /**
162  * @brief Find a PCI(e) capability in an endpoint's configuration space.
163  *
164  * @param bdf the PCI endpoint to examine
165  * @param cap_id the capability ID of interest
166  * @return the index of the configuration word, or 0 if no capability.
167  */
168 extern uint32_t pcie_get_cap(pcie_bdf_t bdf, uint32_t cap_id);
169 
170 /**
171  * @brief Find an Extended PCI(e) capability in an endpoint's configuration space.
172  *
173  * @param bdf the PCI endpoint to examine
174  * @param cap_id the capability ID of interest
175  * @return the index of the configuration word, or 0 if no capability.
176  */
177 extern uint32_t pcie_get_ext_cap(pcie_bdf_t bdf, uint32_t cap_id);
178 
179 /*
180  * Configuration word 13 contains the head of the capabilities list.
181  */
182 
183 #define PCIE_CONF_CAPPTR	13U	/* capabilities pointer */
184 #define PCIE_CONF_CAPPTR_FIRST(w)	(((w) >> 2) & 0x3FU)
185 
186 /*
187  * The first word of every capability contains a capability identifier,
188  * and a link to the next capability (or 0) in configuration space.
189  */
190 
191 #define PCIE_CONF_CAP_ID(w)		((w) & 0xFFU)
192 #define PCIE_CONF_CAP_NEXT(w)		(((w) >> 10) & 0x3FU)
193 
194 /*
195  * The extended PCI Express capabilies lies at the end of the PCI configuration space
196  */
197 
198 #define PCIE_CONF_EXT_CAPPTR	64U
199 
200 /*
201  * The first word of every capability contains an extended capability identifier,
202  * and a link to the next capability (or 0) in the extended configuration space.
203  */
204 
205 #define PCIE_CONF_EXT_CAP_ID(w)		((w) & 0xFFFFU)
206 #define PCIE_CONF_EXT_CAP_VER(w)	(((w) >> 16) & 0xFU)
207 #define PCIE_CONF_EXT_CAP_NEXT(w)	(((w) >> 20) & 0xFFFU)
208 
209 /*
210  * Configuration word 0 aligns directly with pcie_id_t.
211  */
212 
213 #define PCIE_CONF_ID		0U
214 
215 /*
216  * Configuration word 1 contains command and status bits.
217  */
218 
219 #define PCIE_CONF_CMDSTAT	1U	/* command/status register */
220 
221 #define PCIE_CONF_CMDSTAT_IO		0x00000001U  /* I/O access enable */
222 #define PCIE_CONF_CMDSTAT_MEM		0x00000002U  /* mem access enable */
223 #define PCIE_CONF_CMDSTAT_MASTER	0x00000004U  /* bus master enable */
224 #define PCIE_CONF_CMDSTAT_CAPS		0x00100000U  /* capabilities list */
225 
226 /*
227  * Configuration word 2 has additional function identification that
228  * we only care about for debug output (PCIe shell commands).
229  */
230 
231 #define PCIE_CONF_CLASSREV	2U	/* class/revision register */
232 
233 #define PCIE_CONF_CLASSREV_CLASS(w)	(((w) >> 24) & 0xFFU)
234 #define PCIE_CONF_CLASSREV_SUBCLASS(w)  (((w) >> 16) & 0xFFU)
235 #define PCIE_CONF_CLASSREV_PROGIF(w)	(((w) >> 8) & 0xFFU)
236 #define PCIE_CONF_CLASSREV_REV(w)	((w) & 0xFFU)
237 
238 /*
239  * The only part of configuration word 3 that is of interest to us is
240  * the header type, as we use it to distinguish functional endpoints
241  * from bridges (which are, for our purposes, transparent).
242  */
243 
244 #define PCIE_CONF_TYPE		3U
245 
246 #define PCIE_CONF_TYPE_BRIDGE(w)	(((w) & 0x007F0000U) != 0U)
247 
248 /*
249  * Words 4-9 are BARs are I/O or memory decoders. Memory decoders may
250  * be 64-bit decoders, in which case the next configuration word holds
251  * the high-order bits (and is, thus, not a BAR itself).
252  */
253 
254 #define PCIE_CONF_BAR0		4U
255 #define PCIE_CONF_BAR1		5U
256 #define PCIE_CONF_BAR2		6U
257 #define PCIE_CONF_BAR3		7U
258 #define PCIE_CONF_BAR4		8U
259 #define PCIE_CONF_BAR5		9U
260 
261 #define PCIE_CONF_BAR_IO(w)		(((w) & 0x00000001U) == 0x00000001U)
262 #define PCIE_CONF_BAR_MEM(w)		(((w) & 0x00000001U) != 0x00000001U)
263 #define PCIE_CONF_BAR_64(w)		(((w) & 0x00000006U) == 0x00000004U)
264 #define PCIE_CONF_BAR_ADDR(w)		((w) & ~0xfUL)
265 #define PCIE_CONF_BAR_FLAGS(w)		((w) & 0xfUL)
266 #define PCIE_CONF_BAR_NONE		0U
267 
268 #define PCIE_CONF_BAR_INVAL		0xFFFFFFF0U
269 #define PCIE_CONF_BAR_INVAL64		0xFFFFFFFFFFFFFFF0UL
270 
271 #define PCIE_CONF_BAR_INVAL_FLAGS(w)			\
272 	((((w) & 0x00000006U) == 0x00000006U) ||	\
273 	 (((w) & 0x00000006U) == 0x00000002U))
274 
275 /*
276  * Word 15 contains information related to interrupts.
277  *
278  * We're only interested in the low byte, which is [supposed to be] set by
279  * the firmware to indicate which wire IRQ the device interrupt is routed to.
280  */
281 
282 #define PCIE_CONF_INTR		15U
283 
284 #define PCIE_CONF_INTR_IRQ(w)	((w) & 0xFFU)
285 #define PCIE_CONF_INTR_IRQ_NONE	0xFFU  /* no interrupt routed */
286 
287 #define PCIE_MAX_BUS  (0xFFFFFFFF & PCIE_BDF_BUS_MASK)
288 #define PCIE_MAX_DEV  (0xFFFFFFFF & PCIE_BDF_DEV_MASK)
289 #define PCIE_MAX_FUNC (0xFFFFFFFF & PCIE_BDF_FUNC_MASK)
290 
291 #ifdef __cplusplus
292 }
293 #endif
294 
295 #endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_ */
296