Line data Source code
1 1 : /**
2 : * @file
3 : *
4 : * @brief Public APIs for the PCIe Controllers drivers.
5 : */
6 :
7 : /*
8 : * Copyright (c) 2021 BayLibre, SAS
9 : *
10 : * SPDX-License-Identifier: Apache-2.0
11 : */
12 : #ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_CONTROLLERS_H_
13 : #define ZEPHYR_INCLUDE_DRIVERS_PCIE_CONTROLLERS_H_
14 :
15 : #include <zephyr/types.h>
16 : #include <zephyr/device.h>
17 : #include <zephyr/drivers/pcie/pcie.h>
18 :
19 : #ifdef CONFIG_PCIE_MSI
20 : #include <zephyr/drivers/pcie/msi.h>
21 : #endif
22 :
23 : /**
24 : * @brief PCI Express Controller Interface
25 : * @defgroup pcie_controller_interface PCI Express Controller Interface
26 : * @ingroup io_interfaces
27 : * @{
28 : */
29 :
30 : #ifdef __cplusplus
31 : extern "C" {
32 : #endif
33 :
34 : /**
35 : * @brief Function called to read a 32-bit word from an endpoint's configuration space.
36 : *
37 : * Read a 32-bit word from an endpoint's configuration space with the PCI Express Controller
38 : * configuration space access method (I/O port, memory mapped or custom method)
39 : *
40 : * @param dev PCI Express Controller device pointer
41 : * @param bdf PCI(e) endpoint
42 : * @param reg the configuration word index (not address)
43 : * @return the word read (0xFFFFFFFFU if nonexistent endpoint or word)
44 : */
45 1 : typedef uint32_t (*pcie_ctrl_conf_read_t)(const struct device *dev, pcie_bdf_t bdf,
46 : unsigned int reg);
47 :
48 : /**
49 : * @brief Function called to write a 32-bit word to an endpoint's configuration space.
50 : *
51 : * Write a 32-bit word to an endpoint's configuration space with the PCI Express Controller
52 : * configuration space access method (I/O port, memory mapped or custom method)
53 : *
54 : * @param dev PCI Express Controller device pointer
55 : * @param bdf PCI(e) endpoint
56 : * @param reg the configuration word index (not address)
57 : * @param data the value to write
58 : */
59 1 : typedef void (*pcie_ctrl_conf_write_t)(const struct device *dev, pcie_bdf_t bdf,
60 : unsigned int reg, uint32_t data);
61 :
62 : /**
63 : * @brief Function called to allocate a memory region subset for an endpoint Base Address Register.
64 : *
65 : * When enumerating PCIe Endpoints, Type0 endpoints can require up to 6 memory zones
66 : * via the Base Address Registers from I/O or Memory types.
67 : *
68 : * This call allocates such zone in the PCI Express Controller memory regions if
69 : * such region is available and space is still available.
70 : *
71 : * @param dev PCI Express Controller device pointer
72 : * @param bdf PCI(e) endpoint
73 : * @param mem True if the BAR is of memory type
74 : * @param mem64 True if the BAR is of 64bit memory type
75 : * @param bar_size Size in bytes of the Base Address Register as returned by HW
76 : * @param bar_bus_addr bus-centric address allocated to be written in the BAR register
77 : * @return True if allocation was possible, False if allocation failed
78 : */
79 1 : typedef bool (*pcie_ctrl_region_allocate_t)(const struct device *dev, pcie_bdf_t bdf,
80 : bool mem, bool mem64, size_t bar_size,
81 : uintptr_t *bar_bus_addr);
82 :
83 : /**
84 : * @brief Function called to get the current allocation base of a memory region subset
85 : * for an endpoint Base Address Register.
86 : *
87 : * When enumerating PCIe Endpoints, Type1 bridge endpoints requires a range of memory
88 : * allocated by all endpoints in the bridged bus.
89 : *
90 : * @param dev PCI Express Controller device pointer
91 : * @param bdf PCI(e) endpoint
92 : * @param mem True if the BAR is of memory type
93 : * @param mem64 True if the BAR is of 64bit memory type
94 : * @param align size to take in account for alignment
95 : * @param bar_base_addr bus-centric address allocation base
96 : * @return True if allocation was possible, False if allocation failed
97 : */
98 1 : typedef bool (*pcie_ctrl_region_get_allocate_base_t)(const struct device *dev, pcie_bdf_t bdf,
99 : bool mem, bool mem64, size_t align,
100 : uintptr_t *bar_base_addr);
101 :
102 : /**
103 : * @brief Function called to translate an endpoint Base Address Register bus-centric address
104 : * into Physical address.
105 : *
106 : * When enumerating PCIe Endpoints, Type0 endpoints can require up to 6 memory zones
107 : * via the Base Address Registers from I/O or Memory types.
108 : *
109 : * The bus-centric address set in this BAR register is not necessarily accessible from the CPU,
110 : * thus must be translated by using the PCI Express Controller memory regions translation
111 : * ranges to permit mapping from the CPU.
112 : *
113 : * @param dev PCI Express Controller device pointer
114 : * @param bdf PCI(e) endpoint
115 : * @param mem True if the BAR is of memory type
116 : * @param mem64 True if the BAR is of 64bit memory type
117 : * @param bar_bus_addr bus-centric address written in the BAR register
118 : * @param bar_addr CPU-centric address translated from the bus-centric address
119 : * @return True if translation was possible, False if translation failed
120 : */
121 1 : typedef bool (*pcie_ctrl_region_translate_t)(const struct device *dev, pcie_bdf_t bdf,
122 : bool mem, bool mem64, uintptr_t bar_bus_addr,
123 : uintptr_t *bar_addr);
124 :
125 : #ifdef CONFIG_PCIE_MSI
126 : typedef uint8_t (*pcie_ctrl_msi_device_setup_t)(const struct device *dev, unsigned int priority,
127 : msi_vector_t *vectors, uint8_t n_vector);
128 : #endif
129 :
130 : /**
131 : * @brief Read a 32-bit word from a Memory-Mapped endpoint's configuration space.
132 : *
133 : * Read a 32-bit word from an endpoint's configuration space from a Memory-Mapped
134 : * configuration space access method, known as PCI Control Access Method (CAM) or
135 : * PCIe Extended Control Access Method (ECAM).
136 : *
137 : * @param cfg_addr Logical address of Memory-Mapped configuration space
138 : * @param bdf PCI(e) endpoint
139 : * @param reg the configuration word index (not address)
140 : * @return the word read (0xFFFFFFFFU if nonexistent endpoint or word)
141 : */
142 1 : uint32_t pcie_generic_ctrl_conf_read(mm_reg_t cfg_addr, pcie_bdf_t bdf, unsigned int reg);
143 :
144 :
145 : /**
146 : * @brief Write a 32-bit word to a Memory-Mapped endpoint's configuration space.
147 : *
148 : * Write a 32-bit word to an endpoint's configuration space from a Memory-Mapped
149 : * configuration space access method, known as PCI Control Access Method (CAM) or
150 : * PCIe Extended Control Access Method (ECAM).
151 : *
152 : * @param cfg_addr Logical address of Memory-Mapped configuration space
153 : * @param bdf PCI(e) endpoint
154 : * @param reg the configuration word index (not address)
155 : * @param data the value to write
156 : */
157 1 : void pcie_generic_ctrl_conf_write(mm_reg_t cfg_addr, pcie_bdf_t bdf,
158 : unsigned int reg, uint32_t data);
159 :
160 : /**
161 : * @brief Start PCIe Endpoints enumeration.
162 : *
163 : * Start a PCIe Endpoints enumeration from a Bus number.
164 : * When on non-x86 architecture or when firmware didn't setup the PCIe Bus hierarchy,
165 : * the PCIe bus complex must be enumerated to setup the Endpoints Base Address Registers.
166 : *
167 : * @param dev PCI Express Controller device pointer
168 : * @param bdf_start PCI(e) start endpoint (only bus & dev are used to start enumeration)
169 : */
170 1 : void pcie_generic_ctrl_enumerate(const struct device *dev, pcie_bdf_t bdf_start);
171 :
172 : /** @brief Structure providing callbacks to be implemented for devices
173 : * that supports the PCI Express Controller API
174 : */
175 1 : __subsystem struct pcie_ctrl_driver_api {
176 0 : pcie_ctrl_conf_read_t conf_read;
177 0 : pcie_ctrl_conf_write_t conf_write;
178 0 : pcie_ctrl_region_allocate_t region_allocate;
179 0 : pcie_ctrl_region_get_allocate_base_t region_get_allocate_base;
180 0 : pcie_ctrl_region_translate_t region_translate;
181 : #ifdef CONFIG_PCIE_MSI
182 : pcie_ctrl_msi_device_setup_t msi_device_setup;
183 : #endif
184 : };
185 :
186 : /**
187 : * @brief Read a 32-bit word from an endpoint's configuration space.
188 : *
189 : * Read a 32-bit word from an endpoint's configuration space with the PCI Express Controller
190 : * configuration space access method (I/O port, memory mapped or custom method)
191 : *
192 : * @param dev PCI Express Controller device pointer
193 : * @param bdf PCI(e) endpoint
194 : * @param reg the configuration word index (not address)
195 : * @return the word read (0xFFFFFFFFU if nonexistent endpoint or word)
196 : */
197 1 : static inline uint32_t pcie_ctrl_conf_read(const struct device *dev, pcie_bdf_t bdf,
198 : unsigned int reg)
199 : {
200 : const struct pcie_ctrl_driver_api *api =
201 : (const struct pcie_ctrl_driver_api *)dev->api;
202 :
203 : return api->conf_read(dev, bdf, reg);
204 : }
205 :
206 : /**
207 : * @brief Write a 32-bit word to an endpoint's configuration space.
208 : *
209 : * Write a 32-bit word to an endpoint's configuration space with the PCI Express Controller
210 : * configuration space access method (I/O port, memory mapped or custom method)
211 : *
212 : * @param dev PCI Express Controller device pointer
213 : * @param bdf PCI(e) endpoint
214 : * @param reg the configuration word index (not address)
215 : * @param data the value to write
216 : */
217 1 : static inline void pcie_ctrl_conf_write(const struct device *dev, pcie_bdf_t bdf,
218 : unsigned int reg, uint32_t data)
219 : {
220 : const struct pcie_ctrl_driver_api *api =
221 : (const struct pcie_ctrl_driver_api *)dev->api;
222 :
223 : api->conf_write(dev, bdf, reg, data);
224 : }
225 :
226 : /**
227 : * @brief Allocate a memory region subset for an endpoint Base Address Register.
228 : *
229 : * When enumerating PCIe Endpoints, Type0 endpoints can require up to 6 memory zones
230 : * via the Base Address Registers from I/O or Memory types.
231 : *
232 : * This call allocates such zone in the PCI Express Controller memory regions if
233 : * such region is available and space is still available.
234 : *
235 : * @param dev PCI Express Controller device pointer
236 : * @param bdf PCI(e) endpoint
237 : * @param mem True if the BAR is of memory type
238 : * @param mem64 True if the BAR is of 64bit memory type
239 : * @param bar_size Size in bytes of the Base Address Register as returned by HW
240 : * @param bar_bus_addr bus-centric address allocated to be written in the BAR register
241 : * @return True if allocation was possible, False if allocation failed
242 : */
243 1 : static inline bool pcie_ctrl_region_allocate(const struct device *dev, pcie_bdf_t bdf,
244 : bool mem, bool mem64, size_t bar_size,
245 : uintptr_t *bar_bus_addr)
246 : {
247 : const struct pcie_ctrl_driver_api *api =
248 : (const struct pcie_ctrl_driver_api *)dev->api;
249 :
250 : return api->region_allocate(dev, bdf, mem, mem64, bar_size, bar_bus_addr);
251 : }
252 :
253 : /**
254 : * @brief Function called to get the current allocation base of a memory region subset
255 : * for an endpoint Base Address Register.
256 : *
257 : * When enumerating PCIe Endpoints, Type1 bridge endpoints requires a range of memory
258 : * allocated by all endpoints in the bridged bus.
259 : *
260 : * @param dev PCI Express Controller device pointer
261 : * @param bdf PCI(e) endpoint
262 : * @param mem True if the BAR is of memory type
263 : * @param mem64 True if the BAR is of 64bit memory type
264 : * @param align size to take in account for alignment
265 : * @param bar_base_addr bus-centric address allocation base
266 : * @return True if allocation was possible, False if allocation failed
267 : */
268 1 : static inline bool pcie_ctrl_region_get_allocate_base(const struct device *dev, pcie_bdf_t bdf,
269 : bool mem, bool mem64, size_t align,
270 : uintptr_t *bar_base_addr)
271 : {
272 : const struct pcie_ctrl_driver_api *api =
273 : (const struct pcie_ctrl_driver_api *)dev->api;
274 :
275 : return api->region_get_allocate_base(dev, bdf, mem, mem64, align, bar_base_addr);
276 : }
277 :
278 : /**
279 : * @brief Translate an endpoint Base Address Register bus-centric address into Physical address.
280 : *
281 : * When enumerating PCIe Endpoints, Type0 endpoints can require up to 6 memory zones
282 : * via the Base Address Registers from I/O or Memory types.
283 : *
284 : * The bus-centric address set in this BAR register is not necessarily accessible from the CPU,
285 : * thus must be translated by using the PCI Express Controller memory regions translation
286 : * ranges to permit mapping from the CPU.
287 : *
288 : * @param dev PCI Express Controller device pointer
289 : * @param bdf PCI(e) endpoint
290 : * @param mem True if the BAR is of memory type
291 : * @param mem64 True if the BAR is of 64bit memory type
292 : * @param bar_bus_addr bus-centric address written in the BAR register
293 : * @param bar_addr CPU-centric address translated from the bus-centric address
294 : * @return True if translation was possible, False if translation failed
295 : */
296 1 : static inline bool pcie_ctrl_region_translate(const struct device *dev, pcie_bdf_t bdf,
297 : bool mem, bool mem64, uintptr_t bar_bus_addr,
298 : uintptr_t *bar_addr)
299 : {
300 : const struct pcie_ctrl_driver_api *api =
301 : (const struct pcie_ctrl_driver_api *)dev->api;
302 :
303 : if (!api->region_translate) {
304 : *bar_addr = bar_bus_addr;
305 : return true;
306 : } else {
307 : return api->region_translate(dev, bdf, mem, mem64, bar_bus_addr, bar_addr);
308 : }
309 : }
310 :
311 : #ifdef CONFIG_PCIE_MSI
312 : static inline uint8_t pcie_ctrl_msi_device_setup(const struct device *dev, unsigned int priority,
313 : msi_vector_t *vectors, uint8_t n_vector)
314 : {
315 : const struct pcie_ctrl_driver_api *api =
316 : (const struct pcie_ctrl_driver_api *)dev->api;
317 :
318 : return api->msi_device_setup(dev, priority, vectors, n_vector);
319 : }
320 : #endif
321 :
322 : /** @brief Structure describing a device that supports the PCI Express Controller API
323 : */
324 1 : struct pcie_ctrl_config {
325 : #ifdef CONFIG_PCIE_MSI
326 : const struct device *msi_parent;
327 : #endif
328 : /* Configuration space physical address */
329 0 : uintptr_t cfg_addr;
330 : /* Configuration space physical size */
331 0 : size_t cfg_size;
332 : /* BAR regions translation ranges count */
333 0 : size_t ranges_count;
334 : /* BAR regions translation ranges table */
335 : struct {
336 : /* Flags as defined in the PCI Bus Binding to IEEE Std 1275-1994 */
337 0 : uint32_t flags;
338 : /* bus-centric offset from the start of the region */
339 0 : uintptr_t pcie_bus_addr;
340 : /* CPU-centric offset from the start of the region */
341 0 : uintptr_t host_map_addr;
342 : /* region size */
343 0 : size_t map_length;
344 0 : } ranges[];
345 : };
346 :
347 : /*
348 : * Fills the pcie_ctrl_config.ranges table from DT
349 : */
350 0 : #define PCIE_RANGE_FORMAT(node_id, idx) \
351 : { \
352 : .flags = DT_RANGES_CHILD_BUS_FLAGS_BY_IDX(node_id, idx), \
353 : .pcie_bus_addr = DT_RANGES_CHILD_BUS_ADDRESS_BY_IDX(node_id, idx), \
354 : .host_map_addr = DT_RANGES_PARENT_BUS_ADDRESS_BY_IDX(node_id, idx), \
355 : .map_length = DT_RANGES_LENGTH_BY_IDX(node_id, idx), \
356 : },
357 :
358 : #ifdef __cplusplus
359 : }
360 : #endif
361 :
362 : /**
363 : * @}
364 : */
365 :
366 : #endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_CONTROLLERS_H_ */
|