Line data Source code
1 1 : /**
2 : * @file
3 : *
4 : * @brief Public APIs for the PCIe EP drivers.
5 : */
6 :
7 : /*
8 : * SPDX-License-Identifier: Apache-2.0
9 : *
10 : * Copyright 2020 Broadcom
11 : *
12 : */
13 : #ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_EP_H_
14 : #define ZEPHYR_INCLUDE_DRIVERS_PCIE_EP_H_
15 :
16 : #include <zephyr/device.h>
17 : #include <zephyr/init.h>
18 : #include <zephyr/kernel.h>
19 : #include <stdint.h>
20 :
21 0 : enum pcie_ob_mem_type {
22 : PCIE_OB_ANYMEM, /**< PCIe OB window within any address range */
23 : PCIE_OB_LOWMEM, /**< PCIe OB window within 32-bit address range */
24 : PCIE_OB_HIGHMEM, /**< PCIe OB window above 32-bit address range */
25 : };
26 :
27 0 : enum pci_ep_irq_type {
28 : PCIE_EP_IRQ_LEGACY, /**< Raise Legacy interrupt */
29 : PCIE_EP_IRQ_MSI, /**< Raise MSI interrupt */
30 : PCIE_EP_IRQ_MSIX, /**< Raise MSIX interrupt */
31 : };
32 :
33 0 : enum xfer_direction {
34 : HOST_TO_DEVICE, /**< Read from Host */
35 : DEVICE_TO_HOST, /**< Write to Host */
36 : };
37 :
38 0 : enum pcie_reset {
39 : PCIE_PERST, /**< Cold reset */
40 : PCIE_PERST_INB, /**< Inband hot reset */
41 : PCIE_FLR, /**< Functional Level Reset */
42 : PCIE_RESET_MAX
43 : };
44 :
45 : /**
46 : * @typedef pcie_ep_reset_callback_t
47 : * @brief Callback API for PCIe reset interrupts
48 : *
49 : * These callbacks execute in interrupt context. Therefore, use only
50 : * interrupt-safe APIS. Registration of callbacks is done via
51 : * @a pcie_ep_register_reset_cb
52 : *
53 : * @param arg Pointer provided at registration time, later to be
54 : * passed back as argument to callback function
55 : */
56 :
57 1 : typedef void (*pcie_ep_reset_callback_t)(void *arg);
58 :
59 0 : __subsystem struct pcie_ep_driver_api {
60 0 : int (*conf_read)(const struct device *dev, uint32_t offset,
61 : uint32_t *data);
62 0 : void (*conf_write)(const struct device *dev, uint32_t offset,
63 : uint32_t data);
64 0 : int (*map_addr)(const struct device *dev, uint64_t pcie_addr,
65 : uint64_t *mapped_addr, uint32_t size,
66 : enum pcie_ob_mem_type ob_mem_type);
67 0 : void (*unmap_addr)(const struct device *dev, uint64_t mapped_addr);
68 0 : int (*raise_irq)(const struct device *dev,
69 : enum pci_ep_irq_type irq_type,
70 : uint32_t irq_num);
71 0 : int (*register_reset_cb)(const struct device *dev,
72 : enum pcie_reset reset,
73 : pcie_ep_reset_callback_t cb, void *arg);
74 0 : int (*dma_xfer)(const struct device *dev, uint64_t mapped_addr,
75 : uintptr_t local_addr, uint32_t size,
76 : enum xfer_direction dir);
77 : };
78 :
79 : /**
80 : * @brief Read PCIe EP configuration space
81 : *
82 : * @details This API reads EP's own configuration space
83 : *
84 : * @param dev Pointer to the device structure for the driver instance
85 : * @param offset Offset within configuration space
86 : * @param data Pointer to data read from the offset
87 : *
88 : * @return 0 if successful, negative errno code if failure.
89 : */
90 :
91 1 : static inline int pcie_ep_conf_read(const struct device *dev,
92 : uint32_t offset, uint32_t *data)
93 : {
94 : const struct pcie_ep_driver_api *api =
95 : (const struct pcie_ep_driver_api *)dev->api;
96 :
97 : return api->conf_read(dev, offset, data);
98 : }
99 :
100 : /**
101 : * @brief Write PCIe EP configuration space
102 : *
103 : * @details This API writes EP's own configuration space
104 : *
105 : * @param dev Pointer to the device structure for the driver instance
106 : * @param offset Offset within configuration space
107 : * @param data Data to be written at the offset
108 : */
109 :
110 1 : static inline void pcie_ep_conf_write(const struct device *dev,
111 : uint32_t offset, uint32_t data)
112 : {
113 : const struct pcie_ep_driver_api *api =
114 : (const struct pcie_ep_driver_api *)dev->api;
115 :
116 : api->conf_write(dev, offset, data);
117 : }
118 :
119 : /**
120 : * @brief Map a host memory buffer to PCIe outbound region
121 : *
122 : * @details This API maps a host memory buffer to PCIe outbound region,
123 : * It is left to EP driver to manage multiple mappings through
124 : * multiple PCIe outbound regions if supported by SoC
125 : *
126 : * @param dev Pointer to the device structure for the driver instance
127 : * @param pcie_addr Host memory buffer address to be mapped
128 : * @param mapped_addr Mapped PCIe outbound region address
129 : * @param size Host memory buffer size (bytes)
130 : * @param ob_mem_type Hint if lowmem/highmem outbound region has to be used,
131 : * this is useful in cases where bus master cannot generate
132 : * more than 32-bit address; it becomes essential to use
133 : * lowmem outbound region
134 : *
135 : * @return Mapped size : If mapped size is less than requested size,
136 : * then requester has to call the same API again to map
137 : * the unmapped host buffer after data transfer is done with
138 : * mapped size. This situation may arise because of the
139 : * mapping alignment requirements.
140 : *
141 : * @return Negative errno code if failure.
142 : */
143 :
144 1 : static inline int pcie_ep_map_addr(const struct device *dev,
145 : uint64_t pcie_addr,
146 : uint64_t *mapped_addr, uint32_t size,
147 : enum pcie_ob_mem_type ob_mem_type)
148 : {
149 : const struct pcie_ep_driver_api *api =
150 : (const struct pcie_ep_driver_api *)dev->api;
151 :
152 : return api->map_addr(dev, pcie_addr, mapped_addr, size, ob_mem_type);
153 : }
154 :
155 : /**
156 : * @brief Remove mapping to PCIe outbound region
157 : *
158 : * @details This API removes mapping to PCIe outbound region.
159 : * Mapped PCIe outbound region address is given as argument
160 : * to figure out the outbound region to be unmapped
161 : *
162 : * @param dev Pointer to the device structure for the driver instance
163 : * @param mapped_addr PCIe outbound region address
164 : */
165 :
166 1 : static inline void pcie_ep_unmap_addr(const struct device *dev,
167 : uint64_t mapped_addr)
168 : {
169 : const struct pcie_ep_driver_api *api =
170 : (const struct pcie_ep_driver_api *)dev->api;
171 :
172 : api->unmap_addr(dev, mapped_addr);
173 : }
174 :
175 : /**
176 : * @brief Raise interrupt to Host
177 : *
178 : * @details This API raises interrupt to Host
179 : *
180 : * @param dev Pointer to the device structure for the driver instance
181 : * @param irq_type Type of Interrupt be raised (legacy, MSI or MSI-X)
182 : * @param irq_num MSI or MSI-X interrupt number
183 : *
184 : * @return 0 if successful, negative errno code if failure.
185 : */
186 :
187 1 : static inline int pcie_ep_raise_irq(const struct device *dev,
188 : enum pci_ep_irq_type irq_type,
189 : uint32_t irq_num)
190 : {
191 : const struct pcie_ep_driver_api *api =
192 : (const struct pcie_ep_driver_api *)dev->api;
193 : return api->raise_irq(dev, irq_type, irq_num);
194 : }
195 :
196 : /**
197 : * @brief Register callback function for reset interrupts
198 : *
199 : * @details If reset interrupts are handled by device, this API can be
200 : * used to register callback function, which will be
201 : * executed part of corresponding PCIe reset handler
202 : *
203 : * @param dev Pointer to the device structure for the driver instance
204 : * @param reset Reset interrupt type
205 : * @param cb Callback function being registered
206 : * @param arg Argument to be passed back to callback function
207 : *
208 : * @return 0 if successful, negative errno code if failure.
209 : */
210 :
211 1 : static inline int pcie_ep_register_reset_cb(const struct device *dev,
212 : enum pcie_reset reset,
213 : pcie_ep_reset_callback_t cb,
214 : void *arg)
215 : {
216 : const struct pcie_ep_driver_api *api =
217 : (const struct pcie_ep_driver_api *)dev->api;
218 :
219 : if (api->register_reset_cb) {
220 : return api->register_reset_cb(dev, reset, cb, arg);
221 : }
222 :
223 : return -ENOTSUP;
224 : }
225 :
226 : /**
227 : * @brief Data transfer between mapped Host memory and device memory with
228 : * "System DMA". The term "System DMA" is used to clarify that we
229 : * are not talking about dedicated "PCIe DMA"; rather the one
230 : * which does not understand PCIe address directly, and
231 : * uses the mapped Host memory.
232 : *
233 : * @details If DMA controller is available in the EP device, this API can be
234 : * used to achieve data transfer between mapped Host memory,
235 : * i.e. outbound memory and EP device's local memory with DMA
236 : *
237 : * @param dev Pointer to the device structure for the driver instance
238 : * @param mapped_addr Mapped Host memory address
239 : * @param local_addr Device memory address
240 : * @param size DMA transfer length (bytes)
241 : * @param dir Direction of DMA transfer
242 : *
243 : * @return 0 if successful, negative errno code if failure.
244 : */
245 :
246 1 : static inline int pcie_ep_dma_xfer(const struct device *dev,
247 : uint64_t mapped_addr,
248 : uintptr_t local_addr, uint32_t size,
249 : const enum xfer_direction dir)
250 : {
251 : const struct pcie_ep_driver_api *api =
252 : (const struct pcie_ep_driver_api *)dev->api;
253 :
254 : if (api->dma_xfer) {
255 : return api->dma_xfer(dev, mapped_addr, local_addr, size, dir);
256 : }
257 :
258 : return -ENOTSUP;
259 : }
260 :
261 : /**
262 : * @brief Data transfer using memcpy
263 : *
264 : * @details Helper API to achieve data transfer with memcpy
265 : * through PCIe outbound memory
266 : *
267 : * @param dev Pointer to the device structure for the driver instance
268 : * @param pcie_addr Host memory buffer address
269 : * @param local_addr Local memory buffer address
270 : * @param size Data transfer size (bytes)
271 : * @param ob_mem_type Hint if lowmem/highmem outbound region has to be used
272 : * (PCIE_OB_LOWMEM / PCIE_OB_HIGHMEM / PCIE_OB_ANYMEM),
273 : * should be PCIE_OB_LOWMEM if bus master cannot generate
274 : * more than 32-bit address
275 : * @param dir Data transfer direction (HOST_TO_DEVICE / DEVICE_TO_HOST)
276 : *
277 : * @return 0 if successful, negative errno code if failure.
278 : */
279 1 : int pcie_ep_xfer_data_memcpy(const struct device *dev, uint64_t pcie_addr,
280 : uintptr_t *local_addr, uint32_t size,
281 : enum pcie_ob_mem_type ob_mem_type,
282 : enum xfer_direction dir);
283 :
284 : /**
285 : * @brief Data transfer using system DMA
286 : *
287 : * @details Helper API to achieve data transfer with system DMA through PCIe
288 : * outbound memory, this API is based off pcie_ep_xfer_data_memcpy,
289 : * here we use "system dma" instead of memcpy
290 : *
291 : * @param dev Pointer to the device structure for the driver instance
292 : * @param pcie_addr Host memory buffer address
293 : * @param local_addr Local memory buffer address
294 : * @param size Data transfer size (bytes)
295 : * @param ob_mem_type Hint if lowmem/highmem outbound region has to be used
296 : * (PCIE_OB_LOWMEM / PCIE_OB_HIGHMEM / PCIE_OB_ANYMEM)
297 : * @param dir Data transfer direction (HOST_TO_DEVICE / DEVICE_TO_HOST)
298 : *
299 : * @return 0 if successful, negative errno code if failure.
300 : */
301 1 : int pcie_ep_xfer_data_dma(const struct device *dev, uint64_t pcie_addr,
302 : uintptr_t *local_addr, uint32_t size,
303 : enum pcie_ob_mem_type ob_mem_type,
304 : enum xfer_direction dir);
305 :
306 : #endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_EP_H_ */
|