[PATCH v1 25/31] serial: 8250_mxpcie: add basic GPIO helper functions

Crescent Hsieh posted 31 patches 1 day, 11 hours ago
[PATCH v1 25/31] serial: 8250_mxpcie: add basic GPIO helper functions
Posted by Crescent Hsieh 1 day, 11 hours ago
Introduce a set of helper functions for accessing the on-board GPIO
registers on Moxa PCIe serial devices. These cover:

- Initializing all pins as outputs
- Setting the direction of individual pins
- Setting or clearing an output pin
- Bulk set/get operations on OUTPUT and DIRECTION registers

These functions do not change any existing behavior yet. They are added
as a preparation step for follow-up patches that will make use of the
GPIOs to control board-specific signals.

Signed-off-by: Crescent Hsieh <crescentcy.hsieh@moxa.com>
---
 drivers/tty/serial/8250/8250_mxpcie.c | 91 +++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_mxpcie.c b/drivers/tty/serial/8250/8250_mxpcie.c
index a0deb464a318..6e727b77c105 100644
--- a/drivers/tty/serial/8250/8250_mxpcie.c
+++ b/drivers/tty/serial/8250/8250_mxpcie.c
@@ -79,11 +79,18 @@
 #define MOXA_PUART_RX_FIFO_MEM	0x100	/* Memory Space to Rx FIFO Data Register */
 #define MOXA_PUART_TX_FIFO_MEM	0x100	/* Memory Space to Tx FIFO Data Register */
 
+/* GPIO */
 #define MOXA_GPIO_DIRECTION	0x09
 #define MOXA_GPIO_OUTPUT	0x0A
 
 #define MOXA_GPIO_PIN2	BIT(2)
 
+#define MOXA_GPIO_STATE_INPUT	0
+#define MOXA_GPIO_STATE_OUTPUT	1
+
+#define MOXA_GPIO_LOW	0
+#define MOXA_GPIO_HIGH	1
+
 #define MOXA_UIR_OFFSET		0x04
 #define MOXA_UIR_RS232		0x00
 #define MOXA_UIR_RS422		0x01
@@ -120,6 +127,90 @@ static const struct serial_rs485 mxpcie8250_rs485_supported = {
 	.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX | SER_RS485_MODE_RS422,
 };
 
+/**
+ * mxpcie8250_gpio_init() - GPIO initialization routine
+ * @iobar_addr:	The base address of the GPIO I/O region
+ *
+ * Initializes the GPIO direction. After calling this function, all GPIO
+ * pins will be set to output.
+ */
+static void mxpcie8250_gpio_init(resource_size_t iobar_addr)
+{
+	/* Initialize all the GPIO pins into output state */
+	outb(0xff, iobar_addr + MOXA_GPIO_DIRECTION);
+}
+
+/**
+ * mxpcie8250_gpio_set_direction() - Set GPIO pin direction
+ * @iobar_addr:	The base address of the GPIO I/O region
+ * @pin:	The target GPIO pin (MOXA_GPIO_PIN0 to MOXA_GPIO_PIN7)
+ * @direction:	Desired direction (MOXA_GPIO_STATE_INPUT or MOXA_GPIO_STATE_OUTPUT)
+ *
+ * Sets the direction of the specified GPIO pin. This function should be called
+ * before performing GPIO set or get operations.
+ */
+static void mxpcie8250_gpio_set_direction(resource_size_t iobar_addr, int pin, int direction)
+{
+	u8 cval;
+
+	cval = inb(iobar_addr + MOXA_GPIO_DIRECTION);
+
+	if (direction == MOXA_GPIO_STATE_INPUT)
+		cval &= ~pin;
+	else
+		cval |= pin;
+
+	outb(cval, iobar_addr + MOXA_GPIO_DIRECTION);
+}
+
+/**
+ * mxpcie8250_gpio_set() - Set GPIO output state
+ * @iobar_addr:	The base address of the GPIO I/O region
+ * @pin:	The target GPIO pin (MOXA_GPIO_PIN0 to MOXA_GPIO_PIN7)
+ * @state:	Desired output state (MOXA_GPIO_HIGH or MOXA_GPIO_LOW)
+ *
+ * Sets the output state of the specified GPIO pin.
+ */
+static void mxpcie8250_gpio_set(resource_size_t iobar_addr, int pin, int state)
+{
+	u8 cval;
+
+	cval = inb(iobar_addr + MOXA_GPIO_OUTPUT);
+
+	if (state == MOXA_GPIO_HIGH)
+		cval |= pin;
+	else
+		cval &= ~pin;
+
+	outb(cval, iobar_addr + MOXA_GPIO_OUTPUT);
+}
+
+/**
+ * mxpcie8250_gpio_set_all() - Set all GPIO output/direction pins at once
+ * @iobar_addr:	The base address of the GPIO I/O region
+ * @data:	The data to set for all pins
+ * @offset:	Offset of the GPIO register (MOXA_GPIO_OUTPUT or MOXA_GPIO_DIRECTION)
+ *
+ * Sets the output state or direction of all GPIO pins at once.
+ */
+static void mxpcie8250_gpio_set_all(resource_size_t iobar_addr, u8 data, u8 offset)
+{
+	outb(data, iobar_addr + offset);
+}
+
+/**
+ * mxpcie8250_gpio_get_all() - Get all GPIO input/output pins state at once
+ * @iobar_addr:	The base address of the GPIO I/O region
+ * @data:	The buffer to store the states of all pins
+ * @offset:	Offset of the GPIO register (MOXA_GPIO_INPUT or MOXA_GPIO_OUTPUT)
+ *
+ * Gets the input or output state of all GPIO pins at once.
+ */
+static void mxpcie8250_gpio_get_all(resource_size_t iobar_addr, u8 *data, u8 offset)
+{
+	*data = inb(iobar_addr + offset);
+}
+
 static bool mxpcie8250_is_mini_pcie(unsigned short device)
 {
 	if (device == PCI_DEVICE_ID_MOXA_CP102N ||
-- 
2.45.2
Re: [PATCH v1 25/31] serial: 8250_mxpcie: add basic GPIO helper functions
Posted by Andy Shevchenko 19 hours ago
On Sun, Nov 30, 2025 at 12:45 PM Crescent Hsieh
<crescentcy.hsieh@moxa.com> wrote:
>
> Introduce a set of helper functions for accessing the on-board GPIO
> registers on Moxa PCIe serial devices. These cover:
>
> - Initializing all pins as outputs
> - Setting the direction of individual pins
> - Setting or clearing an output pin
> - Bulk set/get operations on OUTPUT and DIRECTION registers

> These functions do not change any existing behavior yet. They are added
> as a preparation step for follow-up patches that will make use of the
> GPIOs to control board-specific signals.

Then do not add them. We do not add the code without users. It might
be better for review (or worse ;-) but at the end of the day it needs
to be squashed with the user.

...

> +/**
> + * mxpcie8250_gpio_init() - GPIO initialization routine
> + * @iobar_addr:        The base address of the GPIO I/O region
> + *
> + * Initializes the GPIO direction. After calling this function, all GPIO
> + * pins will be set to output.

This is quite dangerous! Why not input? At bare minimum this needs a
good comment to explain why it's not a problem.

> + */
> +static void mxpcie8250_gpio_init(resource_size_t iobar_addr)
> +{
> +       /* Initialize all the GPIO pins into output state */
> +       outb(0xff, iobar_addr + MOXA_GPIO_DIRECTION);
> +}

...

Why is this not a drivers/gpio/gpio-moxa.c how it's done for Exar, for example?

-- 
With Best Regards,
Andy Shevchenko