linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] gpio: vortex: add new GPIO device driver
@ 2025-07-09  9:15 Marcos Del Sol Vives
  2025-07-11 10:19 ` Bartosz Golaszewski
  2025-07-11 11:43 ` Andy Shevchenko
  0 siblings, 2 replies; 14+ messages in thread
From: Marcos Del Sol Vives @ 2025-07-09  9:15 UTC (permalink / raw)
  To: linux-kernel; +Cc: marcos, Linus Walleij, Bartosz Golaszewski, linux-gpio

Add a new simple GPIO device driver for Vortex86 lines of SoCs,
implemented according to their programming reference manual [1].

This is required for detecting the status of the poweroff button and
performing the poweroff sequence on ICOP eBox computers.

IRQs are not implemented as they are available for less than half the
GPIO pins, and they are not the ones required for the poweroff stuff, so
polling will be required anyway.

[1]: http://www.dmp.com.tw/tech/DMP_Vortex86_Series_Software_Programming_Reference_091216.pdf

Signed-off-by: Marcos Del Sol Vives <marcos@orca.pet>
---
 MAINTAINERS                |   6 ++
 drivers/gpio/Kconfig       |  10 +++
 drivers/gpio/Makefile      |   1 +
 drivers/gpio/gpio-vortex.c | 169 +++++++++++++++++++++++++++++++++++++
 4 files changed, 186 insertions(+)
 create mode 100644 drivers/gpio/gpio-vortex.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 1ff244fe3e1a..0ad462e8cceb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -26568,6 +26568,12 @@ VOLTAGE AND CURRENT REGULATOR IRQ HELPERS
 R:	Matti Vaittinen <mazziesaccount@gmail.com>
 F:	drivers/regulator/irq_helpers.c
 
+VORTEX GPIO DRIVER
+R:	Marcos Del Sol Vives <marcos@orca.pet>
+L:	linux-gpio@vger.kernel.org
+S:	Maintained
+F:	drivers/gpio/gpio-vortex.c
+
 VRF
 M:	David Ahern <dsahern@kernel.org>
 L:	netdev@vger.kernel.org
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 44f922e10db2..796fd6d43910 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1066,6 +1066,16 @@ config GPIO_TS5500
 	  blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
 	  LCD port.
 
+config GPIO_VORTEX
+	tristate "Vortex86 SoC GPIO support"
+	depends on CPU_SUP_VORTEX_32 || COMPILE_TEST
+	help
+	  Driver to access the five 8-bit bidirectional GPIO ports present on
+	  all DM&P Vortex86 SoCs.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called gpio-vortex.
+
 config GPIO_WINBOND
 	tristate "Winbond Super I/O GPIO support"
 	select ISA_BUS_API
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 88dedd298256..d226fc751686 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -196,6 +196,7 @@ obj-$(CONFIG_GPIO_VIPERBOARD)		+= gpio-viperboard.o
 obj-$(CONFIG_GPIO_VIRTUSER)		+= gpio-virtuser.o
 obj-$(CONFIG_GPIO_VIRTIO)		+= gpio-virtio.o
 obj-$(CONFIG_GPIO_VISCONTI)		+= gpio-visconti.o
+obj-$(CONFIG_GPIO_VORTEX)		+= gpio-vortex.o
 obj-$(CONFIG_GPIO_VX855)		+= gpio-vx855.o
 obj-$(CONFIG_GPIO_WCD934X)		+= gpio-wcd934x.o
 obj-$(CONFIG_GPIO_WHISKEY_COVE)		+= gpio-wcove.o
