From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id A3DD0A034D;
	Wed,  5 Jan 2022 15:01:28 +0100 (CET)
Received: from [217.70.189.124] (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id C42D741176;
	Wed,  5 Jan 2022 15:00:44 +0100 (CET)
Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com
 [67.231.148.174])
 by mails.dpdk.org (Postfix) with ESMTP id A7D2E41159
 for <dev@dpdk.org>; Wed,  5 Jan 2022 15:00:43 +0100 (CET)
Received: from pps.filterd (m0045849.ppops.net [127.0.0.1])
 by mx0a-0016f401.pphosted.com (8.16.1.2/8.16.1.2) with ESMTP id 205CJ2Jg030859;
 Wed, 5 Jan 2022 06:00:42 -0800
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com;
 h=from : to : cc :
 subject : date : message-id : in-reply-to : references : mime-version :
 content-transfer-encoding : content-type; s=pfpt0220;
 bh=34fTv+m5IDJKfSsdMiXSMvBuhMMYF/IkRxd4k/xF3XI=;
 b=VT0/pyUKEi/AEw5qGmHOgMgnWO6kR0VxkG622/WiLqOkNCZW1hOntaF1hOKV2DHJTCZA
 oIq6YNcD8iLM5SB2EjHMpbHGLj6H9dxdnsIyDUsi59GQz9lNqorzhQCuVk123sAiMkG1
 hFrfjTQZVT7G9cjS532rDtoUXuKBoKOoYGHVukOev2ok0cZFeMwt3U0z6Ovan3HFOPpK
 2QHsN/U//pc8GtHMGWmNGw3q/QWW5li5I+fi3T4Ppuk0z7+ZXp2yFo+IZo1oTDph7s7l
 0mQ3kGc+XsFz2MBG9qlDaDQojg4tcFK+vJFkjBGE7LbKS6YWPlk4U7XGH7I3BQaV6TOG VA== 
