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