diff --git a/drivers/gpio/gpio-vortex.c b/drivers/gpio/gpio-vortex.c
new file mode 100644
index 000000000000..cf14d56d22d9
--- /dev/null
+++ b/drivers/gpio/gpio-vortex.c
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  GPIO driver for Vortex86 SoCs
+ *
+ *  Author: Marcos Del Sol Vives <marcos@orca.pet>
+ *
+ *  Based on the it87xx GPIO driver by Diego Elio Pettenò
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+#include <linux/gpio/driver.h>
+#include <linux/platform_device.h>
+
+#define GPIO_PORTS	5
+#define GPIO_PER_PORT	8
+#define GPIO_COUNT	(GPIO_PORTS * GPIO_PER_PORT)
+
+#define GPIO_DATA_BASE		0x78
+#define GPIO_DIRECTION_BASE	0x98
+
+static struct platform_device *pdev;
+
+static DEFINE_SPINLOCK(gpio_lock);
+
+static int vortex_gpio_get(struct gpio_chip *chip, unsigned int gpio_num)
+{
+	uint8_t port = gpio_num / GPIO_PER_PORT;
+	uint8_t bit  = gpio_num % GPIO_PER_PORT;
+	uint8_t val;
+
+	val = inb(GPIO_DATA_BASE + port);
+	return !!(val & (1 << bit));
+}
+
+static int vortex_gpio_direction_in(struct gpio_chip *chip, unsigned int gpio_num)
+{
+	uint8_t port = gpio_num / GPIO_PER_PORT;
+	uint8_t bit  = gpio_num % GPIO_PER_PORT;
+	unsigned long flags;
+	uint8_t dir;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	dir = inb(GPIO_DIRECTION_BASE + port);
+	dir &= ~(1 << bit); /* 0 = input */
+	outb(dir, GPIO_DIRECTION_BASE + port);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	return 0;
+}
+
+static int vortex_gpio_set(struct gpio_chip *chip, unsigned int gpio_num, int value)
+{
+	uint8_t port = gpio_num / GPIO_PER_PORT;
+	uint8_t bit  = gpio_num % GPIO_PER_PORT;
+	unsigned long flags;
+	uint8_t dat;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	dat = inb(GPIO_DATA_BASE + port);
+	if (value)
+		dat |= (1 << bit);
+	else
+		dat &= ~(1 << bit);
+	outb(dat, GPIO_DATA_BASE + port);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	return 0;
+}
+
+static int vortex_gpio_direction_out(struct gpio_chip *chip, unsigned int gpio_num, int value)
+{
+	uint8_t port = gpio_num / GPIO_PER_PORT;
+	uint8_t bit  = gpio_num % GPIO_PER_PORT;
+	unsigned long flags;
+	uint8_t dir, dat;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	/* Have to set direction first. Else writes to data are ignored. */
+	dir = inb(GPIO_DIRECTION_BASE + port);
+	dir |= (1 << bit); /* 1 = output */
+	outb(dir, GPIO_DIRECTION_BASE + port);
+
+	dat = inb(GPIO_DATA_BASE + port);
+	if (value)
+		dat |= (1 << bit);
+	else
+		dat &= ~(1 << bit);
+	outb(dat, GPIO_DATA_BASE + port);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	return 0;
+}
+
+static char labels[GPIO_COUNT][sizeof("vortex_gpXY")];
+static char *labels_table[GPIO_COUNT];
+
+static struct gpio_chip gpio_chip = {
+	.label			= KBUILD_MODNAME,
+	.owner			= THIS_MODULE,
+	.get			= vortex_gpio_get,
+	.direction_input	= vortex_gpio_direction_in,
+	.set_rv			= vortex_gpio_set,
+	.direction_output	= vortex_gpio_direction_out,
+	.base			= -1,
+	.ngpio			= GPIO_COUNT,
+	.names			= (const char * const *)labels_table,
+};
+
+static int vortex_gpio_probe(struct platform_device *pdev)
+{
+	/* Set up GPIO labels */
+	for (int i = 0; i < GPIO_COUNT; i++) {
+		sprintf(labels[i], "vortex_gp%u%u", i / 8, i % 8);
+		labels_table[i] = &labels[i][0];
+	}
+
+	return devm_gpiochip_add_data(&pdev->dev, &gpio_chip, NULL);
+}
+
+static struct platform_driver vortex_gpio_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = vortex_gpio_probe,
+};
+
+static struct resource vortex_gpio_resources[] = {
+	DEFINE_RES_IO_NAMED(GPIO_DATA_BASE, GPIO_PORTS, KBUILD_MODNAME " data"),
+	DEFINE_RES_IO_NAMED(GPIO_DIRECTION_BASE, GPIO_PORTS, KBUILD_MODNAME " dir"),
+};
+
+static int __init vortex_gpio_init(void)
+{
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_VORTEX) {
+		pr_err("Not a Vortex86 CPU, refusing to load\n");
+		return -ENODEV;
+	}
+
+	pdev = platform_create_bundle(&vortex_gpio_driver, vortex_gpio_probe,
+			vortex_gpio_resources, ARRAY_SIZE(vortex_gpio_resources),
+			NULL, 0);
+	return PTR_ERR_OR_ZERO(pdev);
+}
+
+static void __exit vortex_gpio_exit(void)
+{
+	platform_device_unregister(pdev);
+	platform_driver_unregister(&vortex_gpio_driver);
+}
+
+module_init(vortex_gpio_init);
+module_exit(vortex_gpio_exit);
+
+MODULE_AUTHOR("Marcos Del Sol Vives <marcos@orca.pet>");
+MODULE_DESCRIPTION("GPIO driver for Vortex86 SoCs");
+MODULE_LICENSE("GPL");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2025-08-21  9:44 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-09  9:15 [PATCH v2] gpio: vortex: add new GPIO device driver Marcos Del Sol Vives
2025-07-11 10:19 ` Bartosz Golaszewski
2025-07-11 14:24   ` Marcos Del Sol Vives
2025-07-11 15:01     ` Andy Shevchenko
2025-07-11 21:58       ` Marcos Del Sol Vives
2025-07-11 11:43 ` Andy Shevchenko
2025-07-11 11:56   ` Bartosz Golaszewski
2025-07-11 12:06     ` Andy Shevchenko
2025-07-11 13:52   ` Marcos Del Sol Vives
2025-07-11 14:53     ` Andy Shevchenko
2025-08-19 20:17       ` Marcos Del Sol Vives
2025-08-20 11:34         ` Andy Shevchenko
2025-08-20 12:00   ` William Breathitt Gray
2025-08-21  9:44     ` Andy Shevchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).