1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
5 #ifndef _RTE_PMD_CNXK_GPIO_H_
6 #define _RTE_PMD_CNXK_GPIO_H_
8 #include <rte_malloc.h>
9 #include <rte_memcpy.h>
10 #include <rte_rawdev.h>
13 * @file rte_pmd_cnxk_gpio.h
15 * Marvell GPIO PMD specific structures and interface
17 * This API allows applications to manage GPIOs in user space along with
18 * installing interrupt handlers for low latency signal processing.
25 /* Queue default configuration */
26 struct cnxk_gpio_queue_conf {
29 /** GPIO number as seen by hardware */
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,
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,
69 /** Available directions */
70 enum cnxk_gpio_pin_dir {
71 /** Set direction to input */
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,
82 * GPIO interrupt handler
85 * Zero-based GPIO number
87 * Cookie passed to interrupt handler
89 typedef void (*cnxk_gpio_irq_handler_t)(int gpio, void *data);
91 struct cnxk_gpio_irq {
92 /** Interrupt handler */
93 cnxk_gpio_irq_handler_t handler;
94 /** User data passed to irq handler */
96 /** CPU which will run irq handler */
100 struct cnxk_gpio_msg {
102 enum cnxk_gpio_msg_type type;
103 /** Message data passed to PMD or received from PMD */
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,
112 struct rte_rawdev_buf *bufs[1];
113 struct rte_rawdev_buf buf;
117 q = (void *)(size_t)gpio;
121 ret = rte_rawdev_enqueue_buffers(dev_id, bufs, RTE_DIM(bufs), q);
124 if (ret != RTE_DIM(bufs))
130 ret = rte_rawdev_dequeue_buffers(dev_id, bufs, RTE_DIM(bufs), q);
133 if (ret != RTE_DIM(bufs))
136 rte_memcpy(rsp, buf.buf_addr, rsp_size);
137 rte_free(buf.buf_addr);
143 * Set output to specific value
146 * The identifier of the device
148 * Zero-based GPIO number
150 * Value output will be set to. 0 represents low state while
154 * Returns 0 on success, negative error code otherwise
156 static __rte_always_inline int
157 rte_pmd_gpio_set_pin_value(uint16_t dev_id, int gpio, int val)
159 struct cnxk_gpio_msg msg = {
160 .type = CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE,
164 return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
168 * Select signal edge that triggers interrupt
171 * The identifier of the device
173 * Zero-based GPIO number
175 * Signal edge that triggers interrupt
178 * Returns 0 on success, negative error code otherwise
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)
184 struct cnxk_gpio_msg msg = {
185 .type = CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE,
189 return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
193 * Configure GPIO as input or output
196 * The identifier of the device
198 * Zero-based GPIO number
200 * Direction of the GPIO
203 * Returns 0 on success, negative error code otherwise
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)
208 struct cnxk_gpio_msg msg = {
209 .type = CNXK_GPIO_MSG_TYPE_SET_PIN_DIR,
213 return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
217 * Enable or disable inverted logic
219 * If GPIO is configured as output then writing 1 or 0 will result in setting
220 * output to respectively low or high
222 * If GPIO is configured as input then logic inversion applies to edges. Both
223 * current and future settings are affected
226 * The identifier of the device
228 * Zero-based GPIO number
230 * 0 to disable, 1 to enable inverted logic
233 * Returns 0 on success, negative error code otherwise
235 static __rte_always_inline int
236 rte_pmd_gpio_set_pin_active_low(uint16_t dev_id, int gpio, int val)
238 struct cnxk_gpio_msg msg = {
239 .type = CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW,
243 return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
250 * The identifier of the device
252 * Zero-based GPIO number
254 * Where to store read logical signal value i.e 0 or 1
257 * Returns 0 on success, negative error code otherwise
259 static __rte_always_inline int
260 rte_pmd_gpio_get_pin_value(uint16_t dev_id, int gpio, int *val)
262 struct cnxk_gpio_msg msg = {
263 .type = CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE,
266 return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, val, sizeof(*val));
273 * The identifier of the device
275 * Zero-based GPIO number
277 * Where to store edge
280 * Returns 0 on success, negative error code otherwise
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)
286 struct cnxk_gpio_msg msg = {
287 .type = CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE,
290 return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, edge, sizeof(*edge));
294 * Read GPIO direction
297 * The identifier of the device
299 * Zero-based GPIO number
301 * Where to store direction
304 * Returns 0 on success, negative error code otherwise
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)
309 struct cnxk_gpio_msg msg = {
310 .type = CNXK_GPIO_MSG_TYPE_GET_PIN_DIR,
313 return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, dir, sizeof(*dir));
317 * Read whether GPIO is active low
320 * The identifier of the device
322 * Zero-based GPIO number
324 * Where to store active low state
327 * Returns 0 on success, negative error code otherwise
329 static __rte_always_inline int
330 rte_pmd_gpio_get_pin_active_low(uint16_t dev_id, int gpio, int *val)
332 struct cnxk_gpio_msg msg = {
333 .type = CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW,
337 return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, val, sizeof(*val));
341 * Attach interrupt handler to GPIO
344 * The identifier of the device
346 * Zero-based GPIO number
348 * CPU which will be handling interrupt
350 * Interrupt handler to be executed
352 * Data to be passed to interrupt handler
355 * Returns 0 on success, negative error code otherwise
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)
361 struct cnxk_gpio_irq irq = {
366 struct cnxk_gpio_msg msg = {
367 .type = CNXK_GPIO_MSG_TYPE_REGISTER_IRQ,
371 return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
375 * Detach interrupt handler from GPIO
378 * The identifier of the device
380 * Zero-based GPIO number
383 * Returns 0 on success, negative error code otherwise
385 static __rte_always_inline int
386 rte_pmd_gpio_unregister_irq(uint16_t dev_id, int gpio)
388 struct cnxk_gpio_msg msg = {
389 .type = CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ,
393 return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
400 * The identifier of the device
402 * Zero-based GPIO number
404 * Edge that should trigger interrupt
407 * Returns 0 on success, negative error code otherwise
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)
413 return rte_pmd_gpio_set_pin_edge(dev_id, gpio, edge);
420 * The identifier of the device
422 * Zero-based GPIO number
425 * Returns 0 on success, negative error code otherwise
427 static __rte_always_inline int
428 rte_pmd_gpio_disable_interrupt(uint16_t dev_id, int gpio)
430 return rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_NONE);
437 #endif /* _RTE_PMD_CNXK_GPIO_H_ */