Received: from dc5-exch01.marvell.com ([199.233.59.181])
 by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3dd214x13d-1
 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT);
 Wed, 05 Jan 2022 06:00:42 -0800
Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com
 (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.2;
 Wed, 5 Jan 2022 06:00:41 -0800
Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com
 (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.18 via Frontend
 Transport; Wed, 5 Jan 2022 06:00:41 -0800
Received: from localhost.localdomain (unknown [10.28.34.39])
 by maili.marvell.com (Postfix) with ESMTP id 95C513F7077;
 Wed,  5 Jan 2022 06:00:39 -0800 (PST)
From: Tomasz Duszynski <tduszynski@marvell.com>
To: <dev@dpdk.org>
CC: <thomas@monjalon.net>, <jerinj@marvell.com>, Tomasz Duszynski
 <tduszynski@marvell.com>
Subject: [PATCH v4 08/11] raw/cnxk_gpio: support standard GPIO operations
Date: Wed, 5 Jan 2022 15:00:17 +0100
Message-ID: <20220105140020.1615256-9-tduszynski@marvell.com>
X-Mailer: git-send-email 2.25.1
In-Reply-To: <20220105140020.1615256-1-tduszynski@marvell.com>
References: <20211213081732.2096334-1-tduszynski@marvell.com>
 <20220105140020.1615256-1-tduszynski@marvell.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Content-Type: text/plain
X-Proofpoint-GUID: X8rXAJCtDPQemEQrK1u7S-vxPo8OCujb
X-Proofpoint-ORIG-GUID: X8rXAJCtDPQemEQrK1u7S-vxPo8OCujb
X-Proofpoint-Virus-Version: vendor=baseguard
 engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513
 definitions=2022-01-05_03,2022-01-04_01,2021-12-02_01
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

Add support for standard GPIO operations i.e ones normally
provided by GPIO sysfs interface.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
 doc/guides/rawdevs/cnxk_gpio.rst          |  98 ++++++++
 drivers/raw/cnxk_gpio/cnxk_gpio.c         | 147 +++++++++++-
 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h | 279 +++++++++++++++++++++-
 3 files changed, 521 insertions(+), 3 deletions(-)

diff --git a/doc/guides/rawdevs/cnxk_gpio.rst b/doc/guides/rawdevs/cnxk_gpio.rst
index 868302d07f..f6c3c942c5 100644
--- a/doc/guides/rawdevs/cnxk_gpio.rst
+++ b/doc/guides/rawdevs/cnxk_gpio.rst
@@ -63,3 +63,101 @@ call barely exports GPIO to userspace.
 To perform actual data transfer use standard ``rte_rawdev_enqueue_buffers()``
 and ``rte_rawdev_dequeue_buffers()`` APIs. Not all messages produce sensible
 responses hence dequeueing is not always necessary.
+
+CNXK GPIO PMD
+-------------
+
+PMD accepts ``struct cnxk_gpio_msg`` messages which differ by type and payload.
+Message types along with description are listed below. As for the usage examples
+please refer to ``cnxk_gpio_selftest()``. There's a set of convenient wrappers
+available, one for each existing command.
+
+Set GPIO value
+~~~~~~~~~~~~~~
+
+Message is used to set output to low or high. This does not work for GPIOs
+configured as input.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE``.
+
+Payload must be an integer set to 0 (low) or 1 (high).
+
+Consider using ``rte_pmd_gpio_set_pin_value()`` wrapper.
+
+Set GPIO edge
+~~~~~~~~~~~~~
+
+Message is used to set edge that triggers interrupt.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE``.
+
+Payload must be `enum cnxk_gpio_pin_edge`.
+
+Consider using ``rte_pmd_gpio_set_pin_edge()`` wrapper.
+
+Set GPIO direction
+~~~~~~~~~~~~~~~~~~
+
+Message is used to change GPIO direction to either input or output.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_SET_PIN_DIR``.
+
+Payload must be `enum cnxk_gpio_pin_dir`.
+
+Consider using ``rte_pmd_gpio_set_pin_dir()`` wrapper.
+
+Set GPIO active low
+~~~~~~~~~~~~~~~~~~~
+
+Message is used to set whether pin is active low.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW``.
+
+Payload must be an integer set to 0 or 1. The latter activates inversion.
+
+Consider using ``rte_pmd_gpio_set_pin_active_low()`` wrapper.
+
+Get GPIO value
+~~~~~~~~~~~~~~
+
+Message is used to read GPIO value. Value can be 0 (low) or 1 (high).
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE``.
+
+Payload contains integer set to either 0 or 1.
+
+Consider using ``rte_pmd_gpio_get_pin_value()`` wrapper.
+
+Get GPIO edge
+~~~~~~~~~~~~~
+
+Message is used to read GPIO edge.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE``.
+
+Payload contains `enum cnxk_gpio_pin_edge`.
+
+Consider using ``rte_pmd_gpio_get_pin_edge()`` wrapper.
+
+Get GPIO direction
+~~~~~~~~~~~~~~~~~~
+
+Message is used to read GPIO direction.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_GET_PIN_DIR``.
+
+Payload contains `enum cnxk_gpio_pin_dir`.
+
+Consider using ``rte_pmd_gpio_get_pin_dir()`` wrapper.
+
+Get GPIO active low
+~~~~~~~~~~~~~~~~~~~
+
+Message is used check whether inverted logic is active.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW``.
+
+Payload contains an integer set to 0 or 1. The latter means inverted logic
+is turned on.
+
+Consider using ``rte_pmd_gpio_get_pin_active_low()`` wrapper.
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c
index 909fa9d390..e24d8c1b6e 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.c
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c
@@ -267,14 +267,159 @@ cnxk_gpio_queue_count(struct rte_rawdev *dev)
 	return gpiochip->num_gpios;
 }
 
+static const struct {
+	enum cnxk_gpio_pin_edge edge;
+	const char *name;
+} cnxk_gpio_edge_name[] = {
+	{ CNXK_GPIO_PIN_EDGE_NONE, "none" },
+	{ CNXK_GPIO_PIN_EDGE_FALLING, "falling" },
+	{ CNXK_GPIO_PIN_EDGE_RISING, "rising" },
+	{ CNXK_GPIO_PIN_EDGE_BOTH, "both" },
+};
+
+static const char *
+cnxk_gpio_edge_to_name(enum cnxk_gpio_pin_edge edge)
+{
+	unsigned int i;
+
+	for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
+		if (cnxk_gpio_edge_name[i].edge == edge)
+			return cnxk_gpio_edge_name[i].name;
+	}
+
+	return NULL;
+}
+
+static enum cnxk_gpio_pin_edge
+cnxk_gpio_name_to_edge(const char *name)
+{
+	unsigned int i;
+
+	for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
+		if (!strcmp(cnxk_gpio_edge_name[i].name, name))
+			break;
+	}
+
+	return cnxk_gpio_edge_name[i].edge;
+}
+
+static const struct {
+	enum cnxk_gpio_pin_dir dir;
+	const char *name;
+} cnxk_gpio_dir_name[] = {
+	{ CNXK_GPIO_PIN_DIR_IN, "in" },
+	{ CNXK_GPIO_PIN_DIR_OUT, "out" },
+	{ CNXK_GPIO_PIN_DIR_HIGH, "high" },
+	{ CNXK_GPIO_PIN_DIR_LOW, "low" },
+};
+
+static const char *
+cnxk_gpio_dir_to_name(enum cnxk_gpio_pin_dir dir)
+{
+	unsigned int i;
+
+	for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
+		if (cnxk_gpio_dir_name[i].dir == dir)
+			return cnxk_gpio_dir_name[i].name;
+	}
+
+	return NULL;
+}
+
+static enum cnxk_gpio_pin_dir
+cnxk_gpio_name_to_dir(const char *name)
+{
+	unsigned int i;
+
+	for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
+		if (!strcmp(cnxk_gpio_dir_name[i].name, name))
+			break;
+	}
+
+	return cnxk_gpio_dir_name[i].dir;
+}
+
 static int
 cnxk_gpio_process_buf(struct cnxk_gpio *gpio, struct rte_rawdev_buf *rbuf)
 {
 	struct cnxk_gpio_msg *msg = rbuf->buf_addr;
+	enum cnxk_gpio_pin_edge edge;
+	enum cnxk_gpio_pin_dir dir;
+	char buf[CNXK_GPIO_BUFSZ];
 	void *rsp = NULL;
-	int ret;
+	int ret, val, n;
+
+	n = snprintf(buf, sizeof(buf), "%s/gpio%d", CNXK_GPIO_CLASS_PATH,
+		     gpio->num);
 
 	switch (msg->type) {
+	case CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE:
+		snprintf(buf + n, sizeof(buf) - n, "/value");
+		ret = cnxk_gpio_write_attr_int(buf, !!*(int *)msg->data);
+		break;
+	case CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE:
+		snprintf(buf + n, sizeof(buf) - n, "/edge");
+		edge = *(enum cnxk_gpio_pin_edge *)msg->data;
+		ret = cnxk_gpio_write_attr(buf, cnxk_gpio_edge_to_name(edge));
+		break;
+	case CNXK_GPIO_MSG_TYPE_SET_PIN_DIR:
+		snprintf(buf + n, sizeof(buf) - n, "/direction");
+		dir = *(enum cnxk_gpio_pin_dir *)msg->data;
+		ret = cnxk_gpio_write_attr(buf, cnxk_gpio_dir_to_name(dir));
+		break;
+	case CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW:
+		snprintf(buf + n, sizeof(buf) - n, "/active_low");
+		val = *(int *)msg->data;
+		ret = cnxk_gpio_write_attr_int(buf, val);
+		break;
+	case CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE:
+		snprintf(buf + n, sizeof(buf) - n, "/value");
+		ret = cnxk_gpio_read_attr_int(buf, &val);
+		if (ret)
+			break;
+
+		rsp = rte_zmalloc(NULL, sizeof(int), 0);
+		if (!rsp)
+			return -ENOMEM;
+
+		*(int *)rsp = val;
+		break;
+	case CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE:
+		snprintf(buf + n, sizeof(buf) - n, "/edge");
+		ret = cnxk_gpio_read_attr(buf, buf);
+		if (ret)
+			break;
+
+		rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_edge), 0);
+		if (!rsp)
+			return -ENOMEM;
+
+		*(enum cnxk_gpio_pin_edge *)rsp = cnxk_gpio_name_to_edge(buf);
+		break;
+	case CNXK_GPIO_MSG_TYPE_GET_PIN_DIR:
+		snprintf(buf + n, sizeof(buf) - n, "/direction");
+		ret = cnxk_gpio_read_attr(buf, buf);
+		if (ret)
+			break;
+
+		rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_dir), 0);
+		if (!rsp)
+			return -ENOMEM;
+
+		*(enum cnxk_gpio_pin_dir *)rsp = cnxk_gpio_name_to_dir(buf);
+		break;
+	case CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW:
+		snprintf(buf + n, sizeof(buf) - n, "/active_low");
+		ret = cnxk_gpio_read_attr_int(buf, &val);
+		if (ret)
+			break;
+
+		rsp = rte_zmalloc(NULL, sizeof(int), 0);
+		if (!rsp)
+			return -ENOMEM;
+
+		*(int *)rsp = val;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h b/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
index c71065e10c..7c3dc225ca 100644
--- a/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
+++ b/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
@@ -5,6 +5,10 @@
 #ifndef _RTE_PMD_CNXK_GPIO_H_
 #define _RTE_PMD_CNXK_GPIO_H_
 
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_rawdev.h>
+
 /**
  * @file rte_pmd_cnxk_gpio.h
  *
@@ -20,8 +24,46 @@ extern "C" {
 
 /** Available message types */
 enum cnxk_gpio_msg_type {
-	/** Invalid message type */
-	CNXK_GPIO_MSG_TYPE_INVALID,
+	/** Type used to set output value */
+	CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE,
+	/** Type used to set edge */
+	CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE,
+	/** Type used to set direction */
+	CNXK_GPIO_MSG_TYPE_SET_PIN_DIR,
+	/** Type used to set inverted logic */
+	CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW,
+	/** Type used to read value */
+	CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE,
+	/** Type used to read edge */
+	CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE,
+	/** Type used to read direction */
+	CNXK_GPIO_MSG_TYPE_GET_PIN_DIR,
+	/** Type used to read inverted logic state */
+	CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW,
+};
+
+/** Available edges */
+enum cnxk_gpio_pin_edge {
+	/** Set edge to none */
+	CNXK_GPIO_PIN_EDGE_NONE,
+	/** Set edge to falling */
+	CNXK_GPIO_PIN_EDGE_FALLING,
+	/** Set edge to rising */
+	CNXK_GPIO_PIN_EDGE_RISING,
+	/** Set edge to both rising and falling */
+	CNXK_GPIO_PIN_EDGE_BOTH,
+};
+
+/** Available directions */
+enum cnxk_gpio_pin_dir {
+	/** Set direction to input */
+	CNXK_GPIO_PIN_DIR_IN,
+	/** Set direction to output */
+	CNXK_GPIO_PIN_DIR_OUT,
+	/** Set direction to output and value to 1 */
+	CNXK_GPIO_PIN_DIR_HIGH,
+	/* Set direction to output and value to 0 */
+	CNXK_GPIO_PIN_DIR_LOW,
 };
 
 struct cnxk_gpio_msg {
@@ -31,6 +73,239 @@ struct cnxk_gpio_msg {
 	void *data;
 };
 
+/** @internal helper routine for enqueuing/dequeuing messages */
+static __rte_always_inline int
+__rte_pmd_gpio_enq_deq(uint16_t dev_id, int gpio, void *req, void *rsp,
+		       size_t rsp_size)
+{
+	struct rte_rawdev_buf *bufs[1];
+	struct rte_rawdev_buf buf;
+	void *q;
+	int ret;
+
+	q = (void *)(size_t)gpio;
+	buf.buf_addr = req;
+	bufs[0] = &buf;
+
+	ret = rte_rawdev_enqueue_buffers(dev_id, bufs, RTE_DIM(bufs), q);
+	if (ret < 0)
+		return ret;
+	if (ret != RTE_DIM(bufs))
+		return -EIO;
+
+	if (!rsp)
+		return 0;
+
+	ret = rte_rawdev_dequeue_buffers(dev_id, bufs, RTE_DIM(bufs), q);
+	if (ret < 0)
+		return ret;
+	if (ret != RTE_DIM(bufs))
+		return -EIO;
+
+	rte_memcpy(rsp, buf.buf_addr, rsp_size);
+	rte_free(buf.buf_addr);
+
+	return 0;
+}
+
+/**
+ * Set output to specific value
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param val
+ *   Value output will be set to. 0 represents low state while
+ *   1 high state
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_set_pin_value(uint16_t dev_id, int gpio, int val)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE,
+		.data = &val,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
+}
+
+/**
+ * Select signal edge that triggers interrupt
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param edge
+ *   Signal edge that triggers interrupt
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_set_pin_edge(uint16_t dev_id, int gpio,
+			  enum cnxk_gpio_pin_edge edge)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE,
+		.data = &edge
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
+}
+
+/**
+ * Configure GPIO as input or output
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param dir
+ *   Direction of the GPIO
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_set_pin_dir(uint16_t dev_id, int gpio, enum cnxk_gpio_pin_dir dir)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_SET_PIN_DIR,
+		.data = &dir,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
+}
+
+/**
+ * Enable or disable inverted logic
+ *
+ * If GPIO is configured as output then writing 1 or 0 will result in setting
+ * output to respectively low or high
+ *
+ * If GPIO is configured as input then logic inversion applies to edges. Both
+ * current and future settings are affected
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param val
+ *   0 to disable, 1 to enable inverted logic
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_set_pin_active_low(uint16_t dev_id, int gpio, int val)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW,
+		.data = &val,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
+}
+
+/**
+ * Read GPIO value
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param val
+ *   Where to store read logical signal value i.e 0 or 1
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_get_pin_value(uint16_t dev_id, int gpio, int *val)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, val, sizeof(*val));
+}
+
+/**
+ * Read GPIO edge
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param edge
+ *   Where to store edge
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_get_pin_edge(uint16_t dev_id, int gpio,
+			  enum cnxk_gpio_pin_edge *edge)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, edge, sizeof(*edge));
+}
+
+/**
+ * Read GPIO direction
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param dir
+ *   Where to store direction
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_get_pin_dir(uint16_t dev_id, int gpio, enum cnxk_gpio_pin_dir *dir)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_GET_PIN_DIR,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, dir, sizeof(*dir));
+}
+
+/**
+ * Read whether GPIO is active low
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param val
+ *   Where to store active low state
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_get_pin_active_low(uint16_t dev_id, int gpio, int *val)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW,
+		.data = &val,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, val, sizeof(*val));
+}
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.25.1