Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #ifndef _RTE_PMD_CNXK_GPIO_H_
6 : : #define _RTE_PMD_CNXK_GPIO_H_
7 : :
8 : : #include <rte_malloc.h>
9 : : #include <rte_memcpy.h>
10 : : #include <rte_rawdev.h>
11 : :
12 : : /**
13 : : * @file rte_pmd_cnxk_gpio.h
14 : : *
15 : : * Marvell GPIO PMD specific structures and interface
16 : : *
17 : : * This API allows applications to manage GPIOs in user space along with
18 : : * installing interrupt handlers for low latency signal processing.
19 : : */
20 : :
21 : : #ifdef __cplusplus
22 : : extern "C" {
23 : : #endif
24 : :
25 : : /* Queue default configuration */
26 : : struct cnxk_gpio_queue_conf {
27 : : /** Queue size */
28 : : int size;
29 : : /** GPIO number as seen by hardware */
30 : : int gpio;
31 : : };
32 : :
33 : : /** Available message types */
34 : : enum cnxk_gpio_msg_type {
35 : : /** Type used to set output value */
36 : : CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE,
37 : : /** Type used to set edge */
38 : : CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE,
39 : : /** Type used to set direction */
40 : : CNXK_GPIO_MSG_TYPE_SET_PIN_DIR,
41 : : /** Type used to set inverted logic */
42 : : CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW,
43 : : /** Type used to read value */
44 : : CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE,
45 : : /** Type used to read edge */
46 : : CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE,
47 : : /** Type used to read direction */
48 : : CNXK_GPIO_MSG_TYPE_GET_PIN_DIR,
49 : : /** Type used to read inverted logic state */
50 : : CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW,
51 : : /** Type used to register interrupt handler */
52 : : CNXK_GPIO_MSG_TYPE_REGISTER_IRQ,
53 : : /** Type used to remove interrupt handler */
54 : : CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ,
55 : : };
56 : :
57 : : /** Available edges */
58 : : enum cnxk_gpio_pin_edge {
59 : : /** Set edge to none */
60 : : CNXK_GPIO_PIN_EDGE_NONE,
61 : : /** Set edge to falling */
62 : : CNXK_GPIO_PIN_EDGE_FALLING,
63 : : /** Set edge to rising */
64 : : CNXK_GPIO_PIN_EDGE_RISING,
65 : : /** Set edge to both rising and falling */
66 : : CNXK_GPIO_PIN_EDGE_BOTH,
67 : : };
68 : :
69 : : /** Available directions */
70 : : enum cnxk_gpio_pin_dir {
71 : : /** Set direction to input */
72 : : CNXK_GPIO_PIN_DIR_IN,
73 : : /** Set direction to output */
74 : : CNXK_GPIO_PIN_DIR_OUT,
75 : : /** Set direction to output and value to 1 */
76 : : CNXK_GPIO_PIN_DIR_HIGH,
77 : : /* Set direction to output and value to 0 */
78 : : CNXK_GPIO_PIN_DIR_LOW,
79 : : };
80 : :
81 : : /**
82 : : * GPIO interrupt handler
83 : : *
84 : : * @param gpio
85 : : * Zero-based GPIO number
86 : : * @param data
87 : : * Cookie passed to interrupt handler
88 : : */
89 : : typedef void (*cnxk_gpio_irq_handler_t)(int gpio, void *data);
90 : :
91 : : struct cnxk_gpio_irq {
92 : : /** Interrupt handler */
93 : : cnxk_gpio_irq_handler_t handler;
94 : : /** User data passed to irq handler */
95 : : void *data;
96 : : /** CPU which will run irq handler */
97 : : int cpu;
98 : : };
99 : :
100 : : struct cnxk_gpio_msg {
101 : : /** Message type */
102 : : enum cnxk_gpio_msg_type type;
103 : : /** Message data passed to PMD or received from PMD */
104 : : void *data;
105 : : };
106 : :
107 : : /** @internal helper routine for enqueuing/dequeuing messages */
108 : : static __rte_always_inline int
109 : : __rte_pmd_gpio_enq_deq(uint16_t dev_id, int gpio, void *req, void *rsp,
110 : : size_t rsp_size)
111 : : {
112 : : struct rte_rawdev_buf *bufs[1];
113 : : struct rte_rawdev_buf buf;
114 : : void *q;
115 : : int ret;
116 : :
117 : 0 : q = (void *)(size_t)gpio;
118 : 0 : buf.buf_addr = req;
119 : 0 : bufs[0] = &buf;
120 : :
121 : 0 : ret = rte_rawdev_enqueue_buffers(dev_id, bufs, RTE_DIM(bufs), q);
122 [ # # # # : 0 : if (ret < 0)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
123 : : return ret;
124 [ # # # # : 0 : if (ret != RTE_DIM(bufs))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
125 : : return -EIO;
126 : :
127 : : if (!rsp)
128 : : return 0;
129 : :
130 : 0 : ret = rte_rawdev_dequeue_buffers(dev_id, bufs, RTE_DIM(bufs), q);
131 [ # # # # : 0 : if (ret < 0)
# # ]
132 : : return ret;
133 [ # # # # : 0 : if (ret != RTE_DIM(bufs))
# # ]
134 : : return -EIO;
135 : :
136 [ # # # # : 0 : rte_memcpy(rsp, buf.buf_addr, rsp_size);
# # ]
137 : 0 : rte_free(buf.buf_addr);
138 : :
139 : : return 0;
140 : : }
141 : :
142 : : /**
143 : : * Set output to specific value
144 : : *
145 : : * @param dev_id
146 : : * The identifier of the device
147 : : * @param gpio
148 : : * Zero-based GPIO number
149 : : * @param val
150 : : * Value output will be set to. 0 represents low state while
151 : : * 1 high state
152 : : *
153 : : * @return
154 : : * Returns 0 on success, negative error code otherwise
155 : : */
156 : : static __rte_always_inline int
157 : : rte_pmd_gpio_set_pin_value(uint16_t dev_id, int gpio, int val)
158 : : {
159 : 0 : struct cnxk_gpio_msg msg = {
160 : : .type = CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE,
161 : : .data = &val,
162 : : };
163 : :
164 : : return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
165 : : }
166 : :
167 : : /**
168 : : * Select signal edge that triggers interrupt
169 : : *
170 : : * @param dev_id
171 : : * The identifier of the device
172 : : * @param gpio
173 : : * Zero-based GPIO number
174 : : * @param edge
175 : : * Signal edge that triggers interrupt
176 : : *
177 : : * @return
178 : : * Returns 0 on success, negative error code otherwise
179 : : */
180 : : static __rte_always_inline int
181 : : rte_pmd_gpio_set_pin_edge(uint16_t dev_id, int gpio,
182 : : enum cnxk_gpio_pin_edge edge)
183 : : {
184 : 0 : struct cnxk_gpio_msg msg = {
185 : : .type = CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE,
186 : : .data = &edge
187 : : };
188 : :
189 : : return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
190 : : }
191 : :
192 : : /**
193 : : * Configure GPIO as input or output
194 : : *
195 : : * @param dev_id
196 : : * The identifier of the device
197 : : * @param gpio
198 : : * Zero-based GPIO number
199 : : * @param dir
200 : : * Direction of the GPIO
201 : : *
202 : : * @return
203 : : * Returns 0 on success, negative error code otherwise
204 : : */
205 : : static __rte_always_inline int
206 : : rte_pmd_gpio_set_pin_dir(uint16_t dev_id, int gpio, enum cnxk_gpio_pin_dir dir)
207 : : {
208 : 0 : struct cnxk_gpio_msg msg = {
209 : : .type = CNXK_GPIO_MSG_TYPE_SET_PIN_DIR,
210 : : .data = &dir,
211 : : };
212 : :
213 : : return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
214 : : }
215 : :
216 : : /**
217 : : * Enable or disable inverted logic
218 : : *
219 : : * If GPIO is configured as output then writing 1 or 0 will result in setting
220 : : * output to respectively low or high
221 : : *
222 : : * If GPIO is configured as input then logic inversion applies to edges. Both
223 : : * current and future settings are affected
224 : : *
225 : : * @param dev_id
226 : : * The identifier of the device
227 : : * @param gpio
228 : : * Zero-based GPIO number
229 : : * @param val
230 : : * 0 to disable, 1 to enable inverted logic
231 : : *
232 : : * @return
233 : : * Returns 0 on success, negative error code otherwise
234 : : */
235 : : static __rte_always_inline int
236 : : rte_pmd_gpio_set_pin_active_low(uint16_t dev_id, int gpio, int val)
237 : : {
238 : 0 : struct cnxk_gpio_msg msg = {
239 : : .type = CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW,
240 : : .data = &val,
241 : : };
242 : :
243 : : return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
244 : : }
245 : :
246 : : /**
247 : : * Read GPIO value
248 : : *
249 : : * @param dev_id
250 : : * The identifier of the device
251 : : * @param gpio
252 : : * Zero-based GPIO number
253 : : * @param val
254 : : * Where to store read logical signal value i.e 0 or 1
255 : : *
256 : : * @return
257 : : * Returns 0 on success, negative error code otherwise
258 : : */
259 : : static __rte_always_inline int
260 : : rte_pmd_gpio_get_pin_value(uint16_t dev_id, int gpio, int *val)
261 : : {
262 : 0 : struct cnxk_gpio_msg msg = {
263 : : .type = CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE,
264 : : };
265 : :
266 : : return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, val, sizeof(*val));
267 : : }
268 : :
269 : : /**
270 : : * Read GPIO edge
271 : : *
272 : : * @param dev_id
273 : : * The identifier of the device
274 : : * @param gpio
275 : : * Zero-based GPIO number
276 : : * @param edge
277 : : * Where to store edge
278 : : *
279 : : * @return
280 : : * Returns 0 on success, negative error code otherwise
281 : : */
282 : : static __rte_always_inline int
283 : : rte_pmd_gpio_get_pin_edge(uint16_t dev_id, int gpio,
284 : : enum cnxk_gpio_pin_edge *edge)
285 : : {
286 : : struct cnxk_gpio_msg msg = {
287 : : .type = CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE,
288 : : };
289 : :
290 : : return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, edge, sizeof(*edge));
291 : : }
292 : :
293 : : /**
294 : : * Read GPIO direction
295 : : *
296 : : * @param dev_id
297 : : * The identifier of the device
298 : : * @param gpio
299 : : * Zero-based GPIO number
300 : : * @param dir
301 : : * Where to store direction
302 : : *
303 : : * @return
304 : : * Returns 0 on success, negative error code otherwise
305 : : */
306 : : static __rte_always_inline int
307 : : rte_pmd_gpio_get_pin_dir(uint16_t dev_id, int gpio, enum cnxk_gpio_pin_dir *dir)
308 : : {
309 : : struct cnxk_gpio_msg msg = {
310 : : .type = CNXK_GPIO_MSG_TYPE_GET_PIN_DIR,
311 : : };
312 : :
313 : : return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, dir, sizeof(*dir));
314 : : }
315 : :
316 : : /**
317 : : * Read whether GPIO is active low
318 : : *
319 : : * @param dev_id
320 : : * The identifier of the device
321 : : * @param gpio
322 : : * Zero-based GPIO number
323 : : * @param val
324 : : * Where to store active low state
325 : : *
326 : : * @return
327 : : * Returns 0 on success, negative error code otherwise
328 : : */
329 : : static __rte_always_inline int
330 : : rte_pmd_gpio_get_pin_active_low(uint16_t dev_id, int gpio, int *val)
331 : : {
332 : 0 : struct cnxk_gpio_msg msg = {
333 : : .type = CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW,
334 : : .data = &val,
335 : : };
336 : :
337 : : return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, val, sizeof(*val));
338 : : }
339 : :
340 : : /**
341 : : * Attach interrupt handler to GPIO
342 : : *
343 : : * @param dev_id
344 : : * The identifier of the device
345 : : * @param gpio
346 : : * Zero-based GPIO number
347 : : * @param cpu
348 : : * CPU which will be handling interrupt
349 : : * @param handler
350 : : * Interrupt handler to be executed
351 : : * @param data
352 : : * Data to be passed to interrupt handler
353 : : *
354 : : * @return
355 : : * Returns 0 on success, negative error code otherwise
356 : : */
357 : : static __rte_always_inline int
358 : : rte_pmd_gpio_register_irq(uint16_t dev_id, int gpio, int cpu,
359 : : cnxk_gpio_irq_handler_t handler, void *data)
360 : : {
361 : 0 : struct cnxk_gpio_irq irq = {
362 : : .handler = handler,
363 : : .data = data,
364 : : .cpu = cpu,
365 : : };
366 : 0 : struct cnxk_gpio_msg msg = {
367 : : .type = CNXK_GPIO_MSG_TYPE_REGISTER_IRQ,
368 : : .data = &irq,
369 : : };
370 : :
371 : : return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
372 : : }
373 : :
374 : : /**
375 : : * Detach interrupt handler from GPIO
376 : : *
377 : : * @param dev_id
378 : : * The identifier of the device
379 : : * @param gpio
380 : : * Zero-based GPIO number
381 : : *
382 : : * @return
383 : : * Returns 0 on success, negative error code otherwise
384 : : */
385 : : static __rte_always_inline int
386 : : rte_pmd_gpio_unregister_irq(uint16_t dev_id, int gpio)
387 : : {
388 : 0 : struct cnxk_gpio_msg msg = {
389 : : .type = CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ,
390 : : .data = &gpio,
391 : : };
392 : :
393 : : return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
394 : : }
395 : :
396 : : /**
397 : : * Enable interrupt
398 : : *
399 : : * @param dev_id
400 : : * The identifier of the device
401 : : * @param gpio
402 : : * Zero-based GPIO number
403 : : * @param edge
404 : : * Edge that should trigger interrupt
405 : : *
406 : : * @return
407 : : * Returns 0 on success, negative error code otherwise
408 : : */
409 : : static __rte_always_inline int
410 : : rte_pmd_gpio_enable_interrupt(uint16_t dev_id, int gpio,
411 : : enum cnxk_gpio_pin_edge edge)
412 : : {
413 : 0 : return rte_pmd_gpio_set_pin_edge(dev_id, gpio, edge);
414 : : }
415 : :
416 : : /**
417 : : * Disable interrupt
418 : : *
419 : : * @param dev_id
420 : : * The identifier of the device
421 : : * @param gpio
422 : : * Zero-based GPIO number
423 : : *
424 : : * @return
425 : : * Returns 0 on success, negative error code otherwise
426 : : */
427 : : static __rte_always_inline int
428 : : rte_pmd_gpio_disable_interrupt(uint16_t dev_id, int gpio)
429 : : {
430 : 0 : return rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_NONE);
431 : : }
432 : :
433 : : #ifdef __cplusplus
434 : : }
435 : : #endif
436 : :
437 : : #endif /* _RTE_PMD_CNXK_GPIO_H_ */
|