net/ena: make Tx completion timeout configurable
[dpdk.git] / drivers / raw / cnxk_gpio / rte_pmd_cnxk_gpio.h
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         q = (void *)(size_t)gpio;
118         buf.buf_addr = req;
119         bufs[0] = &buf;
120
121         ret = rte_rawdev_enqueue_buffers(dev_id, bufs, RTE_DIM(bufs), q);
122         if (ret < 0)
123                 return ret;
124         if (ret != RTE_DIM(bufs))
125                 return -EIO;
126
127         if (!rsp)
128                 return 0;
129
130         ret = rte_rawdev_dequeue_buffers(dev_id, bufs, RTE_DIM(bufs), q);
131         if (ret < 0)
132                 return ret;
133         if (ret != RTE_DIM(bufs))
134                 return -EIO;
135
136         rte_memcpy(rsp, buf.buf_addr, rsp_size);
137         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         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         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         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         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         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         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         struct cnxk_gpio_irq irq = {
362                 .handler = handler,
363                 .data = data,
364                 .cpu = cpu,
365         };
366         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         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         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         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_ */